Bug Report
Trying to update mypy from 1.6.1 to 1.7.0 has revealed a few regressions in the stub generator output related to pybind11 modules.
To Reproduce
Consider this pybind11 module:
#include <filesystem>
#include <optional>
#include <utility>
#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
std::vector<float> funcReturningVector()
{
return std::vector<float>{1.0, 2.0, 3.0, 4.0};
}
std::pair<int, float> funcReturningPair()
{
return std::pair{42, 1.0};
}
std::optional<int> funcReturningOptional()
{
return std::nullopt;
}
std::filesystem::path funcIncompleteSignature()
{
// This example does not include <pybind11/stl/filesystem.h> on purpose
// to demonstrate the signature of an incomplete binding.
return std::filesystem::path{"foobar"};
}
struct MyStruct
{
int a;
int b;
int c;
};
PYBIND11_MODULE(my_native_module, m)
{
m.def("func_returning_vector", &funcReturningVector);
m.def("func_returning_pair", &funcReturningPair);
m.def("func_returning_optional", &funcReturningOptional);
m.def("func_incomplete_signature", &funcIncompleteSignature);
py::class_<MyStruct>(m, "MyStruct")
.def_readwrite("a", &MyStruct::a)
.def_readwrite("b", &MyStruct::b, "some docstring")
.def_property_readonly(
"c",
[](const MyStruct& x) {
return x.c;
},
"some docstring");
}
To reproduce, store the above snippet as my_native_module.cpp and then:
# Install latest pybind11:
pip install pybind11==2.11.1
# Compile pybind11 module:
c++ -O3 -Wall -shared -std=c++17 -fPIC $(python3 -m pybind11 --includes) my_native_module.cpp -o my_native_module.so
# Run the stub generator on it:
stubgen -p my_native_module
Expected Behavior
mypy 1.6.1 outputs the following, which is pretty reasonable:
from typing import Any, List, Optional, Tuple
class MyStruct:
a: int
b: int
def __init__(self, *args, **kwargs) -> None: ...
@property
def c(self) -> int: ...
def func_incomplete_signature(*args, **kwargs) -> Any: ...
def func_returning_optional() -> Optional[int]: ...
def func_returning_pair() -> Tuple[int,float]: ...
def func_returning_vector() -> List[float]: ...
Actual Behavior
mypy 1.7.0 outputs the following:
from _typeshed import Incomplete
class MyStruct:
a: int
b: Incomplete
def __init__(self, *args, **kwargs) -> None: ...
@property
def c(self): ...
def func_incomplete_signature(*args, **kwargs): ...
def func_returning_optional() -> Optional[int]: ...
def func_returning_pair() -> Tuple[int, float]: ...
def func_returning_vector() -> List[float]: ...
The regressions are:
- The most obvious thing is that the imports for
List, Tuple, and Optional are missing. This makes the resulting .pyi invalid, because it uses symbols that have not been imported. The stub output does not type check. This is not limited to these three types, but applies to other types like Iterable, Iterator, Dict, Set, Union, etc.
- The type annotation of field
b has regressed from int to Incomplete, apparently due to the explicit docstring.
- The type annotation of field
c has regressed from int to not annotated at all, probably also because of the explicit docstring.
- The signature of the
func_incomplete_signature has also slightly worsened: Before, it was at least annotated as -> Any but now it misses any return type annotation at all. This is problematic when users want to validate their generated stubs for completeness, i.e., run mypy --disallow-untyped-defs on the output. Of course semantically it is the same, but still it would be nicer to always produce some return type (arguably a broken signature may be rather annotated as -> object instead of -> Incomplete to avoid running into bugs from incomplete stub output).
Your Environment
- Mypy version used: 1.7.0
- Mypy command-line flags: irrelevant for stubgen
- Mypy configuration options from
mypy.ini (and other config files): irrelevant for stubgen
- Python version used: 3.10
Bug Report
Trying to update mypy from 1.6.1 to 1.7.0 has revealed a few regressions in the stub generator output related to pybind11 modules.
To Reproduce
Consider this pybind11 module:
To reproduce, store the above snippet as
my_native_module.cppand then:Expected Behavior
mypy 1.6.1 outputs the following, which is pretty reasonable:
Actual Behavior
mypy 1.7.0 outputs the following:
The regressions are:
List,Tuple, andOptionalare missing. This makes the resulting.pyiinvalid, because it uses symbols that have not been imported. The stub output does not type check. This is not limited to these three types, but applies to other types likeIterable,Iterator,Dict,Set,Union, etc.bhas regressed frominttoIncomplete, apparently due to the explicit docstring.chas regressed fromintto not annotated at all, probably also because of the explicit docstring.func_incomplete_signaturehas also slightly worsened: Before, it was at least annotated as-> Anybut now it misses any return type annotation at all. This is problematic when users want to validate their generated stubs for completeness, i.e., runmypy --disallow-untyped-defson the output. Of course semantically it is the same, but still it would be nicer to always produce some return type (arguably a broken signature may be rather annotated as-> objectinstead of-> Incompleteto avoid running into bugs from incomplete stub output).Your Environment
mypy.ini(and other config files): irrelevant for stubgen