Цербер - Поле обязательно для заполнения, только когда встречается зависимость - PullRequest
0 голосов
/ 26 февраля 2019

Рассмотрим следующую схему

schema = {
    "value_type":{
        "type": "string", "required": True
    }, 
    "units": {
        "type": "string", 
         "dependencies": {"value_type": ["float", "integer"]},
         "required": True
    }
}

Я хочу, чтобы поле units было обязательным только , если значение поля value_type равно либо float, либо integer.

Вот поведение, к которому я стремлюсь

v = Validator(schema)
v.validate({"value_type": "float", "units": "mm"})  # 1. 
True
v.validate({"value_type": "boolean", "units": "mm"})  # 2.
False
v.validate({"value_type": "float"})  # 3.
False
v.validate({"value_type": "boolean"})  # 4.
True

Приведенная выше схема возвращает ожидаемый результат только для первых 3 случаев.

Если я изменю определение units (опуская "required": True) до

"units": {"type": "string", "dependencies": {"value_type": ["float", "integer"]}}

, тогда проверка

v.validate({"value_type": "float"})  # 3.
True

возвращает True, что не то, что я хочу.

Я взглянул на oneof правила в документации , но не смог найти способ применить это только к свойству required.

Я хочу, чтобы значение требуемого былоTrue только при достижении зависимости.

Как мне изменить мою схему для достижения этой цели?

1 Ответ

0 голосов
/ 03 марта 2019

Поскольку ваши варианты охватывают более одного поля, правила *of не совсем подходят, тем более что в документе это поля верхнего уровня.

Как правило, я бы посоветовалPython и не все должны быть выражены схемой, поэтому вы можете просто определить две допустимые схемы и проверить их на соответствие:

schema1 = {...}
schema2 = {...}

if not any(validator(document, schema=x) for x in (schema1, schema2)):
    boom()

Это также лучше воспринимается, чем любая схема, с которой вы в итоге столкнетесь.

В качестве альтернативы вы можете использовать правило check_with.В этом примере показаны два разных способа сообщения об ошибке, причем последний является предпочтительным, когда ошибки представляются только людям, поскольку они допускают настраиваемые сообщения для различных ситуаций при отсутствии структурной информации об ошибке:

class MyValidator(Validator):
    def _check_with_units_required(self, field, value):
        if value in ("float", "integer"):
            if "units" not in self.document:
                self._error("units", errors.REQUIRED_FIELD, "check_with")
        else:
            if "units" in self.document:
                self._error(
                    "units", "The 'units' field must not be provided for value "
                             "types other than float or integer."
                )

schema = {
    "value_type": {
        "check_with": "units_required",
        "required": True,
        "type": "string"
    },
    "units": {
        "type": "string",
    }
}

validator = MyValidator(schema)

assert validator({"value_type": "float", "units": "mm"})
assert not validator({"value_type": "boolean", "units": "mm"})
assert not validator({"value_type": "float"})
assert validator({"value_type": "boolean"})
...