Skip to content

feat: Support for recursive and circular references using lazy imports #670

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

Merged
merged 32 commits into from
Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
174f090
Add support for recursive/circular refs
maz808 Jan 25, 2022
d9cb65d
Fix array schema object item issues
maz808 Jan 29, 2022
43c58d1
Merge branch 'main' into recursive-references
dbanty Apr 24, 2022
2512e5d
Merge branch 'main' into pr/582
mtovt May 25, 2022
98b3d79
Merge branch 'main' into pr/582
mtovt Jul 23, 2022
f3eaf74
try to add lazy imports to avoid circular import issue
mtovt Sep 8, 2022
d384dcb
Fix tests related to the addition of lazy imports
mtovt Sep 8, 2022
7cce9e7
Merge remote-tracking branch 'upstream/main' into pr/582
mtovt Sep 9, 2022
e11f9cc
Fix class name
mtovt Sep 9, 2022
1bcf7bb
fix: quoting properties type correctly
mtovt Sep 9, 2022
b407d52
Add lazy import to the Union and List properties
mtovt Sep 9, 2022
ca22a3a
Fix: add missing lazy imports to the additional properties. Make mode…
mtovt Sep 12, 2022
8e6a9dc
Fix: remove extra lazy imports in list property
mtovt Sep 13, 2022
d8c60ef
Add lazy imports to the relatives in `Endpoint`s
mtovt Sep 13, 2022
2524509
Use `quoted` arg and base type checking. Enum properties are not quot…
mtovt Sep 13, 2022
93ee14d
Revert changed test
mtovt Sep 13, 2022
cadad67
Update e2e: models
mtovt Sep 13, 2022
11fb3dd
fix: type checking for lazy imports
dbanty Sep 18, 2022
44637c2
Merge branch 'main' into feature/lazy-imports
dbanty Sep 26, 2022
1577f67
test: Regen e2e
dbanty Sep 26, 2022
986f152
Fix: `Property.is_base_type` and it usage
mtovt Oct 1, 2022
fbcfd65
update docstring for `get_base_*type_string`
mtovt Oct 2, 2022
5fe28f5
Add test related to `quoted` argument
mtovt Oct 2, 2022
843ef7f
remove unused lazy import statement in `ModelProperty.__attrs_post_in…
mtovt Oct 2, 2022
8978e6c
remove unused type_string check in `ModelProperty`
mtovt Oct 2, 2022
f1ca683
remove second unused type_string check in `ModelProperty`
mtovt Oct 2, 2022
36b00ed
remove unused type_string checks in `Property`
mtovt Oct 2, 2022
f3e8251
Add missed tests related to `quoted` and `lazy_import`
mtovt Oct 2, 2022
aaf3c70
minor: reformat
mtovt Oct 2, 2022
ba13956
Remove wrong `model_parent` argument in `Property.get_type_string`
mtovt Oct 2, 2022
8fe2c75
update locked `pydantic`
mtovt Oct 2, 2022
42a56da
Add ModelProperty test `test_process_properties_all_of_reference_not_…
mtovt Oct 2, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def _get_kwargs(
union_prop: Union[float, str] = "not a float",
union_prop_with_ref: Union[AnEnum, None, Unset, float] = 0.6,
enum_prop: AnEnum,
model_prop: ModelWithUnionProperty,
required_model_prop: ModelWithUnionProperty,
model_prop: "ModelWithUnionProperty",
required_model_prop: "ModelWithUnionProperty",
) -> Dict[str, Any]:
url = "{}/tests/defaults".format(client.base_url)

Expand Down Expand Up @@ -130,8 +130,8 @@ def sync_detailed(
union_prop: Union[float, str] = "not a float",
union_prop_with_ref: Union[AnEnum, None, Unset, float] = 0.6,
enum_prop: AnEnum,
model_prop: ModelWithUnionProperty,
required_model_prop: ModelWithUnionProperty,
model_prop: "ModelWithUnionProperty",
required_model_prop: "ModelWithUnionProperty",
) -> Response[Union[Any, HTTPValidationError]]:
"""Defaults

Expand Down Expand Up @@ -187,8 +187,8 @@ def sync(
union_prop: Union[float, str] = "not a float",
union_prop_with_ref: Union[AnEnum, None, Unset, float] = 0.6,
enum_prop: AnEnum,
model_prop: ModelWithUnionProperty,
required_model_prop: ModelWithUnionProperty,
model_prop: "ModelWithUnionProperty",
required_model_prop: "ModelWithUnionProperty",
) -> Optional[Union[Any, HTTPValidationError]]:
"""Defaults

Expand Down Expand Up @@ -237,8 +237,8 @@ async def asyncio_detailed(
union_prop: Union[float, str] = "not a float",
union_prop_with_ref: Union[AnEnum, None, Unset, float] = 0.6,
enum_prop: AnEnum,
model_prop: ModelWithUnionProperty,
required_model_prop: ModelWithUnionProperty,
model_prop: "ModelWithUnionProperty",
required_model_prop: "ModelWithUnionProperty",
) -> Response[Union[Any, HTTPValidationError]]:
"""Defaults

Expand Down Expand Up @@ -292,8 +292,8 @@ async def asyncio(
union_prop: Union[float, str] = "not a float",
union_prop_with_ref: Union[AnEnum, None, Unset, float] = 0.6,
enum_prop: AnEnum,
model_prop: ModelWithUnionProperty,
required_model_prop: ModelWithUnionProperty,
model_prop: "ModelWithUnionProperty",
required_model_prop: "ModelWithUnionProperty",
) -> Optional[Union[Any, HTTPValidationError]]:
"""Defaults

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def _get_kwargs(
}


def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, List[AModel]]]:
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, List["AModel"]]]:
if response.status_code == HTTPStatus.OK:
response_200 = []
_response_200 = response.json()
Expand All @@ -90,7 +90,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidatio
return None


def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, List[AModel]]]:
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, List["AModel"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
Expand All @@ -106,7 +106,7 @@ def sync_detailed(
an_enum_value_with_null: List[Optional[AnEnumWithNull]],
an_enum_value_with_only_null: List[None],
some_date: Union[datetime.date, datetime.datetime],
) -> Response[Union[HTTPValidationError, List[AModel]]]:
) -> Response[Union[HTTPValidationError, List["AModel"]]]:
"""Get List

Get a list of things
Expand All @@ -118,7 +118,7 @@ def sync_detailed(
some_date (Union[datetime.date, datetime.datetime]):

Returns:
Response[Union[HTTPValidationError, List[AModel]]]
Response[Union[HTTPValidationError, List['AModel']]]
"""

kwargs = _get_kwargs(
Expand All @@ -144,7 +144,7 @@ def sync(
an_enum_value_with_null: List[Optional[AnEnumWithNull]],
an_enum_value_with_only_null: List[None],
some_date: Union[datetime.date, datetime.datetime],
) -> Optional[Union[HTTPValidationError, List[AModel]]]:
) -> Optional[Union[HTTPValidationError, List["AModel"]]]:
"""Get List

Get a list of things
Expand All @@ -156,7 +156,7 @@ def sync(
some_date (Union[datetime.date, datetime.datetime]):

Returns:
Response[Union[HTTPValidationError, List[AModel]]]
Response[Union[HTTPValidationError, List['AModel']]]
"""

return sync_detailed(
Expand All @@ -175,7 +175,7 @@ async def asyncio_detailed(
an_enum_value_with_null: List[Optional[AnEnumWithNull]],
an_enum_value_with_only_null: List[None],
some_date: Union[datetime.date, datetime.datetime],
) -> Response[Union[HTTPValidationError, List[AModel]]]:
) -> Response[Union[HTTPValidationError, List["AModel"]]]:
"""Get List

Get a list of things
Expand All @@ -187,7 +187,7 @@ async def asyncio_detailed(
some_date (Union[datetime.date, datetime.datetime]):

Returns:
Response[Union[HTTPValidationError, List[AModel]]]
Response[Union[HTTPValidationError, List['AModel']]]
"""

kwargs = _get_kwargs(
Expand All @@ -211,7 +211,7 @@ async def asyncio(
an_enum_value_with_null: List[Optional[AnEnumWithNull]],
an_enum_value_with_only_null: List[None],
some_date: Union[datetime.date, datetime.datetime],
) -> Optional[Union[HTTPValidationError, List[AModel]]]:
) -> Optional[Union[HTTPValidationError, List["AModel"]]]:
"""Get List

Get a list of things
Expand All @@ -223,7 +223,7 @@ async def asyncio(
some_date (Union[datetime.date, datetime.datetime]):

Returns:
Response[Union[HTTPValidationError, List[AModel]]]
Response[Union[HTTPValidationError, List['AModel']]]
"""

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
from .all_of_sub_model import AllOfSubModel
from .all_of_sub_model_type_enum import AllOfSubModelTypeEnum
from .an_all_of_enum import AnAllOfEnum
from .an_array_with_a_circular_ref_in_items_object_a_item import AnArrayWithACircularRefInItemsObjectAItem
from .an_array_with_a_circular_ref_in_items_object_additional_properties_a_item import (
AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem,
)
from .an_array_with_a_circular_ref_in_items_object_additional_properties_b_item import (
AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem,
)
from .an_array_with_a_circular_ref_in_items_object_b_item import AnArrayWithACircularRefInItemsObjectBItem
from .an_array_with_a_recursive_ref_in_items_object_additional_properties_item import (
AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem,
)
from .an_array_with_a_recursive_ref_in_items_object_item import AnArrayWithARecursiveRefInItemsObjectItem
from .an_enum import AnEnum
from .an_enum_with_null import AnEnumWithNull
from .an_int_enum import AnIntEnum
Expand Down Expand Up @@ -33,10 +45,16 @@
from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed
from .model_with_any_json_properties import ModelWithAnyJsonProperties
from .model_with_any_json_properties_additional_property_type_0 import ModelWithAnyJsonPropertiesAdditionalPropertyType0
from .model_with_circular_ref_a import ModelWithCircularRefA
from .model_with_circular_ref_b import ModelWithCircularRefB
from .model_with_circular_ref_in_additional_properties_a import ModelWithCircularRefInAdditionalPropertiesA
from .model_with_circular_ref_in_additional_properties_b import ModelWithCircularRefInAdditionalPropertiesB
from .model_with_date_time_property import ModelWithDateTimeProperty
from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties
from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder
from .model_with_property_ref import ModelWithPropertyRef
from .model_with_recursive_ref import ModelWithRecursiveRef
from .model_with_recursive_ref_in_additional_properties import ModelWithRecursiveRefInAdditionalProperties
from .model_with_union_property import ModelWithUnionProperty
from .model_with_union_property_inlined import ModelWithUnionPropertyInlined
from .model_with_union_property_inlined_fruit_type_0 import ModelWithUnionPropertyInlinedFruitType0
Expand All @@ -58,6 +76,12 @@
"AModel",
"AModelWithPropertiesReferenceThatAreNotObject",
"AnAllOfEnum",
"AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem",
"AnArrayWithACircularRefInItemsObjectAdditionalPropertiesBItem",
"AnArrayWithACircularRefInItemsObjectAItem",
"AnArrayWithACircularRefInItemsObjectBItem",
"AnArrayWithARecursiveRefInItemsObjectAdditionalPropertiesItem",
"AnArrayWithARecursiveRefInItemsObjectItem",
"AnEnum",
"AnEnumWithNull",
"AnIntEnum",
Expand All @@ -83,10 +107,16 @@
"ModelWithAdditionalPropertiesRefed",
"ModelWithAnyJsonProperties",
"ModelWithAnyJsonPropertiesAdditionalPropertyType0",
"ModelWithCircularRefA",
"ModelWithCircularRefB",
"ModelWithCircularRefInAdditionalPropertiesA",
"ModelWithCircularRefInAdditionalPropertiesB",
"ModelWithDateTimeProperty",
"ModelWithPrimitiveAdditionalProperties",
"ModelWithPrimitiveAdditionalPropertiesADateHolder",
"ModelWithPropertyRef",
"ModelWithRecursiveRef",
"ModelWithRecursiveRefInAdditionalProperties",
"ModelWithUnionProperty",
"ModelWithUnionPropertyInlined",
"ModelWithUnionPropertyInlinedFruitType0",
Expand Down
51 changes: 30 additions & 21 deletions end_to_end_tests/golden-record/my_test_api_client/models/a_model.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import datetime
from typing import Any, Dict, List, Optional, Type, TypeVar, Union, cast
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, TypeVar, Union, cast

