Skip to content

Conversation

hugoduncan
Copy link
Contributor

@hugoduncan hugoduncan commented Dec 6, 2018

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

  • Unit tests for the changes exist
  • Tests pass on CI and coverage remains at 100%
  • Documentation reflects the changes
  • No performance deterioration (if applicable)
  • HISTORY.rst has been updated
    • if this is the first change since a release, please add a new section
    • include the issue number or this pull request number #<number>
    • if you're not a regular contributer please include your github username @whatever

Set the Config attribute in create_model, so it is found by the
MetaModel.
@codecov
Copy link

codecov bot commented Dec 6, 2018

Codecov Report

Merging #320 into master will not change coverage.
The diff coverage is 100%.

@@          Coverage Diff          @@
##           master   #320   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          13     13           
  Lines        1761   1771   +10     
  Branches      340    344    +4     
=====================================
+ Hits         1761   1771   +10

Copy link
Member

@samuelcolvin samuelcolvin left a 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):
Copy link
Member

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)
Copy link
Member

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}
Copy link
Member

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)
Copy link
Member

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.

Copy link
Contributor Author

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.

ignore_extra = False
allow_extra = False

model = create_model("FooModel", foo=(int, ...), __config__=Config)
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

@samuelcolvin samuelcolvin left a 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:
Copy link
Member

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_validators

Copy link
Contributor Author

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]

Copy link
Member

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validators =

@hugoduncan
Copy link
Contributor Author

@samuelcolvin I've extended the two existing validation test using inheritance. Is that sufficient or did you have something further in mind?

@samuelcolvin
Copy link
Member

Definitely requires more tests, from above:

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

@hugoduncan
Copy link
Contributor Author

I've added some tests for child classes using validators from parent classes, to complement the existing tests for adding validation in child classes.

  • validators in create_model

Do you have specific test cases in mind that aren't covered by test_inheritance_validators and test_inheritance_validators_all?

@@ -353,6 +353,65 @@ def check_a_two(cls, v):
Child(a='snap')


def test_validate_parent_all():
Copy link
Member

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.

@samuelcolvin
Copy link
Member

Do you have specific test cases in mind

yes, a test where we have a model with validators, then us that as a base in create_model and check the validators are called correctly on the created model.

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.

@hugoduncan
Copy link
Contributor Author

yes, a test where we have a model with validators, then us that as a base in create_model and check the validators are called correctly on the created model.

I've added some detail around the test_inheritance_validators test, adding a case for always=True. Otherwise I'm struggling to see how this doesn't cover what you describe.

@samuelcolvin
Copy link
Member

my mistake, sorry.

LGTM, I'll look full and merge early next week.

@samuelcolvin samuelcolvin merged commit 3249330 into pydantic:master Dec 7, 2018
@samuelcolvin
Copy link
Member

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.

@hugoduncan
Copy link
Contributor Author

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.

@samuelcolvin
Copy link
Member

Will do.

@samuelcolvin
Copy link
Member

done.

alexdrydew pushed a commit to alexdrydew/pydantic that referenced this pull request Dec 23, 2023
* uprev pyo3 to 0.17.3

* hopefully speed up ValidationError.errors()
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

Successfully merging this pull request may close these issues.

2 participants