Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return multiple validation errors at once #16

Open
syastrov opened this issue Nov 26, 2019 · 7 comments
Open

Return multiple validation errors at once #16

syastrov opened this issue Nov 26, 2019 · 7 comments
Labels
enhancement New feature or request

Comments

@syastrov
Copy link
Contributor

Not sure if it's possible, but it would be useful if you could get a list of e.g. ValueErrors, rather than just the first one that failed when there are multiple issues.
It would make typical much more useful for validation purposes.

Perhaps it could be configured somehow which behavior you want, since there could be a performance hit, I suppose.

Example:

>>> @typic.al
... @dataclass
... class N:
...   a: str
...   b: int
...   c: int
... 
>>> N(a="a", b="a", c="b")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in __init__
  File "../typic/api.py", line 143, in __setattr_coerced__
    value = ann[name](value) if name in ann else value
  File "../typic/coercer.py", line 117, in coerce
    return self.coercer(value)
  File "<string>", line 3, in coerce__class_int___class_inspect__empty__False
ValueError: invalid literal for int() with base 10: 'a'
@seandstewart seandstewart added the enhancement New feature or request label Nov 26, 2019
@seandstewart
Copy link
Owner

That would be a nice level of introspection, but it would come at a pretty decent performance cost. We'd need to validate input before passing the values in for initialization. Part of typical's speed on coercion is that it coerces the value on setattr rather than on init.

@syastrov
Copy link
Contributor Author

In light of your response at #15 (comment), I'm not sure this issue is still relevant, since one could do validation in a preprocessing step and gather the errors (I assume that whatever library which handles JSON schema could spit out multiple errors, but not sure).

Perhaps the validate feature could be mentioned more prominently in the Quick Start or Example in the docs.

@syastrov
Copy link
Contributor Author

Just thought about it a bit more: using constrained types means that typical also performs validation, while coercing, right? But I think you could make a constrained type that is not representable in a JSON schema, and therefore typical would raise validation errors when coercing despite the data passing JSON schema validation. Therefore, I still think it would be useful to be able to gather multiple validation errors from typical itself (somehow). If you think it's in scope to implement this, then maybe it could be a (non-default) configuration flag where you know that enabling it will make typical perform worse?

@seandstewart
Copy link
Owner

seandstewart commented Nov 30, 2019

You read my mind. It's a bit of expansion in scope for the constraints validator, but work is ongoing in the v2beta-validator branch to provide "strict" validation of inputs automatically.

@seandstewart
Copy link
Owner

@syastrov - I haven't adding error-chaining, but I've made the validation error quite a bit more informative:

>>> @typic.klass(strict=True)
... class N:
...     a: str
...     b: int
...     c: int
...    
>>> N.validate(dict(a="a", b="a", c="b"))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Users/god/PycharmProjects/typic/typic/serde/des.py", line 440, in des
    return __d(__v(val))
  File "/Users/god/PycharmProjects/typic/typic/constraints/common.py", line 100, in validate
    valid, value = self.validator(value)
  File "<typical generated validator_1f2e84ae80ec8e3f-4>", line 9, in validator_1f2e84ae80ec8e3f
    valid, val = validator_1f2e84ae80ec8e3f_item_validator(val, addtl)
  File "<typical generated validator_1f2e84ae80ec8e3f_item_validator-4>", line 8, in validator_1f2e84ae80ec8e3f_item_validator
    rety = validator_1f2e84ae80ec8e3f_item_validator_items_validators[x](y, field='.'.join((valtname, x)))
  File "/Users/god/PycharmProjects/typic/typic/constraints/common.py", line 105, in validate
    ) from None
typic.constraints.error.ConstraintValueError: N.b: value <'a'> fails constraints: (type=int, nullable=False, coerce=False)

@syastrov
Copy link
Contributor Author

@seandstewart Thanks for the follow up.
And you've done some really nice work since I last checked.

For me, not supporting this is maybe the only technical reason why I wouldn't switch to typical (from pydantic; there are other non-technical reasons, like that typical is not that widely used yet afaik).

So I may send a PR your way if I get the chance.

@seandstewart
Copy link
Owner

@syastrov -

Thanks for the honesty there. Error-chaining should be possible.

I'd put it at a medium-heavy lift, as the current system is really designed to short-circuit ASAP with an informative error. It's not impossible to add a branch for this, but definitely a day or two's worth of work, which is why I'm scheduling it for 2.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants