Validate after setting multiple fields at once
The requirement is to set multiple fields which have individual validators where there could be a period where the invariants are not satisfied but at the end of the "transaction", all validators are satisfied. Is there a way to get this done? If not, can we add this as an enhancement?
class Test(object):
a = field(type_hint=six.integer_types, native=False, default=2)
b = field(type_hint=six.integer_types, native=False, default=1)
@a.validator()
def validate_a(self, new_a):
return new_a == self.b * 2
@b.validator()
def validate_b(self, new_b):
return new_b == self.a / 2
t = Test()
# Start transaction
t.a = 100 # Fails because the invariant is not satisfied
t.b = 50
# End of transaction
This is a great suggestion ! It seems to connect with similar ideas/suggestions #8 and #25
I do not remember if I already wrote something in the code to prepare this, I'll need to investigate.
Anyway a context manager would seem quite appropriate to disable validation temporarily and set it back on exit:
with validate_once(t):
t.a = 100
t.b = 50
Maybe we could think about alternate names or additional complementary helpers, such as
-
with one_validation(t)could be an alternate name to the above -
with no_validation(t)could be a second symbol, that would not validate at all on exit, as opposed to the above. -
other names.... ?
with direct_access(t), ...
What do you think ?
I've just started looking at pyfields as an alternative to marshmallow, with the hopes of using it for convenient form and API parameter validation while providing a simple object with fields representing the submitted values. For me the ability to validate all values at once, providing a Flask form object (or some other dict) as input to my constructor, would be particularly helpful -- especially if I could get a marshmallow-like error result out of the process, mapping fieldnames to lists of error messages for those fields that failed validation. Hope this makes sense... been learning a lot this afternoon. Thanks!
Thanks @jgarbers for your feedback ! Your message does not really seem to relate to this issue #72 - @bharathbhushan1 meant validation that can not be performed field by field but once all fields have been set. So I would recommend that you open a new dedicated issue.
To give a first level of answer, you can already validate all values at once by passing a **dct to the constructor ; however only the first invalid field will appear in the error message as opposed to what you seem to require.
Maybe this should be solved in a different function that we could generate optionally on the class ? or we could imagine a boolean flag triggering this in the constructor. Or maybe we could make this the default behaviour of the generated constructor ? I have no strong opinion here but performance might be something to consider.