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

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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions