Skip to content

Commit

Permalink
Pydantic2 deprecation warnings fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalik committed Jul 7, 2023
1 parent 72bb011 commit 96abf55
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 81 deletions.
1 change: 1 addition & 0 deletions WHATSNEW_V1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Pydnatic2
2 changes: 1 addition & 1 deletion ninja/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def _result_to_response(

resp_object = ResponseObject(result)
# ^ we need object because getter_dict seems work only with from_orm
result = response_model.from_orm(resp_object).dict(
result = response_model.from_orm(resp_object).model_dump(
by_alias=self.by_alias,
exclude_unset=self.exclude_unset,
exclude_defaults=self.exclude_defaults,
Expand Down
10 changes: 5 additions & 5 deletions ninja/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ def view_with_pagination(*args: Tuple[Any], **kwargs: Any) -> Any:
),
]

# def contribute_to_operation(op: Operation) -> None:

# make_response_paginated(schema, paginator, op)

if paginator.Output:
view_with_pagination._ninja_contribute_to_operation = partial( # type: ignore
make_response_paginated, paginator
Expand Down Expand Up @@ -188,7 +184,7 @@ def make_response_paginated(paginator: PaginationBase, op: Operation) -> None:
response=List[Some]
will be changed to:
response=PagedSome
where Paged some willbe a subclass of paginator.Output:
where Paged some will be a subclass of paginator.Output:
class PagedSome:
items: List[Some]
count: int
Expand Down Expand Up @@ -216,6 +212,10 @@ class PagedSome:


def _find_collection_response(op: Operation) -> Tuple[int, Any]:
"""
Walks through defined operation responses and finds the first
that is of a collection type (e.g. List[SomeSchema])
"""
for code, resp_model in op.response_models.items():
if resp_model is None or resp_model is NOT_SET:
continue
Expand Down
2 changes: 1 addition & 1 deletion ninja/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class NinjaJSONEncoder(DjangoJSONEncoder):
def default(self, o: Any) -> Any:
if isinstance(o, BaseModel):
return o.dict()
return o.model_dump()
if isinstance(o, (IPv4Address, IPv6Address)):
return str(o)
return super().default(o)
Expand Down
37 changes: 8 additions & 29 deletions ninja/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,7 @@ def resolve_initials(self, obj):
from django.template import Variable, VariableDoesNotExist
from pydantic import BaseModel, Field, ValidationInfo, model_validator, validator
from pydantic._internal._model_construction import ModelMetaclass
from pydantic.json_schema import (
DEFAULT_REF_TEMPLATE,
GenerateJsonSchema,
JsonSchemaMode,
JsonSchemaValue,
model_json_schema,
)
from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue

from ninja.signature.utils import get_args_names, has_kwargs
from ninja.types import DictStrAny
Expand Down Expand Up @@ -205,7 +199,7 @@ class Config:
from_attributes = True # aka orm_mode

@model_validator(mode="before")
def run_root_validator(cls, values: Any, info: ValidationInfo) -> Any:
def _run_root_validator(cls, values: Any, info: ValidationInfo) -> Any:
values = DjangoGetter(values, cls, info.context)
return values

Expand All @@ -214,33 +208,18 @@ def from_orm(cls: Type[S], obj: Any) -> S:
return cls.model_validate(obj)

def dict(self, *a: Any, **kw: Any) -> DictStrAny:
"Backward compatibility with pydantic 1.x"
return self.model_dump(*a, **kw)

@classmethod
def json_schema(cls) -> DictStrAny:
return cls.model_json_schema(schema_generator=NinjaGenerateJsonSchema)

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

@classmethod
def json_schema(cls) -> DictStrAny:
return cls.model_json_schema()

@classmethod
def model_json_schema(
cls,
by_alias: bool = True,
ref_template: str = DEFAULT_REF_TEMPLATE,
schema_generator: Type[GenerateJsonSchema] = NinjaGenerateJsonSchema,
mode: JsonSchemaMode = "validation",
) -> DictStrAny:
return model_json_schema(
cls,
by_alias=by_alias,
ref_template=ref_template,
schema_generator=schema_generator,
mode=mode,
)
return cls.json_schema()
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
# To be removed once GitHub catches up.

setup(
name='django-ninja',
name="django-ninja",
install_requires=[
'Django>=2.0.13'
"Django>=2.0.13",
"pydantic>=2.0.0",
],
)
2 changes: 1 addition & 1 deletion tests/demo_project/someapp/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Config:

@router.post("/create", url_name="event-create-url-name")
def create_event(request, event: EventSchema):
Event.objects.create(**event.dict())
Event.objects.create(**event.model_dump())
return event


Expand Down
2 changes: 1 addition & 1 deletion tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class SelfReference(BaseModel):
sibling: "SelfReference" = None


SelfReference.update_forward_refs()
SelfReference.model_rebuild()


router = Router()
Expand Down
12 changes: 6 additions & 6 deletions tests/test_orm_metaclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Config:
model = User
model_exclude = ["lastname"]

assert SampleSchema2.schema() == {
assert SampleSchema2.json_schema() == {
"title": "SampleSchema2",
"type": "object",
"properties": {
Expand Down Expand Up @@ -70,7 +70,7 @@ class Config:
model = CustomModel
model_fields = ["f1", "f2"]

assert CustomSchema.schema() == {
assert CustomSchema.json_schema() == {
"title": "CustomSchema",
"type": "object",
"properties": {
Expand Down Expand Up @@ -117,9 +117,9 @@ class Config:
model_fields = "__all__"
model_fields_optional = "__all__"

assert OptSchema.schema().get("required") is None
assert OptSchema.json_schema().get("required") is None

assert OptSchema2.schema().get("required") is None
assert OptSchema2.json_schema().get("required") is None


def test_model_fields_all():
Expand All @@ -135,8 +135,8 @@ class Config:
model = SomeModel
model_fields = "__all__"

print(SomeSchema.schema())
assert SomeSchema.schema() == {
print(SomeSchema.json_schema())
assert SomeSchema.json_schema() == {
"title": "SomeSchema",
"type": "object",
"properties": {
Expand Down
62 changes: 31 additions & 31 deletions tests/test_orm_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ class Meta:
app_label = "tests"

Schema = create_schema(ChildModel)
# print(Schema.schema())
# print(Schema.json_schema())

# TODO: I guess parentmodel_ptr_id must be skipped
assert Schema.schema() == {
assert Schema.json_schema() == {
"title": "ChildModel",
"type": "object",
"properties": {
Expand Down Expand Up @@ -82,8 +82,8 @@ class Meta:
app_label = "tests"

SchemaCls = create_schema(AllFields)
# print(SchemaCls.schema())
assert SchemaCls.schema() == {
# print(SchemaCls.json_schema())
assert SchemaCls.json_schema() == {
"title": "AllFields",
"type": "object",
"properties": {
Expand Down Expand Up @@ -200,8 +200,8 @@ class Meta:
app_label = "tests"

SchemaCls = create_schema(ModelBigAuto)
# print(SchemaCls.schema())
assert SchemaCls.schema() == {
# print(SchemaCls.json_schema())
assert SchemaCls.json_schema() == {
"type": "object",
"properties": {
"bigautofiled": {
Expand All @@ -225,8 +225,8 @@ class Meta:
app_label = "tests"

Schema = create_schema(ModelNewFields)
# print(Schema.schema())
assert Schema.schema() == {
# print(Schema.json_schema())
assert Schema.json_schema() == {
"title": "ModelNewFields",
"type": "object",
"properties": {
Expand Down Expand Up @@ -264,8 +264,8 @@ class Meta:
app_label = "tests"

SchemaCls = create_schema(TestModel, name="TestSchema")
# print(SchemaCls.schema())
assert SchemaCls.schema() == {
# print(SchemaCls.json_schema())
assert SchemaCls.json_schema() == {
"title": "TestSchema",
"type": "object",
"properties": {
Expand All @@ -285,8 +285,8 @@ class Meta:
}

SchemaClsDeep = create_schema(TestModel, name="TestSchemaDeep", depth=1)
# print(SchemaClsDeep.schema())
assert SchemaClsDeep.schema() == {
# print(SchemaClsDeep.json_schema())
assert SchemaClsDeep.json_schema() == {
"type": "object",
"properties": {
"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "ID"},
Expand Down Expand Up @@ -335,8 +335,8 @@ class Meta:
app_label = "tests"

Schema = create_schema(MyModel)
# print(Schema.schema())
assert Schema.schema() == {
# print(Schema.json_schema())
assert Schema.json_schema() == {
"title": "MyModel",
"type": "object",
"properties": {
Expand All @@ -361,8 +361,8 @@ class Meta:
app_label = "tests"

Schema1 = create_schema(SampleModel, fields=["f1", "f2"])
# print(Schema1.schema())
assert Schema1.schema() == {
# print(Schema1.json_schema())
assert Schema1.json_schema() == {
"title": "SampleModel",
"type": "object",
"properties": {
Expand All @@ -373,8 +373,8 @@ class Meta:
}

Schema2 = create_schema(SampleModel, fields=["f3", "f2"])
# print(Schema2.schema())
assert Schema2.schema() == {
# print(Schema2.json_schema())
assert Schema2.json_schema() == {
"title": "SampleModel2",
"type": "object",
"properties": {
Expand All @@ -385,8 +385,8 @@ class Meta:
}

Schema3 = create_schema(SampleModel, exclude=["f3"])
# print(Schema3.schema())
assert Schema3.schema() == {
# print(Schema3.json_schema())
assert Schema3.json_schema() == {
"type": "object",
"properties": {
"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "ID"},
Expand Down Expand Up @@ -433,8 +433,8 @@ def test_with_relations():
from someapp.models import Category

Schema = create_schema(Category)
# print(Schema.schema())
assert Schema.schema() == {
# print(Schema.json_schema())
assert Schema.json_schema() == {
"title": "Category",
"type": "object",
"properties": {
Expand Down Expand Up @@ -488,8 +488,8 @@ class Meta:

Schema1 = create_schema(SmallModel, custom_fields=[("custom", int, ...)])

# print(Schema1.schema())
assert Schema1.schema() == {
# print(Schema1.json_schema())
assert Schema1.json_schema() == {
"type": "object",
"properties": {
"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "ID"},
Expand All @@ -502,9 +502,9 @@ class Meta:
}

Schema2 = create_schema(SmallModel, custom_fields=[("f1", int, ...)])
# print(Schema2.schema())
# print(Schema2.json_schema())

assert Schema2.schema() == {
assert Schema2.json_schema() == {
"type": "object",
"properties": {
"id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "ID"},
Expand Down Expand Up @@ -533,9 +533,9 @@ class TestSchema(Schema):
data1: create_schema(TestModelDuplicate, fields=["field1"]) # noqa: F821
data2: create_schema(TestModelDuplicate, fields=["field2"]) # noqa: F821

# print(TestSchema.schema())
# print(TestSchema.json_schema())

assert TestSchema.schema() == {
assert TestSchema.json_schema() == {
"type": "object",
"properties": {
"data1": {"$ref": "#/$defs/TestModelDuplicate"},
Expand Down Expand Up @@ -570,12 +570,12 @@ class Meta:
app_label = "tests"

Schema = create_schema(SomeReqFieldModel)
assert Schema.schema()["required"] == ["some_field", "other_field"]
assert Schema.json_schema()["required"] == ["some_field", "other_field"]

Schema = create_schema(SomeReqFieldModel, optional_fields=["some_field"])
assert Schema.schema()["required"] == ["other_field"]
assert Schema.json_schema()["required"] == ["other_field"]

Schema = create_schema(
SomeReqFieldModel, optional_fields=["some_field", "other_field", "optional"]
)
assert Schema.schema().get("required") is None
assert Schema.json_schema().get("required") is None
2 changes: 1 addition & 1 deletion tests/test_pydantic_migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_optional_pydantic_model():
with pytest.raises(ValidationError):
OptModel().dict()

assert OptModel(b=None).dict() == {"a": None, "b": None, "c": None}
assert OptModel(b=None).model_dump() == {"a": None, "b": None, "c": None}


def test_optional_schema():
Expand Down
14 changes: 11 additions & 3 deletions tests/test_test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,23 @@ def test_schema_as_data():
with mock.patch.object(client, "_call") as call:
client.post("/test", json=schema_instance)
request = call.call_args[0][1]
assert ClientTestSchema.parse_raw(request.body).json() == schema_instance.json()
assert (
ClientTestSchema.model_validate_json(request.body).model_dump_json()
== schema_instance.model_dump_json()
)


def test_json_as_body():
schema_instance = ClientTestSchema(time=timezone.now().replace(microsecond=0))

with mock.patch.object(client, "_call") as call:
client.post(
"/test", data=schema_instance.json(), content_type="application/json"
"/test",
data=schema_instance.model_dump_json(),
content_type="application/json",
)
request = call.call_args[0][1]
assert ClientTestSchema.parse_raw(request.body).json() == schema_instance.json()
assert (
ClientTestSchema.model_validate_json(request.body).model_dump_json()
== schema_instance.model_dump_json()
)

0 comments on commit 96abf55

Please sign in to comment.