Я хотел бы проверить dict
, где значения соответствуют следующим правилам:
- значение должно быть либо одиночным
float
, либо List(float)
- если это одиночный
float
, значение должно быть 1 - , если это
List(float)
, каждое число с плавающей запятой должно быть положительным
Вот мой код и некоторые тестовые утверждения, которые работают правильно:
import cerberus
v = cerberus.Validator()
schema1 = {
"key1": {
"type": ["float", "list"],
"min": 1,
"max": 1,
"schema": {"type": "float", "min": 0},
}
}
document1 = {"key1": 1}
document2 = {"key1": 5}
document3 = {"key1": "5"}
document4 = {"key1": [0.5, 0.3]}
document5 = {"key1": ["0.5", 0.3]}
assert v.validate(document1, schema1)
assert not v.validate(document2, schema1)
assert not v.validate(document3, schema1)
assert v.validate(document4, schema1)
assert not v.validate(document5, schema1)
Теперь мне нужно выполнить еще одно условие:
- , если это
List(float)
, sum
из float
должно быть равно 1
Поэтому я написал функцию check_with
, как описано в документации (https://docs.python-cerberus.org/en/stable/validation-rules.html).
from cerberus import Validator
class MyValidator(Validator):
def _check_with_sum_eq_one(self, field, value):
"""Checks if sum equals 1"""
if sum(value) != 1:
self._error(field, f"Sum of '{field}' must exactly equal 1")
Скорректированная схема и тестовые документы выглядят следующим образом:
v = MyValidator()
schema2 = {
"key1": {
"type": ["float", "list"],
"min": 1,
"max": 1,
"schema": {"type": "float", "min": 0, "max": 1, "check_with": "sum_eq_one"},
}
}
document1 = {"key1": 1}
document2 = {"key1": 5}
document3 = {"key1": "5"}
document4 = {"key1": [0.5, 0.3]} # error
document5 = {"key1": ["0.5", 0.3]} # error
document6 = {"key1": [0.5, 0.5]} # error
Теперь, когда значение равно List(float)
, только первый элемент list
будет введено в мою функцию, что приводит к TypeError: 'float' object is not iterable
.
При проверке document4
, field
будет int=0
и value=0.5
. Итак, сообщение об ошибке имеет смысл.
Мне интересно, почему весь список не передается в мою функцию? Что мне здесь не хватает?