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

Validate after setting multiple fields at once #72

Open
bharathbhushan1 opened this issue Jun 27, 2020 · 3 comments
Open

Validate after setting multiple fields at once #72

bharathbhushan1 opened this issue Jun 27, 2020 · 3 comments

Comments

@bharathbhushan1
Copy link

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
@smarie
Copy link
Owner

smarie commented Jun 29, 2020

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 ?

@jgarbers
Copy link

jgarbers commented Nov 3, 2020

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!

@smarie
Copy link
Owner

smarie commented Nov 9, 2020

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.

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

No branches or pull requests

3 participants