diff --git a/pydantic/exceptions.py b/pydantic/exceptions.py index ccf3f25..1891ef7 100644 --- a/pydantic/exceptions.py +++ b/pydantic/exceptions.py @@ -11,7 +11,7 @@ def type_json(type_: type): return str(type_) -Error = namedtuple('Error', ['exc', 'validator', 'track_type', 'index']) +Error = namedtuple('Error', ['exc', 'track_type', 'index']) def jsonify_errors(e): @@ -20,7 +20,6 @@ def jsonify_errors(e): elif isinstance(e, Error): d = { 'error_type': e.exc.__class__.__name__, - 'validator': e.validator and e.validator.__qualname__, 'track': type_json(e.track_type), 'index': e.index, } diff --git a/pydantic/fields.py b/pydantic/fields.py index e8ed386..1497f06 100644 --- a/pydantic/fields.py +++ b/pydantic/fields.py @@ -139,7 +139,7 @@ class Field: try: v_iter = enumerate(v) except TypeError as exc: - return v, Error(exc, iter, None, None) + return v, Error(exc, None, None) for i, v_ in v_iter: single_result, single_errors = self._validate_singleton(self.validator_tracks, v_, model, i) if errors or single_errors: @@ -158,7 +158,7 @@ class Field: try: v_iter = dict(v) except TypeError as exc: - return v, Error(exc, dict, None, None) + return v, Error(exc, None, None) result, errors = {}, [] for k, v_ in v_iter.items(): @@ -177,9 +177,9 @@ class Field: def _validate_singleton(self, tracks, v, model, index=None): result, errors = ..., [] for track in tracks: - value, exc, validator = track.validate(v, model, self) + value, exc = track.validate(v, model, self) if exc: - errors.append(Error(exc, validator, track.type_, index)) + errors.append(Error(exc, track.type_, index)) elif isinstance(v, track.type_): # exact match: return immediately return value, None @@ -234,8 +234,8 @@ class ValidatorRoute: else: v = validator(model, v) except (ValueError, TypeError, ImportError) as e: - return v, e, validator - return v, None, None + return v, e + return v, None def _find_validator(self): get_validators = getattr(self.type_, 'get_validators', None) diff --git a/pydantic/main.py b/pydantic/main.py index 72d6862..3236467 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -65,8 +65,8 @@ class MetaModel(type): MISSING = Missing('field required') -MISSING_ERROR = Error(MISSING, None, None, None) -EXTRA_ERROR = Error(Extra('extra fields not permitted'), None, None, None) +MISSING_ERROR = Error(MISSING, None, None) +EXTRA_ERROR = Error(Extra('extra fields not permitted'), None, None) class BaseModel(metaclass=MetaModel): diff --git a/tests/test_complex.py b/tests/test_complex.py index 4fe8bce..70d53b0 100644 --- a/tests/test_complex.py +++ b/tests/test_complex.py @@ -30,15 +30,13 @@ def test_str_bytes(): "error_msg": "None is not an allow value", "error_type": "TypeError", "index": null, - "track": "str", - "validator": "not_none_validator" + "track": "str" }, { "error_msg": "None is not an allow value", "error_type": "TypeError", "index": null, - "track": "bytes", - "validator": "not_none_validator" + "track": "bytes" } ] }""" == exc_info.value.json(2) @@ -94,15 +92,13 @@ def test_union_int_str(): "error_msg": "int() argument must be a string, a bytes-like object or a number, not 'NoneType'", "error_type": "TypeError", "index": null, - "track": "int", - "validator": "int" + "track": "int" }, { "error_msg": "None is not an allow value", "error_type": "TypeError", "index": null, - "track": "str", - "validator": "not_none_validator" + "track": "str" } ] }""" == exc_info.value.json(2) @@ -125,15 +121,13 @@ def test_typed_list(): "error_msg": "invalid literal for int() with base 10: 'x'", "error_type": "ValueError", "index": 1, - "track": "int", - "validator": "int" + "track": "int" }, { "error_msg": "invalid literal for int() with base 10: 'y'", "error_type": "ValueError", "index": 2, - "track": "int", - "validator": "int" + "track": "int" } ] }""" == exc_info.value.json(2) @@ -147,8 +141,7 @@ def test_typed_list(): "error_msg": "'int' object is not iterable", "error_type": "TypeError", "index": null, - "track": null, - "validator": "iter" + "track": null } }""" == exc_info.value.json(2) @@ -174,8 +167,7 @@ def test_typed_dict(value, result): "error_msg": "'int' object is not iterable", "error_type": "TypeError", "index": null, - "track": null, - "validator": "dict" + "track": null } }""" ), @@ -189,8 +181,7 @@ def test_typed_dict(value, result): "error_msg": "invalid literal for int() with base 10: 'b'", "error_type": "ValueError", "index": "a", - "track": "int", - "validator": "int" + "track": "int" } ] ] @@ -203,8 +194,7 @@ def test_typed_dict(value, result): "error_msg": "cannot convert dictionary update sequence element #0 to a sequence", "error_type": "TypeError", "index": null, - "track": null, - "validator": "dict" + "track": null } }""", ) @@ -276,15 +266,13 @@ def test_recursive_list(): "error_msg": "field required", "error_type": "Missing", "index": null, - "track": null, - "validator": null + "track": null } }, "error_msg": "1 error validating input", "error_type": "ValidationError", "index": 0, - "track": "SubModel", - "validator": "BaseModel.validate" + "track": "SubModel" } ] }""" == exc_info.value.json(2) diff --git a/tests/test_main.py b/tests/test_main.py index 1e1a199..c9ba6e7 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -26,8 +26,7 @@ def test_ultra_simple_missing(): "error_msg": "field required", "error_type": "Missing", "index": null, - "track": null, - "validator": null + "track": null } }""" == exc_info.value.json(2) @@ -42,15 +41,13 @@ def test_ultra_simple_failed(): "error_msg": "could not convert string to float: 'x'", "error_type": "ValueError", "index": null, - "track": "float", - "validator": "float" + "track": "float" }, "b": { "error_msg": "invalid literal for int() with base 10: 'x'", "error_type": "ValueError", "index": null, - "track": "int", - "validator": "int" + "track": "int" } }""" == exc_info.value.json(2) @@ -126,15 +123,13 @@ def test_nullable_strings_fails(): "error_msg": "None is not an allow value", "error_type": "TypeError", "index": null, - "track": "bytes", - "validator": "not_none_validator" + "track": "bytes" }, "required_str_value": { "error_msg": "None is not an allow value", "error_type": "TypeError", "index": null, - "track": "str", - "validator": "not_none_validator" + "track": "str" } }""" == json.dumps(jsonify_errors(m.errors), indent=2, sort_keys=True) @@ -181,15 +176,13 @@ def test_prevent_extra_fails(): "error_msg": "extra fields not permitted", "error_type": "Extra", "index": null, - "track": null, - "validator": null + "track": null }, "spam": { "error_msg": "extra fields not permitted", "error_type": "Extra", "index": null, - "track": null, - "validator": null + "track": null } }""" == exc_info.value.json(2) diff --git a/tests/test_settings.py b/tests/test_settings.py index 239271c..fa57513 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -23,5 +23,4 @@ def test_sub_env_missing(): with pytest.raises(ValidationError) as exc_info: SimpleSettings() assert exc_info.value.args[0] == ('1 error validating input: {"apple": {"error_msg": "None is not an allow value", ' - '"error_type": "TypeError", "index": null, "track": "str", ' - '"validator": "not_none_validator"}}') + '"error_type": "TypeError", "index": null, "track": "str"}}') diff --git a/tests/test_types.py b/tests/test_types.py index f02901c..b60e4e1 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -32,8 +32,7 @@ def test_constrained_str_too_long(): "error_msg": "length greater than maximum allowed: 10", "error_type": "ValueError", "index": null, - "track": "ConstrainedStrValue", - "validator": "ConstrainedStr.validate" + "track": "ConstrainedStrValue" } }""" == exc_info.value.json(2) @@ -184,29 +183,25 @@ def test_datetime_errors(): "error_msg": "Invalid date format", "error_type": "ValueError", "index": null, - "track": "date", - "validator": "parse_date" + "track": "date" }, "dt": { "error_msg": "month must be in 1..12", "error_type": "ValueError", "index": null, - "track": "datetime", - "validator": "parse_datetime" + "track": "datetime" }, "duration": { "error_msg": "Invalid duration format", "error_type": "ValueError", "index": null, - "track": "timedelta", - "validator": "parse_duration" + "track": "timedelta" }, "time_": { "error_msg": "hour must be in 0..23", "error_type": "ValueError", "index": null, - "track": "time", - "validator": "parse_time" + "track": "time" } }""" == exc_info.value.json(2) @@ -243,8 +238,7 @@ def test_enum_fails(): "error_msg": "3 is not a valid ToolEnum", "error_type": "ValueError", "index": null, - "track": "ToolEnum", - "validator": "enum_validator" + "track": "ToolEnum" } }""" == exc_info.value.json(2) @@ -288,29 +282,25 @@ def test_string_fails(): "error_msg": "Email address is not valid", "error_type": "ValueError", "index": null, - "track": "NameEmail", - "validator": "NameEmail.validate" + "track": "NameEmail" }, "str_email": { "error_msg": "Email address is not valid", "error_type": "ValueError", "index": null, - "track": "EmailStr", - "validator": "EmailStr.validate" + "track": "EmailStr" }, "str_min_length": { "error_msg": "length less than minimum allowed: 5", "error_type": "ValueError", "index": null, - "track": "ConstrainedStrValue", - "validator": "ConstrainedStr.validate" + "track": "ConstrainedStrValue" }, "str_regex": { "error_msg": "string does not match regex \\"^xxx\\\\d{3}$\\"", "error_type": "ValueError", "index": null, - "track": "ConstrainedStrValue", - "validator": "ConstrainedStr.validate" + "track": "ConstrainedStrValue" } }""" == exc_info.value.json(2)