Skip to content

py::str x = py::none() is a bit confusing; it converts None to a string, rather than setting the value to None #2361

Closed
@EricCousineau-TRI

Description

@EricCousineau-TRI

Issue description

If I have a C++ function with py::str as an argument, I wanted to be able to default it to py::none(). However, I was later surprised in my Python code because I was getting 'None' (a string version) rather than purely None.

Reproducible example code

See this patch here:
9c9b1f5

The test fails with the following:

    def test_str_with_cpp_default_none():                                                              
>       assert m.test_str_with_cpp_default_none() == (None, "Hello")                                   
E       AssertionError: assert ('None', 'Hello') == (None, 'Hello')                                    
E         At index 0 diff: 'None' != None

I got bit in the following downstream code:
https://github.com/RobotLocomotion/drake/blob/feb254ea0a711c6596d7b8bf720672e0a5acd329/bindings/pydrake/common/deprecation_pybind.h#L21-L22

The workarounds I could think of:

  • Use py::object, and then let Python code enforce the safe of string-ification.
  • Use std::optional<std::string> to make it more C++-y

Suggestions

Two options:

  • Somehow distinguish assignment-at-construction py::str x = py::none() (use None), assignment py::str x; x = py::none() and make these set the object truly to None; for conversion, py::str(py::none()), allow this to be stringified.
    • I doubt this is possible in C++ without doing weird implicit converting operators.
  • Warn about this in the docs here: https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#
    • Something like "Warning about assigning py::none() to objects in C++; This may happen with defautl arguments ...".

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions