-
Notifications
You must be signed in to change notification settings - Fork 287
Add validated data args in default factory #1475
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
Add validated data args in default factory #1475
Conversation
src/validators/with_default.rs
Outdated
let co_vars = default_factory.getattr(py, "__code__")?.getattr(py, "co_varnames")?; | ||
let default_factory_args: &Bound<PyTuple> = co_vars.downcast_bound::<PyTuple>(py)?; |
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.
Open to suggestions on better way to do args checking on the python default factory!
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1475 +/- ##
==========================================
- Coverage 90.21% 89.08% -1.13%
==========================================
Files 106 112 +6
Lines 16339 17849 +1510
Branches 36 40 +4
==========================================
+ Hits 14740 15901 +1161
- Misses 1592 1928 +336
- Partials 7 20 +13
... and 49 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
CodSpeed Performance ReportMerging #1475 will not alter performanceComparing Summary
|
please review |
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.
This implementation is more simple than I expected thus far - nice work.
Curious to hear what @Viicos thinks given that he helped with the design choices for this API.
src/validators/with_default.rs
Outdated
Self::DefaultFactory(ref default_factory) => { | ||
// MASSIVE HACK! PyFunction doesn't exist for PyPy, | ||
// ref from https://github.com/pydantic/pydantic-core/pull/161#discussion_r917257635 | ||
let is_func = default_factory.getattr(py, "__class__")?.to_string() == "<class 'function'>"; |
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.
Should we add both branches here so that we can hopefully remove the hack in the long run?
See
pydantic-core/src/input/return_enums.rs
Lines 313 to 327 in 903a1a9
// the PyFunction::is_type_of(attr) catches `staticmethod`, but also any other function, | |
// I think that's better than including static methods in the yielded attributes, | |
// if someone really wants fields, they can use an explicit field, or a function to modify input | |
#[cfg(not(PyPy))] | |
if !is_bound && !attr.is_instance_of::<PyFunction>() { | |
return Some(Ok((name, attr))); | |
} | |
// MASSIVE HACK! PyFunction doesn't exist for PyPy, | |
// is_instance_of::<PyFunction> crashes with a null pointer, hence this hack, see | |
// https://github.com/pydantic/pydantic-core/pull/161#discussion_r917257635 | |
#[cfg(PyPy)] | |
if !is_bound && attr.get_type().to_string() != "<class 'function'>" { | |
return Some(Ok((name, attr))); | |
} | |
} |
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.
Do we even need the function check here? I assume if we got to this point we know this
8000
is a callable bc we've matched on DefaultFactory
...
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.
Yes, because there's a case ex: default_factory=str
in python then the default_factory
here will not have __code__
and raise error.
Thanks @nix010 for the implementation. The proper way (and this will simplify things even more here) to do this is to inspect the default_factory callable in Pydantic, using As an existing example, we do this in |
@Viicos So my intention is exactly the same. But to |
@Viicos is referring to https://github.com/pydantic/pydantic/blob/6c3d3b3bb255422fc64eec8e9014016743207ff0/pydantic/_internal/_decorators.py#L514-L548 Basically, we want to inspect the function in |
Ok. So there will be a |
Correcet, probably on the field core schema |
@@ -2418,10 +2422,14 @@ def with_default_schema( | |||
metadata: Any other information you want to include with the schema, not used by pydantic-core | |||
serialization: Custom serialization schema | |||
""" | |||
|
|||
has_arg = isfunction(default_factory) and len(signature(default_factory).parameters) > 0 |
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.
@nix010, this check should reside in pydantic
, like we do for the validators and determining their info status 👍
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.
Got it!.
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.
@sydney-runkle is this func is what you've mentioned ?
https://github.com/pydantic/pydantic/blob/60f704721a096dced3b19dd465a1e31495fcd802/pydantic/json_schema.py#L1076.
I don't see where it got called in the process.
Also do you think that this line should be removed in pydantic-core
?
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.
Yep, this line should be removed in pydantic-core
, bc the inspect logic should reside in pydantic
.
Re inspection, I'd refer to this as an example: https://github.com/pydantic/pydantic/blob/6c3d3b3bb255422fc64eec8e9014016743207ff0/pydantic/_internal/_decorators.py#L514-L548
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.
@sydney-runkle sorry, I took a while but can't find a good place to put this check in the pydantic
and accomodate with this, so feel free to take over this one.
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.
@nix010 no worries, I'll take it over today
Change Summary
Add feature pydantic pydantic/pydantic#9789
Related issue number
Checklist
pydantic-core
(except for expected changes)Selected Reviewer: @davidhewitt