openapi-python-client icon indicating copy to clipboard operation
openapi-python-client copied to clipboard

feat: Support for recursive and circular references

Open maz808 opened this issue 2 years ago • 2 comments

This PR adds support for recursive and circular references in properties and additionalProperties.

Related To/May Close

  • #338
  • #466

Known Issues

  • Recursive/circular reference paths that are required all the way through would be impossible to use in generated clients
class Example:
    # This would be impossible to create as the `example` attribute would require infinitely
    # recursive creation of Example objects 
    example: Example

maz808 avatar Jan 30 '22 04:01 maz808

Codecov Report

Merging #582 (43c58d1) into main (d8d9cec) will decrease coverage by 0.05%. The diff coverage is 100.00%.

@@             Coverage Diff             @@
##              main     #582      +/-   ##
===========================================
- Coverage   100.00%   99.94%   -0.06%     
===========================================
  Files           49       49              
  Lines         1713     1816     +103     
===========================================
+ Hits          1713     1815     +102     
- Misses           0        1       +1     
Impacted Files Coverage Δ
...penapi_python_client/parser/properties/__init__.py 100.00% <100.00%> (ø)
..._python_client/parser/properties/model_property.py 99.45% <100.00%> (-0.55%) :arrow_down:
...penapi_python_client/parser/properties/property.py 100.00% <100.00%> (ø)
openapi_python_client/parser/properties/schemas.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update d8d9cec...43c58d1. Read the comment docs.

codecov[bot] avatar Apr 24 '22 18:04 codecov[bot]

@maz808 Hello! Thanks for your work and PR! Seems like the generated client doesn’t work due to circular import exceptions.

For example:

openapi: 3.0.3
info:
  title: 'Example'
  version: 0.1.0
servers:
  - url: 'http://example.com'
paths:
  '/foo':
    delete:
      responses:
        '200':
          description: OK
components:
  schemas:
    Brother:
      type: object
      properties:
        sister:
          $ref: '#/components/schemas/Sister'
    Sister:
      type: object
      properties:
        brother:
          $ref: '#/components/schemas/Brother'

When I trying to use Sister model

from example_client.models.sister import Sister

if __name__ == '__main__':
    Sister()
File “…/example_client/models/__init__.py", line 3, in <module>
    from .brother import Brother
  File "…/example_client/models/brother.py", line 5, in <module>
    from ..models.sister import Sister
  File "…/example_client/models/sister.py", line 5, in <module>
    from ..models.brother import Brother
ImportError: cannot import name 'Brother' from partially initialized module 'example_client.models.brother' (most likely due to a circular import)

Seems like the first problem should be solved in the way that supports circular references. It has several workarounds. But I like the approach to use just one module for storing all models, like module models.py with

from __future__ import annotations

@attr.s(auto_attribs=True)
class Brother:
	…
    sister: Union[Unset, Sister] = UNSET
	…

    @classmethod
    def from_dict(cls: Brother, src_dict: Dict[str, Any]) -> Brother:
        …


@attr.s(auto_attribs=True)
class Sister:
	…

@dbanty What do you think about it?

mtovt avatar Jun 15 '22 20:06 mtovt

This PR lives on through @mtovt's work in #670 🥳

dbanty avatar Sep 18 '22 17:09 dbanty

@dbanty I noticed the release page doesn't acknowledge my contribution to the recursive and nested schema issue. Could I be added to the list of thanks?

maz808 avatar Nov 12 '22 21:11 maz808

Weird... I remember explicitly adding you. Sorry about that, I'll fix it!!

dbanty avatar Nov 12 '22 21:11 dbanty

@dbanty I thought you had too 🤔 I appreciate it though! Thank you!

maz808 avatar Nov 12 '22 22:11 maz808