Open dairiki opened 2 months ago
Running this code raises a type error:
python3 asdf.py
Traceback (most recent call last):
File "/pylint/asdf.py", line 9, in <module>
x2: Alias2[int] # <= triggers E1126 (invalid-sequence-index)
~~~~~~^^^^^
TypeError: string indices must be integers, not 'type'
So this looks like a true positive, i.e. Pylint is behaving correctly by warning about an actual error.
Running this code raises a type error: So this looks like a true positive, i.e. Pylint is behaving correctly by warning about an actual error.
My apologies, you're right. I oversimplified my failure test case. It fails without PEP563 deferred evaluation of annotations.
(I.e. it needs a from __future__ import annotations
.)
Try this one:
# pylint: disable=missing-docstring
from __future__ import annotations
from typing import TypeAlias, TypeVar
T = TypeVar("T")
Alias1: TypeAlias = list[T]
Alias2: TypeAlias = "list[T]"
x1: Alias1[int] # ok
x2: Alias2[int] # <= triggers E1126 (invalid-sequence-index)
To add motivation as to why one might want to do this, here's a slightly less contrived example that fails pylint validation the same way:
# pylint: disable=missing-docstring,too-few-public-methods
from __future__ import annotations
from typing import Generic, TypeAlias, TypeVar
T = TypeVar("T")
MaybeWrapped: TypeAlias = "Wrapped[T] | T"
class Wrapped(Generic[T]):
value: T
def __init__(self, v: MaybeWrapped[T], /) -> None: # <= triggers E1126
self.value = v.value if isinstance(v, Wrapped) else v
Thanks, I see the problem now. Looks like Pylint thinks the TypeAlias
is just a string? TBH I don't understand how the string-as-annotation system works. Mypy accepts it fine.
As a workaround, you could work around the bug by moving MaybeWrapped
after Wrapped
and not using string-as-annotation:
from __future__ import annotations
from typing import Generic, TypeAlias, TypeVar
T = TypeVar("T")
class Wrapped(Generic[T]):
value: T
def __init__(self, v: MaybeWrapped[T], /) -> None: # <= triggers E1126
self.value = v.value if isinstance(v, Wrapped) else v
MaybeWrapped: TypeAlias = Wrapped[T] | T
Or in 3.12, you can avoid all that mess by using the type
keyword:
from __future__ import annotations
type MaybeWrapped[T] = Wrapped[T] | T
class Wrapped[T]:
value: T
def __init__(self, v: MaybeWrapped[T], /) -> None:
self.value = v.value if isinstance(v, Wrapped) else v
Bug description
Configuration
No response
Command used
Pylint output
Expected behavior
Should not emit warning.
I've also tested with pylint from the head of the main branch (eb33f8a6c0d).
Pylint version
OS / Environment
Ubuntu 22.04
Additional dependencies
No response