Skip to content

Render NaN default argument as numpy.nan - #2243

Closed
sizmailov wants to merge 4 commits into
pybind:masterfrom
sizmailov:doc-gen-nan-default-arg
Closed

Render NaN default argument as numpy.nan#2243
sizmailov wants to merge 4 commits into
pybind:masterfrom
sizmailov:doc-gen-nan-default-arg

Conversation

@sizmailov

@sizmailovsizmailov commented Jun 5, 2020

Copy link
Copy Markdown
Contributor

This PR changes how nan values are rendered in docstring.

this PRmaster
foo(x: float = numpy.nan) -> None
foo(x: float = nan) -> None

Implemented via float overloads for py::arg_v. Might be considered as an overkill for such a small change. On the other hand nan values are quite common sentinel values so it might be worth it to generate more toolable docstrings.

compare.cpp
#include"pybind11/pybind11.h"
#include"pybind11/embed.h"namespacepy= pybind11;
PYBIND11_EMBEDDED_MODULE(example, m) {
m.def("foo", [](float x) {}, py::arg("x")=std::numeric_limits<float>::quiet_NaN()); }
intmain() {
py::scoped_interpreter guard{};
py::exec(R"( from example import *  print(foo.__doc__, end="") )");
}

Example: generated signature changes from
foo(x: float = nan)
to
foo(x: float = numpy.nan)
std::isnan is not available on gcc-4.8
@sizmailov
sizmailovforce-pushed the doc-gen-nan-default-arg branch from 9136bac to a30af8fCompareJune 6, 2020 07:53
@sizmailov

sizmailov commented Jun 6, 2020

Copy link
Copy Markdown
ContributorAuthor

__cplusplus >= 201103L doesn't mean the library is c++-11 complaint in gcc-4.8 (std::isnan is missing).
To avoid mess with other compilers versions I've enabled it starting from c++14.

@sizmailov
sizmailovforce-pushed the doc-gen-nan-default-arg branch from 54fd417 to d4784d1CompareJune 6, 2020 08:22
@sizmailov

Copy link
Copy Markdown
ContributorAuthor

On second thought I think I chose wrong place inject the change.

The underlying bigger problem is __repr__ function is not intended to produce valid python expressions, therefore we get malformed function signatures quite often. Probably next suggestion is better candidates to format value for signatures.

if (a.descr)
a.descr = strdup(a.descr);
elseif (a.value)
a.descr = strdup(a.value.attr("__repr__")().cast<std::string>().c_str());

For example new extension point can be introduced with something like

tempate<typename T>
structvalue_formatter {
value_formatter(const T& value);
constchar* operator() const;
}// and later in pybind11.hif (a.descr)
a.descr = strdup(a.descr);
elseif (a.value)
a.descr = strdup(value_formatter(cast(a.value))());

@sizmailov
sizmailov marked this pull request as draft June 10, 2020 01:48
@wjakob

Copy link
Copy Markdown
Member

I'm curious: what's wrong with just nan? I don't think numpy.nan is a good alternative, pybind11 is used in all sorts of places that don't even have numpy installed.

@sizmailov

Copy link
Copy Markdown
ContributorAuthor

The problem is that generated signatures are not valid in sense of interpretation as stubs signatures. nan refers to a name which is not defined, so docgen/static analysis tools gets confused. The numpy.nan can be replaced with float('nan'), but I think it's a bit more readable.

The situation is worse when default value is not even valid python expression, e.g. x: Foo = <Foo instance 0xffff>. I think it needs generic solution so I close this PR. In shed of light #2244 closing I think you will argue against any PRs in this direction too.

Documentation matters therefore I think it's worth to produce toolable docstrings.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sizmailov@wjakob