Skip to content

Commit

Permalink
Merge pull request #64 from artsmolin/new-models
Browse files Browse the repository at this point in the history
Add support of allOf
  • Loading branch information
artsmolin authored Sep 2, 2023
2 parents 5bee4e6 + 2efa2c3 commit f4c20a2
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 154 deletions.
2 changes: 1 addition & 1 deletion examples/petstore/client_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# Generator info:
# GitHub Page: https://github.com/artsmolin/pythogen
# Version: 0.2.20
# Version: 0.2.21
# ==============================================================================

# jinja2: lstrip_blocks: "True"
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/client_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# Generator info:
# GitHub Page: https://github.com/artsmolin/pythogen
# Version: 0.2.20
# Version: 0.2.21
# ==============================================================================

# jinja2: lstrip_blocks: "True"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pythogen"
version = "0.2.20"
version = "0.2.21"
description = "Generator of python HTTP-clients from OpenApi specification."
homepage = "https://github.com/artsmolin/pythogen"
repository = "https://github.com/artsmolin/pythogen"
Expand Down
7 changes: 7 additions & 0 deletions pythogen/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import keyword
import re
from dataclasses import dataclass
from dataclasses import field
from enum import Enum


Expand Down Expand Up @@ -148,6 +149,7 @@ class SchemaObject:
properties: list[SchemaProperty]
description: str | None = None
additional_roperties: bool = False
all_of: list['SchemaObject'] = field(default_factory=list)

# Технические поля
discriminator_base_class_schema: DiscriminatorBaseClassSchema | None = None
Expand Down Expand Up @@ -280,6 +282,11 @@ def _build_sorted_schemas(self, keys: list[str], exclude_enums: bool = False):
index = len(sorted) - 1

schema = self.schemas[key]

for all_of_item in schema.all_of:
if all_of_item.id in key_for_processing and all_of_item.id not in sorted:
sorted.insert(index, all_of_item.id)

for property in schema.properties:
if property.schema.id in key_for_processing and property.schema.id not in sorted:
sorted.insert(index, property.schema.id)
Expand Down
23 changes: 12 additions & 11 deletions pythogen/parsers/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def parse_item(
return self._schemas[schema_id]

schema_type = self._parse_type(schema_data)
all_of = self._parse_all_of(schema_data)

self._processiong_parsed_schema_id_count[schema_id] += 1
if self._processiong_parsed_schema_id_count[schema_id] > 1 and from_depth_level:
Expand All @@ -112,6 +113,7 @@ def parse_item(
properties=[],
description=self._get_description(schema_data),
is_fake=True,
all_of=all_of,
)

discr_schema = self._get_discriminator_base_class_schema(schema_data)
Expand All @@ -128,8 +130,18 @@ def parse_item(
items=self._parse_items(schema_id, schema_data),
properties=self._parse_properties(schema_type, schema_data),
description=self._get_description(schema_data),
all_of=all_of,
)

def _parse_all_of(self, data: dict[str, Any]) -> list[models.SchemaObject]:
result: list[models.SchemaObject] = []
for all_of_item in data.get("allOf", []):
if ref := all_of_item.get('$ref'):
resolved_ref = self._ref_resolver.resolve(ref)
all_of_item_schema = self.parse_item(resolved_ref.ref_id, resolved_ref.ref_data)
result.append(all_of_item_schema)
return result

def _parse_type(self, data: dict[str, Any]) -> models.Type:
if data == {}:
# Парсинг пустой схемы
Expand Down Expand Up @@ -216,18 +228,7 @@ def _parse_properties(
elif 'allOf' in property_schema_data:
property_schema_id = key + "_ref_obj"
schema = self.parse_item(property_schema_id, property_schema_data)

for all_of_reference_container in property_schema_data['allOf']:
ref = all_of_reference_container['$ref']
all_of_resolved_ref = self._ref_resolver.resolve(ref)
all_of_reference_parsed_schema = self.parse_item(
schema_id=all_of_resolved_ref.ref_id,
schema_data=all_of_resolved_ref.ref_data,
)
schema.properties += all_of_reference_parsed_schema.properties

self._inline_schema_aggregator.add(property_schema_id, schema)

elif property_schema_data.get('type') == models.Type.array.value:
# specify inline array name
property_schema_id = key + "_list"
Expand Down
8 changes: 8 additions & 0 deletions pythogen/templates/http_client/main.j2
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ class {{ schema.name }}(BaseModel):
{%- for model in models %}

{%- if model.type.value == "any_of" %}
{%- elif model.all_of %}
class {{ classname(model.id) }}(
{% for all_of_item_model in model.all_of %}{{ classname(all_of_item_model.id) }},{% endfor %}
):
"""
{{ model.title }}
"""
...
{%- else %}
class {{ classname(model.id) }}(BaseModel):
"""
Expand Down
55 changes: 27 additions & 28 deletions tests/clients/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# Generator info:
# GitHub Page: https://github.com/artsmolin/pythogen
# Version: 0.2.20
# Version: 0.2.21
# ==============================================================================

# jinja2: lstrip_blocks: "True"
Expand Down Expand Up @@ -408,9 +408,20 @@ class TierObj(BaseModel):
priority: int | None = None


class AllOfRefObj(BaseModel):
class Cat(BaseModel):
"""
All Of
Cat
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
name: str | None = None


class Data(BaseModel):
"""
Data
"""

model_config = ConfigDict(
Expand All @@ -420,6 +431,17 @@ class AllOfRefObj(BaseModel):
data: int | None = None


class AllOfRefObj(
Data,
Cat,
):
"""
All Of
"""

...


class ListAnyOfResp(BaseModel):
"""
PostObjectResp
Expand Down Expand Up @@ -574,17 +596,6 @@ class Dog(BaseModel):
name: str | None = None


class Cat(BaseModel):
"""
Cat
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
name: str | None = None


class GetObjectResp(BaseModel):
"""
GetObjectResp
Expand All @@ -604,18 +615,6 @@ class GetObjectResp(BaseModel):
animal: Cat | Dog | None = None


class Data(BaseModel):
"""
Data
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
id: str | None = None
data: int | None = None


class AllOfResp(BaseModel):
"""
All Of Resp
Expand Down Expand Up @@ -2133,6 +2132,8 @@ def _parse_any_of(self, item: dict[str, Any], schema_classes: list[Any]) -> Any:
GetObjectWithArrayResponseResponse200Item.model_rebuild()
GetObjectNoRefSchemaResponse200.model_rebuild()
TierObj.model_rebuild()
Cat.model_rebuild()
Data.model_rebuild()
AllOfRefObj.model_rebuild()
ListAnyOfResp.model_rebuild()
SafetyKeyForTesting.model_rebuild()
Expand All @@ -2146,7 +2147,5 @@ def _parse_any_of(self, item: dict[str, Any], schema_classes: list[Any]) -> Any:
PatchObjectData.model_rebuild()
PostObjectData.model_rebuild()
Dog.model_rebuild()
Cat.model_rebuild()
GetObjectResp.model_rebuild()
Data.model_rebuild()
AllOfResp.model_rebuild()
55 changes: 27 additions & 28 deletions tests/clients/async_client_with_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# Generator info:
# GitHub Page: https://github.com/artsmolin/pythogen
# Version: 0.2.20
# Version: 0.2.21
# ==============================================================================

# jinja2: lstrip_blocks: "True"
Expand Down Expand Up @@ -408,9 +408,20 @@ class TierObj(BaseModel):
priority: int | None = None


class AllOfRefObj(BaseModel):
class Cat(BaseModel):
"""
All Of
Cat
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
name: str | None = None


class Data(BaseModel):
"""
Data
"""

model_config = ConfigDict(
Expand All @@ -420,6 +431,17 @@ class AllOfRefObj(BaseModel):
data: int | None = None


class AllOfRefObj(
Data,
Cat,
):
"""
All Of
"""

...


class ListAnyOfResp(BaseModel):
"""
PostObjectResp
Expand Down Expand Up @@ -574,17 +596,6 @@ class Dog(BaseModel):
name: str | None = None


class Cat(BaseModel):
"""
Cat
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
name: str | None = None


class GetObjectResp(BaseModel):
"""
GetObjectResp
Expand All @@ -604,18 +615,6 @@ class GetObjectResp(BaseModel):
animal: Cat | Dog | None = None


class Data(BaseModel):
"""
Data
"""

model_config = ConfigDict(
populate_by_name=True, # Addressing by field name, even if there is an alias.
)
id: str | None = None
data: int | None = None


class AllOfResp(BaseModel):
"""
All Of Resp
Expand Down Expand Up @@ -2136,6 +2135,8 @@ def _parse_any_of(self, item: dict[str, Any], schema_classes: list[Any]) -> Any:
GetObjectWithArrayResponseResponse200Item.model_rebuild()
GetObjectNoRefSchemaResponse200.model_rebuild()
TierObj.model_rebuild()
Cat.model_rebuild()
Data.model_rebuild()
AllOfRefObj.model_rebuild()
ListAnyOfResp.model_rebuild()
SafetyKeyForTesting.model_rebuild()
Expand All @@ -2149,7 +2150,5 @@ def _parse_any_of(self, item: dict[str, Any], schema_classes: list[Any]) -> Any:
PatchObjectData.model_rebuild()
PostObjectData.model_rebuild()
Dog.model_rebuild()
Cat.model_rebuild()
GetObjectResp.model_rebuild()
Data.model_rebuild()
AllOfResp.model_rebuild()
Loading

0 comments on commit f4c20a2

Please sign in to comment.