Skip to content

Commit

Permalink
Add type hints for args and kwargs (#5357)
Browse files Browse the repository at this point in the history
* Allow subclasses of args and kwargs

The current implementation disallows subclasses of args and kwargs

* Added object type hint to args and kwargs

* Added type hinted args and kwargs classes

* Changed default type hint to typing.Any

* Removed args and kwargs type hint

* Updated tests

Modified the tests from #5381 to use the real Args and KWArgs classes

* Added comment
  • Loading branch information
gentlegiantJGC authored Nov 11, 2024
1 parent a90e2af commit 6d98d4d
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 22 deletions.
8 changes: 8 additions & 0 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1012,10 +1012,18 @@ template <>
struct handle_type_name<args> {
static constexpr auto name = const_name("*args");
};
template <typename T>
struct handle_type_name<Args<T>> {
static constexpr auto name = const_name("*args: ") + make_caster<T>::name;
};
template <>
struct handle_type_name<kwargs> {
static constexpr auto name = const_name("**kwargs");
};
template <typename T>
struct handle_type_name<KWArgs<T>> {
static constexpr auto name = const_name("**kwargs: ") + make_caster<T>::name;
};
template <>
struct handle_type_name<obj_attr_accessor> {
static constexpr auto name = const_name<obj_attr_accessor>();
Expand Down
12 changes: 12 additions & 0 deletions include/pybind11/pytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,18 @@ class kwargs : public dict {
PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check)
};

// Subclasses of args and kwargs to support type hinting
// as defined in PEP 484. See #5357 for more info.
template <typename T>
class Args : public args {
using args::args;
};

template <typename T>
class KWArgs : public kwargs {
using kwargs::kwargs;
};

class anyset : public object {
public:
PYBIND11_OBJECT(anyset, object, PyAnySet_Check)
Expand Down
22 changes: 1 addition & 21 deletions tests/test_kwargs_and_defaults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,6 @@

#include <utility>

// Classes needed for subclass test.
class ArgsSubclass : public py::args {
using py::args::args;
};
class KWArgsSubclass : public py::kwargs {
using py::kwargs::kwargs;
};
namespace pybind11 {
namespace detail {
template <>
struct handle_type_name<ArgsSubclass> {
static constexpr auto name = const_name("*Args");
};
template <>
struct handle_type_name<KWArgsSubclass> {
static constexpr auto name = const_name("**KWArgs");
};
} // namespace detail
} // namespace pybind11

TEST_SUBMODULE(kwargs_and_defaults, m) {
auto kw_func
= [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); };
Expand Down Expand Up @@ -345,7 +325,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {

// Test support for args and kwargs subclasses
m.def("args_kwargs_subclass_function",
[](const ArgsSubclass &args, const KWArgsSubclass &kwargs) {
[](const py::Args<std::string> &args, const py::KWArgs<std::string> &kwargs) {
return py::make_tuple(args, kwargs);
});
}
2 changes: 1 addition & 1 deletion tests/test_kwargs_and_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_function_signatures(doc):
)
assert (
doc(m.args_kwargs_subclass_function)
== "args_kwargs_subclass_function(*Args, **KWArgs) -> tuple"
== "args_kwargs_subclass_function(*args: str, **kwargs: str) -> tuple"
)
assert (
doc(m.KWClass.foo0)
Expand Down

0 comments on commit 6d98d4d

Please sign in to comment.