-
Notifications
You must be signed in to change notification settings - Fork 1
eng: fix bug in type generation for nullable/union props BNCH-111776#219
eng: fix bug in type generation for nullable/union props BNCH-111776 #219
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.
The changes in this file are just to cut out some test cases that I moved into test_unions.py, because ultimately the issue isn't about the enum itself, it's about the union type (created either explicitly with oneOf, or implicitly by adding "null" as an allowable type).
40702a8 to
8059d24
Compare
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.
This was one of the cases affected by the bug. In the new version of this test that's in test_unions.py, the model class name is correctly rendered as MyEnumIncludingNull.
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 some nicer failure output. In a case like the one I mentioned above, where the generator has created an incorrect type name, if you try to import NameOfThing you'll see something like:
AssertionError: Couldn't find import "NameOfThing" in "testapi_client.models". Available imports in that module are: NameOfThingType0, SomeOtherType, [etc.]
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.
An example of the effect that the bug was having on the reference code in the "golden record"-based tests, causing "Type0" and "_type_0" suffixes to be added for no good reason.
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.
This is for a simple case where the schema is just like:
MyType:
type: ["string", "integer"]
That's equivalent in meaning to anyOf: [{type: string}, {type: int}], so on lines 84-85 we convert it into those explicit variant types. However, if there was redundantly an anyOf or oneOf and a multiple type:, then we do not want to do that, because the variants that are described in the anyOf/oneOf list already fully describe the possible types. For instance:
MyType: type: ["string", "integer"] oneOf: - type: string format: date-time - type: integer default: 3
In that example, prior to my fix, the union would've ended up having four variants instead of two.
8059d24 to
b92fed6
Compare
c4dda2c to
f4d3735
Compare
@damola-benchling
damola-benchling
left a comment
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.
the fix generally looks good at a high level but - I did struggle a bit to finally wrap my head around the implementation. If we can simplify it, that would be great, but at least I think the comment should have an example illustration
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.
It took me a minute to really understand the logic of the two-pass loop in process_items
In addition to (or in place of) this comment block here, I think an example-based description of what this code is doing might be better.
Also, would it be possible to use some sort of lookup to track the schema, and then the single name schema gets updated at the end of the loop if only one named schema was encountered 🤔
I'm not sure if that will be necessarily easier/shorted to read than the current implementation but I think the two loops is more on the less-trivial scale.
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.
Also, would it be possible to use some sort of lookup to track the schema, and then the single name schema gets updated at the end of the loop if only one named schema was encountered
Unfortunately no, that's not possible. I mentioned the reason for this when we talked, but I should clarify it in the comment too: there are maps in schemas that already contain references to the processed classes by name, so we can't just modify one object in place.
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.
ahhh yes, I remember you mentioning it, but I think I hadn't grokked the code enough to fully understand.
Uh oh!
There was an error while loading. Please reload this page.
This is equivalent to my upstream PR openapi-generators#1121. I described the symptoms in detail in openapi-generators#1120, but basically this was a problem that happened with certain patterns of using "oneOf" or "nullable" with an enum, or with an anonymous object schema that was declared inline. The symptom was that it would add spurious suffixes like "Type1" to the class name, and/or generate extra duplicates of the class.
Why we need this fix: we have patterns like this in our API. We fixed the bug in a different, no-longer-applicable way in our old fork.
The main difference between this and my upstream PR is that I was able to use the new functional test framework to verify that the right classes are generated in various slightly different permutations of the problem scenarios.