'Using python code typed with ParamSpec on older versions of Python
So, I was writing an event emitter class using Python.
Code currently looks like this:
from typing import Callable, Generic, ParamSpec
P = ParamSpec('P')
class Event(Generic[P]):
def __init__(self):
...
def addHandler(self, action : Callable[P, None]):
...
def removeHandler(self, action : Callable[P, None]):
...
def fire(self, *args : P.args, **kwargs : P.kwargs):
...
And while it works good in Python 3.10 (on my machine), it fails in Python 3.9 and older (on other machines) because ParamSpec is a new feature.
So, how could I not import ParamSpec when running program, while not confusing typing in editor (pyright)?
Solution 1:[1]
I don't know if there was any reason to reinvent the wheel, but typing_extensions module is maintained by python core team, supports python3.7 and later and is used exactly for this purpose. You can just check python version and choose proper import source:
import sys
if sys.version_info < (3, 10):
from typing_extensions import ParamSpec
else:
from typing import ParamSpec
Solution 2:[2]
This could be solving by wrapping from typing import ... into if TYPE_CHECKING:
if TYPE_CHECKING:
from typing import Callable, Generic, ParamSpec
else:
# Fake ParamSpec
class ParamSpec:
def __init__(self, _):
self.args = None
self.kwargs = None
# Base class to be used instead Generic
class Empty:
pass
# Thing what returns Empty when called like Generic[P]
class _Generic:
def __getitem__(self, _):
return Empty
# Callable[anything] will return None
class _Callable:
def __getitem__(self, _):
return None
# Make instances
Callable = _Callable()
Generic = _Generic()
... code
if not TYPE_CHECKING:
# To allow usage of
# evt : Event[[int, str]]
# Store existing Event class
_Event = Event
class FakeEvent:
# Event(...) calls original constructor
def __call__(self, *args, **kwds):
return _Event(*args, **kwds)
# Event[...] returns original Event
def __getitem__(self, _):
return _Event
# Replace Event class
Event = FakeEvent()
This allows code to be run with older versions of Python while using typing from 3.10 in the editor.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | SUTerliakov |
| Solution 2 |
