feat: Reference schema support (#800) by goodsonjr · Pull Request #1307 · openapi-generators/openapi-python-client · GitHub
Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import pytest

from end_to_end_tests.functional_tests.helpers import assert_bad_schema, with_generated_client_fixture


@with_generated_client_fixture(
"""
components:
schemas:
MyModel:
type: object
properties:
booleanProp: {"type": "boolean"}
stringProp: {"type": "string"}
numberProp: {"type": "number"}
intProp: {"type": "integer"}
anyObjectProp: {"$ref": "#/components/schemas/AnyObject"}
nullProp: {"type": "null"}
anyProp: {}
AnyObject:
$ref: "#/components/schemas/OtherObject"
OtherObject:
$ref: "#/components/schemas/AnyObject"

"""
)
class TestReferenceSchemaProperties:
def test_decode_encode(self, generated_client):
assert "Circular schema references found" in generated_client.generator_result.stdout
24 changes: 19 additions & 5 deletions openapi_python_client/parser/properties/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
Parameters,
ReferencePath,
Schemas,
get_reference_simple_name,
parse_reference_path,
update_parameters_with_data,
update_schemas_with_data,
Expand Down Expand Up @@ -324,17 +325,30 @@ def _create_schemas(
while still_making_progress:
still_making_progress = False
errors = []
next_round = []
next_round: list[tuple[str, oai.Reference | oai.Schema]] = []
# Only accumulate errors from the last round, since we might fix some along the way
for name, data in to_process:
if isinstance(data, oai.Reference):
schemas.errors.append(PropertyError(data=data, detail="Reference schemas are not supported."))
continue
schema_data: oai.Reference | oai.Schema | None = data
ref_path = parse_reference_path(f"#/components/schemas/{name}")
if isinstance(ref_path, ParseError):
schemas.errors.append(PropertyError(detail=ref_path.detail, data=data))
continue
schemas_or_err = update_schemas_with_data(ref_path=ref_path, data=data, schemas=schemas, config=config)
if isinstance(data, oai.Reference):
# Fully dereference reference schemas
seen = [name]
while isinstance(schema_data, oai.Reference):
data_ref_schema = get_reference_simple_name(schema_data.ref)
if data_ref_schema in seen:
schemas.errors.append(PropertyError(detail="Circular schema references found", data=data))
break
# use derefenced schema definition for this schema
schema_data = components.get(data_ref_schema)
if isinstance(schema_data, oai.Schema):
schemas_or_err = update_schemas_with_data(
ref_path=ref_path, data=schema_data, schemas=schemas, config=config
)
else:
schemas.errors.append(PropertyError(detail="Referent schema not found", data=data))
if isinstance(schemas_or_err, PropertyError):
next_round.append((name, data))
errors.append(schemas_or_err)
Expand Down
16 changes: 8 additions & 8 deletions tests/test_parser/test_properties/test_init.py
Loading