python / python/mypy

mypyc: cannot query ClassVar members in __init_subclass__ methods of compiled classes

Open
#14,188 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-mypyc
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

I'm using __init_subclass__ in a class that I'm compiling with mypyc (mostly to avoid using metaclasses), and I'm finding that I'm unable to check the types of the class members within that method. If I annotate a class member with ClassVar[SomeType], then it isn't in available in the class __dir__() yet during __init_subclass__; but if I leave off the ClassVar annotation, then all members are just an instance of <class 'getset_descriptor'>, and I'm unable to differentiate any of them

To Reproduce

compile this module with mypyc:

# test_module.py
from typing import ClassVar


def _print_public_attrs(cls: type) -> None:
    for n in dir(cls):
        if not n.startswith("_"):
            v = getattr(cls, n)
            print(n, v, type(v), isinstance(v, SomeDescriptor))


class SomeThing:
    pass


class SomeDescriptor:
    def __get__(
        self, instance: object | None, owner: type | None = None
    ) -> "SomeDescriptor" | SomeThing:
        return SomeThing() if instance is not None else self


class Sup:
    def __init_subclass__(cls) -> None:
        _print_public_attrs(cls)


class Sub(Sup):
    name1 = SomeDescriptor()
    name2: ClassVar[SomeDescriptor] = SomeDescriptor()


print("-----")
_print_public_attrs(Sub)

Then import it:

$ python -c "import test_module"
name1 <attribute 'name1' of 'Sub' objects> <class 'getset_descriptor'> False
-----
name1 <attribute 'name1' of 'Sub' objects> <class 'getset_descriptor'> False
name2 <psygnal._test.SomeDescriptor object at 0x1093926e0> <class 'psygnal._test.SomeDescriptor'> True

.... note that name2 (with the ClassVar annotation) isn't available yet during __init_subclass__, but name1 (without the ClassVar annotation) isn't yet an instance of SomeDescriptor during __init_subclass__.

Expected Behavior

I was hoping for some way to check the types of objects on the Sub class during __init_subclass__.

Your Environment

  • Mypy version used: mypy 0.991 (compiled: yes)
  • Mypy command-line flags: mypyc test_module.py
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 3.10

thank you!!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the behavior from test_module.py with the mypyc command shown, focusing on the init_subclass entry point and the ClassVar and descriptor members. Compare the attributes visible during subclass creation with those visible after import; done means the issue's expected ability to distinguish the class members is supported or its limitation is clearly resolved.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.