Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ classifiers = [
"Typing :: Typed",
]
dynamic = ["version"]
dependencies = ["pydantic", "importlib_metadata; python_version<'3.8'"]
dependencies = [
"pydantic",
"importlib_metadata; python_version<'3.8'",
"packaging",
]

[tool.hatch.envs.default]
dependencies = [
Expand Down
4 changes: 3 additions & 1 deletion src/pydantic_compat/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

import pydantic
import pydantic.version
from packaging.version import Version

PYDANTIC2 = pydantic.version.VERSION.startswith("2")
PYDANTIC2 = Version(pydantic.version.VERSION) >= Version("2")
PYDANTIC2_10 = Version(pydantic.version.VERSION) >= Version("2.10")
FIELD_KWARGS = {
p.name
for p in signature(pydantic.Field).parameters.values()
Expand Down
3 changes: 2 additions & 1 deletion src/pydantic_compat/_v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pydantic.version
from packaging.version import Version

if not pydantic.version.VERSION.startswith("1"): # pragma: no cover
if Version(pydantic.version.VERSION) >= Version("2"): # pragma: no cover
raise ImportError("pydantic_compat._v1 only supports pydantic v1.x")


Expand Down
3 changes: 2 additions & 1 deletion src/pydantic_compat/_v2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pydantic.version
from packaging.version import Version

if int(pydantic.version.VERSION[0]) <= 1: # pragma: no cover
if Version(pydantic.version.VERSION) < Version("2"): # pragma: no cover
raise ImportError("pydantic_compat._v2 only supports pydantic v2.x")

from .decorators import root_validator as root_validator
Expand Down
11 changes: 9 additions & 2 deletions src/pydantic_compat/_v2/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
from pydantic import BaseModel
from pydantic._internal import _model_construction

from pydantic_compat._shared import V2_RENAMED_CONFIG_KEYS, check_mixin_order
from pydantic_compat._shared import (
PYDANTIC2_10,
V2_RENAMED_CONFIG_KEYS,
check_mixin_order,
)

if TYPE_CHECKING:
from pydantic import ConfigDict
Expand Down Expand Up @@ -93,7 +97,10 @@ def parse_raw(cls: type[Model], *args: Any, **kwargs: Any) -> Any:
# this is needed in addition to the metaclass patch in __init_subclass__
@property
def __fields__(self: Model) -> Dict[str, Any]: # noqa: UP006
return self.model_fields
if PYDANTIC2_10:
return self.__class__.model_fields
else:
return self.model_fields

@property
def __fields_set__(self: Model) -> set[str]:
Expand Down
4 changes: 3 additions & 1 deletion tests/test_base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest

from pydantic_compat import PYDANTIC2, PydanticCompatMixin
from pydantic_compat._shared import PYDANTIC2_10


class Model(PydanticCompatMixin, pydantic.BaseModel):
Expand Down Expand Up @@ -64,7 +65,8 @@ def test_v1_attributes() -> None:

def test_v2_attributes() -> None:
m = Model()
assert "x" in m.model_fields
if not PYDANTIC2_10:
assert "x" in m.model_fields
assert "x" in Model.model_fields
assert "x" not in m.model_fields_set
m.x = 2
Expand Down
8 changes: 4 additions & 4 deletions tests/test_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ def _validate_x_before(cls, v):
return v

@model_validator(mode="after")
def _validate_x_after(cls, v):
mock_after(v)
return v
def _validate_x_after(self):
mock_after()
return self

# this also needs to work
@model_validator(mode="after")
Expand All @@ -133,6 +133,6 @@ def _validate_x_after_cm(cls, v):

m = Model(x="2")
mock_before.assert_called_once_with({"x": "2"})
mock_after.assert_called_once_with(m)
mock_after.assert_called_once_with()
mock_after_cm.assert_called_once_with(m)
assert m.x == 2
Loading