You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you have a question about a behavior that you’re seeing in pyright, consider posting to the Pyright discussion forum.
Is your feature request related to a problem? Please describe.
#10351 disallows namedtuple members whose names start with an underscore (_), but consider the following case:
fromcollectionsimportnamedtuplefromtypingimportTYPE_CHECKING, NamedTupleifnotTYPE_CHECKING:
# Import from extension moduleFoo=namedtuple("Foo", ["_0", "_1", "_2"], rename=True)
else:
# Provide type annotations (i.e., `.pyi` files)classFoo(NamedTuple):
_0: int_1: int_2: int# work normallyfoo=Foo(_0=0, _1=1, _2=2)
print(foo[0])
print(foo._0)
I know that for typing.NamedTuple, member names starting with an underscore are not allowed anyway. However, collections.namedtuple does allow this (with rename=True).
In my use case, I do have a namedtuple with members prefixed by _ (for example, imported from an extension module), and I want to provide type annotations for it (as you would in a .pyi file). This used to work fine, but after #10351, pyright rejects this pattern.
I know I can use pyright: ignore to suppress these errors, but #10351 also affects other IDE features:
# works, but pyright complains: No parameter named "_0"foo=Foo(_0=0, _1=1, _2=2)
# `x, y, z` should be `int`, but pyright says they are `Never`matchfoo:
case (x, y, z):
pass
Describe the solution you’d like
Considering that python/typing#1979 is still just a draft, and that members starting with an underscore are valid at runtime, I request that the changes in #10351 be reverted.
Alternatively, please downgrade this to a warning so that it does not affect other IDE features.
The recent change aims to better align pyright's behavior with runtime behavior. Regardless of whether this behavior is mandated by the spec (as it likely will be in the near future), it's generally a good idea to model runtime behaviors accurately.
I don't think your use case is good justification for modeling NamedTuple incorrectly. In your code above, you're effectively lying to the type checker through the use of a TYPE_CHECKING conditional. Your runtime code differs from the code you're asking the type checker to analyze. I recommend against doing this because it leads to problems like the one you're seeing here.
If you have the option of changing your code to avoid using fields that start with underscores, I recommend doing that.
Okay. However, is it possible to make this rule not affect other IDE features? For example, as I mentioned above:
# works, but pyright complains: No parameter named "_0"foo=Foo(_0=0, _1=1, _2=2)
# `x, y, z` should be `int`, but pyright says they are `Never`matchfoo:
case (x, y, z):
pass
I'm fine with manually adding pyright: ignore for these fields, but I hope it won't affect other IDE features (as it did before). I guess it's just a matter of removing these return statements?
BTW, typing#1979 allows collections.namedtuple to have members starting with _ (with rename=True), but pyright currently rejects this.
This might be a bit off-topic—perhaps I should ask this in python/typing#1979 instead?
If type checker refuses to analyze members like _0, but still allows rename=True (which renames invalid members to _{index}), how can I provide type annotations for them in a type stub (.pyi file) when I cannot modify the code?
Activity
erictraut commentedon May 18, 2025
The recent change aims to better align pyright's behavior with runtime behavior. Regardless of whether this behavior is mandated by the spec (as it likely will be in the near future), it's generally a good idea to model runtime behaviors accurately.
I don't think your use case is good justification for modeling
NamedTupleincorrectly. In your code above, you're effectively lying to the type checker through the use of aTYPE_CHECKINGconditional. Your runtime code differs from the code you're asking the type checker to analyze. I recommend against doing this because it leads to problems like the one you're seeing here.If you have the option of changing your code to avoid using fields that start with underscores, I recommend doing that.
WSH032 commentedon May 18, 2025
Okay. However, is it possible to make this rule not affect other IDE features? For example, as I mentioned above:
This used to work as expected.
I'm fine with manually adding
pyright: ignorefor these fields, but I hope it won't affect other IDE features (as it did before). I guess it's just a matter of removing thesereturnstatements?BTW, typing#1979 allows
collections.namedtupleto have members starting with_(withrename=True), but pyright currently rejects this.WSH032 commentedon May 18, 2025
This might be a bit off-topic—perhaps I should ask this in python/typing#1979 instead?
If type checker refuses to analyze members like
_0, but still allowsrename=True(which renames invalid members to_{index}), how can I provide type annotations for them in a type stub (.pyifile) when I cannot modify the code?WSH032 commentedon May 18, 2025
As evidence, after mypy rejects underscore-named members, it still analyzes those members correctly:
But
pyrightrefuses to analyze them: