From 3c14afce6e9bb77fbe9ba227a6e33d34beb3759d Mon Sep 17 00:00:00 2001 From: artsmolin Date: Mon, 18 Jul 2022 15:50:25 +0300 Subject: [PATCH 1/2] Fix anyOf property --- pythogen/parsers/schemas.py | 7 ++++++- tests/clients/async_client.py | 36 +++++++++++++++++++++++++++++++++++ tests/clients/sync_client.py | 36 +++++++++++++++++++++++++++++++++++ tests/docs/openapi.yaml | 21 ++++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/pythogen/parsers/schemas.py b/pythogen/parsers/schemas.py index 90d4b9e..3654ba2 100644 --- a/pythogen/parsers/schemas.py +++ b/pythogen/parsers/schemas.py @@ -99,7 +99,7 @@ def _parse_type(self, data: Dict[str, Any]) -> models.Type: try: data_type = models.Type(raw_data_type) except ValueError: - raise Exception(f'Unable to parse schema "{id}", unknown type "{raw_data_type}"') + raise Exception(f'Unable to parse schema "{id}", unknown type "{raw_data_type}" on "{data}"') return data_type def _parse_format(self, data: Dict[str, Any]) -> Optional[models.Format]: @@ -183,6 +183,11 @@ def _parse_properties( # specify inline array name property_schema_id = key + "_list" schema = self.parse_item(property_schema_id, property_schema_data) + elif 'anyOf' in property_schema_data: + # extract inline object definition to schema + property_schema_id = key + "_obj" + schema = self.parse_item(property_schema_id, property_schema_data) + self._inline_schema_aggregator.add(property_schema_id, schema) else: property_schema_id = f'' schema = self.parse_item(property_schema_id, property_schema_data) diff --git a/tests/clients/async_client.py b/tests/clients/async_client.py index 5746666..74ba07c 100644 --- a/tests/clients/async_client.py +++ b/tests/clients/async_client.py @@ -289,6 +289,16 @@ class GetObjectWithInlineArrayResponse200Item(BaseModel): # optional --- +class AnimalObj(BaseModel): + """ + None + """ + __root__: Union[ + 'Cat', + 'Dog', + ] + + class TierObj(BaseModel): """ None @@ -481,6 +491,28 @@ def change_name(cls, values): return values +class Dog(BaseModel): + """ + Dog + """ + + # required --- + + # optional --- + name: Optional[str] = None + + +class Cat(BaseModel): + """ + Cat + """ + + # required --- + + # optional --- + name: Optional[str] = None + + class GetObjectResp(BaseModel): """ GetObjectResp @@ -494,6 +526,7 @@ class GetObjectResp(BaseModel): array_data: Optional[List[str]] = None boolean_data: Optional[bool] = None tier: Optional[TierObj] = None + animal: Optional[AnimalObj] = None class Data(BaseModel): @@ -1312,6 +1345,7 @@ def add_tracing_data_to_headers(self, headers_: Dict[str, str]) -> None: RewardsListItem.update_forward_refs() GetObjectWithInlineArrayResponse200.update_forward_refs() GetObjectWithInlineArrayResponse200Item.update_forward_refs() +AnimalObj.update_forward_refs() TierObj.update_forward_refs() GetObjectNoRefSchemaResponse200.update_forward_refs() TestSafetyKey.update_forward_refs() @@ -1324,6 +1358,8 @@ def add_tracing_data_to_headers(self, headers_: Dict[str, str]) -> None: PutObjectData.update_forward_refs() PatchObjectData.update_forward_refs() PostObjectData.update_forward_refs() +Dog.update_forward_refs() +Cat.update_forward_refs() GetObjectResp.update_forward_refs() Data.update_forward_refs() AllOfResp.update_forward_refs() diff --git a/tests/clients/sync_client.py b/tests/clients/sync_client.py index e8efd99..7bd15d9 100644 --- a/tests/clients/sync_client.py +++ b/tests/clients/sync_client.py @@ -289,6 +289,16 @@ class GetObjectWithInlineArrayResponse200Item(BaseModel): # optional --- +class AnimalObj(BaseModel): + """ + None + """ + __root__: Union[ + 'Cat', + 'Dog', + ] + + class TierObj(BaseModel): """ None @@ -481,6 +491,28 @@ def change_name(cls, values): return values +class Dog(BaseModel): + """ + Dog + """ + + # required --- + + # optional --- + name: Optional[str] = None + + +class Cat(BaseModel): + """ + Cat + """ + + # required --- + + # optional --- + name: Optional[str] = None + + class GetObjectResp(BaseModel): """ GetObjectResp @@ -494,6 +526,7 @@ class GetObjectResp(BaseModel): array_data: Optional[List[str]] = None boolean_data: Optional[bool] = None tier: Optional[TierObj] = None + animal: Optional[AnimalObj] = None class Data(BaseModel): @@ -1312,6 +1345,7 @@ def add_tracing_data_to_headers(self, headers_: Dict[str, str]) -> None: RewardsListItem.update_forward_refs() GetObjectWithInlineArrayResponse200.update_forward_refs() GetObjectWithInlineArrayResponse200Item.update_forward_refs() +AnimalObj.update_forward_refs() TierObj.update_forward_refs() GetObjectNoRefSchemaResponse200.update_forward_refs() TestSafetyKey.update_forward_refs() @@ -1324,6 +1358,8 @@ def add_tracing_data_to_headers(self, headers_: Dict[str, str]) -> None: PutObjectData.update_forward_refs() PatchObjectData.update_forward_refs() PostObjectData.update_forward_refs() +Dog.update_forward_refs() +Cat.update_forward_refs() GetObjectResp.update_forward_refs() Data.update_forward_refs() AllOfResp.update_forward_refs() diff --git a/tests/docs/openapi.yaml b/tests/docs/openapi.yaml index 87ba8b2..4d6ec3b 100644 --- a/tests/docs/openapi.yaml +++ b/tests/docs/openapi.yaml @@ -420,6 +420,22 @@ components: title: Data type: integer additionalProperties: false + Cat: + title: Cat + type: object + properties: + name: + title: name + type: string + additionalProperties: false + Dog: + title: Dog + type: object + properties: + name: + title: name + type: string + additionalProperties: false GetObjectResp: title: GetObjectResp type: object @@ -448,6 +464,11 @@ components: type: string priority: type: integer + animal: + type: object + anyOf: + - {$ref: '#/components/schemas/Cat'} + - {$ref: '#/components/schemas/Dog'} additionalProperties: false PostObjectData: title: PostObjectData From cbbc8924182f6fa424ff47962dcbe6cee59f5cd5 Mon Sep 17 00:00:00 2001 From: artsmolin Date: Mon, 18 Jul 2022 15:59:10 +0300 Subject: [PATCH 2/2] Fix anyOf renderer --- pythogen/renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythogen/renderer.py b/pythogen/renderer.py index d526009..9ad165e 100644 --- a/pythogen/renderer.py +++ b/pythogen/renderer.py @@ -192,7 +192,7 @@ def j2_typerepr(schema: models.SchemaObject) -> str: elif schema.type == models.Type.array and schema.items: if schema.items.type is models.Type.any_of: # type: ignore - items = [classname(item.schema.id) for item in schema.items.items] # type: ignore + items = [classname(item.id) for item in schema.items.items] # type: ignore representation = f'List[Union{items}]' else: item = j2_typerepr(schema.items) # type: ignore