Skip to content

Do not simplify Union at runtime? #536

Closed

Description

@ilevkivskyi

Currently unions are simplified at runtime, for example:

class B: ...
class C(B): ...
assert Union[C, B] is B

Also they are flattened, for example Union[A, Union[B, C]] evaluates to Union[A, B, C]. There are however some downsides:

  • Simplification of unions is a concept related to static types, applying it at runtime might blur the distinction between static types and runtime classes.
  • Implementation of this feature had bugs, all of them related to the fact that issublcass is only applicable to proper classes, and it is not always easy to detect those beforehand.
  • This has some (although minor) runtime costs.

On the positive side:

  • This still teaches people how unions work with subclasses
  • It may be too late to change this.

Activity

  1. gvanrossum commented on Jan 29, 2018

    @gvanrossum
    Member
  2. reinhrst commented on May 11, 2018

    @reinhrst

    I would still like to have an option to retrieve the original (unsqashed) union parameters. This has to do with doing more advanced things than just type checking with the same hints (whether this is a good idea is perhaps a different discussion).

    I'm currently trying to automatically validate json based on the python type hints at runtime. In this case:

    class A:
      x: Union[int, bool]
    

    should result in different validation rules than

    class A:
      x: int
    

    to which the current Union evaluates.

    I see that it may be hard to fix this without losing backwards-compatibility. Pep-563 may give a way around this issue in most cases, however not if the union is not used directly in the type-hint:

    IntOrBool = Union[int, bool]
    class A:
      x: IntOrBool
    
  3. gvanrossum commented on May 11, 2018

    @gvanrossum
    Member

    That's an interesting point. I have softened a bit -- I think it would be reasonable if we didn't simplify unions (as long as the == relationship still works the same).

  4. gvanrossum commented on May 17, 2018

    @gvanrossum
    Member

    So looking at the PR, it only deletes the simplification of Union[C, B] to B. It still flattens nested unions, still squashes singleton unions, and still removes redundant items. Hopefully that's enough for the typical use case (keeping Union[int, bool] in a JSON schema).

  5. ilevkivskyi commented on May 17, 2018

    @ilevkivskyi
    MemberAuthor

    Yes, I think we can keep the other simplifications (to minimise possible incompatibility) while still fix the issue with schemas.

    Also other simplifications never caused problems/complains, while issubclass() call in subclass simplification caused several bugs in the past.

  6. gvanrossum commented on May 17, 2018

    @gvanrossum
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions