Conversation
…ther unions, as long as everything flattens down to all primitives or all models
| computed = ctx.field_computed | ||
| inner_serializers: List[Serializer] = [] | ||
| for choice_schema in schema['choices']: | ||
| choice_schemas = _flatten_choice_schemas(schema['choices']) |
There was a problem hiding this comment.
I was not the biggest fan of having to call this both in the module level from_core_schema and in both of the classmethods here, but I did not want to mutate schema. If it's ok to do that I could make this a bit less redundant. Alternatively I could pass in the flattened schemas as an extra argument.
There was a problem hiding this comment.
I think it is ok to mutate the schema in the outer from_core_schema as far as we keep it correct. But it is better to deepcopy it before since we don't know how it could affect pydantic itself.
There was a problem hiding this comment.
Sounds good, I have reworked it to mutate a deepcopy of the schema and pass that flattened schema along to the serializers
| raise AssertionError("unreachable") | ||
|
|
||
|
|
||
| def _flatten_choice_schemas(choice_schemas): |
There was a problem hiding this comment.
it seems like this procedure must be recursive since the union nesting level can be not only 2, but 3, 4 ...
There was a problem hiding this comment.
I believe this is covered with no recursion because when a union choice is found its choices are added to the same list the while loop is using, so it continues until everything is flattened, but I did discover I had missed a case where a choice is a definition-ref, is that what you meant? I updated a test case to include an additional level and added looking up definition-refs. Let me know if you think I'm missing something else here.
…alizers rather than call _flatten_choice_schemas multiple times. cover the case where a choice is a 'definition-ref'
The checks on union choices do not allow for unions that contain other unions, even if those unions when flattened would still be all-primitive or all-model. For example in our project we have a set of response codes in an XML schema we are modeling using this library:
Base Pydantic handles a field of type
Request1Codesfine, but pydantic-xml does not:I modifed
union.pyto flatten union choices down when they consist of other unions so that the check on whether the union is not a mix of primitives and models still happens, but it no longer rejects a union that contains another union.For anyone else running into this, a workaround is just to manually flatten your unions, ie the example above becomes:
but this has the downside of requiring duplication (for us
CommonCodesis quite a bit larger and reused extensively) and not exactly matching your schema, plus not everyone has control over the types they are modeling.