-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/detect discriminator bnch 49688 #143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a minor style change requested. I'll let @bowenwr be the blocking reviewer on this.
@@ -317,6 +317,11 @@ def build_model_property( | |||
optional_properties.append(prop) | |||
relative_imports.update(prop.get_imports(prefix="..")) | |||
|
|||
discriminator_mappings: Dict[str, Property] = {} | |||
if data.discriminator is not None: | |||
for k, v in (data.discriminator.mapping if data.discriminator else {}).items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this since the above line checks data.discriminator is not None?
for k, v in (data.discriminator.mapping if data.discriminator else {}).items(): | |
for k, v in data.discriminator.mapping.items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, good catch, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, good catch, thanks!
Well, hmm. I think I had that there because data.discriminator
might be {"mapping": None}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If {"mapping": None}
then this will still return None
since the check is on data.discriminator
right?
May be worth a closer look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have something like this in mind:
from openapi_python_client.schema import Discriminator, Schema
data = Schema(discriminator=Discriminator(propertyName="resourceType"))
>>> data.discriminator is None
False
>>> data.discriminator.mapping is None
True
>>> [(k,v) for k,v in data.discriminator.mapping.items()]
*** AttributeError: 'NoneType' object has no attribute 'items'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your intent makes sense.
To make your code match your intent I think you need to change the code from:
(data.discriminator.mapping if data.discriminator else {}).items():
to:
(data.discriminator.mapping if data.discriminator.mapping is not None else {}).items():
or:
(data.discriminator.mapping or {}).items():
alternatively you could replace both checks with EAFP
try:
for k, v in data.discriminator.mapping.items():
discriminator_mappings[k] = Reference.from_ref(v)
except AttributeError:
# Either data.discriminator or data.discriminator.mapping was not set
pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right indeed, thanks! hopefully fixed this.
It just needs to be landed first right? Or is there some other dependency I'm missing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please update this PR and/or the related aurelia PR with an example of before/after for code gen? It helps immensely to understand the change and its possible implications.
It might be in Slack already but there are some looooong threads in there and I'd rather centralize PRs are the source of truth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding context from Data Interfaces Office hours today in case this doesn't land before I'm OOO.
The core requirement is that when a user accesses a discriminated class, they receive the concrete discrimated type (and not a composite type).
One suggested implementation is that union classes shouldn't exist as class
but as Union
types.
So ideally something like:
InaccessibleResource = Union[Entity, InaccessibleResource]
Entity = Union[AaSequence, CustomEntity, DnaSequence, ...]
When deserialized in the SDK, you would receive the concrete class.
So as a user I would never receive a InaccessibleResource
, I would receive a CustomEntity
or InacessibleResource
The main impediment is here is that it breaks compatibility, as some users have resorted to their own type detection for classes like Entity
to try to make it work. Although we could say this is unsupported and are willing to "break" the workaround, there's hesitation to do so because of previous customer pushback on "broken" releases.
I suggested that the main priority is satisfying the requirement. We should time box a compatibility investigation to see if there's some small, reasonable thing we might be able to do could help here.
Finally, get sign off for dev advocacy on any "breaking" changes, even if the breakage affects workarounds.
Capture the
discriminator
property and mappings when parsing the OpenAPI spec.See more extensive notes in the PR for aurelia.
The timing of merging this PR needs to be synchronized with the merge of the
aurelia
PR.Effect on generated code
This effect requires changes from two PRs working together
discriminator_property
anddiscriminator_mappings
extracted fromopenapi.yaml
into aModelProperty
instance.Before example
After example