-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Early validation hook #7603
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
Early validation hook #7603
Conversation
|
@SylvainCorlay I think this generally is a good idea. Since passing a callback in as metadata is atypical for the traitlets module, I'm going to ping @ellisonbg to get his opinion. My own opinion is that I like the design, but that may be because it's Javascript-like. :) |
|
I think that there is a great need to allow the |
Definitely! |
|
+1 to the idea. I think it would make sense to make the HasTraits validation come after the traitlet validation. For example, the traitlet validation may cast a value to a specific type, etc. That can be useful to do before the HasTraits validation function runs. For example, suppose I have a CDate function that understands lots of string date formats and casts them to standard python date formats. It's next to useless to have a HasTraits validation run before the traitlet validation since the HasTraits validation doesn't understand the string formats. However, once the traitlet validation has run, there are some guarantees about what is in the value, and the HasTraits validation function can rely on that. |
|
@jasongrout Good idea. This would simply require moving the two lines of code after the validation. Let's wait for other people's feedback. Besides, as suggested by @jasongrout in person, we could remove the validation with |
|
Isn't this already possible using subclassing? i.e. define a new |
|
This would require to make a new subclass of |
|
@takluyver - this proposal allows a HasTraits class to cleanly validate traitlets against each other. To do this at the traitlet level, how would you change the validation of the value attribute when the parity attribute changed? We face the same issue in the slider: how do we validate the value against the max and min? We don't want to set the value and then recant the setting if it was actually invalid to start with. |
|
As per discussion,
|
|
ping @ellisonbg |
|
So I don't forget: I think this would be neater if the API involved defining a |
|
Changed the API according to Thomas' proposition. Here is the working example. from IPython.utils.traitlets import *
class Parity(HasTraits):
value = Int(0)
parity = Enum(['odd', 'even'], default_value='even', allow_none=False)
def _value_validate(self, value, trait):
if self.parity == 'even' and value % 2:
raise TraitError('Expected an even number')
if self.parity == 'odd' and (value % 2 == 0):
raise TraitError('Expected an odd number')
return value
u = Parity()u.parity = 'odd'
u.value = 1 # OK
u.value = 2 # Should raise a TraitError |
|
@takluyver do you have any more thoughts on this? |
|
It looks fine at a glance. We'll look at it in more detail once 3.0 is out. |
6a5dedc to
720c59c
Compare
|
Rebased - just to reflect the latest changes in traitlets. |
1624b02 to
f527309
Compare
f527309 to
b23a83d
Compare
|
Added the example as a test. |
|
This has run afoul of the complex Qt mixins, causing: I'm not sure yet how problematic the behavior is. It might be okay to just swallow the error, it might not. |
|
Do you have a traceback of this? Btw, with #7770, we will be less likely to try to validate default values at init time. |
This allows one to add a validation hook in the traitlet metadata.
For example, define a "Parity" HasTraits instance:
```Python from IPython.utils.traitlets import *
def validate(self, value, trait):
if self.parity == 'even' and value % 2:
raise TraitError('Expected an even number')
if self.parity == 'odd' and (value % 2 == 0):
raise TraitError('Expected an odd number')
return value
class Parity(HasTraits):
value = Int(0, validate=validate)
parity = Enum(['odd', 'even'], default_value='even', allow_none=False)
This is meant to allow custom attribute validation prior to assignment, for issues such as #6814.