Skip to content

Commit

Permalink
Merge pull request #11 from eadwinCode/fixing_pydantic_warning
Browse files Browse the repository at this point in the history
Fixed Pydantic V2 Deprecated Warnings
  • Loading branch information
eadwinCode committed Dec 16, 2023
2 parents a5dbd2a + 7ab75ca commit 3a06d3b
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 36 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/test_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ jobs:
run: pip install flit
- name: Install Dependencies
run: flit install --symlink
- name: Black
run: black --check ninja_schema tests
- name: Ruff Linting Check
run: ruff check ninja_schema tests
- name: mypy
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ clean: ## Removing cached python compiled files
find . -name \*pyo | xargs rm -fv
find . -name \*~ | xargs rm -fv
find . -name __pycache__ | xargs rm -rfv
find . -name .ruff_cache | xargs rm -rfv

install:clean ## Install dependencies
flit install --deps develop --symlink
pre-commit install -f

lint:fmt ## Run code linters
black --check ninja_schema tests
ruff check ninja_schema tests
mypy ninja_schema

fmt format:clean ## Run code formatters
black ninja_schema tests
ruff format ninja_schema tests
ruff check --fix ninja_schema tests

test:clean ## Run tests
Expand Down
6 changes: 0 additions & 6 deletions ninja_schema/orm/mixins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import typing as t
import warnings

from django.db.models import Model as DjangoModel

Expand Down Expand Up @@ -46,11 +45,6 @@ def json_schema(cls) -> DictStrAny:

@classmethod
def schema(cls) -> DictStrAny:
warnings.warn(
".schema() is deprecated, use .json_schema() instead",
DeprecationWarning,
stacklevel=2,
)
return cls.json_schema()

BaseMixins = BaseMixinsV2 # type:ignore[misc]
Expand Down
35 changes: 28 additions & 7 deletions ninja_schema/orm/model_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,16 +420,37 @@ def __new__(


class SchemaBaseModel(SchemaMixins, BaseModel):
pass
if not IS_PYDANTIC_V1:

@classmethod
def from_orm(cls, obj, **options) -> BaseModel:
return cls.model_validate( # type:ignore[attr-defined,no-any-return]
obj, **options
)

def dict(self, *a: Any, **kw: Any) -> Dict[str, Any]:
# Backward compatibility with pydantic 1.x
return self.model_dump(*a, **kw) # type:ignore[attr-defined,no-any-return]

def json(self, *a, **kw) -> str:
# Backward compatibility with pydantic 1.x
return self.model_dump_json(*a, **kw) # type:ignore[attr-defined,no-any-return]

@classmethod
def json_schema(cls) -> Dict[str, Any]:
return cls.model_json_schema()

@classmethod
def schema(cls) -> Dict[str, Any]:
return cls.json_schema()


class ModelSchema(SchemaBaseModel, metaclass=ModelSchemaMetaclass):
class Config:
if IS_PYDANTIC_V1:
if IS_PYDANTIC_V1:

class Config:
orm_mode = True
getter_dict = DjangoGetter
else:
from_attributes = True


# create a class APIModelSchema whose purpose to create ModelSchema during API route creation
else:
model_config = {"from_attributes": True}
10 changes: 6 additions & 4 deletions ninja_schema/orm/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@


class Schema(SchemaMixins, BaseModel):
class Config:
if IS_PYDANTIC_V1:
if IS_PYDANTIC_V1:

class Config:
orm_mode = True
getter_dict = DjangoGetter
else:
from_attributes = True

else:
model_config = {"from_attributes": True}
6 changes: 3 additions & 3 deletions ninja_schema/orm/schema_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def __init__(self) -> None:
def register_model(self, model: Type[Model], schema: Type["ModelSchema"]) -> None:
from .model_schema import ModelSchema

assert is_valid_class(schema) and issubclass(
schema, (ModelSchema,)
), "Only Schema can be" 'registered, received "{}"'.format(schema.__name__)
assert is_valid_class(schema) and issubclass(schema, (ModelSchema,)), (
"Only Schema can be" 'registered, received "{}"'.format(schema.__name__)
)
assert is_valid_django_model(
model
), "Only Django Models are allowed. {}".format(model.__name__)
Expand Down
6 changes: 4 additions & 2 deletions ninja_schema/orm/utils/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def convert_choice_name(name: str) -> str:
def get_choices(
choices: t.Iterable[
t.Union[t.Tuple[t.Any, t.Any], t.Tuple[str, t.Iterable[t.Tuple[t.Any, t.Any]]]]
]
],
) -> t.Iterator[t.Tuple[str, str, str]]:
for value, help_text in choices:
if isinstance(help_text, (tuple, list)):
Expand Down Expand Up @@ -190,7 +190,9 @@ def construct_relational_field_info(
if IS_PYDANTIC_V1:
python_type = t.List[m2m_type]
else:
python_type = t.List[Annotated[inner_type, BeforeValidator(m2m_type.validate)]] # type: ignore
python_type = t.List[
Annotated[inner_type, BeforeValidator(m2m_type.validate)]
] # type: ignore

field_info = PydanticField(
default=default,
Expand Down
14 changes: 10 additions & 4 deletions ninja_schema/pydanticutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import warnings
from typing import TYPE_CHECKING, Any

from pydantic.utils import is_valid_field
from pydantic.version import VERSION as _PYDANTIC_VERSION

from ..errors import ConfigError
Expand All @@ -17,6 +17,10 @@
IS_PYDANTIC_V1 = PYDANTIC_VERSION[0] == 1


def is_valid_field_name(name: str) -> bool:
return not name.startswith("_")


def compute_field_annotations(
namespace: "DictStrAny",
**field_definitions: Any,
Expand All @@ -25,9 +29,11 @@ def compute_field_annotations(
annotations = {}

for f_name, f_def in field_definitions.items():
if not is_valid_field(f_name): # pragma: no cover
logger.debug(
f'fields may not start with an underscore, ignoring "{f_name}"'
if not is_valid_field_name(f_name): # pragma: no cover
warnings.warn(
f'fields may not start with an underscore, ignoring "{f_name}"',
RuntimeWarning,
stacklevel=1,
)
if isinstance(f_def, tuple):
try:
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ test = [
"pytest-cov",
"pytest-django",
"pytest-asyncio",
"mypy ==1.5.1",
"ruff ==0.0.275",
"black == 23.7.0",
"mypy == 1.7.1",
"ruff ==0.1.7",
"django-stubs",
]
dev = [
Expand Down
4 changes: 1 addition & 3 deletions tests/test_v2_pydantic/test_custom_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ class TestCustomFields:
@pytest.mark.skipif(IS_PYDANTIC_V1, reason="requires pydantic == 2.1.x")
def test_enum_field(self):
class StudentSchema(ModelSchema):
class Config:
model = Student
include = "__all__"
model_config = {"model": Student, "include": "__all__"}

print(json.dumps(StudentSchema.schema(), sort_keys=False, indent=4))
assert StudentSchema.schema() == {
Expand Down

0 comments on commit 3a06d3b

Please sign in to comment.