From 6532f32dcb435b12e99962e90a027777bb652f43 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Mon, 11 Aug 2025 11:08:43 +0200 Subject: [PATCH 01/16] Copy bindings from v2.13 --- .../demo/__init__.pyi | 41 ++++++ .../demo/_bindings/__init__.pyi | 35 +++++ .../demo/_bindings/aliases/__init__.pyi | 53 ++++++++ .../demo/_bindings/aliases/foreign_arg.pyi | 7 + .../demo/_bindings/aliases/foreign_attr.pyi | 6 + .../aliases/foreign_class_member.pyi | 12 ++ .../_bindings/aliases/foreign_method_arg.pyi | 8 ++ .../aliases/foreign_method_return.pyi | 9 ++ .../demo/_bindings/aliases/foreign_return.pyi | 7 + .../_bindings/aliases/missing_self_arg.pyi | 8 ++ .../demo/_bindings/classes.pyi | 57 ++++++++ .../demo/_bindings/eigen.pyi | 70 ++++++++++ .../demo/_bindings/enum.pyi | 71 ++++++++++ .../demo/_bindings/flawed_bindings.pyi | 23 ++++ .../demo/_bindings/functions.pyi | 58 ++++++++ .../demo/_bindings/issues.pyi | 37 ++++++ .../demo/_bindings/methods.pyi | 8 ++ .../demo/_bindings/numpy.pyi | 23 ++++ .../demo/_bindings/properties.pyi | 99 ++++++++++++++ .../demo/_bindings/stl.pyi | 21 +++ .../demo/_bindings/stl_bind.pyi | 124 ++++++++++++++++++ .../demo/_bindings/typing.pyi | 10 ++ .../demo/_bindings/values.pyi | 36 +++++ .../numpy-array-use-type-var/demo/core.pyi | 35 +++++ .../demo/pure_python/__init__.pyi | 11 ++ .../demo/pure_python/classes.pyi | 21 +++ .../demo/pure_python/functions.pyi | 31 +++++ .../demo/pure_python/functions_3_8_plus.pyi | 15 +++ .../demo/pure_python/functions_3_9_plus.pyi | 5 + .../demo/pure_python/values.pyi | 4 + .../demo/__init__.pyi | 41 ++++++ .../demo/_bindings/__init__.pyi | 35 +++++ .../demo/_bindings/aliases/__init__.pyi | 53 ++++++++ .../demo/_bindings/aliases/foreign_arg.pyi | 7 + .../demo/_bindings/aliases/foreign_attr.pyi | 6 + .../aliases/foreign_class_member.pyi | 12 ++ .../_bindings/aliases/foreign_method_arg.pyi | 8 ++ .../aliases/foreign_method_return.pyi | 9 ++ .../demo/_bindings/aliases/foreign_return.pyi | 7 + .../_bindings/aliases/missing_self_arg.pyi | 8 ++ .../demo/_bindings/classes.pyi | 57 ++++++++ .../demo/_bindings/eigen.pyi | 100 ++++++++++++++ .../demo/_bindings/enum.pyi | 71 ++++++++++ .../demo/_bindings/flawed_bindings.pyi | 23 ++++ .../demo/_bindings/functions.pyi | 58 ++++++++ .../demo/_bindings/issues.pyi | 37 ++++++ .../demo/_bindings/methods.pyi | 8 ++ .../demo/_bindings/numpy.pyi | 21 +++ .../demo/_bindings/properties.pyi | 99 ++++++++++++++ .../demo/_bindings/stl.pyi | 21 +++ .../demo/_bindings/stl_bind.pyi | 124 ++++++++++++++++++ .../demo/_bindings/typing.pyi | 10 ++ .../demo/_bindings/values.pyi | 36 +++++ .../demo/core.pyi | 35 +++++ .../demo/pure_python/__init__.pyi | 11 ++ .../demo/pure_python/classes.pyi | 21 +++ .../demo/pure_python/functions.pyi | 31 +++++ .../demo/pure_python/functions_3_8_plus.pyi | 15 +++ .../demo/pure_python/functions_3_9_plus.pyi | 5 + .../demo/pure_python/values.pyi | 4 + 60 files changed, 1918 insertions(+) create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_attr.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_class_member.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_return.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_return.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/missing_self_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/values.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/core.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/classes.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_8_plus.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_9_plus.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/values.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_attr.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_class_member.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_return.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_return.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/missing_self_arg.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/values.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/core.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/__init__.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/classes.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_8_plus.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_9_plus.pyi create mode 100644 tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/values.pyi diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/__init__.pyi new file mode 100644 index 0000000..86fb6b8 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/__init__.pyi @@ -0,0 +1,41 @@ +from __future__ import annotations + +from demo._bindings import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +from . import _bindings, core, pure_python + +__all__: list[str] = [ + "aliases", + "classes", + "core", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "pure_python", + "stl", + "stl_bind", + "typing", + "values", + "version", +] +version: str = "0.0.0" diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/__init__.pyi new file mode 100644 index 0000000..c263078 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/__init__.pyi @@ -0,0 +1,35 @@ +from __future__ import annotations + +from . import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +__all__: list[str] = [ + "aliases", + "classes", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "stl", + "stl_bind", + "typing", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi new file mode 100644 index 0000000..93963f4 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi @@ -0,0 +1,53 @@ +from __future__ import annotations + +import typing + +import numpy +from numpy import random + +import demo._bindings.enum +from demo._bindings.aliases.foreign_method_arg import Bar2 as foreign_type_alias +from demo._bindings.aliases.foreign_return import get_foo as foreign_class_alias + +from . import ( + foreign_arg, + foreign_attr, + foreign_class_member, + foreign_method_arg, + foreign_method_return, + foreign_return, + missing_self_arg, +) + +__all__: list[str] = [ + "Color", + "Dummy", + "foreign_arg", + "foreign_attr", + "foreign_class_alias", + "foreign_class_member", + "foreign_enum_default", + "foreign_method_arg", + "foreign_method_return", + "foreign_return", + "foreign_type_alias", + "func", + "local_func_alias", + "local_type_alias", + "missing_self_arg", + "random", +] + +class Color: + pass + +class Dummy: + linalg = numpy.linalg + +def foreign_enum_default( + color: typing.Any = demo._bindings.enum.ConsoleForegroundColor.Blue, +) -> None: ... +def func(arg0: int) -> int: ... + +local_func_alias = func +local_type_alias = Color diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_arg.pyi new file mode 100644 index 0000000..de75e6f --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_arg.pyi @@ -0,0 +1,7 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["set_foo"] + +def set_foo(arg0: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_attr.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_attr.pyi new file mode 100644 index 0000000..10c4a71 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_attr.pyi @@ -0,0 +1,6 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["value"] +value: demo._bindings.classes.Foo # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_class_member.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_class_member.pyi new file mode 100644 index 0000000..497a4e2 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_class_member.pyi @@ -0,0 +1,12 @@ +from __future__ import annotations + +import typing + +import demo._bindings.classes + +__all__: list[str] = ["Bar1"] + +class Bar1: + foo: typing.ClassVar[ + demo._bindings.classes.Foo + ] # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_arg.pyi new file mode 100644 index 0000000..8d4ed4a --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_arg.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar2"] + +class Bar2: + def set_foo(self, arg0: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_return.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_return.pyi new file mode 100644 index 0000000..95d218e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_method_return.pyi @@ -0,0 +1,9 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar3"] + +class Bar3: + @staticmethod + def get_foo() -> demo._bindings.classes.Foo: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_return.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_return.pyi new file mode 100644 index 0000000..7b5b428 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/foreign_return.pyi @@ -0,0 +1,7 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["get_foo"] + +def get_foo() -> demo._bindings.classes.Foo: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/missing_self_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/missing_self_arg.pyi new file mode 100644 index 0000000..ee1a09e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/missing_self_arg.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar4"] + +class Bar4: + def set_foo(self: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi new file mode 100644 index 0000000..ea36dda --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi @@ -0,0 +1,57 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = ["Base", "CppException", "Derived", "Foo", "Outer"] + +class Base: + class Inner: + pass + name: str + +class CppException(Exception): + pass + +class Derived(Base): + count: int + +class Foo: + class FooChild: + def __init__(self) -> None: ... + def g(self) -> None: ... + + def __init__(self) -> None: ... + def f(self) -> None: ... + +class Outer: + class Inner: + class NestedEnum: + """ + Members: + + ONE + + TWO + """ + + ONE: typing.ClassVar[Outer.Inner.NestedEnum] # value = + TWO: typing.ClassVar[Outer.Inner.NestedEnum] # value = + __members__: typing.ClassVar[ + dict[str, Outer.Inner.NestedEnum] + ] # value = {'ONE': , 'TWO': } + def __eq__(self, other: typing.Any) -> bool: ... + def __getstate__(self) -> int: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __init__(self, value: int) -> None: ... + def __int__(self) -> int: ... + def __ne__(self, other: typing.Any) -> bool: ... + def __repr__(self) -> str: ... + def __setstate__(self, state: int) -> None: ... + def __str__(self) -> str: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + value: Outer.Inner.NestedEnum + inner: Outer.Inner diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi new file mode 100644 index 0000000..742d2ee --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi @@ -0,0 +1,70 @@ +from __future__ import annotations + +import typing + +import numpy +import scipy.sparse + +__all__: list[str] = [ + "accept_matrix_int", + "accept_vector_float64", + "dense_matrix_c", + "dense_matrix_r", + "fixed_mutator_a", + "fixed_mutator_c", + "fixed_mutator_r", + "four_col_matrix_r", + "four_row_matrix_r", + "get_matrix_int", + "get_vector_float64", + "sparse_matrix_c", + "sparse_matrix_r", +] +M = typing.TypeVar("M", bound=int) +N = typing.TypeVar("N", bound=int) + +def accept_matrix_int( + arg0: numpy.ndarray[ + tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.int32] + ] +) -> None: ... +def accept_vector_float64( + arg0: numpy.ndarray[ + tuple[typing.Literal[3], typing.Literal[1]], numpy.dtype[numpy.float64] + ] +) -> None: ... +def dense_matrix_c( + arg0: numpy.ndarray[tuple[M, N], numpy.dtype[numpy.float32]] +) -> numpy.ndarray[tuple[M, N], numpy.dtype[numpy.float32]]: ... +def dense_matrix_r( + arg0: numpy.ndarray[tuple[M, N], numpy.dtype[numpy.float32]] +) -> numpy.ndarray[tuple[M, N], numpy.dtype[numpy.float32]]: ... +def fixed_mutator_a( + arg0: numpy.ndarray[ + tuple[typing.Literal[5], typing.Literal[6]], numpy.dtype[numpy.float32] + ] +) -> None: ... +def fixed_mutator_c( + arg0: numpy.ndarray[ + tuple[typing.Literal[5], typing.Literal[6]], numpy.dtype[numpy.float32] + ] +) -> None: ... +def fixed_mutator_r( + arg0: numpy.ndarray[ + tuple[typing.Literal[5], typing.Literal[6]], numpy.dtype[numpy.float32] + ] +) -> None: ... +def four_col_matrix_r( + arg0: numpy.ndarray[tuple[M, typing.Literal[4]], numpy.dtype[numpy.float32]] +) -> numpy.ndarray[tuple[M, typing.Literal[4]], numpy.dtype[numpy.float32]]: ... +def four_row_matrix_r( + arg0: numpy.ndarray[tuple[typing.Literal[4], N], numpy.dtype[numpy.float32]] +) -> numpy.ndarray[tuple[typing.Literal[4], N], numpy.dtype[numpy.float32]]: ... +def get_matrix_int() -> numpy.ndarray[ + tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.int32] +]: ... +def get_vector_float64() -> numpy.ndarray[ + tuple[typing.Literal[3], typing.Literal[1]], numpy.dtype[numpy.float64] +]: ... +def sparse_matrix_c(arg0: scipy.sparse.csc_matrix) -> scipy.sparse.csc_matrix: ... +def sparse_matrix_r(arg0: scipy.sparse.csr_matrix) -> scipy.sparse.csr_matrix: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi new file mode 100644 index 0000000..57aba5b --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi @@ -0,0 +1,71 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "Blue", + "ConsoleForegroundColor", + "Green", + "Magenta", + "None_", + "Yellow", + "accept_defaulted_enum", +] + +class ConsoleForegroundColor: + """ + Members: + + Green + + Yellow + + Blue + + Magenta + + None_ + """ + + Blue: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Green: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Magenta: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + None_: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Yellow: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + __members__: typing.ClassVar[ + dict[str, ConsoleForegroundColor] + ] # value = {'Green': , 'Yellow': , 'Blue': , 'Magenta': , 'None_': } + def __eq__(self, other: typing.Any) -> bool: ... + def __getstate__(self) -> int: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __init__(self, value: int) -> None: ... + def __int__(self) -> int: ... + def __ne__(self, other: typing.Any) -> bool: ... + def __repr__(self) -> str: ... + def __setstate__(self, state: int) -> None: ... + def __str__(self) -> str: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +def accept_defaulted_enum( + color: ConsoleForegroundColor = ConsoleForegroundColor.None_, +) -> None: ... + +Blue: ConsoleForegroundColor # value = +Green: ConsoleForegroundColor # value = +Magenta: ConsoleForegroundColor # value = +None_: ConsoleForegroundColor # value = +Yellow: ConsoleForegroundColor # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi new file mode 100644 index 0000000..4f3886e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi @@ -0,0 +1,23 @@ +from __future__ import annotations + +__all__: list[str] = [ + "Enum", + "Unbound", + "accept_unbound_enum", + "accept_unbound_enum_defaulted", + "accept_unbound_type", + "accept_unbound_type_defaulted", + "get_unbound_type", +] + +class Enum: + pass + +class Unbound: + pass + +def accept_unbound_enum(arg0: ...) -> int: ... +def accept_unbound_enum_defaulted(x: Enum = ...) -> int: ... +def accept_unbound_type(arg0: tuple[..., int]) -> int: ... +def accept_unbound_type_defaulted(x: Unbound = ...) -> int: ... +def get_unbound_type() -> ...: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi new file mode 100644 index 0000000..79f666a --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi @@ -0,0 +1,58 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "Foo", + "accept_annotated_callable", + "accept_callable", + "accept_frozenset", + "accept_py_handle", + "accept_py_object", + "accept_set", + "add", + "default_custom_arg", + "default_int_arg", + "default_list_arg", + "default_optional_arg", + "func_w_anon_args", + "func_w_named_pos_args", + "generic", + "mul", + "pass_callback", + "pos_kw_only_mix", + "pos_kw_only_variadic_mix", +] + +class Foo: + def __init__(self, arg0: int) -> None: ... + +def accept_annotated_callable(arg0: typing.Callable[[int, int], int]) -> typing.Any: ... +def accept_callable(arg0: typing.Callable) -> typing.Any: ... +def accept_frozenset(arg0: frozenset) -> None: ... +def accept_py_handle(arg0: typing.Any) -> str: ... +def accept_py_object(arg0: typing.Any) -> str: ... +def accept_set(arg0: set) -> None: ... +def add(arg0: int, arg1: int) -> int: ... +def default_custom_arg(foo: Foo = Foo(5)) -> None: ... +def default_int_arg(n: int = 5) -> None: ... +def default_list_arg(l: list = [1, 2, 6, 18]) -> None: ... +def default_optional_arg(n: int | None = None) -> None: ... +def func_w_anon_args(arg0: int, arg1: int, arg2: int) -> None: ... +def func_w_named_pos_args(x: int, y: int, z: int) -> None: ... +def generic(*args, **kwargs) -> None: ... +@typing.overload +def mul(x: int, y: int) -> int: + """ + Multiply x and y (int) + """ + +@typing.overload +def mul(p: float, q: float) -> float: + """ + Multiply p and q (double) + """ + +def pass_callback(arg0: typing.Callable[[Foo], Foo]) -> Foo: ... +def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: ... +def pos_kw_only_variadic_mix(i: int, /, j: int, *args, k: int, **kwargs) -> tuple: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi new file mode 100644 index 0000000..cf6abad --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi @@ -0,0 +1,37 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "backslashes_should_be_escaped", + "issue_51_catastrophic_regex", + "issue_73_utf8_doc_chars", +] + +def backslashes_should_be_escaped() -> None: + """ + \\brief A brief description of this function. + + A detailed description of this function. + + Here's some reStructuredText: :math:`x = [x, y, \\theta]^T` + """ + +def issue_51_catastrophic_regex(arg0: int, arg1: int) -> None: + """ + Use-case: + issue_51(os.get_handle_inheritable, os.set_handle_inheritable) + """ + +def issue_73_utf8_doc_chars() -> None: + """ + Construct a Ramsete unicycle controller. + + Tuning parameter (b > 0 rad²/m²) for which larger values make + + convergence more aggressive like a proportional term. + Tuning parameter (0 rad⁻¹ < zeta < 1 rad⁻¹) for which larger + values provide more damping in response. + """ + +_cleanup: typing.Any # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi new file mode 100644 index 0000000..6c115cd --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +__all__: list[str] = ["Dummy"] + +class Dummy: + @staticmethod + def static_method(arg0: int) -> int: ... + def regular_method(self, arg0: int) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi new file mode 100644 index 0000000..08714c5 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi @@ -0,0 +1,23 @@ +from __future__ import annotations + +import typing + +import numpy + +__all__: list[str] = [ + "accept_ndarray_float64", + "accept_ndarray_int", + "get_ndarray_float64", + "get_ndarray_int", + "return_dtype", +] + +def accept_ndarray_float64( + arg0: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]] +) -> None: ... +def accept_ndarray_int( + arg0: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]] +) -> None: ... +def get_ndarray_float64() -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]: ... +def get_ndarray_int() -> numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]: ... +def return_dtype() -> numpy.dtype[typing.Any]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi new file mode 100644 index 0000000..9d81595 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi @@ -0,0 +1,99 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "WithGetterSetterDoc", + "WithPropAndGetterSetterDoc", + "WithPropDoc", + "WithoutDoc", +] + +class WithGetterSetterDoc: + """ + User docstring provided via pybind11::cpp_function(..., doc) to getters/setters, but NOT to `def_*(..., doc)` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + getter doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: + """ + setter doc token + """ + @property + def def_property_readonly(self) -> int: + """ + getter doc token + """ + +class WithPropAndGetterSetterDoc: + """ + User docstring provided via pybind11::cpp_function(..., doc) to getters/setters and to `def_*(, doc)` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + prop doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: ... + @property + def def_property_readonly(self) -> int: + """ + prop doc token + """ + +class WithPropDoc: + """ + User docstring provided only to `def_` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + prop doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: ... + @property + def def_property_readonly(self) -> int: + """ + prop doc token + """ + @property + def def_readonly(self) -> int: + """ + prop doc token + """ + @property + def def_readwrite(self) -> int: + """ + prop doc token + """ + @def_readwrite.setter + def def_readwrite(self, arg0: int) -> None: ... + +class WithoutDoc: + """ + No user docstring provided + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + def_property: int + def_readwrite: int + @property + def def_property_readonly(self) -> int: ... + @property + def def_readonly(self) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi new file mode 100644 index 0000000..bd5bb49 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi @@ -0,0 +1,21 @@ +from __future__ import annotations + +import typing + +import pybind11_stubgen.typing_ext + +__all__: list[str] = [ + "std_array", + "std_map", + "std_optional", + "std_variant", + "std_vector", +] + +def std_array( + arg0: typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)] +) -> typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)]: ... +def std_map() -> dict[int, complex]: ... +def std_optional(arg0: int | None) -> None: ... +def std_variant(arg0: int | float | tuple[int, int]) -> None: ... +def std_vector() -> list[tuple[int, float]]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi new file mode 100644 index 0000000..6f1f9b6 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi @@ -0,0 +1,124 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "MapStringComplex", + "VectorPairStringDouble", + "get_complex_map", + "get_vector_of_pairs", +] + +class MapStringComplex: + def __bool__(self) -> bool: + """ + Check whether the map is nonempty + """ + @typing.overload + def __contains__(self, arg0: str) -> bool: ... + @typing.overload + def __contains__(self, arg0: typing.Any) -> bool: ... + def __delitem__(self, arg0: str) -> None: ... + def __getitem__(self, arg0: str) -> complex: ... + def __init__(self) -> None: ... + def __iter__(self) -> typing.Iterator[str]: ... + def __len__(self) -> int: ... + def __repr__(self) -> str: + """ + Return the canonical string representation of this map. + """ + def __setitem__(self, arg0: str, arg1: complex) -> None: ... + def items(self) -> typing.ItemsView: ... + def keys(self) -> typing.KeysView: ... + def values(self) -> typing.ValuesView: ... + +class VectorPairStringDouble: + __hash__: typing.ClassVar[None] = None + def __bool__(self) -> bool: + """ + Check whether the list is nonempty + """ + def __contains__(self, x: tuple[str, float]) -> bool: + """ + Return true the container contains ``x`` + """ + @typing.overload + def __delitem__(self, arg0: int) -> None: + """ + Delete the list elements at index ``i`` + """ + @typing.overload + def __delitem__(self, arg0: slice) -> None: + """ + Delete list elements using a slice object + """ + def __eq__(self, arg0: VectorPairStringDouble) -> bool: ... + @typing.overload + def __getitem__(self, s: slice) -> VectorPairStringDouble: + """ + Retrieve list elements using a slice object + """ + @typing.overload + def __getitem__(self, arg0: int) -> tuple[str, float]: ... + @typing.overload + def __init__(self) -> None: ... + @typing.overload + def __init__(self, arg0: VectorPairStringDouble) -> None: + """ + Copy constructor + """ + @typing.overload + def __init__(self, arg0: typing.Iterable) -> None: ... + def __iter__(self) -> typing.Iterator[tuple[str, float]]: ... + def __len__(self) -> int: ... + def __ne__(self, arg0: VectorPairStringDouble) -> bool: ... + @typing.overload + def __setitem__(self, arg0: int, arg1: tuple[str, float]) -> None: ... + @typing.overload + def __setitem__(self, arg0: slice, arg1: VectorPairStringDouble) -> None: + """ + Assign list elements using a slice object + """ + def append(self, x: tuple[str, float]) -> None: + """ + Add an item to the end of the list + """ + def clear(self) -> None: + """ + Clear the contents + """ + def count(self, x: tuple[str, float]) -> int: + """ + Return the number of times ``x`` appears in the list + """ + @typing.overload + def extend(self, L: VectorPairStringDouble) -> None: + """ + Extend the list by appending all the items in the given list + """ + @typing.overload + def extend(self, L: typing.Iterable) -> None: + """ + Extend the list by appending all the items in the given list + """ + def insert(self, i: int, x: tuple[str, float]) -> None: + """ + Insert an item at a given position. + """ + @typing.overload + def pop(self) -> tuple[str, float]: + """ + Remove and return the last item + """ + @typing.overload + def pop(self, i: int) -> tuple[str, float]: + """ + Remove and return the item at index ``i`` + """ + def remove(self, x: tuple[str, float]) -> None: + """ + Remove the first item from the list whose value is x. It is an error if there is no such item. + """ + +def get_complex_map() -> MapStringComplex: ... +def get_vector_of_pairs() -> VectorPairStringDouble: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi new file mode 100644 index 0000000..f2c4ab9 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi @@ -0,0 +1,10 @@ +from __future__ import annotations + +import typing + +import typing_extensions + +__all__: list[str] = ["get_buffer", "get_sequence"] + +def get_buffer(arg0: typing_extensions.Buffer) -> typing_extensions.Buffer: ... +def get_sequence(arg0: typing.Sequence) -> typing.Sequence: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/values.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/values.pyi new file mode 100644 index 0000000..7c36d3f --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/values.pyi @@ -0,0 +1,36 @@ +from __future__ import annotations + +import datetime + +import numpy +from numpy import random + +__all__: list[str] = [ + "Dummy", + "Foo", + "add_day", + "foolist", + "foovar", + "list_with_none", + "none", + "random", + "t_10ms", + "t_20ns", + "t_30s", +] + +class Dummy: + linalg = numpy.linalg + +class Foo: + pass + +def add_day(arg0: datetime.datetime) -> datetime.datetime: ... + +foolist: list # value = [, ] +foovar: Foo # value = +list_with_none: list = [None, 2, {}] +none = None +t_10ms: datetime.timedelta # value = datetime.timedelta(microseconds=10000) +t_20ns: datetime.timedelta # value = datetime.timedelta(0) +t_30s: datetime.timedelta # value = datetime.timedelta(seconds=30) diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/core.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/core.pyi new file mode 100644 index 0000000..95c1646 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/core.pyi @@ -0,0 +1,35 @@ +from __future__ import annotations + +from demo._bindings import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +__all__: list[str] = [ + "aliases", + "classes", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "stl", + "stl_bind", + "typing", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/__init__.pyi new file mode 100644 index 0000000..10d343e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/__init__.pyi @@ -0,0 +1,11 @@ +from __future__ import annotations + +from . import classes, functions, functions_3_8_plus, functions_3_9_plus, values + +__all__: list[str] = [ + "classes", + "functions", + "functions_3_8_plus", + "functions_3_9_plus", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/classes.pyi new file mode 100644 index 0000000..32aa068 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/classes.pyi @@ -0,0 +1,21 @@ +from __future__ import annotations + +__all__: list[str] = ["A", "B", "C", "X"] + +class A: + """ + A + """ + +class B(A): + """ + B + """ + +class C(B): + """ + C + """ + +class X: + pass diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions.pyi new file mode 100644 index 0000000..5ed9ef3 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions.pyi @@ -0,0 +1,31 @@ +from __future__ import annotations + +import sys as sys +import typing as typing + +from demo.pure_python.functions_3_8_plus import args_mix +from demo.pure_python.functions_3_9_plus import generic_alias_annotation + +__all__: list[str] = [ + "accept_frozenset", + "args_mix", + "builtin_function_as_default_arg", + "function_as_default_arg", + "generic_alias_annotation", + "lambda_as_default_arg", + "search", + "static_method_as_default_arg", + "sys", + "typing", +] + +class _Dummy: + @staticmethod + def foo(): ... + +def accept_frozenset(arg: frozenset[int | float]) -> int | None: ... +def builtin_function_as_default_arg(func: type(len) = len): ... +def function_as_default_arg(func: type(search) = search): ... +def lambda_as_default_arg(callback=...): ... +def search(a: int, b: list[int]) -> int: ... +def static_method_as_default_arg(callback=_Dummy.foo): ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_8_plus.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_8_plus.pyi new file mode 100644 index 0000000..e916422 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_8_plus.pyi @@ -0,0 +1,15 @@ +from __future__ import annotations + +import typing as typing + +__all__: list[str] = ["args_mix", "typing"] + +def args_mix( + a: int, + b: float = 0.5, + c: str = "", + *args: int, + x: int = 1, + y=int, + **kwargs: typing.Dict[int, str], +): ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_9_plus.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_9_plus.pyi new file mode 100644 index 0000000..59b9b80 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/functions_3_9_plus.pyi @@ -0,0 +1,5 @@ +from __future__ import annotations + +__all__: list[str] = ["generic_alias_annotation"] + +def generic_alias_annotation(a: list[tuple[int]], b: dict[int, str]) -> list[float]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/values.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/values.pyi new file mode 100644 index 0000000..0791339 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/pure_python/values.pyi @@ -0,0 +1,4 @@ +from __future__ import annotations + +__all__: list[str] = ["callables_dict"] +callables_dict: dict = {"len": len, "int": int} diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/__init__.pyi new file mode 100644 index 0000000..86fb6b8 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/__init__.pyi @@ -0,0 +1,41 @@ +from __future__ import annotations + +from demo._bindings import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +from . import _bindings, core, pure_python + +__all__: list[str] = [ + "aliases", + "classes", + "core", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "pure_python", + "stl", + "stl_bind", + "typing", + "values", + "version", +] +version: str = "0.0.0" diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/__init__.pyi new file mode 100644 index 0000000..c263078 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/__init__.pyi @@ -0,0 +1,35 @@ +from __future__ import annotations + +from . import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +__all__: list[str] = [ + "aliases", + "classes", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "stl", + "stl_bind", + "typing", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi new file mode 100644 index 0000000..93963f4 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi @@ -0,0 +1,53 @@ +from __future__ import annotations + +import typing + +import numpy +from numpy import random + +import demo._bindings.enum +from demo._bindings.aliases.foreign_method_arg import Bar2 as foreign_type_alias +from demo._bindings.aliases.foreign_return import get_foo as foreign_class_alias + +from . import ( + foreign_arg, + foreign_attr, + foreign_class_member, + foreign_method_arg, + foreign_method_return, + foreign_return, + missing_self_arg, +) + +__all__: list[str] = [ + "Color", + "Dummy", + "foreign_arg", + "foreign_attr", + "foreign_class_alias", + "foreign_class_member", + "foreign_enum_default", + "foreign_method_arg", + "foreign_method_return", + "foreign_return", + "foreign_type_alias", + "func", + "local_func_alias", + "local_type_alias", + "missing_self_arg", + "random", +] + +class Color: + pass + +class Dummy: + linalg = numpy.linalg + +def foreign_enum_default( + color: typing.Any = demo._bindings.enum.ConsoleForegroundColor.Blue, +) -> None: ... +def func(arg0: int) -> int: ... + +local_func_alias = func +local_type_alias = Color diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_arg.pyi new file mode 100644 index 0000000..de75e6f --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_arg.pyi @@ -0,0 +1,7 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["set_foo"] + +def set_foo(arg0: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_attr.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_attr.pyi new file mode 100644 index 0000000..10c4a71 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_attr.pyi @@ -0,0 +1,6 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["value"] +value: demo._bindings.classes.Foo # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_class_member.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_class_member.pyi new file mode 100644 index 0000000..497a4e2 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_class_member.pyi @@ -0,0 +1,12 @@ +from __future__ import annotations + +import typing + +import demo._bindings.classes + +__all__: list[str] = ["Bar1"] + +class Bar1: + foo: typing.ClassVar[ + demo._bindings.classes.Foo + ] # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_arg.pyi new file mode 100644 index 0000000..8d4ed4a --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_arg.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar2"] + +class Bar2: + def set_foo(self, arg0: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_return.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_return.pyi new file mode 100644 index 0000000..95d218e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_method_return.pyi @@ -0,0 +1,9 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar3"] + +class Bar3: + @staticmethod + def get_foo() -> demo._bindings.classes.Foo: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_return.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_return.pyi new file mode 100644 index 0000000..7b5b428 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/foreign_return.pyi @@ -0,0 +1,7 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["get_foo"] + +def get_foo() -> demo._bindings.classes.Foo: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/missing_self_arg.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/missing_self_arg.pyi new file mode 100644 index 0000000..ee1a09e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/missing_self_arg.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +import demo._bindings.classes + +__all__: list[str] = ["Bar4"] + +class Bar4: + def set_foo(self: demo._bindings.classes.Foo) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi new file mode 100644 index 0000000..ea36dda --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi @@ -0,0 +1,57 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = ["Base", "CppException", "Derived", "Foo", "Outer"] + +class Base: + class Inner: + pass + name: str + +class CppException(Exception): + pass + +class Derived(Base): + count: int + +class Foo: + class FooChild: + def __init__(self) -> None: ... + def g(self) -> None: ... + + def __init__(self) -> None: ... + def f(self) -> None: ... + +class Outer: + class Inner: + class NestedEnum: + """ + Members: + + ONE + + TWO + """ + + ONE: typing.ClassVar[Outer.Inner.NestedEnum] # value = + TWO: typing.ClassVar[Outer.Inner.NestedEnum] # value = + __members__: typing.ClassVar[ + dict[str, Outer.Inner.NestedEnum] + ] # value = {'ONE': , 'TWO': } + def __eq__(self, other: typing.Any) -> bool: ... + def __getstate__(self) -> int: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __init__(self, value: int) -> None: ... + def __int__(self) -> int: ... + def __ne__(self, other: typing.Any) -> bool: ... + def __repr__(self) -> str: ... + def __setstate__(self, state: int) -> None: ... + def __str__(self) -> str: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + value: Outer.Inner.NestedEnum + inner: Outer.Inner diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi new file mode 100644 index 0000000..8e45337 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi @@ -0,0 +1,100 @@ +from __future__ import annotations + +import typing + +import numpy +import pybind11_stubgen.typing_ext +import scipy.sparse + +__all__: list[str] = [ + "accept_matrix_int", + "accept_vector_float64", + "dense_matrix_c", + "dense_matrix_r", + "fixed_mutator_a", + "fixed_mutator_c", + "fixed_mutator_r", + "four_col_matrix_r", + "four_row_matrix_r", + "get_matrix_int", + "get_vector_float64", + "sparse_matrix_c", + "sparse_matrix_r", +] + +def accept_matrix_int( + arg0: typing.Annotated[ + numpy.ndarray, numpy.int32, pybind11_stubgen.typing_ext.FixedSize(3, 3) + ] +) -> None: ... +def accept_vector_float64( + arg0: typing.Annotated[ + numpy.ndarray, numpy.float64, pybind11_stubgen.typing_ext.FixedSize(3, 1) + ] +) -> None: ... +def dense_matrix_c( + arg0: typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") + ] +) -> typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") +]: ... +def dense_matrix_r( + arg0: typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") + ] +) -> typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") +]: ... +def fixed_mutator_a( + arg0: typing.Annotated[ + numpy.ndarray, + numpy.float32, + pybind11_stubgen.typing_ext.FixedSize(5, 6), + numpy.ndarray.flags.writeable, + ] +) -> None: ... +def fixed_mutator_c( + arg0: typing.Annotated[ + numpy.ndarray, + numpy.float32, + pybind11_stubgen.typing_ext.FixedSize(5, 6), + numpy.ndarray.flags.writeable, + numpy.ndarray.flags.f_contiguous, + ] +) -> None: ... +def fixed_mutator_r( + arg0: typing.Annotated[ + numpy.ndarray, + numpy.float32, + pybind11_stubgen.typing_ext.FixedSize(5, 6), + numpy.ndarray.flags.writeable, + numpy.ndarray.flags.c_contiguous, + ] +) -> None: ... +def four_col_matrix_r( + arg0: typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", 4) + ] +) -> typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", 4) +]: ... +def four_row_matrix_r( + arg0: typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize(4, "n") + ] +) -> typing.Annotated[ + numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize(4, "n") +]: ... +def get_matrix_int() -> typing.Annotated[ + numpy.ndarray, numpy.int32, pybind11_stubgen.typing_ext.FixedSize(3, 3) +]: ... +def get_vector_float64() -> typing.Annotated[ + numpy.ndarray, numpy.float64, pybind11_stubgen.typing_ext.FixedSize(3, 1) +]: ... +def sparse_matrix_c( + arg0: typing.Annotated[scipy.sparse.csc_matrix, numpy.float32] +) -> typing.Annotated[scipy.sparse.csc_matrix, numpy.float32]: ... +def sparse_matrix_r( + arg0: typing.Annotated[scipy.sparse.csr_matrix, numpy.float32] +) -> typing.Annotated[scipy.sparse.csr_matrix, numpy.float32]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi new file mode 100644 index 0000000..57aba5b --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi @@ -0,0 +1,71 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "Blue", + "ConsoleForegroundColor", + "Green", + "Magenta", + "None_", + "Yellow", + "accept_defaulted_enum", +] + +class ConsoleForegroundColor: + """ + Members: + + Green + + Yellow + + Blue + + Magenta + + None_ + """ + + Blue: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Green: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Magenta: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + None_: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + Yellow: typing.ClassVar[ + ConsoleForegroundColor + ] # value = + __members__: typing.ClassVar[ + dict[str, ConsoleForegroundColor] + ] # value = {'Green': , 'Yellow': , 'Blue': , 'Magenta': , 'None_': } + def __eq__(self, other: typing.Any) -> bool: ... + def __getstate__(self) -> int: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __init__(self, value: int) -> None: ... + def __int__(self) -> int: ... + def __ne__(self, other: typing.Any) -> bool: ... + def __repr__(self) -> str: ... + def __setstate__(self, state: int) -> None: ... + def __str__(self) -> str: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +def accept_defaulted_enum( + color: ConsoleForegroundColor = ConsoleForegroundColor.None_, +) -> None: ... + +Blue: ConsoleForegroundColor # value = +Green: ConsoleForegroundColor # value = +Magenta: ConsoleForegroundColor # value = +None_: ConsoleForegroundColor # value = +Yellow: ConsoleForegroundColor # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi new file mode 100644 index 0000000..4f3886e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi @@ -0,0 +1,23 @@ +from __future__ import annotations + +__all__: list[str] = [ + "Enum", + "Unbound", + "accept_unbound_enum", + "accept_unbound_enum_defaulted", + "accept_unbound_type", + "accept_unbound_type_defaulted", + "get_unbound_type", +] + +class Enum: + pass + +class Unbound: + pass + +def accept_unbound_enum(arg0: ...) -> int: ... +def accept_unbound_enum_defaulted(x: Enum = ...) -> int: ... +def accept_unbound_type(arg0: tuple[..., int]) -> int: ... +def accept_unbound_type_defaulted(x: Unbound = ...) -> int: ... +def get_unbound_type() -> ...: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi new file mode 100644 index 0000000..79f666a --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi @@ -0,0 +1,58 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "Foo", + "accept_annotated_callable", + "accept_callable", + "accept_frozenset", + "accept_py_handle", + "accept_py_object", + "accept_set", + "add", + "default_custom_arg", + "default_int_arg", + "default_list_arg", + "default_optional_arg", + "func_w_anon_args", + "func_w_named_pos_args", + "generic", + "mul", + "pass_callback", + "pos_kw_only_mix", + "pos_kw_only_variadic_mix", +] + +class Foo: + def __init__(self, arg0: int) -> None: ... + +def accept_annotated_callable(arg0: typing.Callable[[int, int], int]) -> typing.Any: ... +def accept_callable(arg0: typing.Callable) -> typing.Any: ... +def accept_frozenset(arg0: frozenset) -> None: ... +def accept_py_handle(arg0: typing.Any) -> str: ... +def accept_py_object(arg0: typing.Any) -> str: ... +def accept_set(arg0: set) -> None: ... +def add(arg0: int, arg1: int) -> int: ... +def default_custom_arg(foo: Foo = Foo(5)) -> None: ... +def default_int_arg(n: int = 5) -> None: ... +def default_list_arg(l: list = [1, 2, 6, 18]) -> None: ... +def default_optional_arg(n: int | None = None) -> None: ... +def func_w_anon_args(arg0: int, arg1: int, arg2: int) -> None: ... +def func_w_named_pos_args(x: int, y: int, z: int) -> None: ... +def generic(*args, **kwargs) -> None: ... +@typing.overload +def mul(x: int, y: int) -> int: + """ + Multiply x and y (int) + """ + +@typing.overload +def mul(p: float, q: float) -> float: + """ + Multiply p and q (double) + """ + +def pass_callback(arg0: typing.Callable[[Foo], Foo]) -> Foo: ... +def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: ... +def pos_kw_only_variadic_mix(i: int, /, j: int, *args, k: int, **kwargs) -> tuple: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi new file mode 100644 index 0000000..cf6abad --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi @@ -0,0 +1,37 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "backslashes_should_be_escaped", + "issue_51_catastrophic_regex", + "issue_73_utf8_doc_chars", +] + +def backslashes_should_be_escaped() -> None: + """ + \\brief A brief description of this function. + + A detailed description of this function. + + Here's some reStructuredText: :math:`x = [x, y, \\theta]^T` + """ + +def issue_51_catastrophic_regex(arg0: int, arg1: int) -> None: + """ + Use-case: + issue_51(os.get_handle_inheritable, os.set_handle_inheritable) + """ + +def issue_73_utf8_doc_chars() -> None: + """ + Construct a Ramsete unicycle controller. + + Tuning parameter (b > 0 rad²/m²) for which larger values make + + convergence more aggressive like a proportional term. + Tuning parameter (0 rad⁻¹ < zeta < 1 rad⁻¹) for which larger + values provide more damping in response. + """ + +_cleanup: typing.Any # value = diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi new file mode 100644 index 0000000..6c115cd --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +__all__: list[str] = ["Dummy"] + +class Dummy: + @staticmethod + def static_method(arg0: int) -> int: ... + def regular_method(self, arg0: int) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi new file mode 100644 index 0000000..e211caa --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi @@ -0,0 +1,21 @@ +from __future__ import annotations + +import typing + +import numpy + +__all__: list[str] = [ + "accept_ndarray_float64", + "accept_ndarray_int", + "get_ndarray_float64", + "get_ndarray_int", + "return_dtype", +] + +def accept_ndarray_float64( + arg0: typing.Annotated[numpy.ndarray, numpy.float64] +) -> None: ... +def accept_ndarray_int(arg0: typing.Annotated[numpy.ndarray, numpy.int32]) -> None: ... +def get_ndarray_float64() -> typing.Annotated[numpy.ndarray, numpy.float64]: ... +def get_ndarray_int() -> typing.Annotated[numpy.ndarray, numpy.int32]: ... +def return_dtype() -> numpy.dtype[typing.Any]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi new file mode 100644 index 0000000..9d81595 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi @@ -0,0 +1,99 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "WithGetterSetterDoc", + "WithPropAndGetterSetterDoc", + "WithPropDoc", + "WithoutDoc", +] + +class WithGetterSetterDoc: + """ + User docstring provided via pybind11::cpp_function(..., doc) to getters/setters, but NOT to `def_*(..., doc)` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + getter doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: + """ + setter doc token + """ + @property + def def_property_readonly(self) -> int: + """ + getter doc token + """ + +class WithPropAndGetterSetterDoc: + """ + User docstring provided via pybind11::cpp_function(..., doc) to getters/setters and to `def_*(, doc)` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + prop doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: ... + @property + def def_property_readonly(self) -> int: + """ + prop doc token + """ + +class WithPropDoc: + """ + User docstring provided only to `def_` calls + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + @property + def def_property(self) -> int: + """ + prop doc token + """ + @def_property.setter + def def_property(self, arg1: int) -> None: ... + @property + def def_property_readonly(self) -> int: + """ + prop doc token + """ + @property + def def_readonly(self) -> int: + """ + prop doc token + """ + @property + def def_readwrite(self) -> int: + """ + prop doc token + """ + @def_readwrite.setter + def def_readwrite(self, arg0: int) -> None: ... + +class WithoutDoc: + """ + No user docstring provided + """ + + def_property_readonly_static: typing.ClassVar[int] = 0 + def_property_static: typing.ClassVar[int] = 0 + def_property: int + def_readwrite: int + @property + def def_property_readonly(self) -> int: ... + @property + def def_readonly(self) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi new file mode 100644 index 0000000..bd5bb49 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi @@ -0,0 +1,21 @@ +from __future__ import annotations + +import typing + +import pybind11_stubgen.typing_ext + +__all__: list[str] = [ + "std_array", + "std_map", + "std_optional", + "std_variant", + "std_vector", +] + +def std_array( + arg0: typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)] +) -> typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)]: ... +def std_map() -> dict[int, complex]: ... +def std_optional(arg0: int | None) -> None: ... +def std_variant(arg0: int | float | tuple[int, int]) -> None: ... +def std_vector() -> list[tuple[int, float]]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi new file mode 100644 index 0000000..6f1f9b6 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi @@ -0,0 +1,124 @@ +from __future__ import annotations + +import typing + +__all__: list[str] = [ + "MapStringComplex", + "VectorPairStringDouble", + "get_complex_map", + "get_vector_of_pairs", +] + +class MapStringComplex: + def __bool__(self) -> bool: + """ + Check whether the map is nonempty + """ + @typing.overload + def __contains__(self, arg0: str) -> bool: ... + @typing.overload + def __contains__(self, arg0: typing.Any) -> bool: ... + def __delitem__(self, arg0: str) -> None: ... + def __getitem__(self, arg0: str) -> complex: ... + def __init__(self) -> None: ... + def __iter__(self) -> typing.Iterator[str]: ... + def __len__(self) -> int: ... + def __repr__(self) -> str: + """ + Return the canonical string representation of this map. + """ + def __setitem__(self, arg0: str, arg1: complex) -> None: ... + def items(self) -> typing.ItemsView: ... + def keys(self) -> typing.KeysView: ... + def values(self) -> typing.ValuesView: ... + +class VectorPairStringDouble: + __hash__: typing.ClassVar[None] = None + def __bool__(self) -> bool: + """ + Check whether the list is nonempty + """ + def __contains__(self, x: tuple[str, float]) -> bool: + """ + Return true the container contains ``x`` + """ + @typing.overload + def __delitem__(self, arg0: int) -> None: + """ + Delete the list elements at index ``i`` + """ + @typing.overload + def __delitem__(self, arg0: slice) -> None: + """ + Delete list elements using a slice object + """ + def __eq__(self, arg0: VectorPairStringDouble) -> bool: ... + @typing.overload + def __getitem__(self, s: slice) -> VectorPairStringDouble: + """ + Retrieve list elements using a slice object + """ + @typing.overload + def __getitem__(self, arg0: int) -> tuple[str, float]: ... + @typing.overload + def __init__(self) -> None: ... + @typing.overload + def __init__(self, arg0: VectorPairStringDouble) -> None: + """ + Copy constructor + """ + @typing.overload + def __init__(self, arg0: typing.Iterable) -> None: ... + def __iter__(self) -> typing.Iterator[tuple[str, float]]: ... + def __len__(self) -> int: ... + def __ne__(self, arg0: VectorPairStringDouble) -> bool: ... + @typing.overload + def __setitem__(self, arg0: int, arg1: tuple[str, float]) -> None: ... + @typing.overload + def __setitem__(self, arg0: slice, arg1: VectorPairStringDouble) -> None: + """ + Assign list elements using a slice object + """ + def append(self, x: tuple[str, float]) -> None: + """ + Add an item to the end of the list + """ + def clear(self) -> None: + """ + Clear the contents + """ + def count(self, x: tuple[str, float]) -> int: + """ + Return the number of times ``x`` appears in the list + """ + @typing.overload + def extend(self, L: VectorPairStringDouble) -> None: + """ + Extend the list by appending all the items in the given list + """ + @typing.overload + def extend(self, L: typing.Iterable) -> None: + """ + Extend the list by appending all the items in the given list + """ + def insert(self, i: int, x: tuple[str, float]) -> None: + """ + Insert an item at a given position. + """ + @typing.overload + def pop(self) -> tuple[str, float]: + """ + Remove and return the last item + """ + @typing.overload + def pop(self, i: int) -> tuple[str, float]: + """ + Remove and return the item at index ``i`` + """ + def remove(self, x: tuple[str, float]) -> None: + """ + Remove the first item from the list whose value is x. It is an error if there is no such item. + """ + +def get_complex_map() -> MapStringComplex: ... +def get_vector_of_pairs() -> VectorPairStringDouble: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi new file mode 100644 index 0000000..f2c4ab9 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi @@ -0,0 +1,10 @@ +from __future__ import annotations + +import typing + +import typing_extensions + +__all__: list[str] = ["get_buffer", "get_sequence"] + +def get_buffer(arg0: typing_extensions.Buffer) -> typing_extensions.Buffer: ... +def get_sequence(arg0: typing.Sequence) -> typing.Sequence: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/values.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/values.pyi new file mode 100644 index 0000000..7c36d3f --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/values.pyi @@ -0,0 +1,36 @@ +from __future__ import annotations + +import datetime + +import numpy +from numpy import random + +__all__: list[str] = [ + "Dummy", + "Foo", + "add_day", + "foolist", + "foovar", + "list_with_none", + "none", + "random", + "t_10ms", + "t_20ns", + "t_30s", +] + +class Dummy: + linalg = numpy.linalg + +class Foo: + pass + +def add_day(arg0: datetime.datetime) -> datetime.datetime: ... + +foolist: list # value = [, ] +foovar: Foo # value = +list_with_none: list = [None, 2, {}] +none = None +t_10ms: datetime.timedelta # value = datetime.timedelta(microseconds=10000) +t_20ns: datetime.timedelta # value = datetime.timedelta(0) +t_30s: datetime.timedelta # value = datetime.timedelta(seconds=30) diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/core.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/core.pyi new file mode 100644 index 0000000..95c1646 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/core.pyi @@ -0,0 +1,35 @@ +from __future__ import annotations + +from demo._bindings import ( + aliases, + classes, + eigen, + enum, + flawed_bindings, + functions, + issues, + methods, + numpy, + properties, + stl, + stl_bind, + typing, + values, +) + +__all__: list[str] = [ + "aliases", + "classes", + "eigen", + "enum", + "flawed_bindings", + "functions", + "issues", + "methods", + "numpy", + "properties", + "stl", + "stl_bind", + "typing", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/__init__.pyi new file mode 100644 index 0000000..10d343e --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/__init__.pyi @@ -0,0 +1,11 @@ +from __future__ import annotations + +from . import classes, functions, functions_3_8_plus, functions_3_9_plus, values + +__all__: list[str] = [ + "classes", + "functions", + "functions_3_8_plus", + "functions_3_9_plus", + "values", +] diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/classes.pyi new file mode 100644 index 0000000..32aa068 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/classes.pyi @@ -0,0 +1,21 @@ +from __future__ import annotations + +__all__: list[str] = ["A", "B", "C", "X"] + +class A: + """ + A + """ + +class B(A): + """ + B + """ + +class C(B): + """ + C + """ + +class X: + pass diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions.pyi new file mode 100644 index 0000000..5ed9ef3 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions.pyi @@ -0,0 +1,31 @@ +from __future__ import annotations + +import sys as sys +import typing as typing + +from demo.pure_python.functions_3_8_plus import args_mix +from demo.pure_python.functions_3_9_plus import generic_alias_annotation + +__all__: list[str] = [ + "accept_frozenset", + "args_mix", + "builtin_function_as_default_arg", + "function_as_default_arg", + "generic_alias_annotation", + "lambda_as_default_arg", + "search", + "static_method_as_default_arg", + "sys", + "typing", +] + +class _Dummy: + @staticmethod + def foo(): ... + +def accept_frozenset(arg: frozenset[int | float]) -> int | None: ... +def builtin_function_as_default_arg(func: type(len) = len): ... +def function_as_default_arg(func: type(search) = search): ... +def lambda_as_default_arg(callback=...): ... +def search(a: int, b: list[int]) -> int: ... +def static_method_as_default_arg(callback=_Dummy.foo): ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_8_plus.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_8_plus.pyi new file mode 100644 index 0000000..e916422 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_8_plus.pyi @@ -0,0 +1,15 @@ +from __future__ import annotations + +import typing as typing + +__all__: list[str] = ["args_mix", "typing"] + +def args_mix( + a: int, + b: float = 0.5, + c: str = "", + *args: int, + x: int = 1, + y=int, + **kwargs: typing.Dict[int, str], +): ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_9_plus.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_9_plus.pyi new file mode 100644 index 0000000..59b9b80 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/functions_3_9_plus.pyi @@ -0,0 +1,5 @@ +from __future__ import annotations + +__all__: list[str] = ["generic_alias_annotation"] + +def generic_alias_annotation(a: list[tuple[int]], b: dict[int, str]) -> list[float]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/values.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/values.pyi new file mode 100644 index 0000000..0791339 --- /dev/null +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/pure_python/values.pyi @@ -0,0 +1,4 @@ +from __future__ import annotations + +__all__: list[str] = ["callables_dict"] +callables_dict: dict = {"len": len, "int": int} From 0a566ba1ac3cb1a892150caa8f6308157babffce Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Mon, 11 Aug 2025 11:33:13 +0200 Subject: [PATCH 02/16] Add pybind v3.0.0 to CI --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9082e1e..0dc24db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,12 @@ jobs: - python: "3.13" pybind11-branch: "v2.13" numpy-format: "numpy-array-use-type-var" + - python: "3.13" + pybind11-branch: "v3.0.0" + numpy-format: "numpy-array-wrap-with-annotated" + - python: "3.13" + pybind11-branch: "v3.0.0" + numpy-format: "numpy-array-use-type-var" # # TODO: uncomment # - python: "3.13" # pybind11-branch: "master" From 0fb7918fa1704a28a5de397a57b7311eb3c9f424 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 12:34:45 +0200 Subject: [PATCH 03/16] Fix FixNumpyArrayDimTypeVar for pybind v3.0.0 --- pybind11_stubgen/parser/mixins/fix.py | 186 +++++++++++++----- tests/demo-lib/include/demo/Foo.h | 2 +- .../py-demo/bindings/src/modules/methods.cpp | 8 +- tests/py-demo/bindings/src/modules/values.cpp | 12 +- .../demo/_bindings/aliases/__init__.pyi | 2 +- .../demo/_bindings/classes.pyi | 9 +- .../demo/_bindings/eigen.pyi | 1 + .../demo/_bindings/enum.pyi | 4 +- .../demo/_bindings/flawed_bindings.pyi | 4 +- .../demo/_bindings/functions.pyi | 42 ++-- .../demo/_bindings/issues.pyi | 4 +- .../demo/_bindings/methods.pyi | 6 +- .../demo/_bindings/numpy.pyi | 1 + .../demo/_bindings/properties.pyi | 18 +- .../demo/_bindings/stl.pyi | 15 +- .../demo/_bindings/stl_bind.pyi | 31 +-- .../demo/_bindings/typing.pyi | 8 +- 17 files changed, 242 insertions(+), 111 deletions(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index 8789890..b027402 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -40,7 +40,6 @@ class RemoveSelfAnnotation(IParser): - __any_t_name = QualifiedName.from_str("Any") __typing_any_t_name = QualifiedName.from_str("typing.Any") @@ -632,10 +631,19 @@ def report_error(self, error: ParserError) -> None: class FixNumpyArrayDimTypeVar(IParser): - __array_names: set[QualifiedName] = {QualifiedName.from_str("numpy.ndarray")} + __array_names: set[QualifiedName] = { + QualifiedName.from_str("numpy.ndarray"), + QualifiedName.from_str("numpy.typing.ArrayLike"), + QualifiedName.from_str("numpy.typing.NDArray"), + } + __typing_annotated_names = { + QualifiedName.from_str("typing.Annotated"), + QualifiedName.from_str("typing_extensions.Annotated"), + } numpy_primitive_types = FixNumpyArrayDimAnnotation.numpy_primitive_types __DIM_VARS: set[str] = set() + __DIM_STRING_PATTERN = re.compile(r'"\[(.*?)\]"') def handle_module( self, path: QualifiedName, module: types.ModuleType @@ -659,19 +667,12 @@ def handle_module( ) self.__DIM_VARS.clear() - return result def parse_annotation_str( self, annotation_str: str ) -> ResolvedType | InvalidExpression | Value: - # Affects types of the following pattern: - # numpy.ndarray[PRIMITIVE_TYPE[*DIMS], *FLAGS] - # Replace with: - # numpy.ndarray[tuple[M, Literal[1]], numpy.dtype[numpy.float32]] - result = super().parse_annotation_str(annotation_str) - if not isinstance(result, ResolvedType): return result @@ -679,65 +680,142 @@ def parse_annotation_str( if len(result.name) == 1 and len(result.name[0]) == 1: result.name = QualifiedName.from_str(result.name[0].upper()) self.__DIM_VARS.add(result.name[0]) + return result - if result.name not in self.__array_names: + if result.name == QualifiedName.from_str("numpy.ndarray"): + parameters = self._handle_old_style_numpy_array(result.parameters) + elif result.name in self.__array_names: + parameters = self._handle_new_style_numpy_array([result]) + elif result.name in self.__typing_annotated_names: + parameters = self._handle_new_style_numpy_array(result.parameters) + else: + parameters = None + if parameters is None: # Failure. return result + return ResolvedType( + name=QualifiedName.from_str("numpy.ndarray"), parameters=parameters + ) + + def _process_numpy_array_type( + self, scalar_type_name: QualifiedName, dimensions: list[int | str] | None + ) -> tuple[ResolvedType, ResolvedType]: + # Pybind annotates a bool Python type, which cannot be used with + # numpy.dtype because it does not inherit from numpy.generic. + # Only numpy.bool_ works reliably with both NumPy 1.x and 2.x. + if str(scalar_type_name) == "bool": + scalar_type_name = QualifiedName.from_str("numpy.bool_") + dtype = ResolvedType( + name=QualifiedName.from_str("numpy.dtype"), + parameters=[ResolvedType(name=scalar_type_name)], + ) + + shape = self.parse_annotation_str("Any") + if dimensions is not None and len(dimensions) > 0: + shape = self.parse_annotation_str("Tuple") + assert isinstance(shape, ResolvedType) + shape.parameters = [] + for dim in dimensions: + if isinstance(dim, int): + literal_dim = self.parse_annotation_str("Literal") + assert isinstance(literal_dim, ResolvedType) + literal_dim.parameters = [Value(repr=str(dim))] + shape.parameters.append(literal_dim) + else: + shape.parameters.append( + ResolvedType(name=QualifiedName.from_str(dim.upper())) + ) + return shape, dtype + + def _handle_new_style_numpy_array( + self, parameters: list[ResolvedType | Value | InvalidExpression] | None + ) -> list[ResolvedType] | None: + # Annotated[numpy.typing.ArrayLike, numpy.float32, "[m, n]"] + # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]"] + # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]", "flags.writeable", "flags.c_contiguous"] + if parameters is None or len(parameters) == 0: + return + + array_type, *parameters = parameters + if ( + not isinstance(array_type, ResolvedType) + or array_type.name not in self.__array_names + ): + return + + dims_and_flags: Sequence[ResolvedType | Value | InvalidExpression] + if array_type.name == QualifiedName.from_str("numpy.typing.ArrayLike"): + if not parameters: + return + scalar_type, *dims_and_flags = parameters + elif array_type.name == QualifiedName.from_str("numpy.typing.NDArray"): + if array_type.parameters is None or len(array_type.parameters) == 0: + return + [scalar_type] = array_type.parameters + dims_and_flags = parameters + elif array_type.name == QualifiedName.from_str("numpy.ndarray"): + _, dtype_param = array_type.parameters + if not ( + isinstance(dtype_param, ResolvedType) + and dtype_param.name == QualifiedName.from_str("numpy.dtype") + and dtype_param.parameters + ): + return + [scalar_type] = dtype_param.parameters + dims_and_flags = parameters + else: + return + scalar_type_name = scalar_type.name + if scalar_type_name not in self.numpy_primitive_types: + return + + dims: list[int | str] | None = None + if dims_and_flags: + dims_str, *flags = dims_and_flags + del flags # Unused. + if isinstance(dims_str, Value): + match = self.__DIM_STRING_PATTERN.search(dims_str.repr) + if match: + dims_str_content = match.group(1) + dims_list = [ + d.strip() for d in dims_str_content.split(",") if d.strip() + ] + if dims_list: + dims = self.__to_dims_from_strings(dims_list) + + return self._process_numpy_array_type(scalar_type_name, dims) + + def _handle_old_style_numpy_array( + self, parameters: list[ResolvedType | Value | InvalidExpression] | None + ) -> list[ResolvedType] | None: + # Affects types of the following pattern: + # numpy.ndarray[PRIMITIVE_TYPE[*DIMS], *FLAGS] + # Replace with: + # numpy.ndarray[tuple[M, Literal[1]], numpy.dtype[numpy.float32]] # ndarray is generic and should have 2 type arguments - if result.parameters is None or len(result.parameters) == 0: - result.parameters = [ + if parameters is None or len(parameters) == 0: + return [ self.parse_annotation_str("Any"), ResolvedType( name=QualifiedName.from_str("numpy.dtype"), parameters=[self.parse_annotation_str("Any")], ), ] - return result - - scalar_with_dims = result.parameters[0] # e.g. numpy.float64[32, 32] + scalar_with_dims = parameters[0] # e.g. numpy.float64[32, 32] if ( not isinstance(scalar_with_dims, ResolvedType) or scalar_with_dims.name not in self.numpy_primitive_types ): - return result - - name = scalar_with_dims.name - # Pybind annotates a bool Python type, which cannot be used with - # numpy.dtype because it does not inherit from numpy.generic. - # Only numpy.bool_ works reliably with both NumPy 1.x and 2.x. - if str(name) == "bool": - name = QualifiedName.from_str("numpy.bool_") - dtype = ResolvedType( - name=QualifiedName.from_str("numpy.dtype"), - parameters=[ResolvedType(name=name)], - ) + return - shape = self.parse_annotation_str("Any") + dims: list[int | str] | None = None if ( scalar_with_dims.parameters is not None and len(scalar_with_dims.parameters) > 0 ): dims = self.__to_dims(scalar_with_dims.parameters) - if dims is not None: - shape = self.parse_annotation_str("Tuple") - assert isinstance(shape, ResolvedType) - shape.parameters = [] - for dim in dims: - if isinstance(dim, int): - # self.parse_annotation_str will qualify Literal with either - # typing or typing_extensions and add the import to the module - literal_dim = self.parse_annotation_str("Literal") - assert isinstance(literal_dim, ResolvedType) - literal_dim.parameters = [Value(repr=str(dim))] - shape.parameters.append(literal_dim) - else: - shape.parameters.append( - ResolvedType(name=QualifiedName.from_str(dim)) - ) - - result.parameters = [shape, dtype] - return result + return self._process_numpy_array_type(scalar_with_dims.name, dims) def __to_dims( self, dimensions: Sequence[ResolvedType | Value | InvalidExpression] @@ -756,6 +834,20 @@ def __to_dims( result.append(dim) return result + def __to_dims_from_strings( + self, dimensions: Sequence[str] + ) -> list[int | str] | None: + result: list[int | str] = [] + for dim_str in dimensions: + try: + dim = int(dim_str) + except ValueError: + dim = dim_str + if len(dim) == 1: # Assuming single letter dims are type vars + self.__DIM_VARS.add(dim.upper()) # Add uppercase to TypeVar set + result.append(dim) + return result + def report_error(self, error: ParserError) -> None: if ( isinstance(error, NameResolutionError) diff --git a/tests/demo-lib/include/demo/Foo.h b/tests/demo-lib/include/demo/Foo.h index 53bf7c2..ae19bdd 100644 --- a/tests/demo-lib/include/demo/Foo.h +++ b/tests/demo-lib/include/demo/Foo.h @@ -5,7 +5,7 @@ namespace demo{ class CppException : public std::runtime_error { - using std::runtime_error::runtime_error; + //using std::runtime_error; }; struct Foo { diff --git a/tests/py-demo/bindings/src/modules/methods.cpp b/tests/py-demo/bindings/src/modules/methods.cpp index f281495..4f96a0c 100644 --- a/tests/py-demo/bindings/src/modules/methods.cpp +++ b/tests/py-demo/bindings/src/modules/methods.cpp @@ -1,6 +1,6 @@ #include "modules.h" -namespace { +namespace mymodules { struct Dummy { int regular_method(int x) { return x + 1; } static int static_method(int x) { return x + 1; } @@ -9,8 +9,8 @@ struct Dummy { } // namespace void bind_methods_module(py::module&& m) { - auto &&pyDummy = py::class_(m, "Dummy"); + auto &&pyDummy = py::class_(m, "Dummy"); - pyDummy.def_static("static_method", &Dummy::static_method); - pyDummy.def("regular_method", &Dummy::regular_method); + pyDummy.def_static("static_method", &mymodules::Dummy::static_method); + pyDummy.def("regular_method", &mymodules::Dummy::regular_method); } diff --git a/tests/py-demo/bindings/src/modules/values.cpp b/tests/py-demo/bindings/src/modules/values.cpp index 98ae806..415ff8a 100644 --- a/tests/py-demo/bindings/src/modules/values.cpp +++ b/tests/py-demo/bindings/src/modules/values.cpp @@ -4,7 +4,7 @@ #include -namespace { +namespace myvalues { class Dummy {}; class Foo {}; } // namespace @@ -12,7 +12,7 @@ class Foo {}; void bind_values_module(py::module &&m) { { // python module as value - auto &&pyDummy = py::class_(m, "Dummy"); + auto &&pyDummy = py::class_(m, "Dummy"); pyDummy.def_property_readonly_static( "linalg", [](py::object &) { return py::module::import("numpy.linalg"); }); @@ -27,12 +27,12 @@ void bind_values_module(py::module &&m) { m.attr("list_with_none") = li; } { - auto pyFoo = py::class_(m, "Foo"); - m.attr("foovar") = Foo(); + auto pyFoo = py::class_(m, "Foo"); + m.attr("foovar") = myvalues::Foo(); py::list foolist; - foolist.append(Foo()); - foolist.append(Foo()); + foolist.append(myvalues::Foo()); + foolist.append(myvalues::Foo()); m.attr("foolist") = foolist; m.attr("none") = py::none(); diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi index 93963f4..8d6f4ce 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/aliases/__init__.pyi @@ -47,7 +47,7 @@ class Dummy: def foreign_enum_default( color: typing.Any = demo._bindings.enum.ConsoleForegroundColor.Blue, ) -> None: ... -def func(arg0: int) -> int: ... +def func(arg0: typing.SupportsInt) -> int: ... local_func_alias = func local_type_alias = Color diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi index ea36dda..addca14 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/classes.pyi @@ -13,7 +13,10 @@ class CppException(Exception): pass class Derived(Base): - count: int + @property + def count(self) -> int: ... + @count.setter + def count(self, arg0: typing.SupportsInt) -> None: ... class Foo: class FooChild: @@ -43,11 +46,11 @@ class Outer: def __getstate__(self) -> int: ... def __hash__(self) -> int: ... def __index__(self) -> int: ... - def __init__(self, value: int) -> None: ... + def __init__(self, value: typing.SupportsInt) -> None: ... def __int__(self) -> int: ... def __ne__(self, other: typing.Any) -> bool: ... def __repr__(self) -> str: ... - def __setstate__(self, state: int) -> None: ... + def __setstate__(self, state: typing.SupportsInt) -> None: ... def __str__(self) -> str: ... @property def name(self) -> str: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi index 742d2ee..56e5da5 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi @@ -3,6 +3,7 @@ from __future__ import annotations import typing import numpy +import numpy.typing import scipy.sparse __all__: list[str] = [ diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi index 57aba5b..a994e39 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/enum.pyi @@ -49,11 +49,11 @@ class ConsoleForegroundColor: def __getstate__(self) -> int: ... def __hash__(self) -> int: ... def __index__(self) -> int: ... - def __init__(self, value: int) -> None: ... + def __init__(self, value: typing.SupportsInt) -> None: ... def __int__(self) -> int: ... def __ne__(self, other: typing.Any) -> bool: ... def __repr__(self) -> str: ... - def __setstate__(self, state: int) -> None: ... + def __setstate__(self, state: typing.SupportsInt) -> None: ... def __str__(self) -> str: ... @property def name(self) -> str: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi index 4f3886e..d95bbb3 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/flawed_bindings.pyi @@ -1,5 +1,7 @@ from __future__ import annotations +import typing + __all__: list[str] = [ "Enum", "Unbound", @@ -18,6 +20,6 @@ class Unbound: def accept_unbound_enum(arg0: ...) -> int: ... def accept_unbound_enum_defaulted(x: Enum = ...) -> int: ... -def accept_unbound_type(arg0: tuple[..., int]) -> int: ... +def accept_unbound_type(arg0: tuple[..., typing.SupportsInt]) -> int: ... def accept_unbound_type_defaulted(x: Unbound = ...) -> int: ... def get_unbound_type() -> ...: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi index 79f666a..5888147 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/functions.pyi @@ -1,5 +1,6 @@ from __future__ import annotations +import collections.abc import typing __all__: list[str] = [ @@ -25,34 +26,49 @@ __all__: list[str] = [ ] class Foo: - def __init__(self, arg0: int) -> None: ... + def __init__(self, arg0: typing.SupportsInt) -> None: ... -def accept_annotated_callable(arg0: typing.Callable[[int, int], int]) -> typing.Any: ... -def accept_callable(arg0: typing.Callable) -> typing.Any: ... +def accept_annotated_callable( + arg0: collections.abc.Callable[[typing.SupportsInt, typing.SupportsInt], int] +) -> typing.Any: ... +def accept_callable(arg0: collections.abc.Callable) -> typing.Any: ... def accept_frozenset(arg0: frozenset) -> None: ... def accept_py_handle(arg0: typing.Any) -> str: ... def accept_py_object(arg0: typing.Any) -> str: ... def accept_set(arg0: set) -> None: ... -def add(arg0: int, arg1: int) -> int: ... +def add(arg0: typing.SupportsInt, arg1: typing.SupportsInt) -> int: ... def default_custom_arg(foo: Foo = Foo(5)) -> None: ... -def default_int_arg(n: int = 5) -> None: ... +def default_int_arg(n: typing.SupportsInt = 5) -> None: ... def default_list_arg(l: list = [1, 2, 6, 18]) -> None: ... -def default_optional_arg(n: int | None = None) -> None: ... -def func_w_anon_args(arg0: int, arg1: int, arg2: int) -> None: ... -def func_w_named_pos_args(x: int, y: int, z: int) -> None: ... +def default_optional_arg(n: typing.SupportsInt | None = None) -> None: ... +def func_w_anon_args( + arg0: typing.SupportsInt, arg1: typing.SupportsInt, arg2: typing.SupportsInt +) -> None: ... +def func_w_named_pos_args( + x: typing.SupportsInt, y: typing.SupportsInt, z: typing.SupportsInt +) -> None: ... def generic(*args, **kwargs) -> None: ... @typing.overload -def mul(x: int, y: int) -> int: +def mul(x: typing.SupportsInt, y: typing.SupportsInt) -> int: """ Multiply x and y (int) """ @typing.overload -def mul(p: float, q: float) -> float: +def mul(p: typing.SupportsFloat, q: typing.SupportsFloat) -> float: """ Multiply p and q (double) """ -def pass_callback(arg0: typing.Callable[[Foo], Foo]) -> Foo: ... -def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: ... -def pos_kw_only_variadic_mix(i: int, /, j: int, *args, k: int, **kwargs) -> tuple: ... +def pass_callback(arg0: collections.abc.Callable[[Foo], Foo]) -> Foo: ... +def pos_kw_only_mix( + i: typing.SupportsInt, /, j: typing.SupportsInt, *, k: typing.SupportsInt +) -> tuple: ... +def pos_kw_only_variadic_mix( + i: typing.SupportsInt, + /, + j: typing.SupportsInt, + *args, + k: typing.SupportsInt, + **kwargs, +) -> tuple: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi index cf6abad..165940c 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/issues.pyi @@ -17,7 +17,9 @@ def backslashes_should_be_escaped() -> None: Here's some reStructuredText: :math:`x = [x, y, \\theta]^T` """ -def issue_51_catastrophic_regex(arg0: int, arg1: int) -> None: +def issue_51_catastrophic_regex( + arg0: typing.SupportsInt, arg1: typing.SupportsInt +) -> None: """ Use-case: issue_51(os.get_handle_inheritable, os.set_handle_inheritable) diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi index 6c115cd..406a301 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/methods.pyi @@ -1,8 +1,10 @@ from __future__ import annotations +import typing + __all__: list[str] = ["Dummy"] class Dummy: @staticmethod - def static_method(arg0: int) -> int: ... - def regular_method(self, arg0: int) -> int: ... + def static_method(arg0: typing.SupportsInt) -> int: ... + def regular_method(self, arg0: typing.SupportsInt) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi index 08714c5..0bc51bc 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi @@ -3,6 +3,7 @@ from __future__ import annotations import typing import numpy +import numpy.typing __all__: list[str] = [ "accept_ndarray_float64", diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi index 9d81595..d7ae367 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/properties.pyi @@ -22,7 +22,7 @@ class WithGetterSetterDoc: getter doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: + def def_property(self, arg1: typing.SupportsInt) -> None: """ setter doc token """ @@ -45,7 +45,7 @@ class WithPropAndGetterSetterDoc: prop doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: ... + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: """ @@ -65,7 +65,7 @@ class WithPropDoc: prop doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: ... + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: """ @@ -82,7 +82,7 @@ class WithPropDoc: prop doc token """ @def_readwrite.setter - def def_readwrite(self, arg0: int) -> None: ... + def def_readwrite(self, arg0: typing.SupportsInt) -> None: ... class WithoutDoc: """ @@ -91,9 +91,15 @@ class WithoutDoc: def_property_readonly_static: typing.ClassVar[int] = 0 def_property_static: typing.ClassVar[int] = 0 - def_property: int - def_readwrite: int + @property + def def_property(self) -> int: ... + @def_property.setter + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: ... @property def def_readonly(self) -> int: ... + @property + def def_readwrite(self) -> int: ... + @def_readwrite.setter + def def_readwrite(self, arg0: typing.SupportsInt) -> None: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi index bd5bb49..dbc3269 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl.pyi @@ -1,9 +1,8 @@ from __future__ import annotations +import collections.abc import typing -import pybind11_stubgen.typing_ext - __all__: list[str] = [ "std_array", "std_map", @@ -13,9 +12,13 @@ __all__: list[str] = [ ] def std_array( - arg0: typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)] -) -> typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)]: ... + arg0: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"] +) -> typing.Annotated[list[int], "FixedSize(3)"]: ... def std_map() -> dict[int, complex]: ... -def std_optional(arg0: int | None) -> None: ... -def std_variant(arg0: int | float | tuple[int, int]) -> None: ... +def std_optional(arg0: typing.SupportsInt | None) -> None: ... +def std_variant( + arg0: typing.SupportsInt + | typing.SupportsFloat + | tuple[typing.SupportsInt, typing.SupportsInt] +) -> None: ... def std_vector() -> list[tuple[int, float]]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi index 6f1f9b6..0020e1d 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/stl_bind.pyi @@ -1,5 +1,6 @@ from __future__ import annotations +import collections.abc import typing __all__: list[str] = [ @@ -21,7 +22,7 @@ class MapStringComplex: def __delitem__(self, arg0: str) -> None: ... def __getitem__(self, arg0: str) -> complex: ... def __init__(self) -> None: ... - def __iter__(self) -> typing.Iterator[str]: ... + def __iter__(self) -> collections.abc.Iterator[str]: ... def __len__(self) -> int: ... def __repr__(self) -> str: """ @@ -38,12 +39,12 @@ class VectorPairStringDouble: """ Check whether the list is nonempty """ - def __contains__(self, x: tuple[str, float]) -> bool: + def __contains__(self, x: tuple[str, typing.SupportsFloat]) -> bool: """ Return true the container contains ``x`` """ @typing.overload - def __delitem__(self, arg0: int) -> None: + def __delitem__(self, arg0: typing.SupportsInt) -> None: """ Delete the list elements at index ``i`` """ @@ -59,7 +60,7 @@ class VectorPairStringDouble: Retrieve list elements using a slice object """ @typing.overload - def __getitem__(self, arg0: int) -> tuple[str, float]: ... + def __getitem__(self, arg0: typing.SupportsInt) -> tuple[str, float]: ... @typing.overload def __init__(self) -> None: ... @typing.overload @@ -68,18 +69,20 @@ class VectorPairStringDouble: Copy constructor """ @typing.overload - def __init__(self, arg0: typing.Iterable) -> None: ... - def __iter__(self) -> typing.Iterator[tuple[str, float]]: ... + def __init__(self, arg0: collections.abc.Iterable) -> None: ... + def __iter__(self) -> collections.abc.Iterator[tuple[str, float]]: ... def __len__(self) -> int: ... def __ne__(self, arg0: VectorPairStringDouble) -> bool: ... @typing.overload - def __setitem__(self, arg0: int, arg1: tuple[str, float]) -> None: ... + def __setitem__( + self, arg0: typing.SupportsInt, arg1: tuple[str, typing.SupportsFloat] + ) -> None: ... @typing.overload def __setitem__(self, arg0: slice, arg1: VectorPairStringDouble) -> None: """ Assign list elements using a slice object """ - def append(self, x: tuple[str, float]) -> None: + def append(self, x: tuple[str, typing.SupportsFloat]) -> None: """ Add an item to the end of the list """ @@ -87,7 +90,7 @@ class VectorPairStringDouble: """ Clear the contents """ - def count(self, x: tuple[str, float]) -> int: + def count(self, x: tuple[str, typing.SupportsFloat]) -> int: """ Return the number of times ``x`` appears in the list """ @@ -97,11 +100,13 @@ class VectorPairStringDouble: Extend the list by appending all the items in the given list """ @typing.overload - def extend(self, L: typing.Iterable) -> None: + def extend(self, L: collections.abc.Iterable) -> None: """ Extend the list by appending all the items in the given list """ - def insert(self, i: int, x: tuple[str, float]) -> None: + def insert( + self, i: typing.SupportsInt, x: tuple[str, typing.SupportsFloat] + ) -> None: """ Insert an item at a given position. """ @@ -111,11 +116,11 @@ class VectorPairStringDouble: Remove and return the last item """ @typing.overload - def pop(self, i: int) -> tuple[str, float]: + def pop(self, i: typing.SupportsInt) -> tuple[str, float]: """ Remove and return the item at index ``i`` """ - def remove(self, x: tuple[str, float]) -> None: + def remove(self, x: tuple[str, typing.SupportsFloat]) -> None: """ Remove the first item from the list whose value is x. It is an error if there is no such item. """ diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi index f2c4ab9..98fd047 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/typing.pyi @@ -1,10 +1,8 @@ from __future__ import annotations -import typing - -import typing_extensions +import collections.abc __all__: list[str] = ["get_buffer", "get_sequence"] -def get_buffer(arg0: typing_extensions.Buffer) -> typing_extensions.Buffer: ... -def get_sequence(arg0: typing.Sequence) -> typing.Sequence: ... +def get_buffer(arg0: collections.abc.Buffer) -> collections.abc.Buffer: ... +def get_sequence(arg0: collections.abc.Sequence) -> collections.abc.Sequence: ... From 8396e1ee68aa2b9f6a664a9a92afe14b6ee78d69 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 12:35:05 +0200 Subject: [PATCH 04/16] Avoid unnecessary imports to numpy.typing --- pybind11_stubgen/parser/mixins/fix.py | 5 +++++ .../numpy-array-use-type-var/demo/_bindings/eigen.pyi | 1 - .../numpy-array-use-type-var/demo/_bindings/numpy.pyi | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index b027402..f58e82a 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -168,6 +168,11 @@ def _add_import(self, name: QualifiedName) -> None: if module_name is None: self.report_error(NameResolutionError(name)) return + # Corner case: we know that annotations in numpy.typing.* are accessible from + # numpy and we want to avoid unnecessary imports once these annotations are + # replaced by subsequent numpy fixers. + if module_name == ("numpy", "typing"): + module_name = module_name.parent self.__extra_imports.add(Import(name=None, origin=module_name)) def _get_parent_module(self, name: QualifiedName) -> QualifiedName | None: diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi index 56e5da5..742d2ee 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/eigen.pyi @@ -3,7 +3,6 @@ from __future__ import annotations import typing import numpy -import numpy.typing import scipy.sparse __all__: list[str] = [ diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi index 0bc51bc..08714c5 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-use-type-var/demo/_bindings/numpy.pyi @@ -3,7 +3,6 @@ from __future__ import annotations import typing import numpy -import numpy.typing __all__: list[str] = [ "accept_ndarray_float64", From b47aa1297181b58d3e90cc60bf75e8bfcb484064 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 12:44:07 +0200 Subject: [PATCH 05/16] Make flake8 happy --- pybind11_stubgen/parser/mixins/fix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index f58e82a..ce640d8 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -736,7 +736,7 @@ def _handle_new_style_numpy_array( ) -> list[ResolvedType] | None: # Annotated[numpy.typing.ArrayLike, numpy.float32, "[m, n]"] # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]"] - # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]", "flags.writeable", "flags.c_contiguous"] + # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]", "flags.writeable" , "flags.c_contiguous"] # noqa: E501 if parameters is None or len(parameters) == 0: return From b34c9058743d8c39233434d6d04634dcef3d36ca Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 14:17:31 +0200 Subject: [PATCH 06/16] Unify logic for different cases --- pybind11_stubgen/__init__.py | 2 - pybind11_stubgen/parser/mixins/fix.py | 546 +++++++++++++------------- 2 files changed, 274 insertions(+), 274 deletions(-) diff --git a/pybind11_stubgen/__init__.py b/pybind11_stubgen/__init__.py index 89f7a9c..a6010aa 100644 --- a/pybind11_stubgen/__init__.py +++ b/pybind11_stubgen/__init__.py @@ -36,7 +36,6 @@ FixMissingNoneHashFieldAnnotation, FixNumpyArrayDimAnnotation, FixNumpyArrayDimTypeVar, - FixNumpyArrayFlags, FixNumpyArrayRemoveParameters, FixNumpyDtype, FixPEP585CollectionNames, @@ -265,7 +264,6 @@ class Parser( OverridePrintSafeValues, *numpy_fixes, # type: ignore[misc] FixNumpyDtype, - FixNumpyArrayFlags, FixCurrentModulePrefixInTypeNames, FixBuiltinTypes, RewritePybind11EnumValueRepr, diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index ce640d8..f7382f0 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -7,7 +7,7 @@ import sys import types from logging import getLogger -from typing import Any, Sequence +from typing import Any, Optional, Sequence from pybind11_stubgen.parser.errors import ( InvalidExpressionError, @@ -501,19 +501,21 @@ def handle_value(self, value: Any) -> Value: return result -class FixNumpyArrayDimAnnotation(IParser): +class _NumpyArrayAnnotation: __array_names: set[QualifiedName] = { QualifiedName.from_str("numpy.ndarray"), + QualifiedName.from_str("numpy.typing.ArrayLike"), + QualifiedName.from_str("numpy.typing.NDArray"), *( QualifiedName.from_str(f"scipy.sparse.{storage}_{arr}") for storage in ["bsr", "coo", "csr", "csc", "dia", "dok", "lil"] for arr in ["array", "matrix"] ), } - # NB: Not using full name due to ambiguity `typing.Annotated` vs - # `typing_extension.Annotated` in different python versions - # Rely on later fix by `FixTypingTypeNames` - __annotated_name = QualifiedName.from_str("Annotated") + __typing_annotated_names = { + QualifiedName.from_str("typing.Annotated"), + QualifiedName.from_str("typing_extensions.Annotated"), + } numpy_primitive_types: set[QualifiedName] = set( map( QualifiedName.from_str, @@ -541,71 +543,172 @@ class FixNumpyArrayDimAnnotation(IParser): ), ) ) - __DIM_VARS = ["n", "m"] - - def parse_annotation_str( - self, annotation_str: str - ) -> ResolvedType | InvalidExpression | Value: - # Affects types of the following pattern: - # ARRAY_T[PRIMITIVE_TYPE[*DIMS], *FLAGS] - # Replace with: - # Annotated[ARRAY_T, PRIMITIVE_TYPE, FixedSize/DynamicSize[*DIMS], *FLAGS] - - result = super().parse_annotation_str(annotation_str) + __DIM_STRING_PATTERN = re.compile(r'"\[(.*?)\]"') + + def __init__( + self, + array_type: ResolvedType, + scalar_type: ResolvedType, + dimensions: Optional[list[str | int]], + flags: list[ResolvedType | Value | InvalidExpression], + ): + self.array_type = array_type + self.scalar_type = scalar_type + self.dimensions = dimensions + self.flags = flags + + def to_type_hint( + self, parser: IParser, on_dynamic_dim: Optional[callable[[str], None]] = None + ) -> tuple[ResolvedType, ResolvedType]: + scalar_type_name = self.scalar_type.name + # Pybind annotates a bool Python type, which cannot be used with + # numpy.dtype because it does not inherit from numpy.generic. + # Only numpy.bool_ works reliably with both NumPy 1.x and 2.x. + if str(scalar_type_name) == "bool": + scalar_type_name = QualifiedName.from_str("numpy.bool_") + dtype = ResolvedType( + name=QualifiedName.from_str("numpy.dtype"), + parameters=[ResolvedType(name=scalar_type_name)], + ) + + shape = parser.parse_annotation_str("Any") + if self.dimensions: + shape = parser.parse_annotation_str("Tuple") + assert isinstance(shape, ResolvedType) + shape.parameters = [] + for dim in self.dimensions: + if isinstance(dim, int): + literal_dim = parser.parse_annotation_str("Literal") + assert isinstance(literal_dim, ResolvedType) + literal_dim.parameters = [Value(repr=str(dim))] + shape.parameters.append(literal_dim) + else: + if on_dynamic_dim: + on_dynamic_dim(dim) + shape.parameters.append( + ResolvedType(name=QualifiedName.from_str(dim.upper())) + ) + return shape, dtype + + @classmethod + def from_annotation( + cls, resolved_type: ResolvedType + ) -> Optional[_NumpyArrayAnnotation]: + if resolved_type.name in cls.__typing_annotated_names: + return cls._from_new_style(resolved_type) + elif resolved_type.name in cls.__array_names: + return cls._from_old_style(resolved_type) + else: + return None + + @classmethod + def _from_old_style( + cls, resolved_type: ResolvedType + ) -> Optional[_NumpyArrayAnnotation]: + if resolved_type.parameters is None or len(resolved_type.parameters) == 0: + return None + + scalar_with_dims = resolved_type.parameters[0] + flags = resolved_type.parameters[1:] + if ( - not isinstance(result, ResolvedType) - or result.name not in self.__array_names - or result.parameters is None - or len(result.parameters) == 0 + not isinstance(scalar_with_dims, ResolvedType) + or scalar_with_dims.name not in cls.numpy_primitive_types ): - return result - - scalar_with_dims = result.parameters[0] # e.g. numpy.float64[32, 32] - flags = result.parameters[1:] - + return None + + array_type = ResolvedType(name=resolved_type.name) + scalar_type = ResolvedType(name=scalar_with_dims.name) + dimensions: Optional[list[str | int]] = None if ( - not isinstance(scalar_with_dims, ResolvedType) - or scalar_with_dims.name not in self.numpy_primitive_types + scalar_with_dims.parameters is not None + and len(scalar_with_dims.parameters) > 0 ): - return result - - result = ResolvedType( - name=self.__annotated_name, - parameters=[ - self.parse_annotation_str(str(result.name)), - ResolvedType(scalar_with_dims.name), - ], - ) + dimensions = cls._to_dims(scalar_with_dims.parameters) + + return _NumpyArrayAnnotation(array_type, scalar_type, dimensions, flags) + + @classmethod + def _from_new_style( + cls, resolved_type: ResolvedType + ) -> Optional[_NumpyArrayAnnotation]: + if resolved_type.parameters is None or len(resolved_type.parameters) == 0: + return None - assert result.parameters is not None + # Handle nested Annotated: Annotated[Annotated[NDArray[...]], "[m, n]"] if ( - scalar_with_dims.parameters is not None - and len(scalar_with_dims.parameters) >= 0 + len(resolved_type.parameters) > 1 + and isinstance(resolved_type.parameters[0], ResolvedType) + and resolved_type.parameters[0].name in cls.__typing_annotated_names ): - dims = self.__to_dims(scalar_with_dims.parameters) - if dims is not None and len(dims) > 0: - result.parameters += [ - self.handle_value(self.__wrap_with_size_helper(dims)) - ] + inner_annotated = resolved_type.parameters[0] + if inner_annotated.parameters is None: + return None + array_type_param = inner_annotated.parameters[0] + other_params = resolved_type.parameters[1:] + else: + array_type_param, *other_params = resolved_type.parameters - result.parameters += flags + if not isinstance(array_type_param, ResolvedType): + return None - return result + if array_type_param.name not in cls.__array_names: + return None - def __wrap_with_size_helper(self, dims: list[int | str]) -> FixedSize | DynamicSize: - if all(isinstance(d, int) for d in dims): - return_t = FixedSize + array_type = ResolvedType(name=array_type_param.name) + scalar_type: Optional[ResolvedType] = None + dims_and_flags: list[ResolvedType | Value | InvalidExpression] = [] + + if array_type.name == QualifiedName.from_str("numpy.typing.ArrayLike"): + if not other_params: + return None + scalar_type_param, *dims_and_flags = other_params + if isinstance(scalar_type_param, ResolvedType): + scalar_type = scalar_type_param + elif array_type.name == QualifiedName.from_str("numpy.typing.NDArray"): + array_type = ResolvedType(name=QualifiedName.from_str("numpy.ndarray")) + if array_type_param.parameters: + scalar_type_param = array_type_param.parameters[0] + if isinstance(scalar_type_param, ResolvedType): + scalar_type = scalar_type_param + dims_and_flags = other_params + elif array_type.name == QualifiedName.from_str("numpy.ndarray"): + if array_type_param.parameters and len(array_type_param.parameters) == 2: + _, dtype_param = array_type_param.parameters + if ( + isinstance(dtype_param, ResolvedType) + and dtype_param.name == QualifiedName.from_str("numpy.dtype") + and dtype_param.parameters + ): + scalar_type = dtype_param.parameters[0] + dims_and_flags = other_params else: - return_t = DynamicSize + return None - # TRICK: Use `self.handle_type` to make `FixedSize`/`DynamicSize` - # properly added to the list of imports - self.handle_type(return_t) - return return_t(*dims) # type: ignore[arg-type] + if scalar_type is None or scalar_type.name not in cls.numpy_primitive_types: + return None - def __to_dims( - self, dimensions: Sequence[ResolvedType | Value | InvalidExpression] + dims: list[int | str] | None = None + flags: list[ResolvedType | Value | InvalidExpression] = [] + if dims_and_flags: + dims_str_param = dims_and_flags[0] + if isinstance(dims_str_param, Value): + match = cls.__DIM_STRING_PATTERN.search(dims_str_param.repr) + if match: + dims_str_content = match.group(1) + dims_list = [ + d.strip() for d in dims_str_content.split(",") if d.strip() + ] + if dims_list: + dims = cls._to_dims_from_strings(dims_list) + flags = dims_and_flags[1:] + + return _NumpyArrayAnnotation(array_type, scalar_type, dims, flags) + + @classmethod + def _to_dims( + cls, dimensions: Sequence[ResolvedType | Value | InvalidExpression] ) -> list[int | str] | None: result = [] for dim_param in dimensions: @@ -616,13 +719,98 @@ def __to_dims( return None elif isinstance(dim_param, ResolvedType): dim = str(dim_param) - if dim not in self.__DIM_VARS: + if dim not in cls.__DIM_VARS: return None else: return None result.append(dim) return result + + @staticmethod + def _to_dims_from_strings(dimensions: Sequence[str]) -> list[int | str] | None: + result: list[int | str] = [] + for dim_str in dimensions: + try: + dim = int(dim_str) + except ValueError: + dim = dim_str + result.append(dim) + return result + + +class FixNumpyArrayDimAnnotation(IParser): + # NB: Not using full name due to ambiguity `typing.Annotated` vs + # `typing_extension.Annotated` in different python versions + # Rely on later fix by `FixTypingTypeNames` + __annotated_name = QualifiedName.from_str("Annotated") + __DIM_VARS = _NumpyArrayAnnotation._NumpyArrayAnnotation__DIM_VARS + + def parse_annotation_str( + self, annotation_str: str + ) -> ResolvedType | InvalidExpression | Value: + # Affects types of the following pattern: + # ARRAY_T[PRIMITIVE_TYPE[*DIMS], *FLAGS] + # Replace with: + # Annotated[ARRAY_T, PRIMITIVE_TYPE, FixedSize/DynamicSize[*DIMS], *FLAGS] + + result = super().parse_annotation_str(annotation_str) + # if 'scipy.sparse' in str(result): + # __import__('ipdb').set_trace() + if not isinstance(result, ResolvedType): + return result + + numpy_array = _NumpyArrayAnnotation.from_annotation(result) + if numpy_array is None: + return result + + params = [] + if numpy_array.array_type.name == QualifiedName.from_str( + "numpy.ndarray" + ) or numpy_array.array_type.name[:2] == ("scipy", "sparse"): + params.append(self.parse_annotation_str(str(numpy_array.array_type))) + params.append(self.parse_annotation_str(str(numpy_array.scalar_type))) + elif numpy_array.array_type.name == QualifiedName.from_str( + "numpy.typing.ArrayLike" + ): + params.append(self.parse_annotation_str(str(numpy_array.array_type))) + params.append(self.parse_annotation_str(str(numpy_array.scalar_type))) + else: + return result # Should not happen + if numpy_array.dimensions: + params.append( + self.handle_value(self.__wrap_with_size_helper(numpy_array.dimensions)) + ) + + for flag in numpy_array.flags: + if isinstance(flag, Value): + flag_str = flag.repr.strip('"') + if flag_str in ( + "flags.writeable", + "flags.c_contiguous", + "flags.f_contiguous", + ): + params.append( + ResolvedType(name=QualifiedName.from_str(f"numpy.ndarray.{flag_str}")) + ) + else: + params.append(flag) + else: + params.append(flag) + + return ResolvedType(name=self.__annotated_name, parameters=params) + + def __wrap_with_size_helper(self, dims: list[int | str]) -> FixedSize | DynamicSize: + if all(isinstance(d, int) for d in dims): + return_t = FixedSize + else: + return_t = DynamicSize + + # TRICK: Use `self.handle_type` to make `FixedSize`/`DynamicSize` + # properly added to the list of imports + self.handle_type(return_t) + return return_t(*dims) # type: ignore[arg-type] + def report_error(self, error: ParserError) -> None: if ( isinstance(error, NameResolutionError) @@ -636,33 +824,21 @@ def report_error(self, error: ParserError) -> None: class FixNumpyArrayDimTypeVar(IParser): - __array_names: set[QualifiedName] = { - QualifiedName.from_str("numpy.ndarray"), - QualifiedName.from_str("numpy.typing.ArrayLike"), - QualifiedName.from_str("numpy.typing.NDArray"), - } - __typing_annotated_names = { - QualifiedName.from_str("typing.Annotated"), - QualifiedName.from_str("typing_extensions.Annotated"), - } - numpy_primitive_types = FixNumpyArrayDimAnnotation.numpy_primitive_types - __DIM_VARS: set[str] = set() - __DIM_STRING_PATTERN = re.compile(r'"\[(.*?)\]"') - + def handle_module( self, path: QualifiedName, module: types.ModuleType ) -> Module | None: result = super().handle_module(path, module) if result is None: return None - + if self.__DIM_VARS: # the TypeVar_'s generated code will reference `typing` result.imports.add( Import(name=None, origin=QualifiedName.from_str("typing")) ) - + for name in self.__DIM_VARS: result.type_vars.append( TypeVar_( @@ -670,10 +846,10 @@ def handle_module( bound=self.parse_annotation_str("int"), ), ) - + self.__DIM_VARS.clear() return result - + def parse_annotation_str( self, annotation_str: str ) -> ResolvedType | InvalidExpression | Value: @@ -687,172 +863,25 @@ def parse_annotation_str( self.__DIM_VARS.add(result.name[0]) return result - if result.name == QualifiedName.from_str("numpy.ndarray"): - parameters = self._handle_old_style_numpy_array(result.parameters) - elif result.name in self.__array_names: - parameters = self._handle_new_style_numpy_array([result]) - elif result.name in self.__typing_annotated_names: - parameters = self._handle_new_style_numpy_array(result.parameters) - else: - parameters = None - if parameters is None: # Failure. + numpy_array = _NumpyArrayAnnotation.from_annotation(result) + if numpy_array is None: return result + # __import__('ipdb').set_trace() + + # scipy.sparse arrays/matrices are not currently generic and do not accept type + # arguments + if numpy_array.array_type.name[:2] == ("scipy", "sparse"): + return result + + def on_dynamic_dim(dim: str) -> None: + if len(dim) == 1: # Assuming single letter dims are type vars + self.__DIM_VARS.add(dim.upper()) + + shape, dtype = numpy_array.to_type_hint(self, on_dynamic_dim) return ResolvedType( - name=QualifiedName.from_str("numpy.ndarray"), parameters=parameters - ) - - def _process_numpy_array_type( - self, scalar_type_name: QualifiedName, dimensions: list[int | str] | None - ) -> tuple[ResolvedType, ResolvedType]: - # Pybind annotates a bool Python type, which cannot be used with - # numpy.dtype because it does not inherit from numpy.generic. - # Only numpy.bool_ works reliably with both NumPy 1.x and 2.x. - if str(scalar_type_name) == "bool": - scalar_type_name = QualifiedName.from_str("numpy.bool_") - dtype = ResolvedType( - name=QualifiedName.from_str("numpy.dtype"), - parameters=[ResolvedType(name=scalar_type_name)], + name=QualifiedName.from_str("numpy.ndarray"), parameters=[shape, dtype] ) - - shape = self.parse_annotation_str("Any") - if dimensions is not None and len(dimensions) > 0: - shape = self.parse_annotation_str("Tuple") - assert isinstance(shape, ResolvedType) - shape.parameters = [] - for dim in dimensions: - if isinstance(dim, int): - literal_dim = self.parse_annotation_str("Literal") - assert isinstance(literal_dim, ResolvedType) - literal_dim.parameters = [Value(repr=str(dim))] - shape.parameters.append(literal_dim) - else: - shape.parameters.append( - ResolvedType(name=QualifiedName.from_str(dim.upper())) - ) - return shape, dtype - - def _handle_new_style_numpy_array( - self, parameters: list[ResolvedType | Value | InvalidExpression] | None - ) -> list[ResolvedType] | None: - # Annotated[numpy.typing.ArrayLike, numpy.float32, "[m, n]"] - # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]"] - # Annotated[numpy.typing.NDArray[numpy.float32], "[m, n]", "flags.writeable" , "flags.c_contiguous"] # noqa: E501 - if parameters is None or len(parameters) == 0: - return - - array_type, *parameters = parameters - if ( - not isinstance(array_type, ResolvedType) - or array_type.name not in self.__array_names - ): - return - - dims_and_flags: Sequence[ResolvedType | Value | InvalidExpression] - if array_type.name == QualifiedName.from_str("numpy.typing.ArrayLike"): - if not parameters: - return - scalar_type, *dims_and_flags = parameters - elif array_type.name == QualifiedName.from_str("numpy.typing.NDArray"): - if array_type.parameters is None or len(array_type.parameters) == 0: - return - [scalar_type] = array_type.parameters - dims_and_flags = parameters - elif array_type.name == QualifiedName.from_str("numpy.ndarray"): - _, dtype_param = array_type.parameters - if not ( - isinstance(dtype_param, ResolvedType) - and dtype_param.name == QualifiedName.from_str("numpy.dtype") - and dtype_param.parameters - ): - return - [scalar_type] = dtype_param.parameters - dims_and_flags = parameters - else: - return - scalar_type_name = scalar_type.name - if scalar_type_name not in self.numpy_primitive_types: - return - - dims: list[int | str] | None = None - if dims_and_flags: - dims_str, *flags = dims_and_flags - del flags # Unused. - if isinstance(dims_str, Value): - match = self.__DIM_STRING_PATTERN.search(dims_str.repr) - if match: - dims_str_content = match.group(1) - dims_list = [ - d.strip() for d in dims_str_content.split(",") if d.strip() - ] - if dims_list: - dims = self.__to_dims_from_strings(dims_list) - - return self._process_numpy_array_type(scalar_type_name, dims) - - def _handle_old_style_numpy_array( - self, parameters: list[ResolvedType | Value | InvalidExpression] | None - ) -> list[ResolvedType] | None: - # Affects types of the following pattern: - # numpy.ndarray[PRIMITIVE_TYPE[*DIMS], *FLAGS] - # Replace with: - # numpy.ndarray[tuple[M, Literal[1]], numpy.dtype[numpy.float32]] - - # ndarray is generic and should have 2 type arguments - if parameters is None or len(parameters) == 0: - return [ - self.parse_annotation_str("Any"), - ResolvedType( - name=QualifiedName.from_str("numpy.dtype"), - parameters=[self.parse_annotation_str("Any")], - ), - ] - - scalar_with_dims = parameters[0] # e.g. numpy.float64[32, 32] - if ( - not isinstance(scalar_with_dims, ResolvedType) - or scalar_with_dims.name not in self.numpy_primitive_types - ): - return - - dims: list[int | str] | None = None - if ( - scalar_with_dims.parameters is not None - and len(scalar_with_dims.parameters) > 0 - ): - dims = self.__to_dims(scalar_with_dims.parameters) - return self._process_numpy_array_type(scalar_with_dims.name, dims) - - def __to_dims( - self, dimensions: Sequence[ResolvedType | Value | InvalidExpression] - ) -> list[int | str] | None: - result: list[int | str] = [] - for dim_param in dimensions: - if isinstance(dim_param, Value): - try: - dim = int(dim_param.repr) - except ValueError: - return None - elif isinstance(dim_param, ResolvedType): - dim = str(dim_param) - else: - return None - result.append(dim) - return result - - def __to_dims_from_strings( - self, dimensions: Sequence[str] - ) -> list[int | str] | None: - result: list[int | str] = [] - for dim_str in dimensions: - try: - dim = int(dim_str) - except ValueError: - dim = dim_str - if len(dim) == 1: # Assuming single letter dims are type vars - self.__DIM_VARS.add(dim.upper()) # Add uppercase to TypeVar set - result.append(dim) - return result - + def report_error(self, error: ParserError) -> None: if ( isinstance(error, NameResolutionError) @@ -862,17 +891,18 @@ def report_error(self, error: ParserError) -> None: # allow type variables, which are manually resolved in `handle_module` return super().report_error(error) - - + + class FixNumpyArrayRemoveParameters(IParser): - __ndarray_name = QualifiedName.from_str("numpy.ndarray") - def parse_annotation_str( self, annotation_str: str ) -> ResolvedType | InvalidExpression | Value: result = super().parse_annotation_str(annotation_str) - if isinstance(result, ResolvedType) and result.name == self.__ndarray_name: - result.parameters = None + if isinstance(result, ResolvedType): + numpy_array = _NumpyArrayAnnotation.from_annotation(result) + if numpy_array is not None: + numpy_array.array_type.parameters = None + return numpy_array.array_type return result @@ -912,34 +942,6 @@ def parse_annotation_str( return result -class FixNumpyArrayFlags(IParser): - __ndarray_name = QualifiedName.from_str("numpy.ndarray") - __flags: set[QualifiedName] = { - QualifiedName.from_str("flags.writeable"), - QualifiedName.from_str("flags.c_contiguous"), - QualifiedName.from_str("flags.f_contiguous"), - } - - def parse_annotation_str( - self, annotation_str: str - ) -> ResolvedType | InvalidExpression | Value: - result = super().parse_annotation_str(annotation_str) - if isinstance(result, ResolvedType) and result.name == self.__ndarray_name: - if result.parameters is not None: - for param in result.parameters: - if isinstance(param, ResolvedType) and param.name in self.__flags: - param.name = QualifiedName.from_str( - f"numpy.ndarray.{param.name}" - ) - - return result - - def report_error(self, error: ParserError) -> None: - if isinstance(error, NameResolutionError) and error.name in self.__flags: - return - super().report_error(error) - - class FixRedundantMethodsFromBuiltinObject(IParser): def handle_method(self, path: QualifiedName, method: Any) -> list[Method]: result = super().handle_method(path, method) From a6c85685c13dac66c9f11abbb31eb8d709961bf6 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 14:21:36 +0200 Subject: [PATCH 07/16] Update stubs for numpy-array-wrap-with-annotated --- .../demo/_bindings/aliases/__init__.pyi | 2 +- .../demo/_bindings/classes.pyi | 9 ++-- .../demo/_bindings/eigen.pyi | 22 +++++++--- .../demo/_bindings/enum.pyi | 4 +- .../demo/_bindings/flawed_bindings.pyi | 4 +- .../demo/_bindings/functions.pyi | 42 +++++++++++++------ .../demo/_bindings/issues.pyi | 4 +- .../demo/_bindings/methods.pyi | 6 ++- .../demo/_bindings/numpy.pyi | 10 +++-- .../demo/_bindings/properties.pyi | 18 +++++--- .../demo/_bindings/stl.pyi | 15 ++++--- .../demo/_bindings/stl_bind.pyi | 31 ++++++++------ .../demo/_bindings/typing.pyi | 8 ++-- 13 files changed, 112 insertions(+), 63 deletions(-) diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi index 93963f4..8d6f4ce 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/aliases/__init__.pyi @@ -47,7 +47,7 @@ class Dummy: def foreign_enum_default( color: typing.Any = demo._bindings.enum.ConsoleForegroundColor.Blue, ) -> None: ... -def func(arg0: int) -> int: ... +def func(arg0: typing.SupportsInt) -> int: ... local_func_alias = func local_type_alias = Color diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi index ea36dda..addca14 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/classes.pyi @@ -13,7 +13,10 @@ class CppException(Exception): pass class Derived(Base): - count: int + @property + def count(self) -> int: ... + @count.setter + def count(self, arg0: typing.SupportsInt) -> None: ... class Foo: class FooChild: @@ -43,11 +46,11 @@ class Outer: def __getstate__(self) -> int: ... def __hash__(self) -> int: ... def __index__(self) -> int: ... - def __init__(self, value: int) -> None: ... + def __init__(self, value: typing.SupportsInt) -> None: ... def __int__(self) -> int: ... def __ne__(self, other: typing.Any) -> bool: ... def __repr__(self) -> str: ... - def __setstate__(self, state: int) -> None: ... + def __setstate__(self, state: typing.SupportsInt) -> None: ... def __str__(self) -> str: ... @property def name(self) -> str: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi index 8e45337..2f7b79f 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/eigen.pyi @@ -24,24 +24,30 @@ __all__: list[str] = [ def accept_matrix_int( arg0: typing.Annotated[ - numpy.ndarray, numpy.int32, pybind11_stubgen.typing_ext.FixedSize(3, 3) + numpy.typing.ArrayLike, numpy.int32, pybind11_stubgen.typing_ext.FixedSize(3, 3) ] ) -> None: ... def accept_vector_float64( arg0: typing.Annotated[ - numpy.ndarray, numpy.float64, pybind11_stubgen.typing_ext.FixedSize(3, 1) + numpy.typing.ArrayLike, + numpy.float64, + pybind11_stubgen.typing_ext.FixedSize(3, 1), ] ) -> None: ... def dense_matrix_c( arg0: typing.Annotated[ - numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") + numpy.typing.ArrayLike, + numpy.float32, + pybind11_stubgen.typing_ext.DynamicSize("m", "n"), ] ) -> typing.Annotated[ numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") ]: ... def dense_matrix_r( arg0: typing.Annotated[ - numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") + numpy.typing.ArrayLike, + numpy.float32, + pybind11_stubgen.typing_ext.DynamicSize("m", "n"), ] ) -> typing.Annotated[ numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", "n") @@ -74,14 +80,18 @@ def fixed_mutator_r( ) -> None: ... def four_col_matrix_r( arg0: typing.Annotated[ - numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", 4) + numpy.typing.ArrayLike, + numpy.float32, + pybind11_stubgen.typing_ext.DynamicSize("m", 4), ] ) -> typing.Annotated[ numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize("m", 4) ]: ... def four_row_matrix_r( arg0: typing.Annotated[ - numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize(4, "n") + numpy.typing.ArrayLike, + numpy.float32, + pybind11_stubgen.typing_ext.DynamicSize(4, "n"), ] ) -> typing.Annotated[ numpy.ndarray, numpy.float32, pybind11_stubgen.typing_ext.DynamicSize(4, "n") diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi index 57aba5b..a994e39 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/enum.pyi @@ -49,11 +49,11 @@ class ConsoleForegroundColor: def __getstate__(self) -> int: ... def __hash__(self) -> int: ... def __index__(self) -> int: ... - def __init__(self, value: int) -> None: ... + def __init__(self, value: typing.SupportsInt) -> None: ... def __int__(self) -> int: ... def __ne__(self, other: typing.Any) -> bool: ... def __repr__(self) -> str: ... - def __setstate__(self, state: int) -> None: ... + def __setstate__(self, state: typing.SupportsInt) -> None: ... def __str__(self) -> str: ... @property def name(self) -> str: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi index 4f3886e..d95bbb3 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/flawed_bindings.pyi @@ -1,5 +1,7 @@ from __future__ import annotations +import typing + __all__: list[str] = [ "Enum", "Unbound", @@ -18,6 +20,6 @@ class Unbound: def accept_unbound_enum(arg0: ...) -> int: ... def accept_unbound_enum_defaulted(x: Enum = ...) -> int: ... -def accept_unbound_type(arg0: tuple[..., int]) -> int: ... +def accept_unbound_type(arg0: tuple[..., typing.SupportsInt]) -> int: ... def accept_unbound_type_defaulted(x: Unbound = ...) -> int: ... def get_unbound_type() -> ...: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi index 79f666a..5888147 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/functions.pyi @@ -1,5 +1,6 @@ from __future__ import annotations +import collections.abc import typing __all__: list[str] = [ @@ -25,34 +26,49 @@ __all__: list[str] = [ ] class Foo: - def __init__(self, arg0: int) -> None: ... + def __init__(self, arg0: typing.SupportsInt) -> None: ... -def accept_annotated_callable(arg0: typing.Callable[[int, int], int]) -> typing.Any: ... -def accept_callable(arg0: typing.Callable) -> typing.Any: ... +def accept_annotated_callable( + arg0: collections.abc.Callable[[typing.SupportsInt, typing.SupportsInt], int] +) -> typing.Any: ... +def accept_callable(arg0: collections.abc.Callable) -> typing.Any: ... def accept_frozenset(arg0: frozenset) -> None: ... def accept_py_handle(arg0: typing.Any) -> str: ... def accept_py_object(arg0: typing.Any) -> str: ... def accept_set(arg0: set) -> None: ... -def add(arg0: int, arg1: int) -> int: ... +def add(arg0: typing.SupportsInt, arg1: typing.SupportsInt) -> int: ... def default_custom_arg(foo: Foo = Foo(5)) -> None: ... -def default_int_arg(n: int = 5) -> None: ... +def default_int_arg(n: typing.SupportsInt = 5) -> None: ... def default_list_arg(l: list = [1, 2, 6, 18]) -> None: ... -def default_optional_arg(n: int | None = None) -> None: ... -def func_w_anon_args(arg0: int, arg1: int, arg2: int) -> None: ... -def func_w_named_pos_args(x: int, y: int, z: int) -> None: ... +def default_optional_arg(n: typing.SupportsInt | None = None) -> None: ... +def func_w_anon_args( + arg0: typing.SupportsInt, arg1: typing.SupportsInt, arg2: typing.SupportsInt +) -> None: ... +def func_w_named_pos_args( + x: typing.SupportsInt, y: typing.SupportsInt, z: typing.SupportsInt +) -> None: ... def generic(*args, **kwargs) -> None: ... @typing.overload -def mul(x: int, y: int) -> int: +def mul(x: typing.SupportsInt, y: typing.SupportsInt) -> int: """ Multiply x and y (int) """ @typing.overload -def mul(p: float, q: float) -> float: +def mul(p: typing.SupportsFloat, q: typing.SupportsFloat) -> float: """ Multiply p and q (double) """ -def pass_callback(arg0: typing.Callable[[Foo], Foo]) -> Foo: ... -def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: ... -def pos_kw_only_variadic_mix(i: int, /, j: int, *args, k: int, **kwargs) -> tuple: ... +def pass_callback(arg0: collections.abc.Callable[[Foo], Foo]) -> Foo: ... +def pos_kw_only_mix( + i: typing.SupportsInt, /, j: typing.SupportsInt, *, k: typing.SupportsInt +) -> tuple: ... +def pos_kw_only_variadic_mix( + i: typing.SupportsInt, + /, + j: typing.SupportsInt, + *args, + k: typing.SupportsInt, + **kwargs, +) -> tuple: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi index cf6abad..165940c 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/issues.pyi @@ -17,7 +17,9 @@ def backslashes_should_be_escaped() -> None: Here's some reStructuredText: :math:`x = [x, y, \\theta]^T` """ -def issue_51_catastrophic_regex(arg0: int, arg1: int) -> None: +def issue_51_catastrophic_regex( + arg0: typing.SupportsInt, arg1: typing.SupportsInt +) -> None: """ Use-case: issue_51(os.get_handle_inheritable, os.set_handle_inheritable) diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi index 6c115cd..406a301 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/methods.pyi @@ -1,8 +1,10 @@ from __future__ import annotations +import typing + __all__: list[str] = ["Dummy"] class Dummy: @staticmethod - def static_method(arg0: int) -> int: ... - def regular_method(self, arg0: int) -> int: ... + def static_method(arg0: typing.SupportsInt) -> int: ... + def regular_method(self, arg0: typing.SupportsInt) -> int: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi index e211caa..3ee3357 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/numpy.pyi @@ -13,9 +13,11 @@ __all__: list[str] = [ ] def accept_ndarray_float64( - arg0: typing.Annotated[numpy.ndarray, numpy.float64] + arg0: typing.Annotated[numpy.typing.ArrayLike, numpy.float64] ) -> None: ... -def accept_ndarray_int(arg0: typing.Annotated[numpy.ndarray, numpy.int32]) -> None: ... -def get_ndarray_float64() -> typing.Annotated[numpy.ndarray, numpy.float64]: ... -def get_ndarray_int() -> typing.Annotated[numpy.ndarray, numpy.int32]: ... +def accept_ndarray_int( + arg0: typing.Annotated[numpy.typing.ArrayLike, numpy.int32] +) -> None: ... +def get_ndarray_float64() -> numpy.typing.NDArray[numpy.float64]: ... +def get_ndarray_int() -> numpy.typing.NDArray[numpy.int32]: ... def return_dtype() -> numpy.dtype[typing.Any]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi index 9d81595..d7ae367 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/properties.pyi @@ -22,7 +22,7 @@ class WithGetterSetterDoc: getter doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: + def def_property(self, arg1: typing.SupportsInt) -> None: """ setter doc token """ @@ -45,7 +45,7 @@ class WithPropAndGetterSetterDoc: prop doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: ... + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: """ @@ -65,7 +65,7 @@ class WithPropDoc: prop doc token """ @def_property.setter - def def_property(self, arg1: int) -> None: ... + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: """ @@ -82,7 +82,7 @@ class WithPropDoc: prop doc token """ @def_readwrite.setter - def def_readwrite(self, arg0: int) -> None: ... + def def_readwrite(self, arg0: typing.SupportsInt) -> None: ... class WithoutDoc: """ @@ -91,9 +91,15 @@ class WithoutDoc: def_property_readonly_static: typing.ClassVar[int] = 0 def_property_static: typing.ClassVar[int] = 0 - def_property: int - def_readwrite: int + @property + def def_property(self) -> int: ... + @def_property.setter + def def_property(self, arg1: typing.SupportsInt) -> None: ... @property def def_property_readonly(self) -> int: ... @property def def_readonly(self) -> int: ... + @property + def def_readwrite(self) -> int: ... + @def_readwrite.setter + def def_readwrite(self, arg0: typing.SupportsInt) -> None: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi index bd5bb49..dbc3269 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl.pyi @@ -1,9 +1,8 @@ from __future__ import annotations +import collections.abc import typing -import pybind11_stubgen.typing_ext - __all__: list[str] = [ "std_array", "std_map", @@ -13,9 +12,13 @@ __all__: list[str] = [ ] def std_array( - arg0: typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)] -) -> typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(3)]: ... + arg0: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"] +) -> typing.Annotated[list[int], "FixedSize(3)"]: ... def std_map() -> dict[int, complex]: ... -def std_optional(arg0: int | None) -> None: ... -def std_variant(arg0: int | float | tuple[int, int]) -> None: ... +def std_optional(arg0: typing.SupportsInt | None) -> None: ... +def std_variant( + arg0: typing.SupportsInt + | typing.SupportsFloat + | tuple[typing.SupportsInt, typing.SupportsInt] +) -> None: ... def std_vector() -> list[tuple[int, float]]: ... diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi index 6f1f9b6..0020e1d 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/stl_bind.pyi @@ -1,5 +1,6 @@ from __future__ import annotations +import collections.abc import typing __all__: list[str] = [ @@ -21,7 +22,7 @@ class MapStringComplex: def __delitem__(self, arg0: str) -> None: ... def __getitem__(self, arg0: str) -> complex: ... def __init__(self) -> None: ... - def __iter__(self) -> typing.Iterator[str]: ... + def __iter__(self) -> collections.abc.Iterator[str]: ... def __len__(self) -> int: ... def __repr__(self) -> str: """ @@ -38,12 +39,12 @@ class VectorPairStringDouble: """ Check whether the list is nonempty """ - def __contains__(self, x: tuple[str, float]) -> bool: + def __contains__(self, x: tuple[str, typing.SupportsFloat]) -> bool: """ Return true the container contains ``x`` """ @typing.overload - def __delitem__(self, arg0: int) -> None: + def __delitem__(self, arg0: typing.SupportsInt) -> None: """ Delete the list elements at index ``i`` """ @@ -59,7 +60,7 @@ class VectorPairStringDouble: Retrieve list elements using a slice object """ @typing.overload - def __getitem__(self, arg0: int) -> tuple[str, float]: ... + def __getitem__(self, arg0: typing.SupportsInt) -> tuple[str, float]: ... @typing.overload def __init__(self) -> None: ... @typing.overload @@ -68,18 +69,20 @@ class VectorPairStringDouble: Copy constructor """ @typing.overload - def __init__(self, arg0: typing.Iterable) -> None: ... - def __iter__(self) -> typing.Iterator[tuple[str, float]]: ... + def __init__(self, arg0: collections.abc.Iterable) -> None: ... + def __iter__(self) -> collections.abc.Iterator[tuple[str, float]]: ... def __len__(self) -> int: ... def __ne__(self, arg0: VectorPairStringDouble) -> bool: ... @typing.overload - def __setitem__(self, arg0: int, arg1: tuple[str, float]) -> None: ... + def __setitem__( + self, arg0: typing.SupportsInt, arg1: tuple[str, typing.SupportsFloat] + ) -> None: ... @typing.overload def __setitem__(self, arg0: slice, arg1: VectorPairStringDouble) -> None: """ Assign list elements using a slice object """ - def append(self, x: tuple[str, float]) -> None: + def append(self, x: tuple[str, typing.SupportsFloat]) -> None: """ Add an item to the end of the list """ @@ -87,7 +90,7 @@ class VectorPairStringDouble: """ Clear the contents """ - def count(self, x: tuple[str, float]) -> int: + def count(self, x: tuple[str, typing.SupportsFloat]) -> int: """ Return the number of times ``x`` appears in the list """ @@ -97,11 +100,13 @@ class VectorPairStringDouble: Extend the list by appending all the items in the given list """ @typing.overload - def extend(self, L: typing.Iterable) -> None: + def extend(self, L: collections.abc.Iterable) -> None: """ Extend the list by appending all the items in the given list """ - def insert(self, i: int, x: tuple[str, float]) -> None: + def insert( + self, i: typing.SupportsInt, x: tuple[str, typing.SupportsFloat] + ) -> None: """ Insert an item at a given position. """ @@ -111,11 +116,11 @@ class VectorPairStringDouble: Remove and return the last item """ @typing.overload - def pop(self, i: int) -> tuple[str, float]: + def pop(self, i: typing.SupportsInt) -> tuple[str, float]: """ Remove and return the item at index ``i`` """ - def remove(self, x: tuple[str, float]) -> None: + def remove(self, x: tuple[str, typing.SupportsFloat]) -> None: """ Remove the first item from the list whose value is x. It is an error if there is no such item. """ diff --git a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi index f2c4ab9..98fd047 100644 --- a/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi +++ b/tests/stubs/python-3.12/pybind11-v3.0.0/numpy-array-wrap-with-annotated/demo/_bindings/typing.pyi @@ -1,10 +1,8 @@ from __future__ import annotations -import typing - -import typing_extensions +import collections.abc __all__: list[str] = ["get_buffer", "get_sequence"] -def get_buffer(arg0: typing_extensions.Buffer) -> typing_extensions.Buffer: ... -def get_sequence(arg0: typing.Sequence) -> typing.Sequence: ... +def get_buffer(arg0: collections.abc.Buffer) -> collections.abc.Buffer: ... +def get_sequence(arg0: collections.abc.Sequence) -> collections.abc.Sequence: ... From 6be49ef44edc3c7d5d24cb0a720336f780eab499 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 14:25:06 +0200 Subject: [PATCH 08/16] Formatting --- pybind11_stubgen/parser/mixins/fix.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index f7382f0..2ca707e 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -627,7 +627,7 @@ def _from_old_style( ): dimensions = cls._to_dims(scalar_with_dims.parameters) - return _NumpyArrayAnnotation(array_type, scalar_type, dimensions, flags) + return cls(array_type, scalar_type, dimensions, flags) @classmethod def _from_new_style( @@ -704,7 +704,7 @@ def _from_new_style( dims = cls._to_dims_from_strings(dims_list) flags = dims_and_flags[1:] - return _NumpyArrayAnnotation(array_type, scalar_type, dims, flags) + return cls(array_type, scalar_type, dims, flags) @classmethod def _to_dims( From 4444838bf15bf6e57473348dfab16947ab2df248 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 14:41:28 +0200 Subject: [PATCH 09/16] Fix broken handling of v2.13 --- pybind11_stubgen/parser/mixins/fix.py | 97 +++++++++++++++++---------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index 2ca707e..918a4cc 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -545,7 +545,7 @@ class _NumpyArrayAnnotation: ) __DIM_VARS = ["n", "m"] __DIM_STRING_PATTERN = re.compile(r'"\[(.*?)\]"') - + def __init__( self, array_type: ResolvedType, @@ -557,7 +557,7 @@ def __init__( self.scalar_type = scalar_type self.dimensions = dimensions self.flags = flags - + def to_type_hint( self, parser: IParser, on_dynamic_dim: Optional[callable[[str], None]] = None ) -> tuple[ResolvedType, ResolvedType]: @@ -571,7 +571,7 @@ def to_type_hint( name=QualifiedName.from_str("numpy.dtype"), parameters=[ResolvedType(name=scalar_type_name)], ) - + shape = parser.parse_annotation_str("Any") if self.dimensions: shape = parser.parse_annotation_str("Tuple") @@ -590,7 +590,7 @@ def to_type_hint( ResolvedType(name=QualifiedName.from_str(dim.upper())) ) return shape, dtype - + @classmethod def from_annotation( cls, resolved_type: ResolvedType @@ -601,23 +601,23 @@ def from_annotation( return cls._from_old_style(resolved_type) else: return None - + @classmethod def _from_old_style( cls, resolved_type: ResolvedType ) -> Optional[_NumpyArrayAnnotation]: if resolved_type.parameters is None or len(resolved_type.parameters) == 0: return None - + scalar_with_dims = resolved_type.parameters[0] flags = resolved_type.parameters[1:] - + if ( not isinstance(scalar_with_dims, ResolvedType) or scalar_with_dims.name not in cls.numpy_primitive_types ): return None - + array_type = ResolvedType(name=resolved_type.name) scalar_type = ResolvedType(name=scalar_with_dims.name) dimensions: Optional[list[str | int]] = None @@ -626,9 +626,11 @@ def _from_old_style( and len(scalar_with_dims.parameters) > 0 ): dimensions = cls._to_dims(scalar_with_dims.parameters) - - return cls(array_type, scalar_type, dimensions, flags) - + + cls._fix_flags(flags) + + return _NumpyArrayAnnotation(array_type, scalar_type, dimensions, flags) + @classmethod def _from_new_style( cls, resolved_type: ResolvedType @@ -705,7 +707,7 @@ def _from_new_style( flags = dims_and_flags[1:] return cls(array_type, scalar_type, dims, flags) - + @classmethod def _to_dims( cls, dimensions: Sequence[ResolvedType | Value | InvalidExpression] @@ -719,13 +721,24 @@ def _to_dims( return None elif isinstance(dim_param, ResolvedType): dim = str(dim_param) - if dim not in cls.__DIM_VARS: + if len(dim) > 1 and dim not in cls.__DIM_VARS: return None else: return None result.append(dim) return result - + + @staticmethod + def _fix_flags(flags: list[ResolvedType | Value | InvalidExpression]): + __flags: set[QualifiedName] = { + QualifiedName.from_str("flags.writeable"), + QualifiedName.from_str("flags.c_contiguous"), + QualifiedName.from_str("flags.f_contiguous"), + } + for flag in flags: + if isinstance(flag, ResolvedType) and flag.name in __flags: + flag.name = QualifiedName.from_str(f"numpy.ndarray.{flag.name}") + @staticmethod def _to_dims_from_strings(dimensions: Sequence[str]) -> list[int | str] | None: result: list[int | str] = [] @@ -736,15 +749,15 @@ def _to_dims_from_strings(dimensions: Sequence[str]) -> list[int | str] | None: dim = dim_str result.append(dim) return result - - + + class FixNumpyArrayDimAnnotation(IParser): # NB: Not using full name due to ambiguity `typing.Annotated` vs # `typing_extension.Annotated` in different python versions # Rely on later fix by `FixTypingTypeNames` __annotated_name = QualifiedName.from_str("Annotated") __DIM_VARS = _NumpyArrayAnnotation._NumpyArrayAnnotation__DIM_VARS - + def parse_annotation_str( self, annotation_str: str ) -> ResolvedType | InvalidExpression | Value: @@ -752,13 +765,11 @@ def parse_annotation_str( # ARRAY_T[PRIMITIVE_TYPE[*DIMS], *FLAGS] # Replace with: # Annotated[ARRAY_T, PRIMITIVE_TYPE, FixedSize/DynamicSize[*DIMS], *FLAGS] - + result = super().parse_annotation_str(annotation_str) - # if 'scipy.sparse' in str(result): - # __import__('ipdb').set_trace() if not isinstance(result, ResolvedType): return result - + numpy_array = _NumpyArrayAnnotation.from_annotation(result) if numpy_array is None: return result @@ -791,7 +802,9 @@ def parse_annotation_str( "flags.f_contiguous", ): params.append( - ResolvedType(name=QualifiedName.from_str(f"numpy.ndarray.{flag_str}")) + ResolvedType( + name=QualifiedName.from_str(f"numpy.ndarray.{flag_str}") + ) ) else: params.append(flag) @@ -805,13 +818,18 @@ def __wrap_with_size_helper(self, dims: list[int | str]) -> FixedSize | DynamicS return_t = FixedSize else: return_t = DynamicSize - + # TRICK: Use `self.handle_type` to make `FixedSize`/`DynamicSize` # properly added to the list of imports self.handle_type(return_t) return return_t(*dims) # type: ignore[arg-type] - + def report_error(self, error: ParserError) -> None: + __flags: set[QualifiedName] = { + QualifiedName.from_str("flags.writeable"), + QualifiedName.from_str("flags.c_contiguous"), + QualifiedName.from_str("flags.f_contiguous"), + } if ( isinstance(error, NameResolutionError) and len(error.name) == 1 @@ -820,25 +838,27 @@ def report_error(self, error: ParserError) -> None: ): # Ignores all unknown 'm' and 'n' regardless of the context return + if isinstance(error, NameResolutionError) and error.name in __flags: + return super().report_error(error) class FixNumpyArrayDimTypeVar(IParser): __DIM_VARS: set[str] = set() - + def handle_module( self, path: QualifiedName, module: types.ModuleType ) -> Module | None: result = super().handle_module(path, module) if result is None: return None - + if self.__DIM_VARS: # the TypeVar_'s generated code will reference `typing` result.imports.add( Import(name=None, origin=QualifiedName.from_str("typing")) ) - + for name in self.__DIM_VARS: result.type_vars.append( TypeVar_( @@ -846,10 +866,10 @@ def handle_module( bound=self.parse_annotation_str("int"), ), ) - + self.__DIM_VARS.clear() return result - + def parse_annotation_str( self, annotation_str: str ) -> ResolvedType | InvalidExpression | Value: @@ -867,22 +887,27 @@ def parse_annotation_str( if numpy_array is None: return result # __import__('ipdb').set_trace() - + # scipy.sparse arrays/matrices are not currently generic and do not accept type # arguments if numpy_array.array_type.name[:2] == ("scipy", "sparse"): return result - + def on_dynamic_dim(dim: str) -> None: if len(dim) == 1: # Assuming single letter dims are type vars self.__DIM_VARS.add(dim.upper()) - + shape, dtype = numpy_array.to_type_hint(self, on_dynamic_dim) return ResolvedType( name=QualifiedName.from_str("numpy.ndarray"), parameters=[shape, dtype] ) - + def report_error(self, error: ParserError) -> None: + __flags: set[QualifiedName] = { + QualifiedName.from_str("flags.writeable"), + QualifiedName.from_str("flags.c_contiguous"), + QualifiedName.from_str("flags.f_contiguous"), + } if ( isinstance(error, NameResolutionError) and len(error.name) == 1 @@ -890,9 +915,11 @@ def report_error(self, error: ParserError) -> None: ): # allow type variables, which are manually resolved in `handle_module` return + if isinstance(error, NameResolutionError) and error.name in __flags: + return super().report_error(error) - - + + class FixNumpyArrayRemoveParameters(IParser): def parse_annotation_str( self, annotation_str: str From b96457c9e4ab74add36d12686e5974a2c1fc3116 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 14:58:24 +0200 Subject: [PATCH 10/16] Remove numpy-related errors --- tests/demo.errors.stderr.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/demo.errors.stderr.txt b/tests/demo.errors.stderr.txt index f8fd843..e858fa4 100644 --- a/tests/demo.errors.stderr.txt +++ b/tests/demo.errors.stderr.txt @@ -1,10 +1,4 @@ pybind11_stubgen - [ ERROR] In demo._bindings.aliases.foreign_enum_default : Invalid expression '' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.dense_matrix_c : Can't find/import 'm' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.dense_matrix_c : Can't find/import 'n' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.dense_matrix_r : Can't find/import 'm' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.dense_matrix_r : Can't find/import 'n' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.four_col_matrix_r : Can't find/import 'm' -pybind11_stubgen - [ ERROR] In demo._bindings.eigen.four_row_matrix_r : Can't find/import 'n' pybind11_stubgen - [ ERROR] In demo._bindings.enum.accept_defaulted_enum : Invalid expression '' pybind11_stubgen - [ ERROR] In demo._bindings.flawed_bindings.accept_unbound_enum : Invalid expression '(anonymous namespace)::Enum' pybind11_stubgen - [ ERROR] In demo._bindings.flawed_bindings.accept_unbound_enum_defaulted : Invalid expression '' From 59e373d752129923bb836983bb82999106876d49 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 15:09:32 +0200 Subject: [PATCH 11/16] Cleanup --- pybind11_stubgen/parser/mixins/fix.py | 47 ++++++++++++--------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index 918a4cc..260201f 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -543,8 +543,13 @@ class _NumpyArrayAnnotation: ), ) ) - __DIM_VARS = ["n", "m"] - __DIM_STRING_PATTERN = re.compile(r'"\[(.*?)\]"') + numpy_flags: set[QualifiedName] = { + QualifiedName.from_str("flags.writeable"), + QualifiedName.from_str("flags.c_contiguous"), + QualifiedName.from_str("flags.f_contiguous"), + } + dim_vars: set[str] = {"n", "m"} + __dim_string_pattern = re.compile(r'"\[(.*?)\]"') def __init__( self, @@ -696,7 +701,7 @@ def _from_new_style( if dims_and_flags: dims_str_param = dims_and_flags[0] if isinstance(dims_str_param, Value): - match = cls.__DIM_STRING_PATTERN.search(dims_str_param.repr) + match = cls.__dim_string_pattern.search(dims_str_param.repr) if match: dims_str_content = match.group(1) dims_list = [ @@ -721,22 +726,17 @@ def _to_dims( return None elif isinstance(dim_param, ResolvedType): dim = str(dim_param) - if len(dim) > 1 and dim not in cls.__DIM_VARS: + if len(dim) > 1 and dim not in cls.dim_vars: return None else: return None result.append(dim) return result - @staticmethod - def _fix_flags(flags: list[ResolvedType | Value | InvalidExpression]): - __flags: set[QualifiedName] = { - QualifiedName.from_str("flags.writeable"), - QualifiedName.from_str("flags.c_contiguous"), - QualifiedName.from_str("flags.f_contiguous"), - } + @classmethod + def _fix_flags(cls, flags: list[ResolvedType | Value | InvalidExpression]): for flag in flags: - if isinstance(flag, ResolvedType) and flag.name in __flags: + if isinstance(flag, ResolvedType) and flag.name in cls.numpy_flags: flag.name = QualifiedName.from_str(f"numpy.ndarray.{flag.name}") @staticmethod @@ -756,7 +756,6 @@ class FixNumpyArrayDimAnnotation(IParser): # `typing_extension.Annotated` in different python versions # Rely on later fix by `FixTypingTypeNames` __annotated_name = QualifiedName.from_str("Annotated") - __DIM_VARS = _NumpyArrayAnnotation._NumpyArrayAnnotation__DIM_VARS def parse_annotation_str( self, annotation_str: str @@ -825,20 +824,18 @@ def __wrap_with_size_helper(self, dims: list[int | str]) -> FixedSize | DynamicS return return_t(*dims) # type: ignore[arg-type] def report_error(self, error: ParserError) -> None: - __flags: set[QualifiedName] = { - QualifiedName.from_str("flags.writeable"), - QualifiedName.from_str("flags.c_contiguous"), - QualifiedName.from_str("flags.f_contiguous"), - } if ( isinstance(error, NameResolutionError) and len(error.name) == 1 and len(error.name[0]) == 1 - and error.name[0] in self.__DIM_VARS + and error.name[0] in _NumpyArrayAnnotation.dim_vars ): # Ignores all unknown 'm' and 'n' regardless of the context return - if isinstance(error, NameResolutionError) and error.name in __flags: + if ( + isinstance(error, NameResolutionError) + and error.name in _NumpyArrayAnnotation.numpy_flags + ): return super().report_error(error) @@ -903,11 +900,6 @@ def on_dynamic_dim(dim: str) -> None: ) def report_error(self, error: ParserError) -> None: - __flags: set[QualifiedName] = { - QualifiedName.from_str("flags.writeable"), - QualifiedName.from_str("flags.c_contiguous"), - QualifiedName.from_str("flags.f_contiguous"), - } if ( isinstance(error, NameResolutionError) and len(error.name) == 1 @@ -915,7 +907,10 @@ def report_error(self, error: ParserError) -> None: ): # allow type variables, which are manually resolved in `handle_module` return - if isinstance(error, NameResolutionError) and error.name in __flags: + if ( + isinstance(error, NameResolutionError) + and error.name in _NumpyArrayAnnotation.numpy_flags + ): return super().report_error(error) From 3e8877d414cc2c212024552b55237da8962a8bee Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 15:54:12 +0200 Subject: [PATCH 12/16] Fix flags also when numpy annotations are not converted --- pybind11_stubgen/__init__.py | 2 + pybind11_stubgen/parser/mixins/fix.py | 79 +++++++++++++-------------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/pybind11_stubgen/__init__.py b/pybind11_stubgen/__init__.py index a6010aa..89f7a9c 100644 --- a/pybind11_stubgen/__init__.py +++ b/pybind11_stubgen/__init__.py @@ -36,6 +36,7 @@ FixMissingNoneHashFieldAnnotation, FixNumpyArrayDimAnnotation, FixNumpyArrayDimTypeVar, + FixNumpyArrayFlags, FixNumpyArrayRemoveParameters, FixNumpyDtype, FixPEP585CollectionNames, @@ -264,6 +265,7 @@ class Parser( OverridePrintSafeValues, *numpy_fixes, # type: ignore[misc] FixNumpyDtype, + FixNumpyArrayFlags, FixCurrentModulePrefixInTypeNames, FixBuiltinTypes, RewritePybind11EnumValueRepr, diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index 260201f..d5b7c70 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -543,11 +543,6 @@ class _NumpyArrayAnnotation: ), ) ) - numpy_flags: set[QualifiedName] = { - QualifiedName.from_str("flags.writeable"), - QualifiedName.from_str("flags.c_contiguous"), - QualifiedName.from_str("flags.f_contiguous"), - } dim_vars: set[str] = {"n", "m"} __dim_string_pattern = re.compile(r'"\[(.*?)\]"') @@ -632,8 +627,6 @@ def _from_old_style( ): dimensions = cls._to_dims(scalar_with_dims.parameters) - cls._fix_flags(flags) - return _NumpyArrayAnnotation(array_type, scalar_type, dimensions, flags) @classmethod @@ -711,6 +704,14 @@ def _from_new_style( dims = cls._to_dims_from_strings(dims_list) flags = dims_and_flags[1:] + for i, flag in enumerate(flags): + if isinstance(flag, Value): + flag_str = flag.repr.strip('"') + if flag_str.startswith("flags."): + flags[i] = ResolvedType( + name=QualifiedName.from_str(f"numpy.ndarray.{flag_str}") + ) + return cls(array_type, scalar_type, dims, flags) @classmethod @@ -733,12 +734,6 @@ def _to_dims( result.append(dim) return result - @classmethod - def _fix_flags(cls, flags: list[ResolvedType | Value | InvalidExpression]): - for flag in flags: - if isinstance(flag, ResolvedType) and flag.name in cls.numpy_flags: - flag.name = QualifiedName.from_str(f"numpy.ndarray.{flag.name}") - @staticmethod def _to_dims_from_strings(dimensions: Sequence[str]) -> list[int | str] | None: result: list[int | str] = [] @@ -791,24 +786,7 @@ def parse_annotation_str( params.append( self.handle_value(self.__wrap_with_size_helper(numpy_array.dimensions)) ) - - for flag in numpy_array.flags: - if isinstance(flag, Value): - flag_str = flag.repr.strip('"') - if flag_str in ( - "flags.writeable", - "flags.c_contiguous", - "flags.f_contiguous", - ): - params.append( - ResolvedType( - name=QualifiedName.from_str(f"numpy.ndarray.{flag_str}") - ) - ) - else: - params.append(flag) - else: - params.append(flag) + params.extend(numpy_array.flags) return ResolvedType(name=self.__annotated_name, parameters=params) @@ -832,11 +810,6 @@ def report_error(self, error: ParserError) -> None: ): # Ignores all unknown 'm' and 'n' regardless of the context return - if ( - isinstance(error, NameResolutionError) - and error.name in _NumpyArrayAnnotation.numpy_flags - ): - return super().report_error(error) @@ -883,7 +856,6 @@ def parse_annotation_str( numpy_array = _NumpyArrayAnnotation.from_annotation(result) if numpy_array is None: return result - # __import__('ipdb').set_trace() # scipy.sparse arrays/matrices are not currently generic and do not accept type # arguments @@ -907,11 +879,6 @@ def report_error(self, error: ParserError) -> None: ): # allow type variables, which are manually resolved in `handle_module` return - if ( - isinstance(error, NameResolutionError) - and error.name in _NumpyArrayAnnotation.numpy_flags - ): - return super().report_error(error) @@ -964,6 +931,34 @@ def parse_annotation_str( return result +class FixNumpyArrayFlags(IParser): + __ndarray_name = QualifiedName.from_str("numpy.ndarray") + __flags: set[QualifiedName] = { + QualifiedName.from_str("flags.writeable"), + QualifiedName.from_str("flags.c_contiguous"), + QualifiedName.from_str("flags.f_contiguous"), + } + + def parse_annotation_str( + self, annotation_str: str + ) -> ResolvedType | InvalidExpression | Value: + result = super().parse_annotation_str(annotation_str) + if isinstance(result, ResolvedType) and result.name == self.__ndarray_name: + if result.parameters is not None: + for param in result.parameters: + if isinstance(param, ResolvedType) and param.name in self.__flags: + param.name = QualifiedName.from_str( + f"numpy.ndarray.{param.name}" + ) + + return result + + def report_error(self, error: ParserError) -> None: + if isinstance(error, NameResolutionError) and error.name in self.__flags: + return + super().report_error(error) + + class FixRedundantMethodsFromBuiltinObject(IParser): def handle_method(self, path: QualifiedName, method: Any) -> list[Method]: result = super().handle_method(path, method) From 020eb419167acd1049458ed8d0f7f30627b25a52 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 15:55:40 +0200 Subject: [PATCH 13/16] Check errors with --numpy-array-wrap-with-annotated since v3.0.0 does not throw errors anymore --- tests/check-demo-errors-generation.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/check-demo-errors-generation.sh b/tests/check-demo-errors-generation.sh index 71906c7..add3767 100755 --- a/tests/check-demo-errors-generation.sh +++ b/tests/check-demo-errors-generation.sh @@ -22,6 +22,7 @@ run_stubgen() { pybind11-stubgen \ demo \ --output-dir=${STUBS_DIR} \ + --numpy-array-wrap-with-annotated \ --exit-code \ 2> "${DEMO_ERRORS_FILE}" \ || exit 0 From 06f204fd85749335541c6b821c2cabc4250c1b10 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Sun, 17 Aug 2025 16:06:33 +0200 Subject: [PATCH 14/16] Ensure demo is built with the correct C++ standard --- tests/demo-lib/include/demo/Foo.h | 2 +- tests/install-demo-module.sh | 5 ++++- tests/py-demo/bindings/src/modules/methods.cpp | 8 ++++---- tests/py-demo/bindings/src/modules/values.cpp | 12 ++++++------ 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/demo-lib/include/demo/Foo.h b/tests/demo-lib/include/demo/Foo.h index ae19bdd..53bf7c2 100644 --- a/tests/demo-lib/include/demo/Foo.h +++ b/tests/demo-lib/include/demo/Foo.h @@ -5,7 +5,7 @@ namespace demo{ class CppException : public std::runtime_error { - //using std::runtime_error; + using std::runtime_error::runtime_error; }; struct Foo { diff --git a/tests/install-demo-module.sh b/tests/install-demo-module.sh index 6209846..ffe8a3d 100755 --- a/tests/install-demo-module.sh +++ b/tests/install-demo-module.sh @@ -59,7 +59,10 @@ install_pybind11() { } install_demo() { - cmake -S "${TESTS_ROOT}/demo-lib" -B "${BUILD_ROOT}/demo" + cmake \ + -S "${TESTS_ROOT}/demo-lib" \ + -B "${BUILD_ROOT}/demo" \ + -DCMAKE_CXX_STANDARD=17 cmake --build "${BUILD_ROOT}/demo" cmake --install "${BUILD_ROOT}/demo" \ --prefix "${INSTALL_PREFIX}" diff --git a/tests/py-demo/bindings/src/modules/methods.cpp b/tests/py-demo/bindings/src/modules/methods.cpp index 4f96a0c..f281495 100644 --- a/tests/py-demo/bindings/src/modules/methods.cpp +++ b/tests/py-demo/bindings/src/modules/methods.cpp @@ -1,6 +1,6 @@ #include "modules.h" -namespace mymodules { +namespace { struct Dummy { int regular_method(int x) { return x + 1; } static int static_method(int x) { return x + 1; } @@ -9,8 +9,8 @@ struct Dummy { } // namespace void bind_methods_module(py::module&& m) { - auto &&pyDummy = py::class_(m, "Dummy"); + auto &&pyDummy = py::class_(m, "Dummy"); - pyDummy.def_static("static_method", &mymodules::Dummy::static_method); - pyDummy.def("regular_method", &mymodules::Dummy::regular_method); + pyDummy.def_static("static_method", &Dummy::static_method); + pyDummy.def("regular_method", &Dummy::regular_method); } diff --git a/tests/py-demo/bindings/src/modules/values.cpp b/tests/py-demo/bindings/src/modules/values.cpp index 415ff8a..98ae806 100644 --- a/tests/py-demo/bindings/src/modules/values.cpp +++ b/tests/py-demo/bindings/src/modules/values.cpp @@ -4,7 +4,7 @@ #include -namespace myvalues { +namespace { class Dummy {}; class Foo {}; } // namespace @@ -12,7 +12,7 @@ class Foo {}; void bind_values_module(py::module &&m) { { // python module as value - auto &&pyDummy = py::class_(m, "Dummy"); + auto &&pyDummy = py::class_(m, "Dummy"); pyDummy.def_property_readonly_static( "linalg", [](py::object &) { return py::module::import("numpy.linalg"); }); @@ -27,12 +27,12 @@ void bind_values_module(py::module &&m) { m.attr("list_with_none") = li; } { - auto pyFoo = py::class_(m, "Foo"); - m.attr("foovar") = myvalues::Foo(); + auto pyFoo = py::class_(m, "Foo"); + m.attr("foovar") = Foo(); py::list foolist; - foolist.append(myvalues::Foo()); - foolist.append(myvalues::Foo()); + foolist.append(Foo()); + foolist.append(Foo()); m.attr("foolist") = foolist; m.attr("none") = py::none(); From d555c427a9bcef48c811dbf985c817fff7d19711 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Wed, 20 Aug 2025 00:15:15 +0200 Subject: [PATCH 15/16] Fix incorrect parsing of compound types --- pybind11_stubgen/parser/mixins/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybind11_stubgen/parser/mixins/parse.py b/pybind11_stubgen/parser/mixins/parse.py index f886760..e88fe35 100644 --- a/pybind11_stubgen/parser/mixins/parse.py +++ b/pybind11_stubgen/parser/mixins/parse.py @@ -583,7 +583,7 @@ def parse_annotation_str( assert isinstance(union_t, ResolvedType) return ResolvedType( name=union_t.name, - parameters=[self.parse_type_str(variant) for variant in variants], + parameters=[self.parse_annotation_str(variant) for variant in variants], ) def parse_type_str( From d85d060d3ea71845186d1015e8d9ec68b292ffb5 Mon Sep 17 00:00:00 2001 From: sarlinpe Date: Wed, 20 Aug 2025 00:15:35 +0200 Subject: [PATCH 16/16] Fix incorrect parsing of numpy.bool dtype --- pybind11_stubgen/parser/mixins/fix.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pybind11_stubgen/parser/mixins/fix.py b/pybind11_stubgen/parser/mixins/fix.py index d5b7c70..0a0ef98 100644 --- a/pybind11_stubgen/parser/mixins/fix.py +++ b/pybind11_stubgen/parser/mixins/fix.py @@ -538,6 +538,8 @@ class _NumpyArrayAnnotation: "complex32", "complex64", "longcomplex", + "bool", + "bool_", ), ), ), @@ -565,7 +567,7 @@ def to_type_hint( # Pybind annotates a bool Python type, which cannot be used with # numpy.dtype because it does not inherit from numpy.generic. # Only numpy.bool_ works reliably with both NumPy 1.x and 2.x. - if str(scalar_type_name) == "bool": + if str(scalar_type_name) in {"bool", "numpy.bool"}: scalar_type_name = QualifiedName.from_str("numpy.bool_") dtype = ResolvedType( name=QualifiedName.from_str("numpy.dtype"),