Skip to content

Commit 0435861

Browse files
authored
[stubgen] Added support for typing.ParamSpec (#1194)
I did not add any tests, because typing.ParamSpec is 3.10+ and we have no support for version-conditioned stubgen tests atm.
1 parent e69b349 commit 0435861

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

docs/api_extra.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,16 @@ include directive:
15611561
<https://docs.python.org/3/library/typing.html#typing.TypeVarTuple>`__
15621562
(i.e., an instance of ``typing.TypeVarTuple``).
15631563

1564+
.. cpp:function:: template <typename... Args> object param_spec(Args&&... args)
1565+
1566+
Analogous to :cpp:func:`type_var`, create a `parameter specification variable
1567+
<https://docs.python.org/3/library/typing.html#typing.ParamSpec>`__
1568+
(i.e., an instance of ``typing.ParamSpec``).
1569+
1570+
.. code-block:: cpp
1571+
1572+
m.attr("P") = nb::param_spec("P");
1573+
15641574
.. cpp:function:: object any_type()
15651575

15661576
Convenience wrapper, which returns ``typing.Any``.

include/nanobind/typing.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ object type_var_tuple(Args&&... args) {
2828
return typing().attr("TypeVarTuple")((detail::forward_t<Args>) args...);
2929
}
3030

31+
template <typename... Args>
32+
object param_spec(Args&&... args) {
33+
return typing().attr("ParamSpec")((detail::forward_t<Args>) args...);
34+
}
35+
3136
NAMESPACE_END(NB_NAMESPACE)

src/stubgen.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -642,12 +642,24 @@ def put_value(self, value: object, name: str, parent: Optional[object] = None, a
642642
self.write_ln(f"{name}{types} = {value_str}\n")
643643

644644
def is_type_var(self, tp: type) -> bool:
645-
return (issubclass(tp, typing.TypeVar)
646-
or (sys.version_info >= (3, 11) and issubclass(tp, typing.TypeVarTuple))
647-
or (typing_extensions is not None
648-
and (
649-
issubclass(tp, typing_extensions.TypeVar)
650-
or issubclass(tp, typing_extensions.TypeVarTuple))))
645+
if issubclass(tp, typing.TypeVar):
646+
return True
647+
if sys.version_info >= (3, 10) and issubclass(tp, typing.ParamSpec):
648+
return True
649+
if sys.version_info >= (3, 11) and issubclass(tp, typing.TypeVarTuple):
650+
return True
651+
if typing_extensions is not None:
652+
if issubclass(
653+
tp,
654+
(
655+
typing_extensions.TypeVar,
656+
typing_extensions.ParamSpec,
657+
typing_extensions.TypeVarTuple
658+
)
659+
):
660+
return True
661+
return False
662+
651663

652664
def simplify_types(self, s: str) -> str:
653665
"""
@@ -1017,6 +1029,10 @@ def expr_str(self, e: Any, abbrev: bool = True) -> Optional[str]:
10171029
return f'"{e.__forward_arg__}"'
10181030
elif issubclass(tp, enum.Enum):
10191031
return self.type_str(tp) + '.' + e.name
1032+
elif (sys.version_info >= (3, 10) and issubclass(tp, typing.ParamSpec)) \
1033+
or (typing_extensions is not None and issubclass(tp, typing_extensions.ParamSpec)):
1034+
tv = self.import_object(tp.__module__, "ParamSpec")
1035+
return f'{tv}("{e.__name__}")'
10201036
elif (sys.version_info >= (3, 11) and issubclass(tp, typing.TypeVarTuple)) \
10211037
or (typing_extensions is not None and issubclass(tp, typing_extensions.TypeVarTuple)):
10221038
tv = self.import_object(tp.__module__, "TypeVarTuple")

0 commit comments

Comments
 (0)