Closed
Description
Bug Report
In mypy version 0.942, the stub generator used to create __members__
fields like:
class MyEnum:
__members__: ClassVar[dict] = ... # read-only
In our case, MyEnum
is a C++ enum class
exposed to Python via pybind11. The type annotation seemed to be correct, because at runtime, __members__
does exist.
In mypy version 0.950 the __members__
field is no longer annotated, which means that existing value code no longer type checks properly.
To Reproduce
- Create a temporary venv:
$ mkdir some_temporary_folder
$ cd some_temporary_folder
$ virtualenv ./tmp_venv -p /usr/bin/python3.8
$ . ./tmp_venv/bin/activate
$ pip install -U pip setuptools
$ pip install mypy==0.950 pybind11==2.9.0
- Create a file
native_enum_test.cpp
with content:
#include <cstddef>
#include <memory>
#include <pybind11/pybind11.h>
namespace py = pybind11;
enum class MyEnum { FOO, BAR };
PYBIND11_MODULE(native_enum_test, module) {
pybind11::enum_<MyEnum>(module, "MyEnum", pybind11::arithmetic())
.value("FOO", MyEnum::FOO)
.value("BAR", MyEnum::BAR);
}
- Compile via:
$ c++ -O3 -Wall -shared -std=c++17 -fPIC $(python3 -m pybind11 --includes) native_enum_test.cpp -o native_enum_test.so
- Run the stub generator:
$ stubgen -p native_enum_test
Expected Behavior
As far as I can see, __members__
should be generated by the stub generator.
Check against the previous mypy version: pip install mypy==0.942
and re-running the stub generator produces:
Generator output mypy 0.942
from typing import ClassVar
class MyEnum:
__doc__: ClassVar[str] = ... # read-only
__members__: ClassVar[dict] = ... # read-only
BAR: ClassVar[MyEnum] = ...
FOO: ClassVar[MyEnum] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __gt__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __le__(self, other: object) -> bool: ...
def __lt__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
Actual Behavior
__members__
is missing in the stub generator output.
Generator output mypy 0.950
from typing import ClassVar
class MyEnum:
BAR: ClassVar[MyEnum] = ...
FOO: ClassVar[MyEnum] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __gt__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __le__(self, other: object) -> bool: ...
def __lt__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
Your Environment
- Mypy version used: 0.950
- Mypy command-line flags: not relevant, this is about the stub generator
- Mypy configuration options from
mypy.ini
(and other config files): not relevant, this is about the stub generator - Python version used: 3.8.10
- Operating system and version: Ubuntu 20.04