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

Unable to parse schema definition with anyOf/allOf within one another

Open ajoga opened this issue 2 years ago • 1 comments

Describe the bug

Schema definition in components of combined schemas are failing to be parsed, with the following error:

Unable to parse this part of your OpenAPI document: : Invalid property in union /components/schemas/composite_object

Schema(title=None, multipleOf=None, maximum=None, exclusiveMaximum=None, minimum=None, exclusiveMinimum=None, maxLength=None, minLength=None, pattern=None, maxItems=None, minItems=None, uniqueItems=None, maxProperties=None, minProperties=None, required=None, enum=None, type=None, allOf=[Reference(ref='#/components/schemas/simple_object1'), Reference(ref='#/components/schemas/simple_object2')], oneOf=[], anyOf=[], schema_not=None, items=None, properties=None, additionalProperties=None, description=None, schema_format=None, default=None, nullable=False, discriminator=None, readOnly=None, writeOnly=None, xml=None, externalDocs=None, example=None, deprecated=None)

Surprisingly, combined schemas are correctly parsed when defined in paths : this is the uncommented part in the gist.

OpenAPI Spec File A link to an OpenAPI document which produces this issue. Ideally, write a minimal reproduction only containing the problematic pieces.

Desktop (please complete the following information):

  • OS: Amazon Linux 2
  • Python Version: 3.11.5
  • openapi-python-client version 0.15.2

ajoga avatar Oct 05 '23 10:10 ajoga

I believe the problem has to do with the deferred way in which model schemas are resolved.

The parser processes the schemas section in two passes. In the first pass, it creates an object (like ModelProperty) corresponding to each schema, and builds an index of their names, but doesn't fully try to fill in the details as it goes— since those may depend on references to other schemas that it hasn't seen yet. In the second pass, it revisits the things that it hasn't filled in yet (in the current implementation, it only does this for object types, i.e. ModelProperty).

What's happening here, I think, is that the logic for building a union type (anyOf) incorrectly expects that everything can be resolved in the first pass. When it looks at the types in the anyOf list, it expects them to all be in their fully-filled-in state, but they're not.

The reason it works for an equivalent schema in paths is that the parser doesn't try to process anything in paths until it has already done both passes on schemas.

eli-bl avatar Sep 19 '24 22:09 eli-bl