mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
Use generic arg names for functions without explicitly named arguments
Example signatures (old => new): foo(int) => foo(arg0: int) bar(Object, int) => bar(self: Object, arg0: int) The change makes the signatures uniform for named and unnamed arguments and it helps static analysis tools reconstruct function signatures from docstrings. This also tweaks the signature whitespace style to better conform to PEP 8 for annotations and default arguments: " : " => ": " " = " => "="
This commit is contained in:
parent
52d77d9db9
commit
ecced6c5ae
@ -40,8 +40,13 @@ void args_kwargs_function(py::args args, py::kwargs kwargs) {
|
||||
}
|
||||
}
|
||||
|
||||
struct KWClass {
|
||||
void foo(int, float) {}
|
||||
};
|
||||
|
||||
void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
m.def("kw_func", &kw_func, py::arg("x"), py::arg("y"));
|
||||
m.def("kw_func0", &kw_func);
|
||||
m.def("kw_func1", &kw_func, py::arg("x"), py::arg("y"));
|
||||
m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200);
|
||||
m.def("kw_func3", [](const char *) { }, py::arg("data") = std::string("Hello world!"));
|
||||
|
||||
@ -59,4 +64,8 @@ void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
using namespace py::literals;
|
||||
m.def("kw_func_udl", &kw_func, "x"_a, "y"_a=300);
|
||||
m.def("kw_func_udl_z", &kw_func, "x"_a, "y"_a=0);
|
||||
|
||||
py::class_<KWClass>(m, "KWClass")
|
||||
.def("foo0", &KWClass::foo)
|
||||
.def("foo1", &KWClass::foo, "x"_a, "y"_a);
|
||||
}
|
||||
|
@ -5,19 +5,26 @@ import pydoc
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
from example import kw_func, kw_func2, kw_func3, kw_func4, call_kw_func
|
||||
from example import kw_func0, kw_func1, kw_func2, kw_func3, kw_func4, call_kw_func
|
||||
from example import args_function, args_kwargs_function, kw_func_udl, kw_func_udl_z
|
||||
from example import KWClass
|
||||
|
||||
print(pydoc.render_doc(kw_func, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func0, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func1, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func2, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func3, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func4, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func_udl, "Help on %s"))
|
||||
print(pydoc.render_doc(kw_func_udl_z, "Help on %s"))
|
||||
print(pydoc.render_doc(args_function, "Help on %s"))
|
||||
print(pydoc.render_doc(args_kwargs_function, "Help on %s"))
|
||||
|
||||
kw_func(5, 10)
|
||||
kw_func(5, y=10)
|
||||
kw_func(y=10, x=5)
|
||||
print(KWClass.foo0.__doc__)
|
||||
print(KWClass.foo1.__doc__)
|
||||
|
||||
kw_func1(5, 10)
|
||||
kw_func1(5, y=10)
|
||||
kw_func1(y=10, x=5)
|
||||
|
||||
kw_func2()
|
||||
|
||||
|
@ -1,32 +1,52 @@
|
||||
Help on built-in function kw_func in module example
|
||||
Help on built-in function kw_func0 in module example
|
||||
|
||||
kkww__ffuunncc(...)
|
||||
kw_func(x : int, y : int) -> NoneType
|
||||
kkww__ffuunncc00(...)
|
||||
kw_func0(arg0: int, arg1: int) -> NoneType
|
||||
|
||||
Help on built-in function kw_func1 in module example
|
||||
|
||||
kkww__ffuunncc11(...)
|
||||
kw_func1(x: int, y: int) -> NoneType
|
||||
|
||||
Help on built-in function kw_func2 in module example
|
||||
|
||||
kkww__ffuunncc22(...)
|
||||
kw_func2(x : int = 100L, y : int = 200L) -> NoneType
|
||||
kw_func2(x: int=100L, y: int=200L) -> NoneType
|
||||
|
||||
Help on built-in function kw_func3 in module example
|
||||
|
||||
kkww__ffuunncc33(...)
|
||||
kw_func3(data : unicode = u'Hello world!') -> NoneType
|
||||
kw_func3(data: unicode=u'Hello world!') -> NoneType
|
||||
|
||||
Help on built-in function kw_func4 in module example
|
||||
|
||||
kkww__ffuunncc44(...)
|
||||
kw_func4(myList : list<int> = [13L, 17L]) -> NoneType
|
||||
kw_func4(myList: list<int>=[13L, 17L]) -> NoneType
|
||||
|
||||
Help on built-in function kw_func_udl in module example
|
||||
|
||||
kkww__ffuunncc__uuddll(...)
|
||||
kw_func_udl(x : int, y : int = 300L) -> NoneType
|
||||
kw_func_udl(x: int, y: int=300L) -> NoneType
|
||||
|
||||
Help on built-in function kw_func_udl_z in module example
|
||||
|
||||
kkww__ffuunncc__uuddll__zz(...)
|
||||
kw_func_udl_z(x : int, y : int = 0L) -> NoneType
|
||||
kw_func_udl_z(x: int, y: int=0L) -> NoneType
|
||||
|
||||
Help on built-in function args_function in module example
|
||||
|
||||
aarrggss__ffuunnccttiioonn(...)
|
||||
args_function(*args) -> NoneType
|
||||
|
||||
Help on built-in function args_kwargs_function in module example
|
||||
|
||||
aarrggss__kkwwaarrggss__ffuunnccttiioonn(...)
|
||||
args_kwargs_function(*args, **kwargs) -> NoneType
|
||||
|
||||
|
||||
foo0(self: KWClass, arg0: int, arg1: float) -> NoneType
|
||||
foo1(self: KWClass, x: int, y: float) -> NoneType
|
||||
|
||||
|
||||
kw_func(x=5, y=10)
|
||||
kw_func(x=5, y=10)
|
||||
@ -38,7 +58,7 @@ kw_func(x=100, y=10)
|
||||
kw_func(x=5, y=10)
|
||||
kw_func(x=5, y=10)
|
||||
Caught expected exception: Incompatible function arguments. The following argument types are supported:
|
||||
1. (x : int = 100L, y : int = 200L) -> NoneType
|
||||
1. (x: int=100L, y: int=200L) -> NoneType
|
||||
Invoked with:
|
||||
kw_func4: 13 17
|
||||
kw_func4: 1 2 3
|
||||
|
@ -6,7 +6,7 @@ Molly is a dog
|
||||
Molly is a dog
|
||||
Woof!
|
||||
The following error is expected: Incompatible function arguments. The following argument types are supported:
|
||||
1. (example.Dog) -> NoneType
|
||||
1. (arg0: example.Dog) -> NoneType
|
||||
Invoked with: <example.Pet object at 0>
|
||||
Callback function 1 called!
|
||||
False
|
||||
|
@ -6,10 +6,10 @@ Yay..
|
||||
[3, 5, 7, 9, 11, 13, 15]
|
||||
0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9,
|
||||
Failed as expected: Incompatible function arguments. The following argument types are supported:
|
||||
1. (example.issues.ElementA) -> NoneType
|
||||
1. (arg0: example.issues.ElementA) -> NoneType
|
||||
Invoked with: None
|
||||
Failed as expected: Incompatible function arguments. The following argument types are supported:
|
||||
1. (int) -> int
|
||||
1. (arg0: int) -> int
|
||||
Invoked with: 5.2
|
||||
12.0
|
||||
C++ version
|
||||
@ -21,6 +21,6 @@ In python f()
|
||||
StrIssue.__str__ called
|
||||
StrIssue[3]
|
||||
Failed as expected: Incompatible constructor arguments. The following argument types are supported:
|
||||
1. example.issues.StrIssue(int)
|
||||
1. example.issues.StrIssue(arg0: int)
|
||||
2. example.issues.StrIssue()
|
||||
Invoked with: no, such, constructor
|
||||
|
@ -157,7 +157,7 @@ protected:
|
||||
|
||||
/// Register a function call with Python (generic non-templated code goes here)
|
||||
void initialize_generic(detail::function_record *rec, const char *text,
|
||||
const std::type_info *const *types, int args) {
|
||||
const std::type_info *const *types, size_t args) {
|
||||
|
||||
/* Create copies of all referenced C-style strings */
|
||||
rec->name = strdup(rec->name ? rec->name : "");
|
||||
@ -182,16 +182,23 @@ protected:
|
||||
break;
|
||||
|
||||
if (c == '{') {
|
||||
if (type_depth == 1 && arg_index < rec->args.size()) {
|
||||
signature += rec->args[arg_index].name;
|
||||
signature += " : ";
|
||||
// Write arg name for everything except *args, **kwargs and return type.
|
||||
if (type_depth == 1 && text[char_index] != '*' && arg_index < args) {
|
||||
if (!rec->args.empty()) {
|
||||
signature += rec->args[arg_index].name;
|
||||
} else if (arg_index == 0 && rec->class_) {
|
||||
signature += "self";
|
||||
} else {
|
||||
signature += "arg" + std::to_string(arg_index - (rec->class_ ? 1 : 0));
|
||||
}
|
||||
signature += ": ";
|
||||
}
|
||||
++type_depth;
|
||||
} else if (c == '}') {
|
||||
--type_depth;
|
||||
if (type_depth == 1 && arg_index < rec->args.size()) {
|
||||
if (rec->args[arg_index].descr) {
|
||||
signature += " = ";
|
||||
if (type_depth == 1) {
|
||||
if (arg_index < rec->args.size() && rec->args[arg_index].descr) {
|
||||
signature += "=";
|
||||
signature += rec->args[arg_index].descr;
|
||||
}
|
||||
arg_index++;
|
||||
@ -453,9 +460,9 @@ protected:
|
||||
|
||||
bool wrote_sig = false;
|
||||
if (overloads->is_constructor) {
|
||||
// For a constructor, rewrite `(Object, arg0, ...) -> NoneType` as `Object(arg0, ...)`
|
||||
// For a constructor, rewrite `(self: Object, arg0, ...) -> NoneType` as `Object(arg0, ...)`
|
||||
std::string sig = it2->signature;
|
||||
size_t start = sig.find('(') + 1;
|
||||
size_t start = sig.find('(') + 7; // skip "(self: "
|
||||
if (start < sig.size()) {
|
||||
// End at the , for the next argument
|
||||
size_t end = sig.find(", "), next = end + 2;
|
||||
|
Loading…
Reference in New Issue
Block a user