Spec change: Do not require an error for a generic class attribute

The conformance suite currently requires an error for this code:

from typing import Any, TypeVar, Generic, assert_type

T = TypeVar("T")

class Node(Generic[T]):
    label: T
    def __init__(self, label: T | None = None) -> None:
        if label is not None:
            self.label = label

n1: Node[int] = Node()
type(n1).label       # E

While that error is correct in this specific case, it’s difficult to justify it in general: the attribute may be defined on a child class, for example. Currently mypy and ty do not error on this code. Pyright also considered changing this but backed out the change to maintain compliance with the spec.

@erictraut opened a PR last year to change the spec here, but it slipped through the cracks. I looked at it again today and feel we should change the conformance suite here; I’m posting to Discuss to fulfill the requirements in the change procedure.

1 Like

I’m in favor of this proposed change. Looking through previous discussions ( Accessing generic attribute on `type[X]` , Is it ambiguous to access a generic instance variable on a class which is bound to a specific type? · microsoft/pyright · Discussion #10303 · GitHub ), the motivating example for removing the error on type(n1) is something like this:

class Node[T]:
    label: T

class IntNode(Node[int]):
    label: int

n1: IntNode = IntNode()
type(n1).label # mypy, pyrefly, pyright, ty, and zuban all allow this

def f(n1: Node):
    return type(n1).label  # but this is an error?
f(n1)

The error doesn’t make much sense here, so not requiring it seems very reasonable.

1 Like