Hi, I'm adding type hints to unwrapping proxy class but it's getting difficult.
I got eudplib\core\rawtrigger\constenc.py:304: error: Incompatible return value type (got "Union[int, EUDVariable, ConstExpr, ExprProxy[Any]]", expected "Union[int, EUDVariable, ConstExpr]") [return-value]
T_co = TypeVar("T_co", covariant=True)
class ExprProxy(Generic[T_co]):
def __init__(self, initval: T_co) -> None:
self._value: T_co = initval
def getValue(self) -> T_co:
return self._value
T = TypeVar("T")
@overload
def unProxy(x: "ExprProxy[T]") -> T:
...
@overload
def unProxy(x: T) -> T:
...
def unProxy(x):
while isinstance(x, ExprProxy):
x = x.getValue()
return x
def _EncodeConst(
t: str, d: dict[_Unique, int], s: "int | _Unique | EUDVariable | ConstExpr | ExprProxy"
) -> "int | EUDVariable | ConstExpr":
u = unProxy(s)
if isinstance(u, _Unique):
if u in d:
return d[u]
raise EPError(_('[Warning] "{}" is not a {}').format(u, t))
return u
unProxy
can return any object except ExprProxy
but apparently mypy can't understand this although I tried using TypeVar
to hint this. Should I add type: ignore[return-value]
on every functions which accepts proxy class?
Hi everyone! I hope I might be in the right chat. I'm having some trouble with getting mypy to work correctly on my project.
It's a Django project with restframework. All the necessary setup (stubs, plugins, etc) is done and works correctly.
The issue is with another installed module - restframework_simplejwt. This package does not appear to have types configured; I don't even import anything directly, but I assume mypy is checking it because it's in my Django INSTALLED_APPS and the Django plugin probably typechecks those.
So logically I am getting a Skipping analyzing "rest_framework_simplejwt.token_blacklist.models": module is installed, but missing library stubs or py.typed marker
error. This should not be a big deal to fix as I can easily type that single file and make the error go away. The issue is how can I type it in a way that integrates with CI/CD.
Basically, I created a stub file - but I can't have it inside the package file (that is installed trough pip) - it should be somewhere inside the project structure. Reading the documentation, I should perhaps change the MYPYPATH variable to point to whichever folder has this file (which I assume has to keep the rest_framework_simplejwt/token_blacklist/models.pyi file path?). The problem is that changing the MYPYPATH variable makes the Django plugin stop working (I believe it starts looking for the "app.settings" file from the MYPYPATH).
Any clue on how I can go about this?
This brings me to a new question: writting a stub, how can I indicate that something has the type of a class in another file?
For example, I have the following project structure:
app
- foo.py
- bar.py
stubs
- bar.pyi
The foo.py looks like this
class Foo:
pass
The bar.py look like this:
from foo import Foo
foo = Foo()
The bar.pyi file should look like this:
from foo import Foo
foo: Foo
But that throws an error: Cannot find implementation or library stub for module named "foo"
Does anyone have resources on the workings of mypy plugins? For my own dark reasons, I want to generate a django model from another object using the type function.
MyType = type('MyType', (models.Model,), namespace_mapped_from_some_other_object())
instance = MyType()
That works, but I'm trying to get mypy to recognise instance
as an instance of the MyType
class. From what I can gather, I'm supposed to use a plugin with get_dynamic_class_hook
, which fires for the fullname module.MyType
, but I'm struggling to make head or tail of the requirements.
not sure where the best place to put this is, but reporting a potential mypy bug:
given this preamble
from typing import Union, Dict, Optional, List, TypeAlias, TypeVar
U = TypeVar("U")
V = TypeVar("V")
the following code typechecks:
_TreeNode: TypeAlias = Union[
Dict[U, "_TreeNode[U, V]"], List["_TreeNode[U, V]"], V
]
but the following code fails with INTERNAL ERROR: maximum semantic analysis iteration count reached
:
_TreeNode: TypeAlias = Union[
Dict[U, Optional["_TreeNode[U, V]"]], List[Optional["_TreeNode[U, V]"]], V
]
is this a bug, or am I abusing python types?
class Middleware(Protocol):
def __call__(
self,
__next_resolver: Resolver,
__parent: Any,
__info: GraphQLResolveInfo,
) -> Any:
...
class Middleware(Protocol):
def __call__(
self,
__next_resolver: Resolver,
__parent: Any,
__info: GraphQLResolveInfo,
**kwargs: Any,
) -> Any:
...
Hi I'm having sending a file as a parameter to pickle.load
. I get this error
conver_pickle.py:2: error: Argument 1 to "load" has incompatible type "TextIOWrapper"; expected "_ReadableFileobj" [arg-type]
While the code is :
with open(pickle_filename, 'r') as file:
data = pickle.load(file) # type: typing.TextIO
I'm not sure what is going on and why Readable FileObj doesn't cover TextIOWrapper or if I need to add a different hint
asyncio.create_datagram_endpoint
accepts either an (address, port) tuple or a str for its local_addr
argument, depending on if the family
parameter is set to AF_UNIX
or not (at least, since around python 3.7 when the ability to use unix sockets was added to this function). However, this possibility isn't represented in typeshed as far as I can tell: https://github.com/python/typeshed/blob/main/stdlib/asyncio/base_events.pyi#L345
family
argument? or would it be appropriate to just add str to the union?
Hi, I'm wondering if someone can help me figure out the correct types for this series of classes.
from abc import ABC, abstractmethod
from typing import TypeVar
T = TypeVar("T", bound="A")
U = TypeVar("U", bound="ThirdPartyClass")
class ThirdPartyClass:
"""
This is from a third-party library and I don't control the implementation.
"""
@classmethod
def create(cls: type[U]) -> U:
return cls()
class A(ABC):
@classmethod
@abstractmethod
def f(cls: type[T]) -> T:
pass
class B(ThirdPartyClass, A):
@classmethod
def f(cls) -> T:
return cls.create()
Mypy errors on the last two lines with
error: A function returning TypeVar should receive at least one argument containing the same Typevar
error: Incompatible return value type (got "B", expected "T")
Those don't seem right to me, but I don't know how to fix them.
Good day, I'm trying to provide better type annotations for native library (OpenCV) wrapped in Python package using stub files and facing strange behavior when trying to validate stubs using mypy.stubtest
and during package usage.
Consider the following toy example:
Package structure:
. geometry
|- typing
| `- __init__.pyi
|- geometry.cpython-39-x86_64-linux-gnu.so
|- __init__.py
|- __init__.pyi
`- py.typed
Stub files have the following content:
geometry/typing/__init__.pyi
import geometry
import typing
Point = tuple[int, int]
Primitive = geometry.Circle | geometry.Rect
Primitives = typing.Sequence[Primitive]
geometry/__init__.pyi
import geometry.typing
class Circle:
center: geometry.typing.Point
radius: int
def __init__(self, center: geometry.typing.Point, radius: int): ...
class Rect:
top_left: geometry.typing.Point
width: int
height: int
def __init__(self, top_left: geometry.typing.Point, width: int, height: int): ...
def calculate_union_area(primitives: geometry.typing.Primitives) -> float: ...
geometry/__init__.py
from .geometry import Circle, Rect, calculate_union_area
Running mypy.stubtest
via: python -m mypy.stubtest geometry
gives the following output:
error: not checking stubs due to mypy build errors:
geometry/__init__.pyi:4: error: Name "geometry.typing.Point" is not defined [name-defined]
geometry/__init__.pyi:7: error: Name "geometry.typing.Point" is not defined [name-defined]
geometry/__init__.pyi:10: error: Name "geometry.typing.Point" is not defined [name-defined]
geometry/__init__.pyi:14: error: Name "geometry.typing.Point" is not defined [name-defined]
geometry/__init__.pyi:16: error: Name "geometry.typing.Primitives" is not defined [name-defined]
If I try to use types from geometry.typing
in external file:
import geometry
import geometry.typing
from geometry.typing import Point
def foo(pt: Point) -> None:
print(pt)
foo((1, 2))
foo(('bar', 31))
def baz(primitives: geometry.typing.Primitives) -> None:
print(len(primitives))
baz([geometry.Circle([0, 0], 3)), geometry.Rect((1, 2), width=10, height=10)])
Type hints and autocompletion from pylance and pyright language servers are working as expected.
Invoking mypy as python -m mypy --strict --follow_imports_for_stubs main.py
on above example again gives an error regarding usage of geometry.typing.Primitives
annotation: Name "geometry.typing.Primitives" is not defined [name-defined]
, but resolves Point
name and even its type complaining about wrong usage in foo(('bar', 31))
.
Versions:
mypy version: 0.991
python version: 3.10.9
NOTE: Changing geometry.typing.__init__.pyi
to geometry.typing.__init__.py
with
import typing
if typing.TYPE_CHECKING:
# same content goes here
does nothing - errors are still there.
NOTE: Using from geometry.typing import Name
form is not the case, because in the real package there might be name collisions between modules.
NOTE: Using from geometry.typing import Name as geometry_typing_Name
form is not the case too, because it looks ugly and apart from that it is a crutch to resolve possible mypy checker issue.
So, the question is the following:
Is there any flag to make mypy happy with such names or it is expected bahvoir or a bug?
geometry.typing.Primitives
which does seem like a bug
stubtest
checks that all types and functions accessible in runtime are present in stub files. The actual function (methods) interfaces are kind of out of scope for this check, because, as far as I know, it is impossible to precisely derive function arguments type from native code (e.g. custom conversion rules). If object exists at type checking type it should be totally fine, shouldn't it?mypy
when he/she passes wrong arguments (as pointed in example) when using package-qualified name instead of direct import. This is true for both library and user functions.import httpx
from pydantic import BaseModel
class X(BaseModel):
abc: list[str]
x: str = await httpx.get('someURL').json()['someKey'] # x is now a str
tunnel_info: dict[str, X | None]
tunnel_info[x] = None
if tunnel_info[x] is None:
tunnel_info[x] = X(abc=['hello'])
tunnel_info[x].abc.append('jonas')
This raises error: Item "None" of "Optional[X]" has no attribute "abc" [union-attr]
.I'm getting a bit confused with some TypeVar stuff that I'm finding hard to give a headline summary of.
I have a TypeVar("Var", A, B)
and a function with argument some_var: Type[Var]
Being called with an argument that is Type[A] | Type[B]
and mypy is not happy.
After playing around a bit I'm unsure if there are 2 separate issues related to whether I'm using bound
or not, and also whether I'm using Type
or not, OR whether I've got a more fundamental misunderstanding of whats going on.
Here's the mypy-play which hopefully makes things clearer
https://mypy-play.net/?mypy=latest&python=3.11&gist=664ac4f67d5887022fa879d6478a0952
Hi all, I'm having a code like this:
from typing import Iterable, TypeVar, Generic
from multimethod import multimethod
from abc import ABC
from types import GenericAlias
T = TypeVar("T")
class MyIterable(ABC, Generic[T]):
@classmethod
def __subclasshook__(cls, subclass):
return issubclass(subclass, Iterable) and not issubclass(subclass, str)
def __class_getitem__(cls, key):
return GenericAlias(cls, key)
@multimethod
def validate_enum_list(key: str, value: str, allowed_values: MyIterable[str]) -> None:
print("key: str, value: str, allowed_values: MyIterable[str]")
print(type(value))
print(type(allowed_values))
@validate_enum_list.register
def _(key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]) -> None:
print("key: str, value: List[str], allowed_values: MyIterable[MyIterable[str]]")
print(type(value))
print(type(allowed_values))
value = sorted(value)
allowed_values = sorted([sorted(item) for item in allowed_values])
validate_enum_list("test1", "test1", ["test1"])
validate_enum_list("test2", ["test2"], [["test2"]])
validate_enum_list("test1", "test1", [["test1"]])
and the problem with mypy is that it returns me this errors:
multi2.py:29: error: No overload variant of "sorted" matches argument type "MyIterable[str]" [call-overload]
multi2.py:29: note: Possible overload variants:
multi2.py:29: note: def [SupportsRichComparisonT] sorted(Iterable[SupportsRichComparisonT], /, *, key: None = ..., reverse: bool = ...) -> List[SupportsRichComparisonT]
multi2.py:29: note: def [_T] sorted(Iterable[_T], /, *, key: Callable[[_T], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]], reverse: bool = ...) -> List[_T]
multi2.py:30: error: Incompatible types in assignment (expression has type "List[List[Any]]", variable has type "MyIterable[MyIterable[str]]") [assignment]
multi2.py:30: error: "MyIterable[MyIterable[str]]" has no attribute "__iter__" (not iterable) [attr-defined]
Found 3 errors in 1 file (checked 1 source file)
So am I suppoused to overload sorted method with MyIterable
? Shouldn't It be working automatically? Another thing is why mypy is complaining about __iter__
if MyIterable
has defined __class_getitem__
?
__iter__
. Then sorted should also work.
--disallow-any-expr
in that mypy
(version 0.971) resolves this strictly local variable to Any
but, well, it was just assigned a known type. I can't find anything about this in the docs for the above option. Is this working as intended? def test_header_values_properly_converted_to_str(self, _: MockedEntity):
f = CdcMessageFixtures(self)
tests/processors/messages/test_cdc_message.py:66: error: Expression has type "Any" [misc]
f = CdcMessageFixtures(self)
import typing as t
class A:
a = 1
class B:
a = 2
VarBound = t.TypeVar('VarBound', bound=A | B)
def init_bound_type(var: t.Type[VarBound]) -> VarBound:
return var() # error: Incompatible return value type (got "Union[A, B]", expected "VarBound")
VarExact = t.TypeVar('VarExact', A, B)
def init_exact_type(var: t.Type[VarExact]) -> VarExact:
return var()
Hi all, I'm having a code like this:
from typing import Iterable, TypeVar, Generic from multimethod import multimethod from abc import ABC from types import GenericAlias T = TypeVar("T") class MyIterable(ABC, Generic[T]): @classmethod def __subclasshook__(cls, subclass): return issubclass(subclass, Iterable) and not issubclass(subclass, str) def __class_getitem__(cls, key): return GenericAlias(cls, key) @multimethod def validate_enum_list(key: str, value: str, allowed_values: MyIterable[str]) -> None: print("key: str, value: str, allowed_values: MyIterable[str]") print(type(value)) print(type(allowed_values)) @validate_enum_list.register def _(key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]) -> None: print("key: str, value: List[str], allowed_values: MyIterable[MyIterable[str]]") print(type(value)) print(type(allowed_values)) value = sorted(value) allowed_values = sorted([sorted(item) for item in allowed_values]) validate_enum_list("test1", "test1", ["test1"]) validate_enum_list("test2", ["test2"], [["test2"]]) validate_enum_list("test1", "test1", [["test1"]])
and the problem with mypy is that it returns me this errors:
multi2.py:29: error: No overload variant of "sorted" matches argument type "MyIterable[str]" [call-overload] multi2.py:29: note: Possible overload variants: multi2.py:29: note: def [SupportsRichComparisonT] sorted(Iterable[SupportsRichComparisonT], /, *, key: None = ..., reverse: bool = ...) -> List[SupportsRichComparisonT] multi2.py:29: note: def [_T] sorted(Iterable[_T], /, *, key: Callable[[_T], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]], reverse: bool = ...) -> List[_T] multi2.py:30: error: Incompatible types in assignment (expression has type "List[List[Any]]", variable has type "MyIterable[MyIterable[str]]") [assignment] multi2.py:30: error: "MyIterable[MyIterable[str]]" has no attribute "__iter__" (not iterable) [attr-defined] Found 3 errors in 1 file (checked 1 source file)
So am I suppoused to overload sorted method with
MyIterable
? Shouldn't It be working automatically? Another thing is why mypy is complaining about__iter__
ifMyIterable
has defined__class_getitem__
?
I have few more questions if I'm having additional functions which are calling validate_enum_list e.g.:
def get_enum_str(key: str, value: str, allowed_values: MyIterable[str]) -> None:
validate_enum_list(key, value, allowed_values)
print("get_enum_str")
def get_enum_str_list(key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]) -> None:
validate_enum_list(key, value, allowed_values)
get_enum_str("test1", "test1", ["test1"])
get_enum_str_list("test2", ["test2"], [["test2"]])
get_enum_str_list("test2", ["test2"], [["test2", "tkip", "ccmp"]])
I'm getting this mypy errors:
multi2.py:51: error: Argument 3 to "get_enum_str" has incompatible type "List[str]"; expected "MyIterable[str]" [arg-type]
multi2.py:52: error: Argument 2 to "get_enum_str_list" has incompatible type "List[str]"; expected "MyIterable[str]" [arg-type]
multi2.py:52: error: Argument 3 to "get_enum_str_list" has incompatible type "List[List[str]]"; expected "MyIterable[MyIterable[str]]" [arg-type]
multi2.py:53: error: Argument 2 to "get_enum_str_list" has incompatible type "List[str]"; expected "MyIterable[str]" [arg-type]
multi2.py:53: error: Argument 3 to "get_enum_str_list" has incompatible type "List[List[str]]"; expected "MyIterable[MyIterable[str]]" [arg-type]
Does anyone know how may I solve that mypy could verify statically that MyIterable[str] is any type of Iterable without str?
Hey folks, I'm new here, just wondering if what I'm seeing is a bug in mypy or a bug in my understanding.
I've got a function that returns a tuple containing a bool as the first element and, if that bool is True
, an int
as the second element . If the bool is False
, the second position is None
instead.
The naive type for that would be something like tuple[bool, Optional[int]]
, but that's not strictly correct: it's more like Union[tuple[Literal[True], int], tuple[Literal[False], None]]
. When I try using the latter type, though, mypy
seems to break it down into the former.
I've got a minimal example here which shows this:
import random
from typing import Literal, Union
def check_type_variant() -> Union[
tuple[Literal[True], int], tuple[Literal[False], None]
]:
if random.random() > 0.5:
return True, 1
return False, None
is_int, maybe_int = check_type_variant()
if is_int:
maybe_int += 1
and mypy produces the following output:
example.py:15: error: Unsupported operand types for + ("None" and "int") [operator]
example.py:15: note: Left operand is of type "Optional[int]"
Found 1 error in 1 file (checked 1 source file)
res=check_type_variant()
if res[0]:
...
Incompatible return value type (got "int", expected "slice")
. Is there a way to make it type check?from typing import TypeVar, Union
Idx = TypeVar("Idx", int, slice)
# Idx = Union[int, slice]
def incr(obj: Idx, delta: int) -> Idx:
if isinstance(obj, int):
return obj + delta
else:
return slice(obj.start + delta, obj.stop + delta)
def negate(i: int) -> int:
return -i
def reverse(s: slice) -> slice:
return slice(s.stop - 1, s.start - 1, -1)
def test() -> None:
negate(incr(5, 3))
reverse(incr(slice(5, 10), 3))
According to PEP 673 this code should work:
from typing import Self
class Shape:
def difference(self: Self, other: Self) -> float:
return 0
"Note that specifying self: Self is harmless, so some users may find it more readable to write" as above.
But I'm getting the error:
testTypeHintingSelf.py:4: error: Variable "typing.Self" is not valid as a type [valid-type]
def difference(self: Self, other: Self) -> float:
^
testTypeHintingSelf.py:4: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
Am I doing something wrong, or is mypy not checking Self
correctly?
(I understand the first Self is not needed, but according to the PEP it should be allowed, and I like it for consistency).
(I'm running Python 3.11.1 on Windows with mypy 0.991)
Hi, I get the following error (no-redef
) when running mypy against this code snippet:
import json
import os
class A:
def __init__(self, file: str = "file.json"):
if os.path.isfile(file):
with open(file, 'r') as f:
self.data: dict = json.load(f)
else:
self.data: dict = {"random_data": "asdf"}
Received error message:
script.py:11: error: Attribute "data" already defined on line 9 [no-redef]
Found 1 error in 1 file (checked 1 source file)
Can anyone else confirm if this is a bug?
self.data: dict
and then remove the type hint on both assignment lines
TypeVar("IntOrStr", int, str)
and TypeVar("IntOrSlice", int, slice)
at https://mypy-play.net/?mypy=latest&python=3.11&gist=71d1dd4d4d02e5427cc55a4d6e573280? Why does the second may have <subclass of "slice" and "int">
revealed type but the first one doesn't? By the way at runtime both attempts to extend from these two pairs of classes raise TypeError
:In [6]: class IntOrStr(int, str):
...: pass
TypeError: multiple bases have instance lay-out conflict
In [7]: class IntOrSlice(int, slice):
...: pass
TypeError: type 'slice' is not an acceptable base type