sourcery
sourcery copied to clipboard
Simplify `Union` type annotations
Issue description or question
Hi again! It would be awesome if Sourcery were able to simplify Unions in type annotations, just like described in the docs. There would be a number of possible refactorings here:
- Flattening unions:
Union[int, Union[str, float]]→Union[int, str, float] - Simplifying single-type unions:
Union[int]→int - Skipping redundant types:
Union[int, int, str, int]→Union[int, str] - Suggesting
Optional:Union[None, int]→Optional[int]Union[None, int, float]→Optional[Union[int, float]]
Note: when suggesting Optional, it is important to add from typing import Optional, and also to make sure that this newly imported name does not clash with user-defined classes named Optional... Perhaps it is better to avoid this case for now.
Another example of refactoring (although a lot more complex to get right) is simplifying "subtypes":
Union[int, bool]→int(since everyboolis anint)Union[List[bool], Sequence[int]]→Sequence[int](since everyListis aSequence, they are covariant types and everyboolis anint)
Note: Perhaps it is better to avoid those refactorings as well, for now :grimacing:
Given all of those refactoring options, the following piece code:
from typing import Union
def f(x: Union[int, Union[None, bool]]) -> Union[int, Union[int]]:
...
would be refactored as:
from typing import Optional, Union
def f(x: Optional[int]) -> int:
...
Sourcery Version
0.9.4
Code editor or IDE name and version
VS Code 1.60.0 (x64)
OS name and version
Ubuntu 20.04.3 LTS
Nice suggestions!
A consequence from the subtype simplification is that Unions with Anys always result in Any:
Union[Any, <whatever>]→Any
Hard mode: piped types using py3.10's unions where str | int == Union[str, int]
Ideally this would be a setting per-project, somehow. I wouldn't want my 3.8+ lib to use 3.10 features such as this, but I'd like my 3.10 projects to take advantage of this.