-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Properly set Config in create_model #320
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
Conversation
Set the Config attribute in create_model, so it is found by the MetaModel.
Codecov Report
@@ Coverage Diff @@
## master #320 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 13 13
Lines 1761 1771 +10
Branches 340 344 +4
=====================================
+ Hits 1761 1771 +10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes, overall this looks like a good idea. Thanks.
There are a few changes here that require tests:
- validator inheritance in the standard model inheritance case, with and without further subsequent validators on the same field in inheriting models
- validators in
create_model
| @@ -100,17 +100,25 @@ def _extract_validators(namespace): | |||
| return validators | |||
|
|
|||
|
|
|||
| def inherit_validators(base_validators, validators): | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better if this method returns validators so it's clear what's going on.
pydantic/main.py
Outdated
| @@ -100,17 +100,25 @@ def _extract_validators(namespace): | |||
| return validators | |||
|
|
|||
|
|
|||
| def inherit_validators(base_validators, validators): | |||
| for field, field_validators in base_validators.items(): | |||
| validators.setdefault(field, []).extend(field_validators) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to be explicit
if field in validators:
validators[field] += field_validators
else:
validators[field] = field_validators
pydantic/main.py
Outdated
| annotations[f_name] = f_annotation | ||
| fields[f_name] = f_value | ||
|
|
||
| namespace = {"__annotations__": annotations, "__validators__": vg.validators} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quotes please.
pydantic/main.py
Outdated
| namespace = {'config': config, '__fields__': fields} | ||
| # f_validators = vg.get_validators(f_name) | ||
| # if f_validators: | ||
| # setattr(f_value, "__validator_config", f_validators) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this definitely not required? if so please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll strip out some more incorrect validator logic.
tests/test_create_model.py
Outdated
| ignore_extra = False | ||
| allow_extra = False | ||
|
|
||
| model = create_model("FooModel", foo=(int, ...), __config__=Config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't got around to finding a way to lint this, but pydantic should use single quotes always unless single quotes are used in the string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We struggled with this with black as well. Ended up just using the Black convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still needs the extra tests mentioned above, otherwise looking good.
pydantic/main.py
Outdated
| @@ -100,17 +100,30 @@ def _extract_validators(namespace): | |||
| return validators | |||
|
|
|||
|
|
|||
| def inherit_validators(base_validators, validators): | |||
| for field, field_validators in base_validators.items(): | |||
| if field in validators: | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want to do it this way
if field not in validators:
validators[field] = []
validators[field] += field_validatorsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to avoid mutating the validators in the base classes.
a = []
b = a
b += [1]
assert a == [1]There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what I've suggested has exactly the same effect as what you have now, just avoids duplicated lines.
pydantic/main.py
Outdated
|
|
||
| config = inherit_config(namespace.get('Config'), config) | ||
| vg = ValidatorGroup(_extract_validators(namespace)) | ||
| inherit_validators(_extract_validators(namespace), validators) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validators =
|
@samuelcolvin I've extended the two existing validation test using inheritance. Is that sufficient or did you have something further in mind? |
|
Definitely requires more tests, from above:
|
|
I've added some tests for child classes using validators from parent classes, to complement the existing tests for adding validation in child classes.
Do you have specific test cases in mind that aren't covered by |
tests/test_validators.py
Outdated
| @@ -353,6 +353,65 @@ def check_a_two(cls, v): | |||
| Child(a='snap') | |||
|
|
|||
|
|
|||
| def test_validate_parent_all(): | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this test and the one at the bottom should swap name, so this becomes test_validate_child_all.
yes, a test where we have a model with validators, then us that as a base in I'm not saying it'll add any specific coverage (it can't since we have 100% coverage), but since we think that should be possible we should have a test of doing it. |
I've added some detail around the |
|
my mistake, sorry. LGTM, I'll look full and merge early next week. |
|
great, thank you very much. Will deploy in a week or two, unless you need it urgently in which case let me know and I'll deploy sooner. |
|
Thank you - the review process was definitely useful! If you could manage to release sooner it would save me the work of deploying an internal fork. |
|
Will do. |
|
done. |
* uprev pyo3 to 0.17.3 * hopefully speed up ValidationError.errors()
Change Summary
Set the Config attribute in create_model, so it is found by the
MetaModel. Pushes the field and validator configuration into the
metaclass.
Related issue number
None
Performance Changes
Not run.
Checklist
HISTORY.rsthas been updated#<number>@whatever