Skip to content

Commit

Permalink
Adapt v2 impl to latest mypy
Browse files Browse the repository at this point in the history
  • Loading branch information
surenkov committed Nov 6, 2023
1 parent 9db8faa commit e30649d
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 32 deletions.
2 changes: 1 addition & 1 deletion django_pydantic_field/compat/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
try:
from typing import get_args, get_origin
except ImportError:
from typing_extensions import get_args, get_origin
from typing_extensions import get_args, get_origin # type: ignore[no-redef]

from django.db.migrations.serializer import BaseSerializer, serializer_factory
from django.db.migrations.writer import MigrationWriter
Expand Down
22 changes: 3 additions & 19 deletions django_pydantic_field/fields.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ from __future__ import annotations

import typing as ty

from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from pydantic.dataclasses import DataclassClassOrWrapper

from .compat.pydantic import PYDANTIC_V1, PYDANTIC_V2

__all__ = ("SchemaField",)

SchemaT: ty.TypeAlias = ty.Union[
Expand All @@ -20,22 +18,11 @@ SchemaT: ty.TypeAlias = ty.Union[
OptSchemaT: ty.TypeAlias = ty.Optional[SchemaT]
ST = ty.TypeVar("ST", bound=SchemaT)

ConfigType: ty.TypeAlias = ty.Any

if PYDANTIC_V1:
from pydantic import ConfigDict, BaseConfig

ConfigType = ty.Union[ConfigDict, type[BaseConfig], type]
elif PYDANTIC_V2:
from pydantic import ConfigDict

ConfigType = ConfigDict


@ty.overload
def SchemaField(
schema: type[ST | None] | ty.ForwardRef = ...,
config: ConfigType = ...,
config: ConfigDict = ...,
default: OptSchemaT | ty.Callable[[], OptSchemaT] = ...,
*args,
null: ty.Literal[True],
Expand All @@ -47,13 +34,10 @@ def SchemaField(
@ty.overload
def SchemaField(
schema: type[ST] | ty.ForwardRef = ...,
config: ConfigType = ...,
config: ConfigDict = ...,
default: ty.Union[SchemaT, ty.Callable[[], SchemaT]] = ...,
*args,
null: ty.Literal[False] = ...,
**kwargs,
) -> ST:
...

def SchemaField(*args, **kwargs) -> ty.Any:
...
15 changes: 7 additions & 8 deletions django_pydantic_field/v2/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def __set__(self, obj, value):


class PydanticSchemaField(JSONField, ty.Generic[types.ST]):
descriptor_class = SchemaAttribute
descriptor_class: type[DeferredAttribute] = SchemaAttribute
adapter: types.SchemaAdapter

def __init__(
self,
Expand Down Expand Up @@ -76,23 +77,21 @@ def to_python(self, value: ty.Any):
try:
return self.adapter.validate_python(value)
except pydantic.ValidationError as exc:
raise exceptions.ValidationError(exc.title, code="invalid", params=exc.errors()) from exc
error_params = {"errors": exc.errors(), "field": self}
raise exceptions.ValidationError(exc.title, code="invalid", params=error_params) from exc

def get_prep_value(self, value: ty.Any):
if isinstance(value, BaseExpression):
# We don't want to perform coercion on database query expressions.
return super().get_prep_value(value)

try:
prep_value = self.adapter.validate_python(value, strict=True)
except pydantic.ValidationError:
prep_value = self.adapter.dump_python(value)
prep_value = self.adapter.validate_python(prep_value)

prep_value = self.adapter.validate_python(value)
plain_value = self.adapter.dump_python(prep_value)

return super().get_prep_value(plain_value)

def get_transform(self, lookup_name: str):
transform: type[Transform] | SchemaKeyTransformAdapter | None
transform = super().get_transform(lookup_name)
if transform is not None:
transform = SchemaKeyTransformAdapter(transform)
Expand Down
7 changes: 5 additions & 2 deletions django_pydantic_field/v2/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

class ExportKwargs(ty.TypedDict, total=False):
strict: bool
from_attributes: bool
mode: ty.Literal["json", "python"]
include: IncEx | None
exclude: IncEx | None
Expand Down Expand Up @@ -80,11 +81,13 @@ def validate_schema(self) -> None:
"""Validate the schema and raise an exception if it is invalid."""
self._get_prepared_schema()

def validate_python(self, value: ty.Any, *, strict: bool | None = None) -> ST:
def validate_python(self, value: ty.Any, *, strict: bool | None = None, from_attributes: bool | None = None) -> ST:
"""Validate the value and raise an exception if it is invalid."""
if strict is None:
strict = self.export_kwargs.get("strict", None)
return self.type_adapter.validate_python(value, strict=strict)
if from_attributes is None:
from_attributes = self.export_kwargs.get("from_attributes", None)
return self.type_adapter.validate_python(value, strict=strict, from_attributes=from_attributes)

def dump_python(self, value: ty.Any) -> ty.Any:
"""Dump the value to a Python object."""
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ dev = [
"mypy",
"pytest==7.0.*",
"djangorestframework>=3.11,<4",
"django-stubs[compatible-mypy]~=1.12.0",
"djangorestframework-stubs[compatible-mypy]~=1.7.0",
"django-stubs[compatible-mypy]~=4.2",
"djangorestframework-stubs[compatible-mypy]~=3.14",
"pytest-django>=4.5,<5",
]
test = [
Expand Down Expand Up @@ -106,6 +106,7 @@ plugins = [
"mypy_drf_plugin.main"
]
exclude = [".env", "tests"]
enable_incomplete_feature = ["Unpack"]

[tool.django-stubs]
django_settings_module = "tests.settings.django_test_settings"
Expand Down

0 comments on commit e30649d

Please sign in to comment.