I currently have:
_T_OPT = TypeVar("_T_OPT", bound=Type)
class UserInputOptional(Generic[_T_OPT]):
def __class_getitem__(cls, key: _T_OPT) -> _T_OPT:
if isinstance(key, tuple):
raise TypeError("Must only provide a single type to Optional")
return keywhich is not valid for usage like (or any other generic alias): UserInputOptional[Union[int, str]]
__class_getitem__ for figuring out type annotations, so it seems like I will have to settle for making this an alias of Union, even if it may result in unwanted multiple arguments. Only other alternative I see is writing mypy plugin and that seems a bit much.
>>> T = TypeVar("T")
>>> class Base(Generic[T]):
... __slots__ = ("__weakref__",)
...
>>> Base[T]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.6/typing.py", line 682, in inner
return func(*args, **kwds)
File "/usr/local/lib/python3.6/typing.py", line 1143, in __getitem__
orig_bases=self.__orig_bases__)
File "/usr/local/lib/python3.6/typing.py", line 978, in __new__
self = super().__new__(cls, name, bases, namespace, _root=True)
File "/usr/local/lib/python3.6/typing.py", line 137, in __new__
return super().__new__(cls, name, bases, namespace)
File "/usr/local/lib/python3.6/abc.py", line 133, in __new__
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0
>>> del Base.__slots__
>>> Base[T]
__main__.Base[~T]
>>> class Derived(Base[T]):
... __slots__ = ()
...
>>> Derived()
<__main__.Derived object at 0x7fcb99be7888>
>>> Derived().__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Derived' object has no attribute '__dict__'
>>>
bug.py:7: error: "AsyncContextManager[Any]" has no attribute "__enter__"; maybe "__aenter__"?
bug.py:7: error: "AsyncContextManager[Any]" has no attribute "__exit__"; maybe "__aexit__"?
T_Item
Hi all, I submitted a PR adding type hints to bidict, my bidirectional mapping library: jab/bidict#112
As I commented in the PR:
"""
Doesn't have to block merging, but there are a few places where I used # type: ignore internally that may actually be worth type checking. Maybe. (In many of these places though I suspect appeasing mypy would not be worth it, e.g. namedbidict and _invcls.) Open to suggestions.
One thing I had trouble with was using @typing.overload with __init__() and update(). For example, mypy rejects:
@_t.overload
def update(self, **kw: VT) -> None: ...
@_t.overload
def update(self, map: _t.Mapping[KT, VT], **kw: VT) -> None: ...
@_t.overload
def update(self, col: IterItems[KT, VT], **kw: VT) -> None: ...
def update(self, *args: MapOrIterItems[KT, VT], **kw: VT) -> None:
# (implementation here)I think this may be a current limitation in mypy, so I left those without the overloads. If someone wants to suggest an alternative, I'll be happy to take another look.
"""
Would much appreciate another pair of eyes on this if anyone is interested. bidict poses some particularly interesting type hinting challenges, so maybe several would find it interesting to review. (For example, I hit https://bugs.python.org/issue41451 and https://github.com/python/typing/issues/548#issuecomment-621571821 while working on this.)
Maybe the best way to review is to start at https://github.com/jab/bidict/blob/dev/bidict/_abc.py and then follow the suggested code review path in the header comments, focusing on the type hints. Please comment (or just react to the PR with :eyes:) if you're interested in reviewing, and I'll wait for feedback before I merge.
Thanks in advance to anyone who can help this lonely solo-maintainer make bidict's first type hints as good as can be! :heart:
Hi all,
I want to define a Callable
my function looks like -
def foo1(read: ReadClient, name: str) -> Any:
def foo2(read: ReadClient, name: str, count: int) -> Any:
def too1(write: WriteClient, name: str) -> Any:
def too2(read: WriteClient, name: str, count: int) -> Any:The function call will have the 1st positional argument as ReadClient or WriteClient and it can variable args, kwargs.
I tried something like
Callable[[ReadClient, Any, ...], Any]
Callable[[ReadClient, ...], Any]but none of the above formats work
Hence I want to define Callable somewhat like -
Callable[[ReadClient, *args: Any, **kwargs: Any], Any]
Callable[[WriteClient, *args: Any, **kwargs: Any], Any]I know the above format is incorrect, but is there a way to define a Callable where the first positional argument is ReadClient and it could take variable args/kwargs of Any type. Same would be true for WriteClient.
I tried using Protocol as -
class ReadCmdFunc(Protocol):
def __call__(self, device: ReadClient, *args: Any, **kwargs: Any) -> Any: ...
class WriteCmdFunc(Protocol):
def __call__(self, device: WriteClient, *args: Any, **kwargs: Any) -> Any: ...HOwever, mypy throws an error as -Argument 1 has incompatible type "Callable[[WriteClient, str,], Any]"; expected "WriteCmdFunc"
but my WriteCmdFunc is defined exactly as in the __call__ of WriteCmdFunc.
So not sure, what I am missing here.
I really appreciate your help.
mypy to solve a problem with nested overloades in our own plugin dry-python/returns/@curry: python/mypy#9259 I would love to hear the feedback on it! :+1:
I get a certain errror
error: "Callable[..., Any]" has no attribute "for_platform" [attr-defined]This error could be in any line in a file.
Is there a way to ignore this error from all the files using mypy config file where I say, if I get the above error in any files, just ignore it instead of having #type: ignore [attr-defined] in each file ?
Hi folks, trying to understand this result and how to fix it:
T = TypeVar('T')
def f(a: T, b: T) -> T: ...
reveal_type(f(1, '2')) # builtins.object*I assumed T to be invariant and thus either int or str. It seems that variance is taken from the function (contravariant arguments, covariant return) and T's variance being ignored.
Can I force T to be invariant here?
A but not to restrict T to some pre-determined domain. It should just be some concrete type, though I could see inference selecting something like Union[type(a), type(b)]. Definitely did not expect a generic catch-all like Any/object.
List[int] with None as default argument. I used None instead of [] to avoid this problem. When mypy complained about the type List[int] being wrong, I made it def fn(Optional[List[int]] = None) -> None: But operations inside cannot be done with None and mypy complains. How can I get around this? Can some one help me out?
This one has error.
from dataclasses import dataclass
from typing import List, Optional
class Example:
lst: List[int] = None
def __post__init__(self):
if self.lst is None:
self.lst = [1, 2, 3]
def fn(self):
if len(self.lst) < 2:
print("Aww...")
elif self.lst[1] == 2:
print("Yes")
else:
print("No")This one has no error.
def fn(lst: Optional[List[int]] = None) -> None:
if lst is None:
lst = [1, 2, 3]
if len(lst) < 2:
print("Aww...")
elif lst[1] == 2:
print("Yes")
else:
print("No")I have no idea what I'm doing wrong..
dataclass can have a factory for a field? The example in the docs is specifically for a List[int].
Hi typing folks, the following code matches https://github.com/python/typeshed/blob/master/stdlib/3/typing.pyi#L452-L457 and yet mypy complains with a few hard-to-debug errors :
# mymapping_with_overload.py
import typing as _t
KT = _t.TypeVar('KT')
VT = _t.TypeVar('VT')
class MyMapping(_t.MutableMapping[KT, VT]):
@_t.overload
def update(self, arg: _t.Mapping[KT, VT], **kw: VT) -> None: ...
@_t.overload
def update(self, arg: _t.Iterable[_t.Tuple[KT, VT]], **kw: VT) -> None: ...
@_t.overload
def update(self, **kw: VT) -> None: ...
def update(self, *args: _t.Union[_t.Mapping[KT, VT], _t.Iterable[_t.Tuple[KT, VT]]], **kw: VT) -> None:
... # implementation here (validate either 0 or 1 positional arg provided)
# more methods defined hereResults:
➜ mypy mymapping_with_overload.py
mymapping_with_overload.py:9: error: Signature of "update" incompatible with supertype "MutableMapping"
mymapping_with_overload.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 1
mymapping_with_overload.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 2
Found 3 errors in 1 file (checked 1 source file)Any ideas? Thanks for any help!
Hi @jab ,
Your code does not in fact match the typing.py code you linked, because the code you linked uses positional only arguments (python/mypy#2497), but your code allows keyword args(ie, one can do map.update(arg=some_other_map)). You should add __ to the name of the argument to make it positional only(look at the mypy issue I linked, also the typing.py code that you linked)
The last two errors also have to do with this difference. The overloaded signatures indicate one can domap.update(arg=some_other_map), but that is in fact not allowed by the signature of the implementation, where keyword arguments must be of VT type, not Mapping[KT, VT])
arg to __arg on lines 10 and 12 was all it took to fix this! This seems unusually hard to debug and Google for. Could mypy give users a more helpful error message here, given how rare it is that the problem is with the formal param name, not the actual type hints?
You're welcome @jab . From my experience, this is a problem with overloading in general, not this specific positional-only thing. In fact, if you remove the overloading and recreate the error, mypy gives a reasonable error message "unexpected keyword argument ..."
While I think error reporting for overloading can be improved, I think the mypy team has other priorities(by the look of their Github issues). I'd bet that they would be happy for a PR about it though.
FYI, I'm totally unaffiliated iwht the mypy team, I've just been following thir work kind of closely :)