import attr
from dateutil.parser import isoparse

from ..models.an_all_of_enum import AnAllOfEnum
from ..models.an_enum import AnEnum
from ..models.different_enum import DifferentEnum
from ..models.free_form_model import FreeFormModel
from ..models.model_with_union_property import ModelWithUnionProperty
from ..types import UNSET, Unset

if TYPE_CHECKING:
from ..models.free_form_model import FreeFormModel
from ..models.model_with_union_property import ModelWithUnionProperty


T = TypeVar("T", bound="AModel")


Expand All @@ -24,7 +27,7 @@ class AModel:
a_camel_date_time (Union[datetime.date, datetime.datetime]):
a_date (datetime.date):
required_not_nullable (str):
one_of_models (Union[Any, FreeFormModel, ModelWithUnionProperty]):
one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', Any]):
model (ModelWithUnionProperty):
any_value (Union[Unset, Any]):
an_optional_allof_enum (Union[Unset, AnAllOfEnum]):
Expand All @@ -35,9 +38,9 @@ class AModel:
required_nullable (Optional[str]):
not_required_nullable (Union[Unset, None, str]):
not_required_not_nullable (Union[Unset, str]):
nullable_one_of_models (Union[FreeFormModel, ModelWithUnionProperty, None]):
not_required_one_of_models (Union[FreeFormModel, ModelWithUnionProperty, Unset]):
not_required_nullable_one_of_models (Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str]):
nullable_one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', None]):
not_required_one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', Unset]):
not_required_nullable_one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', None, Unset, str]):
nullable_model (Optional[ModelWithUnionProperty]):
not_required_model (Union[Unset, ModelWithUnionProperty]):
not_required_nullable_model (Union[Unset, None, ModelWithUnionProperty]):
Expand All @@ -47,12 +50,12 @@ class AModel:
a_camel_date_time: Union[datetime.date, datetime.datetime]
a_date: datetime.date
required_not_nullable: str
one_of_models: Union[Any, FreeFormModel, ModelWithUnionProperty]
model: ModelWithUnionProperty
one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", Any]
model: "ModelWithUnionProperty"
a_nullable_date: Optional[datetime.date]
required_nullable: Optional[str]
nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None]
nullable_model: Optional[ModelWithUnionProperty]
nullable_one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", None]
nullable_model: Optional["ModelWithUnionProperty"]
an_allof_enum_with_overridden_default: AnAllOfEnum = AnAllOfEnum.OVERRIDDEN_DEFAULT
any_value: Union[Unset, Any] = UNSET
an_optional_allof_enum: Union[Unset, AnAllOfEnum] = UNSET
Expand All @@ -61,12 +64,15 @@ class AModel:
attr_1_leading_digit: Union[Unset, str] = UNSET
not_required_nullable: Union[Unset, None, str] = UNSET
not_required_not_nullable: Union[Unset, str] = UNSET
not_required_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, Unset] = UNSET
not_required_nullable_one_of_models: Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str] = UNSET
not_required_model: Union[Unset, ModelWithUnionProperty] = UNSET
not_required_nullable_model: Union[Unset, None, ModelWithUnionProperty] = UNSET
not_required_one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", Unset] = UNSET
not_required_nullable_one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", None, Unset, str] = UNSET
not_required_model: Union[Unset, "ModelWithUnionProperty"] = UNSET
not_required_nullable_model: Union[Unset, None, "ModelWithUnionProperty"] = UNSET

def to_dict(self) -> Dict[str, Any]:
from ..models.free_form_model import FreeFormModel
from ..models.model_with_union_property import ModelWithUnionProperty

an_enum_value = self.an_enum_value.value

an_allof_enum_with_overridden_default = self.an_allof_enum_with_overridden_default.value
Expand Down Expand Up @@ -218,6 +224,9 @@ def to_dict(self) -> Dict[str, Any]:

@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
from ..models.free_form_model import FreeFormModel
from ..models.model_with_union_property import ModelWithUnionProperty

d = src_dict.copy()
an_enum_value = AnEnum(d.pop("an_enum_value"))

Expand All @@ -244,7 +253,7 @@ def _parse_a_camel_date_time(data: object) -> Union[datetime.date, datetime.date

required_not_nullable = d.pop("required_not_nullable")

def _parse_one_of_models(data: object) -> Union[Any, FreeFormModel, ModelWithUnionProperty]:
def _parse_one_of_models(data: object) -> Union["FreeFormModel", "ModelWithUnionProperty", Any]:
try:
if not isinstance(data, dict):
raise TypeError()
Expand All @@ -261,7 +270,7 @@ def _parse_one_of_models(data: object) -> Union[Any, FreeFormModel, ModelWithUni
return one_of_models_type_1
except: # noqa: E722
pass
return cast(Union[Any, FreeFormModel, ModelWithUnionProperty], data)
return cast(Union["FreeFormModel", "ModelWithUnionProperty", Any], data)

one_of_models = _parse_one_of_models(d.pop("one_of_models"))

Expand Down Expand Up @@ -310,7 +319,7 @@ def _parse_one_of_models(data: object) -> Union[Any, FreeFormModel, ModelWithUni

not_required_not_nullable = d.pop("not_required_not_nullable", UNSET)

def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, None]:
def _parse_nullable_one_of_models(data: object) -> Union["FreeFormModel", "ModelWithUnionProperty", None]:
if data is None:
return data
try:
Expand All @@ -329,7 +338,7 @@ def _parse_nullable_one_of_models(data: object) -> Union[FreeFormModel, ModelWit

nullable_one_of_models = _parse_nullable_one_of_models(d.pop("nullable_one_of_models"))

def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, ModelWithUnionProperty, Unset]:
def _parse_not_required_one_of_models(data: object) -> Union["FreeFormModel", "ModelWithUnionProperty", Unset]:
if isinstance(data, Unset):
return data
try:
Expand Down Expand Up @@ -360,7 +369,7 @@ def _parse_not_required_one_of_models(data: object) -> Union[FreeFormModel, Mode

def _parse_not_required_nullable_one_of_models(
data: object,
) -> Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str]:
) -> Union["FreeFormModel", "ModelWithUnionProperty", None, Unset, str]:
if data is None:
return data
if isinstance(data, Unset):
Expand Down Expand Up @@ -395,7 +404,7 @@ def _parse_not_required_nullable_one_of_models(
return not_required_nullable_one_of_models_type_1
except: # noqa: E722
pass
return cast(Union[FreeFormModel, ModelWithUnionProperty, None, Unset, str], data)
return cast(Union["FreeFormModel", "ModelWithUnionProperty", None, Unset, str], data)

not_required_nullable_one_of_models = _parse_not_required_nullable_one_of_models(
d.pop("not_required_nullable_one_of_models", UNSET)
Expand Down
Loading