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
Handle constraints being applied to schemas that don't accept it #6951
Conversation
Deploying with Cloudflare Pages
|
Open questions:
|
please review Most tests are passing, a couple are failing, in part because of the questions above. |
This is now working and allowing constraint re-ordering. The cost is running things in Python when they can't be "inlined" into Rust. There's also a slight inconsistency I belive since when we do "inline" it the order is not preserved (it's whatever the order of the if statements is in Rust). I guess that's fine. |
These two give different results: from typing_extensions import Annotated
from pydantic import BaseModel, Field, AfterValidator
from pydantic.type_adapter import TypeAdapter
Tp = Annotated[int, AfterValidator(lambda x: x * 2), Field(gt=3)]
class A(BaseModel):
x: Tp
print(A.__pydantic_core_schema__['definitions'][0]['schema']['fields']['x']['schema'])
ta = TypeAdapter(Tp)
print(ta.core_schema) It seems like this is because BaseModel merges field infos when it's constructed. We'd have to get rid of all field-info merging to get the right behavior w.r.t. ordering of constraints. I'm inclined to leave fixing that for a future PR. WDYT @dmontagu? |
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.
otherwise LGTM.
for constraint in URL_CONSTRAINTS: | ||
CONSTRAINTS_TO_ALLOWED_SCHEMAS[constraint].update(('url', 'multi-host-url')) | ||
for constraint in BOOL_CONSTRAINTS: | ||
CONSTRAINTS_TO_ALLOWED_SCHEMAS[constraint].update(('bool',)) |
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.
does this get called on from pydantic import X
? If so we might need to worry about import time, if it's later/when require it shouldn't be a problem.
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 believe it is imported immediately. It's not all that complex though, just assigning times to a dict. I could hide it behind an lru_cache function or something, but that would probably make schema generation slower (one more dict lookup), and that seems to be a bigger problem right now than import time
please update. |
please review |
Co-authored-by: Samuel Colvin <s@muelcolvin.com>
please review |
maybe_as_any: Optional[SerializeAsAny[User]] | ||
maybe_as_any: Optional[SerializeAsAny[User]] = None |
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.
Not strictly necessary for this PR but the insert_assert() below doesn't work without it
def forbid_inf_nan_check(x: Any) -> Any: | ||
if not math.isfinite(x): | ||
raise PydanticKnownError('finite_number') | ||
return x |
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.
Added a test for the error case here
This handles the particular case of
pattern
not working when using a customGenerateSchema
(reported in #6045 (comment)) but also tries to be more general to handle other similar issues.Selected Reviewer: @samuelcolvin