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(fastapi): update pydantic utilities #5373

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
15 changes: 15 additions & 0 deletions fern/pages/changelogs/fastapi/2024-12-09.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 1.6.0
**`(fix):`** The FastAPI generator now supports a new mode for pydantic model generation,
to use pydantic v1 on v2 versions.

```yml generators.yml
generators:
server:
- name: fernapi/fern-fastapi-server
version: 1.6.0
config:
pydantic:
version: "v1_on_v2"
````


4 changes: 4 additions & 0 deletions fern/pages/changelogs/python-sdk/2024-12-08.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 4.3.9
**`(fix):`** Fix indentation in generated README.md sections to ensure proper formatting and readability.


Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This file was auto-generated by Fern from our API Definition.

# nopycln: file
import datetime as dt
import typing
Expand All @@ -7,37 +9,42 @@

import pydantic

from .datetime_utils import serialize_datetime
from .serialization import convert_and_respect_annotation_metadata

IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")

from pydantic.datetime_parse import (
parse_date as parse_date, # type: ignore # Pydantic v1
from .datetime_utils import serialize_datetime

# isort will try to reformat the comments on these imports, which breaks mypy
# isort: off
from pydantic.v1.datetime_parse import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
parse_date as parse_date,
)
from pydantic.v1.datetime_parse import ( # pyright: ignore[reportMissingImports] # Pydantic v2
parse_datetime as parse_datetime,
)
from pydantic.datetime_parse import (
parse_datetime as parse_datetime, # type: ignore # Pydantic v1
from pydantic.v1.json import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
ENCODERS_BY_TYPE as encoders_by_type,
)
from pydantic.fields import ModelField as ModelField # type: ignore # Pydantic v1
from pydantic.json import (
ENCODERS_BY_TYPE as encoders_by_type, # type: ignore # Pydantic v1
from pydantic.v1.typing import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
get_args as get_args,
)
from pydantic.typing import get_args as get_args # type: ignore # Pydantic v1
from pydantic.typing import get_origin as get_origin # type: ignore # Pydantic v1
from pydantic.typing import (
is_literal_type as is_literal_type, # type: ignore # Pydantic v1
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
get_origin as get_origin,
)
from pydantic.typing import is_union as is_union # type: ignore # Pydantic v1
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
is_literal_type as is_literal_type,
)
from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
is_union as is_union,
)
from pydantic.v1.fields import ModelField as ModelField # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2

# isort: on

T = typing.TypeVar("T")
Model = typing.TypeVar("Model", bound=pydantic.BaseModel)


def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T:
dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
return pydantic.parse_obj_as(type_, dealiased_object)
return pydantic.v1.parse_obj_as(type_, object_)


def to_jsonable_with_fallback(
Expand All @@ -48,22 +55,12 @@ def to_jsonable_with_fallback(

class UniversalBaseModel(pydantic.v1.BaseModel):
class Config:
populate_by_name = True
smart_union = True
allow_population_by_field_name = True
json_encoders = {dt.datetime: serialize_datetime}

@classmethod
def model_construct(
cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any
) -> "Model":
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
return cls.construct(_fields_set, **dealiased_object)

@classmethod
def construct(
cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any
) -> "Model":
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
return super().construct(_fields_set, **dealiased_object)
# Allow fields begining with `model_` to be used in the model
protected_namespaces = ()

def json(self, **kwargs: typing.Any) -> str:
kwargs_with_defaults: typing.Any = {
Expand Down Expand Up @@ -106,9 +103,7 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
**kwargs,
}

dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields)

return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
return super().dict(**kwargs_with_defaults_exclude_unset_include_fields)


def _union_list_of_pydantic_dicts(
Expand Down Expand Up @@ -173,14 +168,14 @@ def universal_root_validator(
pre: bool = False,
) -> typing.Callable[[AnyCallable], AnyCallable]:
def decorator(func: AnyCallable) -> AnyCallable:
return pydantic.root_validator(pre=pre)(func) # type: ignore # Pydantic v1
return pydantic.v1.root_validator(pre=pre)(func) # type: ignore # Pydantic v1

return decorator


def universal_field_validator(field_name: str, pre: bool = False) -> typing.Callable[[AnyCallable], AnyCallable]:
def decorator(func: AnyCallable) -> AnyCallable:
return pydantic.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1
return pydantic.v1.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1

return decorator

Expand Down
7 changes: 7 additions & 0 deletions generators/python/fastapi/versions.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# For unreleased changes, use unreleased.yml
- version: 1.6.1
irVersion: 53
changelogEntry:
- type: fix
summary: |
Update `pydantic_utilities.py` to handle `__slots__` in v2 on v1 mode.

- version: 1.6.0
irVersion: 53
changelogEntry:
Expand Down
Binary file not shown.
61 changes: 61 additions & 0 deletions seed/fastapi/inline-types/.mock/definition/__package__.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions seed/fastapi/inline-types/.mock/definition/api.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions seed/fastapi/inline-types/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions seed/fastapi/inline-types/core/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions seed/fastapi/inline-types/core/abstract_fern_service.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions seed/fastapi/inline-types/core/exceptions/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading