Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/github-actions-tests.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: Tests
on: [ pull_request ]
on:
pull_request:
push:
Copy link
Contributor

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"?

Copy link
Contributor Author

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.


jobs:
pre-commit:
Expand Down
18 changes: 15 additions & 3 deletions beanie/odm/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from beanie.odm.utils.parsing import parse_obj
from beanie.odm.utils.pydantic import (
IS_PYDANTIC_V2,
IS_PYDANTIC_V2_10,
get_field_type,
get_model_fields,
parse_object_as,
Expand Down Expand Up @@ -147,9 +148,8 @@ def _validate(cls, v):
def __get_pydantic_core_schema__(
cls, source_type: Type[Any], handler: GetCoreSchemaHandler
) -> CoreSchema:
return json_or_python_schema(
python_schema=no_info_plain_validator_function(cls._validate),
json_schema=no_info_plain_validator_function(
if not IS_PYDANTIC_V2_10:
return no_info_plain_validator_function(
cls._validate,
metadata={
"pydantic_js_input_core_schema": str_schema(
Expand All @@ -158,6 +158,18 @@ def __get_pydantic_core_schema__(
max_length=24,
)
},
serialization=plain_serializer_function_ser_schema(
lambda instance: str(instance),
return_schema=str_schema(),
when_used="json",
),
)
return no_info_plain_validator_function(
cls._validate,
json_schema_input_schema=str_schema(
pattern="^[0-9a-f]{24}$",
min_length=24,
max_length=24,
),
serialization=plain_serializer_function_ser_schema(
lambda instance: str(instance),
Expand Down
11 changes: 10 additions & 1 deletion beanie/odm/utils/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@

import beanie
from beanie.odm.fields import Link, LinkTypes
from beanie.odm.utils.pydantic import IS_PYDANTIC_V2, get_model_fields
from beanie.odm.utils.pydantic import (
IS_PYDANTIC_V2,
IS_PYDANTIC_V2_10,
get_model_fields,
)

SingleArgCallable = Callable[[Any], Any]
DEFAULT_CUSTOM_ENCODERS: MutableMapping[type, SingleArgCallable] = {
Expand All @@ -51,6 +55,11 @@

DEFAULT_CUSTOM_ENCODERS[Url] = str

if IS_PYDANTIC_V2_10:
from pydantic import AnyUrl

DEFAULT_CUSTOM_ENCODERS[AnyUrl] = str

BSON_SCALAR_TYPES = (
type(None),
str,
Expand Down
15 changes: 14 additions & 1 deletion beanie/odm/utils/pydantic.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
from typing import Any, Type

import pydantic
from packaging.specifiers import SpecifierSet
Copy link
Contributor

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.

Copy link
Contributor

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.

from packaging.version import Version
from pydantic import BaseModel

IS_PYDANTIC_V2 = int(pydantic.VERSION.split(".")[0]) >= 2

def is_version_valid(version, requirement):
# Parse the requirement as a SpecifierSet
specifiers = SpecifierSet(requirement)
# Parse the version as a Version
v = Version(version)
# Check if the version satisfies the specifiers
return v in specifiers


IS_PYDANTIC_V2 = is_version_valid(pydantic.VERSION, ">=2")
IS_PYDANTIC_V2_10 = is_version_valid(pydantic.VERSION, ">=2.10")

if IS_PYDANTIC_V2:
from pydantic import TypeAdapter
Expand Down
Loading