-
Notifications
You must be signed in to change notification settings - Fork 222
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
fix: pydantic 2.10.x breaking change #1095
base: main
Are you sure you want to change the base?
fix: pydantic 2.10.x breaking change #1095
Conversation
beanie/odm/fields.py
Outdated
return_schema=str_schema(), | ||
when_used="json", | ||
), | ||
) | ||
return json_or_python_schema( |
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.
Hello, Pydantic maintainer here.
I don't think there's a need to make a distinction between JSON and Python here. pydantic_js_input_core_schema
can be specified for both, it's not an issue:
return no_info_plain_validator_function(
cls._validate,
json_schema_input_schema=...,
serialization=...,
)
As a side note, I know our logic to create custom types through __get_pydantic_core_schema__
isn't ideal (confusing pattern, need to create core schemas manually, etc). Ideally, PydanticObjectId
could be defined as an annotated type:
PydanticObjectId = Annotated[
ObjectId,
PlainValidator(_validate, json_schema_input_type=Annotated[str, Field(pattern="^[0-9a-f]{24}$", min_length=24, max_length=24)]),
PlainSerializer(lambda v: str(v), return_type=str),
]
This way, you go through the "user facing" validators API, where json_schema_input_type
is guaranteed to not change (unlike how this attribute was stored on the core schema — we had to change it in 2.10 to avoid core schema simplification errors).
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 suggestion. I updated on the plain validator function. But for the
PydanticObjectId = Annotated[
ObjectId,
PlainValidator(_validate, json_schema_input_type=Annotated[str, Field(pattern="^[0-9a-f]{24}$", min_length=24, max_length=24)]),
PlainSerializer(lambda v: str(v), return_type=str),
]
I have noticed there are some breaking changes that would require significant modifications to the codebase since it changes the checker for PydanticObjectId
as typing.Annotated
and not a normal class. One of the example is:
def extract_id_class(annotation) -> Type[Any]:
if get_origin(annotation) is not None:
try:
annotation = next(
arg for arg in get_args(annotation) if arg is not type(None)
)
except StopIteration:
annotation = None
if inspect.isclass(annotation):
return annotation
raise ValueError("Unknown annotation: {}".format(annotation))
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 indeed this will most likely break things (and the Annotated
form also has some drawbacks). And it seems that beanie expects PydanticObjectId
to be instantiable, which is not going to be the case with Annotated
:/
beanie/odm/utils/pydantic.py
Outdated
@@ -1,9 +1,22 @@ | |||
from typing import Any, Type | |||
|
|||
import pydantic | |||
from packaging.specifiers import SpecifierSet |
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.
You'll need to switch back to the pydantic.VERSION
manual parsing as packacing
is a 3rd party dependency, and currently not included in the requirements.
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 agree here, lets not introduce packaging
as a dependency.
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.
Hi, thank you for your contribution.
Looks good in general, no further major comments apart from what @Viicos already commented.
on: | ||
pull_request: | ||
push: |
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'm not so sure about this seemingly unrelated change.
Won't this run multiple jobs for a "PR open" and a "branch push"?
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.
Hi thanks to check this PR.
I used it in for CI tests on current branch before make the PR. That part has been removed now.
beanie/odm/utils/pydantic.py
Outdated
@@ -1,9 +1,22 @@ | |||
from typing import Any, Type | |||
|
|||
import pydantic | |||
from packaging.specifiers import SpecifierSet |
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 agree here, lets not introduce packaging
as a dependency.
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.
No other comments apart from the version check one, looks good.
beanie/odm/utils/pydantic.py
Outdated
IS_PYDANTIC_V2 = int(pydantic.VERSION.split(".")[0]) >= 2 | ||
IS_PYDANTIC_V2_10 = ( | ||
IS_PYDANTIC_V2 and int(pydantic.VERSION.split(".")[1]) >= 10 | ||
) or int(pydantic.VERSION.split(".")[0]) > 2 |
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 would remove this "or" part. Any other major Pydantic version would not necessarily be compatible with Beanie and I think we should not bet on this.
Lets make this check do what it says in the name, to explicitly check for Pydantic v2.10.x (or above, constrained to v2).
Sorry, @mdaffad, one other thing also popped to mind. Lets also include latest Pydantic v2.10.4 in our CI testing as well? |
It seems version 2.10.4 from matrix dropped after this run: https://github.com/BeanieODM/beanie/actions/runs/12488481332/workflow. I will re-add 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.
LGTM
Changes:
AnyUrl
typepydantic_core.core_schema.no_info_plain_validator_function
Known affected test on pydantic latest release:
Related issues: