Skip to content

Commit d3d7bbe

Browse files
committed
parser / properties / tests cleanup + behaviour fixes
1 parent ce6bb1e commit d3d7bbe

File tree

2 files changed

+36
-102
lines changed

2 files changed

+36
-102
lines changed

openapi_python_client/parser/properties/__init__.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -571,11 +571,17 @@ def _property_from_data(
571571
else:
572572

573573
def lookup_is_reference_to_itself(
574-
ref_name: str, owner_class_name: str, lazy_references: Dict[str, oai.Reference]
574+
ref_name: str,
575+
owner_class_name: str,
576+
lazy_references: Dict[str, oai.Reference],
575577
) -> bool:
576578
if ref_name in lazy_references:
577579
next_ref_name = _reference_pointer_name(lazy_references[ref_name])
578-
return lookup_is_reference_to_itself(next_ref_name, owner_class_name, lazy_references)
580+
return lookup_is_reference_to_itself(
581+
next_ref_name,
582+
owner_class_name,
583+
lazy_references,
584+
)
579585

580586
return ref_name.casefold() == owner_class_name.casefold()
581587

@@ -783,14 +789,14 @@ def build_schemas(*, components: Dict[str, Union[oai.Reference, oai.Schema]]) ->
783789
to_process: Iterable[Tuple[str, Union[oai.Reference, oai.Schema]]] = components.items()
784790
processing = True
785791
errors: List[PropertyError] = []
786-
LazyReferencePropertyProxy.flush_internal_references() # Cleanup side effects
787792
lazy_self_references: Dict[str, oai.Reference] = dict()
788793
visited: List[str] = []
794+
references_by_name: Dict[str, oai.Reference] = dict()
795+
references_to_process: List[Tuple[str, oai.Reference]] = list()
796+
LazyReferencePropertyProxy.flush_internal_references() # Cleanup side effects
789797

790798
# References could have forward References so keep going as long as we are making progress
791799
while processing:
792-
references_by_name: Dict[str, oai.Reference] = dict()
793-
references_to_process: List[Tuple[str, oai.Reference]] = list()
794800
processing = False
795801
errors = []
796802
next_round = []
@@ -822,24 +828,29 @@ def build_schemas(*, components: Dict[str, Union[oai.Reference, oai.Schema]]) ->
822828
schemas_or_err = resolve_reference_and_update_schemas(name, reference, schemas, references_by_name)
823829

824830
if isinstance(schemas_or_err, PropertyError):
825-
if _reference_pointer_name(reference) in visited:
831+
if _reference_pointer_name(reference) in visited and name not in lazy_self_references:
826832
# It's a reference to an already visited Enum|Model; not yet resolved
827833
# It's an indirect reference toward this Enum|Model;
828834
# It will be lazy proxified and resolved later on
829835
lazy_self_references[name] = reference
836+
processing = True
830837
else:
831838
errors.append(schemas_or_err)
832839

840+
schemas.errors.extend(errors)
841+
833842
for name in lazy_self_references.keys():
834843
schemas_or_err = resolve_reference_and_update_schemas(
835844
name, lazy_self_references[name], schemas, references_by_name
836845
)
846+
if isinstance(schemas_or_err, PropertyError):
847+
schemas.errors.extend(errors)
837848

838-
schemas.errors.extend(errors)
839849
LazyReferencePropertyProxy.update_schemas(schemas)
840850
for reference_proxy, data in LazyReferencePropertyProxy.created_proxies():
841851
if not reference_proxy.resolve():
842852
schemas.errors.append(
843853
PropertyError(data=data, detail="Could not find reference in parsed models or enums.")
844854
)
855+
845856
return schemas

tests/test_parser/test_properties/test_init.py

Lines changed: 18 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,7 @@ def _base_api_data():
14921492
content:
14931493
application/json:
14941494
schema:
1495-
$ref: '#/components/schemas/fooBarModel'
1495+
$ref: '#/components/schemas/fooBar'
14961496
"""
14971497

14981498

@@ -1607,93 +1607,7 @@ def test_build_schemas_resolve_inner_property_remote_reference():
16071607
)
16081608

16091609

1610-
def test_build_schemas_lazy_resolve_known_inner_property_local_reference():
1611-
import yaml
1612-
1613-
import openapi_python_client.schema as oai
1614-
from openapi_python_client.parser.properties import Schemas, build_schemas
1615-
1616-
data = yaml.safe_load(
1617-
f"""
1618-
{_base_api_data()}
1619-
components:
1620-
schemas:
1621-
fooBar:
1622-
type: object
1623-
properties:
1624-
childSettings:
1625-
type: array
1626-
items:
1627-
$ref: '#/components/schemas/bar'
1628-
bar:
1629-
type: object
1630-
properties:
1631-
a_prop:
1632-
type: number
1633-
"""
1634-
)
1635-
openapi = oai.OpenAPI.parse_obj(data)
1636-
1637-
schemas = build_schemas(components=openapi.components.schemas)
1638-
1639-
foo_bar = schemas.models.get("FooBar")
1640-
bar = schemas.models.get("Bar")
1641-
assert len(schemas.errors) == 0
1642-
assert foo_bar and bar
1643-
child_settings = foo_bar.optional_properties[0]
1644-
assert child_settings.inner_property.reference == bar.reference
1645-
1646-
1647-
def test_build_schemas_lazy_resolve_known_inner_property_local_reference_with_loop():
1648-
import yaml
1649-
1650-
import openapi_python_client.schema as oai
1651-
from openapi_python_client.parser.properties import Schemas, build_schemas
1652-
1653-
data = yaml.safe_load(
1654-
f"""
1655-
{_base_api_data()}
1656-
components:
1657-
schemas:
1658-
fooBar:
1659-
type: object
1660-
properties:
1661-
childSettings:
1662-
type: array
1663-
items:
1664-
$ref: '#/components/schemas/barDeeperLoop'
1665-
1666-
barDeeperLoop:
1667-
$ref: '#/components/schemas/barLoop'
1668-
barLoop:
1669-
$ref: '#/components/schemas/bar'
1670-
bar:
1671-
type: object
1672-
properties:
1673-
a_prop:
1674-
type: number
1675-
1676-
"""
1677-
)
1678-
openapi = oai.OpenAPI.parse_obj(data)
1679-
1680-
schemas = build_schemas(components=openapi.components.schemas)
1681-
1682-
foo_bar = schemas.models.get("FooBar")
1683-
bar_deeper_loop = schemas.models.get("BarDeeperLoop")
1684-
bar_loop = schemas.models.get("BarLoop")
1685-
bar = schemas.models.get("Bar")
1686-
assert len(schemas.errors) == 0
1687-
assert foo_bar and bar_deeper_loop and bar_loop and bar
1688-
assert bar == bar_deeper_loop == bar_loop
1689-
1690-
child_settings = foo_bar.optional_properties[0]
1691-
assert child_settings.inner_property.reference == bar.reference
1692-
assert child_settings.inner_property.reference == bar_loop.reference
1693-
assert child_settings.inner_property.reference == bar_deeper_loop.reference
1694-
1695-
1696-
def test_build_schemas_lazy_resolve_inner_property_self_local_reference():
1610+
def test_build_schemas_lazy_resolve_inner_property_self_direct_reference():
16971611
import yaml
16981612

16991613
import openapi_python_client.schema as oai
@@ -1724,7 +1638,7 @@ def test_build_schemas_lazy_resolve_inner_property_self_local_reference():
17241638
assert child_settings.inner_property.reference == foo_bar.reference
17251639

17261640

1727-
def test_build_schemas_lazy_resolve_unknown_inner_property_local_reference():
1641+
def test_build_schemas_lazy_resolve_known_inner_property_self_indirect_reference():
17281642
import yaml
17291643

17301644
import openapi_python_client.schema as oai
@@ -1740,16 +1654,25 @@ def test_build_schemas_lazy_resolve_unknown_inner_property_local_reference():
17401654
properties:
17411655
childSettings:
17421656
type: array
1657+
description: test
17431658
items:
1744-
$ref: '#/components/schemas/noexist'
1659+
$ref: '#/components/schemas/FoobarSelfIndirectReference'
1660+
FoobarSelfIndirectReference:
1661+
$ref: '#/components/schemas/foobarSelfDeeperIndirectReference'
1662+
foobarSelfDeeperIndirectReference:
1663+
$ref: '#/components/schemas/fooBar'
17451664
"""
17461665
)
17471666
openapi = oai.OpenAPI.parse_obj(data)
17481667

17491668
schemas = build_schemas(components=openapi.components.schemas)
17501669

1751-
assert len(schemas.errors) == 1
1752-
assert schemas.errors[0] == PropertyError(
1753-
detail="invalid data in items of array childSettings",
1754-
data=oai.Reference(ref="#/components/schemas/noexist"),
1755-
)
1670+
assert len(schemas.errors) == 0
1671+
foobar = schemas.models.get("FooBar")
1672+
foobar_indirect_ref = schemas.models.get("FoobarSelfIndirectReference")
1673+
foobar_deep_indirect_ref = schemas.models.get("FoobarSelfDeeperIndirectReference")
1674+
assert foobar is not None and foobar_indirect_ref is not None and foobar_deep_indirect_ref is not None
1675+
assert foobar == foobar_indirect_ref == foobar_deep_indirect_ref
1676+
1677+
child_settings = foobar.optional_properties[0]
1678+
assert child_settings.inner_property.reference == foobar.reference

0 commit comments

Comments
 (0)