@@ -611,7 +611,12 @@ def test_property_from_data_ref_model(self):
611
611
assert schemas == new_schemas
612
612
613
613
def test_property_from_data_ref_not_found (self , mocker ):
614
- from openapi_python_client .parser .properties import PropertyError , Schemas , property_from_data
614
+ from openapi_python_client .parser .properties import (
615
+ LazyReferencePropertyProxy ,
616
+ PropertyError ,
617
+ Schemas ,
618
+ property_from_data ,
619
+ )
615
620
616
621
name = mocker .MagicMock ()
617
622
required = mocker .MagicMock ()
@@ -624,8 +629,13 @@ def test_property_from_data_ref_not_found(self, mocker):
624
629
name = name , required = required , data = data , schemas = schemas , parent_name = "parent"
625
630
)
626
631
627
- from_ref .assert_called_once_with (data .ref )
628
- assert prop == PropertyError (data = data , detail = "Could not find reference in parsed models or enums" )
632
+ from_ref .assert_called_with (data .ref )
633
+ assert isinstance (prop , LazyReferencePropertyProxy )
634
+ assert prop .resolve () == None
635
+ with pytest .raises (RuntimeError ):
636
+ prop .resolve (False )
637
+ with pytest .raises (RuntimeError ):
638
+ prop .template
629
639
assert schemas == new_schemas
630
640
631
641
def test_property_from_data_string (self , mocker ):
@@ -1389,3 +1399,287 @@ def test__resolve_local_reference_schema(mocker):
1389
1399
assert schemas .enums ["FooBarLowerCaseDeeperReferenceLoop" ] == schemas .enums ["Foobar" ]
1390
1400
assert isinstance (res_7 , PropertyError )
1391
1401
assert isinstance (res_8 , PropertyError )
1402
+
1403
+
1404
+ def _base_api_data ():
1405
+ return """
1406
+ ---
1407
+ openapi: 3.0.2
1408
+ info:
1409
+ title: test
1410
+ description: test
1411
+ version: 1.0.0
1412
+ paths:
1413
+ /tests/:
1414
+ get:
1415
+ operationId: getTests
1416
+ description: test
1417
+ responses:
1418
+ '200':
1419
+ description: test
1420
+ content:
1421
+ application/json:
1422
+ schema:
1423
+ $ref: '#/components/schemas/fooBarModel'
1424
+ """
1425
+
1426
+
1427
+ def test_lazy_proxy_reference_unresolved ():
1428
+ import copy
1429
+
1430
+ import openapi_python_client .schema as oai
1431
+ from openapi_python_client .parser .properties import LazyReferencePropertyProxy , Schemas
1432
+
1433
+ LazyReferencePropertyProxy .update_schemas (Schemas ())
1434
+ lazy_reference_proxy = LazyReferencePropertyProxy .create (
1435
+ "childProperty" , False , oai .Reference (ref = "#/foobar" ), "AModel"
1436
+ )
1437
+
1438
+ assert lazy_reference_proxy .get_instance_type_string () == "LazyReferencePropertyProxy"
1439
+ assert lazy_reference_proxy .get_type_string (no_optional = False ) == "LazyReferencePropertyProxy"
1440
+ assert lazy_reference_proxy .get_type_string (no_optional = True ) == "LazyReferencePropertyProxy"
1441
+ assert lazy_reference_proxy .get_imports (prefix = ".." ) == set ()
1442
+ assert lazy_reference_proxy .resolve () == None
1443
+ with pytest .raises (RuntimeError ):
1444
+ lazy_reference_proxy .resolve (False )
1445
+ with pytest .raises (RuntimeError ):
1446
+ copy .copy (lazy_reference_proxy )
1447
+ with pytest .raises (RuntimeError ):
1448
+ copy .deepcopy (lazy_reference_proxy )
1449
+ with pytest .raises (RuntimeError ):
1450
+ lazy_reference_proxy .name
1451
+ with pytest .raises (RuntimeError ):
1452
+ lazy_reference_proxy .required
1453
+ with pytest .raises (RuntimeError ):
1454
+ lazy_reference_proxy .nullable
1455
+ with pytest .raises (RuntimeError ):
1456
+ lazy_reference_proxy .default
1457
+ with pytest .raises (RuntimeError ):
1458
+ lazy_reference_proxy .python_name
1459
+ with pytest .raises (RuntimeError ):
1460
+ lazy_reference_proxy .template
1461
+
1462
+
1463
+ def test_lazy_proxy_reference_resolved ():
1464
+ import copy
1465
+
1466
+ import yaml
1467
+
1468
+ import openapi_python_client .schema as oai
1469
+ from openapi_python_client .parser .properties import LazyReferencePropertyProxy , Schemas , build_schemas
1470
+
1471
+ data = yaml .safe_load (
1472
+ f"""
1473
+ { _base_api_data ()}
1474
+ components:
1475
+ schemas:
1476
+ fooBar:
1477
+ type: object
1478
+ properties:
1479
+ childSettings:
1480
+ type: number
1481
+ """
1482
+ )
1483
+ openapi = oai .OpenAPI .parse_obj (data )
1484
+ schemas = build_schemas (components = openapi .components .schemas )
1485
+ foobar = schemas .models .get ("FooBar" )
1486
+
1487
+ LazyReferencePropertyProxy .update_schemas (schemas )
1488
+ lazy_reference_proxy = LazyReferencePropertyProxy .create (
1489
+ "childProperty" , True , oai .Reference (ref = "#/components/schemas/fooBar" ), "AModel"
1490
+ )
1491
+
1492
+ assert foobar
1493
+ assert lazy_reference_proxy .get_instance_type_string () == foobar .get_instance_type_string ()
1494
+ assert lazy_reference_proxy .get_type_string (no_optional = False ) == foobar .get_type_string (no_optional = False )
1495
+ assert lazy_reference_proxy .get_type_string (no_optional = True ) == foobar .get_type_string (no_optional = True )
1496
+ assert lazy_reference_proxy .get_imports (prefix = ".." ) == foobar .get_imports (prefix = ".." )
1497
+ assert lazy_reference_proxy .name == "childProperty" and foobar .name == "fooBar"
1498
+ assert lazy_reference_proxy .nullable == foobar .nullable
1499
+ assert lazy_reference_proxy .default == foobar .default
1500
+ assert lazy_reference_proxy .python_name == "child_property" and foobar .python_name == "foo_bar"
1501
+ assert lazy_reference_proxy .template == foobar .template
1502
+ try :
1503
+ copy .copy (lazy_reference_proxy )
1504
+ copy .deepcopy (lazy_reference_proxy )
1505
+ except Exception as e :
1506
+ pytest .fail (e )
1507
+
1508
+
1509
+ def test_build_schemas_resolve_inner_property_remote_reference ():
1510
+ import yaml
1511
+
1512
+ import openapi_python_client .schema as oai
1513
+ from openapi_python_client .parser .properties import Schemas , build_schemas
1514
+
1515
+ data = yaml .safe_load (
1516
+ f"""
1517
+ { _base_api_data ()}
1518
+ components:
1519
+ schemas:
1520
+ fooBar:
1521
+ type: object
1522
+ properties:
1523
+ childSettings:
1524
+ type: array
1525
+ items:
1526
+ $ref: 'AnOtherDocument#/components/schemas/bar'
1527
+ """
1528
+ )
1529
+ openapi = oai .OpenAPI .parse_obj (data )
1530
+
1531
+ schemas = build_schemas (components = openapi .components .schemas )
1532
+
1533
+ assert len (schemas .errors ) == 1
1534
+ assert schemas .errors [0 ] == PropertyError (
1535
+ data = oai .Reference (ref = "AnOtherDocument#/components/schemas/bar" ),
1536
+ detail = "invalid data in items of array childSettings" ,
1537
+ )
1538
+
1539
+
1540
+ def test_build_schemas_lazy_resolve_known_inner_property_local_reference ():
1541
+ import yaml
1542
+
1543
+ import openapi_python_client .schema as oai
1544
+ from openapi_python_client .parser .properties import Schemas , build_schemas
1545
+
1546
+ data = yaml .safe_load (
1547
+ f"""
1548
+ { _base_api_data ()}
1549
+ components:
1550
+ schemas:
1551
+ fooBar:
1552
+ type: object
1553
+ properties:
1554
+ childSettings:
1555
+ type: array
1556
+ items:
1557
+ $ref: '#/components/schemas/bar'
1558
+ bar:
1559
+ type: object
1560
+ properties:
1561
+ a_prop:
1562
+ type: number
1563
+ """
1564
+ )
1565
+ openapi = oai .OpenAPI .parse_obj (data )
1566
+
1567
+ schemas = build_schemas (components = openapi .components .schemas )
1568
+
1569
+ foo_bar = schemas .models .get ("FooBar" )
1570
+ bar = schemas .models .get ("Bar" )
1571
+ assert len (schemas .errors ) == 0
1572
+ assert foo_bar and bar
1573
+ child_settings = foo_bar .optional_properties [0 ]
1574
+ assert child_settings .inner_property .reference == bar .reference
1575
+
1576
+
1577
+ def test_build_schemas_lazy_resolve_known_inner_property_local_reference_with_loop ():
1578
+ import yaml
1579
+
1580
+ import openapi_python_client .schema as oai
1581
+ from openapi_python_client .parser .properties import Schemas , build_schemas
1582
+
1583
+ data = yaml .safe_load (
1584
+ f"""
1585
+ { _base_api_data ()}
1586
+ components:
1587
+ schemas:
1588
+ fooBar:
1589
+ type: object
1590
+ properties:
1591
+ childSettings:
1592
+ type: array
1593
+ items:
1594
+ $ref: '#/components/schemas/barDeeperLoop'
1595
+
1596
+ barDeeperLoop:
1597
+ $ref: '#/components/schemas/barLoop'
1598
+ barLoop:
1599
+ $ref: '#/components/schemas/bar'
1600
+ bar:
1601
+ type: object
1602
+ properties:
1603
+ a_prop:
1604
+ type: number
1605
+
1606
+ """
1607
+ )
1608
+ openapi = oai .OpenAPI .parse_obj (data )
1609
+
1610
+ schemas = build_schemas (components = openapi .components .schemas )
1611
+
1612
+ foo_bar = schemas .models .get ("FooBar" )
1613
+ bar_deeper_loop = schemas .models .get ("BarDeeperLoop" )
1614
+ bar_loop = schemas .models .get ("BarLoop" )
1615
+ bar = schemas .models .get ("Bar" )
1616
+ assert len (schemas .errors ) == 0
1617
+ assert foo_bar and bar_deeper_loop and bar_loop and bar
1618
+ assert bar == bar_deeper_loop == bar_loop
1619
+
1620
+ child_settings = foo_bar .optional_properties [0 ]
1621
+ assert child_settings .inner_property .reference == bar .reference
1622
+ assert child_settings .inner_property .reference == bar_loop .reference
1623
+ assert child_settings .inner_property .reference == bar_deeper_loop .reference
1624
+
1625
+
1626
+ def test_build_schemas_lazy_resolve_inner_property_self_local_reference ():
1627
+ import yaml
1628
+
1629
+ import openapi_python_client .schema as oai
1630
+ from openapi_python_client .parser .properties import Schemas , build_schemas
1631
+
1632
+ data = yaml .safe_load (
1633
+ f"""
1634
+ { _base_api_data ()}
1635
+ components:
1636
+ schemas:
1637
+ fooBar:
1638
+ type: object
1639
+ properties:
1640
+ childSettings:
1641
+ type: array
1642
+ items:
1643
+ $ref: '#/components/schemas/fooBar'
1644
+ """
1645
+ )
1646
+ openapi = oai .OpenAPI .parse_obj (data )
1647
+
1648
+ schemas = build_schemas (components = openapi .components .schemas )
1649
+
1650
+ foo_bar = schemas .models .get ("FooBar" )
1651
+ assert len (schemas .errors ) == 0
1652
+ assert foo_bar
1653
+ child_settings = foo_bar .optional_properties [0 ]
1654
+ assert child_settings .inner_property .reference == foo_bar .reference
1655
+
1656
+
1657
+ def test_build_schemas_lazy_resolve_unknown_inner_property_local_reference ():
1658
+ import yaml
1659
+
1660
+ import openapi_python_client .schema as oai
1661
+ from openapi_python_client .parser .properties import Schemas , build_schemas
1662
+
1663
+ data = yaml .safe_load (
1664
+ f"""
1665
+ { _base_api_data ()}
1666
+ components:
1667
+ schemas:
1668
+ fooBar:
1669
+ type: object
1670
+ properties:
1671
+ childSettings:
1672
+ type: array
1673
+ items:
1674
+ $ref: '#/components/schemas/noexist'
1675
+ """
1676
+ )
1677
+ openapi = oai .OpenAPI .parse_obj (data )
1678
+
1679
+ schemas = build_schemas (components = openapi .components .schemas )
1680
+
1681
+ assert len (schemas .errors ) == 1
1682
+ assert schemas .errors [0 ] == PropertyError (
1683
+ detail = "Could not find reference in parsed models or enums." ,
1684
+ data = oai .Reference (ref = "#/components/schemas/noexist" ),
1685
+ )
0 commit comments