Zac-HD / shed

`shed` canonicalises Python code. Shed your legacy, stop bikeshedding, and move on. Black++
https://pypi.org/project/shed/
GNU Affero General Public License v3.0
342 stars 23 forks source link

Shed can break code using runtime type annotations in python 3.9 #19

Closed danielknell closed 3 years ago

danielknell commented 3 years ago

Shed looks amazing, and i want to adopt it into some existing projects instead of the cludge of making isort/black/etc play nice each time, but i have hit a problem with python 3.9 code that uses type annotations at runtime.

the problem comes from pyupgrade and specifically this rule:

https://github.com/asottile/pyupgrade#pep-604-typing-rewrites

in short it converts:

from __future__ import annotations
import typing

def foo(bar: typing.Optional[str]) -> None:
    ...

into

from __future__ import annotations

def foo(bar: str | None) -> None:
    ...

this breaks any runtime code interpreting the types (e.g. pydantic, possibly hypothesis.infer too?) as the | format is not supported at runtime until python 3.10.

pyupgrade offers --keep-runtime-typing to prevent it doing this update, but there seems to be no way to plumb that in via shed considering pyupgrade lacks a config file?

maybe this and any other potentially dangerous pyupgrade changes could be gated behind the --refactor cli param?


i suspect there is probably a similar problem for python 3.8 and this rule:

https://github.com/asottile/pyupgrade#pep-585-typing-rewrites

Zac-HD commented 3 years ago

I see where you're coming from, but I think you shouldn't be using from __future__ import annotations if you also depend on runtime typing behaviour - both Hypothesis and Pydantic do their best, but it's inevitably lossy in some subtle but not-that-rare cases. This is why PEP-563 has been deferred from 3.10, and will probably be replaced.

So while this could be changed in shed - we already use pyupgrade internals - I think it's working correctly and the best solution is to delete the future import from your code.