diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 000000000..004a03aec --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,2 @@ +conda: + file: docs/environment.yml diff --git a/.travis.yml b/.travis.yml index e8c58846d..7a9d763e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,10 @@ matrix: env: DOCS STYLE LINT install: - pip install --upgrade sphinx sphinx_rtd_theme flake8 pep8-naming - - pip install docutils==0.12 + - | + curl -fsSL ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.12.linux.bin.tar.gz | tar xz + export PATH="$PWD/doxygen-1.8.12/bin:$PATH" + pip install https://github.com/michaeljones/breathe/archive/master.zip script: - make -C docs html SPHINX_OPTIONS=-W - tools/check-style.sh diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 000000000..4dc8bf059 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,19 @@ +PROJECT_NAME = pybind11 +INPUT = ../include/pybind11/ + +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_OUTPUT = .build/doxygenxml +XML_PROGRAMLISTING = YES + +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +EXPAND_AS_DEFINED = PYBIND11_RUNTIME_EXCEPTION + +ALIASES = "rst=\verbatim embed:rst" +ALIASES += "endrst=\endverbatim" + +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO diff --git a/docs/advanced/cast/chrono.rst b/docs/advanced/cast/chrono.rst index 6d4a5ee55..8c6b3d7e5 100644 --- a/docs/advanced/cast/chrono.rst +++ b/docs/advanced/cast/chrono.rst @@ -4,8 +4,8 @@ Chrono When including the additional header file :file:`pybind11/chrono.h` conversions from C++11 chrono datatypes to python datetime objects are automatically enabled. This header also enables conversions of python floats (often from sources such -as `time.monotonic()`, `time.perf_counter()` and `time.process_time()`) into -durations. +as ``time.monotonic()``, ``time.perf_counter()`` and ``time.process_time()``) +into durations. An overview of clocks in C++11 ------------------------------ diff --git a/docs/advanced/functions.rst b/docs/advanced/functions.rst index 878888541..7c97a0f7e 100644 --- a/docs/advanced/functions.rst +++ b/docs/advanced/functions.rst @@ -14,7 +14,7 @@ lifetime of objects managed by them. This can lead to issues when creating bindings for functions that return a non-trivial type. Just by looking at the type information, it is not clear whether Python should take charge of the returned value and eventually free its resources, or if this is handled on the -C++ side. For this reason, pybind11 provides a several `return value policy` +C++ side. For this reason, pybind11 provides a several *return value policy* annotations that can be passed to the :func:`module::def` and :func:`class_::def` functions. The default policy is :enum:`return_value_policy::automatic`. @@ -24,11 +24,11 @@ Just to illustrate what can go wrong, consider the following simple example: .. code-block:: cpp - /* Function declaration */ + /* Function declaration */ Data *get_data() { return _data; /* (pointer to a static data structure) */ } ... - /* Binding code */ + /* Binding code */ m.def("get_data", &get_data); // <-- KABOOM, will cause crash when called from Python What's going on here? When ``get_data()`` is called from Python, the return @@ -44,7 +44,7 @@ silent data corruption. In the above example, the policy :enum:`return_value_policy::reference` should have been specified so that the global data instance is only *referenced* without any -implied transfer of ownership, i.e.: +implied transfer of ownership, i.e.: .. code-block:: cpp @@ -158,9 +158,9 @@ targeted arguments can be passed through the :class:`cpp_function` constructor: Additional call policies ======================== -In addition to the above return value policies, further `call policies` can be -specified to indicate dependencies between parameters. In general, call policies -are required when the C++ object is any kind of container and another object is being +In addition to the above return value policies, further *call policies* can be +specified to indicate dependencies between parameters. In general, call policies +are required when the C++ object is any kind of container and another object is being added to the container. There is currently just diff --git a/docs/advanced/pycpp/object.rst b/docs/advanced/pycpp/object.rst index 8e737cc02..ae58876de 100644 --- a/docs/advanced/pycpp/object.rst +++ b/docs/advanced/pycpp/object.rst @@ -33,6 +33,8 @@ The reverse direction uses the following syntax: When conversion fails, both directions throw the exception :class:`cast_error`. +.. _calling_python_functions: + Calling Python functions ======================== diff --git a/docs/classes.rst b/docs/classes.rst index 0bddfe29b..2c1ff2a39 100644 --- a/docs/classes.rst +++ b/docs/classes.rst @@ -38,7 +38,7 @@ The binding code for ``Pet`` looks as follows: return m.ptr(); } -:class:`class_` creates bindings for a C++ `class` or `struct`-style data +:class:`class_` creates bindings for a C++ *class* or *struct*-style data structure. :func:`init` is a convenience function that takes the types of a constructor's parameters as template arguments and wraps the corresponding constructor (see the :ref:`custom_constructors` section for details). An diff --git a/docs/conf.py b/docs/conf.py index c8f964422..82dfe262d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,7 @@ import sys import os import shlex +import subprocess # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -30,7 +31,11 @@ import shlex # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] +extensions = ['breathe'] + +breathe_projects = {'pybind11': '.build/doxygenxml/'} +breathe_default_project = 'pybind11' +breathe_domain_by_extension = {'h': 'cpp'} # Add any paths that contain templates here, relative to this directory. templates_path = ['.templates'] @@ -79,7 +84,7 @@ exclude_patterns = ['.build', 'release.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +default_role = 'any' # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True @@ -306,3 +311,22 @@ texinfo_documents = [ primary_domain = 'cpp' highlight_language = 'cpp' + + +def generate_doxygen_xml(app): + build_dir = '.build' + if not os.path.exists(build_dir): + os.mkdir(build_dir) + + try: + subprocess.call(['doxygen', '--version']) + retcode = subprocess.call(['doxygen']) + if retcode < 0: + sys.stderr.write("doxygen error code: {}\n".format(-retcode)) + except OSError as e: + sys.stderr.write("doxygen execution failed: {}\n".format(e)) + + +def setup(app): + """Add hook for building doxygen xml when needed""" + app.connect("builder-inited", generate_doxygen_xml) diff --git a/docs/environment.yml b/docs/environment.yml new file mode 100644 index 000000000..5a3332b27 --- /dev/null +++ b/docs/environment.yml @@ -0,0 +1,9 @@ +name: rtd +channels: +- dean0x7d +- defaults +dependencies: +- doxygen +- pip +- pip: + - https://github.com/michaeljones/breathe/archive/master.zip diff --git a/docs/reference.rst b/docs/reference.rst index 542259eba..3d211f7e9 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -12,236 +12,69 @@ Reference Macros ====== -.. function:: PYBIND11_PLUGIN(const char *name) - - This macro creates the entry point that will be invoked when the Python - interpreter imports a plugin library. Please create a - :class:`module` in the function body and return the pointer to its - underlying Python object at the end. - - .. code-block:: cpp - - PYBIND11_PLUGIN(example) { - pybind11::module m("example", "pybind11 example plugin"); - /// Set up bindings here - return m.ptr(); - } +.. doxygendefine:: PYBIND11_PLUGIN .. _core_types: Convenience classes for arbitrary Python types ============================================== +Common member functions +----------------------- + +.. doxygenclass:: object_api + :members: + Without reference counting -------------------------- -.. class:: handle - - The :class:`handle` class is a thin wrapper around an arbitrary Python - object (i.e. a ``PyObject *`` in Python's C API). It does not perform any - automatic reference counting and merely provides a basic C++ interface to - various Python API functions. - -.. seealso:: - - The :class:`object` class inherits from :class:`handle` and adds automatic - reference counting features. - -.. function:: handle::handle() - - The default constructor creates a handle with a ``nullptr``-valued pointer. - -.. function:: handle::handle(const handle&) - - Copy constructor - -.. function:: handle::handle(PyObject *) - - Creates a :class:`handle` from the given raw Python object pointer. - -.. function:: PyObject * handle::ptr() const - - Return the ``PyObject *`` underlying a :class:`handle`. - -.. function:: const handle& handle::inc_ref() const - - Manually increase the reference count of the Python object. Usually, it is - preferable to use the :class:`object` class which derives from - :class:`handle` and calls this function automatically. Returns a reference - to itself. - -.. function:: const handle& handle::dec_ref() const - - Manually decrease the reference count of the Python object. Usually, it is - preferable to use the :class:`object` class which derives from - :class:`handle` and calls this function automatically. Returns a reference - to itself. - -.. function:: void handle::ref_count() const - - Return the object's current reference count - -.. function:: handle handle::get_type() const - - Return a handle to the Python type object underlying the instance - -.. function detail::accessor handle::operator[](handle key) const - - Return an internal functor to invoke the object's sequence protocol. - Casting the returned ``detail::accessor`` instance to a :class:`handle` or - :class:`object` subclass causes a corresponding call to ``__getitem__``. - Assigning a :class:`handle` or :class:`object` subclass causes a call to - ``__setitem__``. - -.. function detail::accessor handle::operator[](const char *key) const - - See the above function (the only difference is that they key is provided as - a string literal). - -.. function detail::accessor handle::attr(handle key) const - - Return an internal functor to access the object's attributes. - Casting the returned ``detail::accessor`` instance to a :class:`handle` or - :class:`object` subclass causes a corresponding call to ``__getattr``. - Assigning a :class:`handle` or :class:`object` subclass causes a call to - ``__setattr``. - -.. function detail::accessor handle::attr(const char *key) const - - See the above function (the only difference is that they key is provided as - a string literal). - -.. function operator handle::bool() const - - Return ``true`` when the :class:`handle` wraps a valid Python object. - -.. function str handle::str() const - - Return a string representation of the object. This is analogous to - the ``str()`` function in Python. - -.. function:: template T handle::cast() const - - Attempt to cast the Python object into the given C++ type. A - :class:`cast_error` will be throw upon failure. - -.. function:: template object handle::call(Args&&... args) const - - Assuming the Python object is a function or implements the ``__call__`` - protocol, ``call()`` invokes the underlying function, passing an arbitrary - set of parameters. The result is returned as a :class:`object` and may need - to be converted back into a Python object using :func:`handle::cast`. - - When some of the arguments cannot be converted to Python objects, the - function will throw a :class:`cast_error` exception. When the Python - function call fails, a :class:`error_already_set` exception is thrown. +.. doxygenclass:: handle + :members: With reference counting ----------------------- -.. class:: object : public handle +.. doxygenclass:: object + :members: - Like :class:`handle`, the object class is a thin wrapper around an - arbitrary Python object (i.e. a ``PyObject *`` in Python's C API). In - contrast to :class:`handle`, it optionally increases the object's reference - count upon construction, and it *always* decreases the reference count when - the :class:`object` instance goes out of scope and is destructed. When - using :class:`object` instances consistently, it is much easier to get - reference counting right at the first attempt. +.. doxygenfunction:: reinterpret_borrow -.. function:: object::object(const object &o) - - Copy constructor; always increases the reference count - -.. function:: object::object(const handle &h, bool borrowed) - - Creates a :class:`object` from the given :class:`handle`. The reference - count is only increased if the ``borrowed`` parameter is set to ``true``. - -.. function:: object::object(PyObject *ptr, bool borrowed) - - Creates a :class:`object` from the given raw Python object pointer. The - reference count is only increased if the ``borrowed`` parameter is set to - ``true``. - -.. function:: object::object(object &&other) - - Move constructor; steals the object from ``other`` and preserves its - reference count. - -.. function:: handle object::release() - - Resets the internal pointer to ``nullptr`` without without decreasing the - object's reference count. The function returns a raw handle to the original - Python object. - -.. function:: object::~object() - - Destructor, which automatically calls :func:`handle::dec_ref()`. +.. doxygenfunction:: reinterpret_steal Convenience classes for specific Python types ============================================= +.. doxygenclass:: module + :members: -.. class:: module : public object - -.. function:: module::module(const char *name, const char *doc = nullptr) - - Create a new top-level Python module with the given name and docstring - -.. function:: module module::def_submodule(const char *name, const char *doc = nullptr) - - Create and return a new Python submodule with the given name and docstring. - This also works recursively, i.e. - - .. code-block:: cpp - - pybind11::module m("example", "pybind11 example plugin"); - pybind11::module m2 = m.def_submodule("sub", "A submodule of 'example'"); - pybind11::module m3 = m2.def_submodule("subsub", "A submodule of 'example.sub'"); - -.. cpp:function:: template module& module::def(const char *name, Func && f, Extra && ... extra) - - Create Python binding for a new function within the module scope. ``Func`` - can be a plain C++ function, a function pointer, or a lambda function. For - details on the ``Extra&& ... extra`` argument, see section :ref:`extras`. +.. doxygengroup:: pytypes + :members: .. _extras: -Passing extra arguments to the def function -=========================================== +Passing extra arguments to ``def`` or ``class_`` +================================================ -.. class:: arg +.. doxygengroup:: annotations + :members: -.. function:: arg::arg(const char *name) +Python build-in functions +========================= -.. function:: template arg_v arg::operator=(T &&value) +.. doxygengroup:: python_builtins + :members: -.. class:: arg_v : public arg +Exceptions +========== - Represents a named argument with a default value +.. doxygenclass:: error_already_set + :members: -.. class:: sibling +.. doxygenclass:: builtin_exception + :members: - Used to specify a handle to an existing sibling function; used internally - to implement function overloading in :func:`module::def` and - :func:`class_::def`. -.. function:: sibling::sibling(handle handle) - -.. class doc - - This is class is internally used by pybind11. - -.. function:: doc::doc(const char *value) - - Create a new docstring with the specified value - -.. class name - - This is class is internally used by pybind11. - -.. function:: name::name(const char *value) - - Used to specify the function name +Literals +======== +.. doxygennamespace:: literals diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h index 740d3beff..41f59e78b 100644 --- a/include/pybind11/attr.h +++ b/include/pybind11/attr.h @@ -14,6 +14,9 @@ NAMESPACE_BEGIN(pybind11) +/// \addtogroup annotations +/// @{ + /// Annotation for methods struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; @@ -56,6 +59,8 @@ struct metaclass { }; /// Annotation to mark enums as an arithmetic type struct arithmetic { }; +/// @} annotations + NAMESPACE_BEGIN(detail) /* Forward declarations */ enum op_id : int; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 9077dbba7..a52d843ba 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1177,14 +1177,18 @@ template arg_v operator=(T &&value) const; const char *name; }; +/// \ingroup annotations /// Annotation for keyword arguments with values struct arg_v : arg { template @@ -1213,7 +1217,9 @@ arg_v arg::operator=(T &&value) const { return {name, std::forward(value)}; } template using arg_t = arg_v; inline namespace literals { -/// String literal version of arg +/** \rst + String literal version of `arg` + \endrst */ constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } } diff --git a/include/pybind11/common.h b/include/pybind11/common.h index ce0c2ed4c..a0894ead9 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -159,6 +159,19 @@ extern "C" { #define PYBIND11_INTERNALS_ID "__pybind11_" \ PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__" +/** \rst + This macro creates the entry point that will be invoked when the Python interpreter + imports a plugin library. Please create a `module` in the function body and return + the pointer to its underlying Python object at the end. + + .. code-block:: cpp + + PYBIND11_PLUGIN(example) { + pybind11::module m("example", "pybind11 example plugin"); + /// Set up bindings here + return m.ptr(); + } +\endrst */ #define PYBIND11_PLUGIN(name) \ static PyObject *pybind11_init(); \ PYBIND11_PLUGIN_IMPL(name) { \ @@ -388,7 +401,7 @@ template using bool_constant = std::integral_constant; template using negation = bool_constant; #endif -/// Compile-time all/any/none of that check the ::value of all template types +/// Compile-time all/any/none of that check the boolean value of all template types #ifdef PYBIND11_CPP17 template using all_of = bool_constant<(Ts::value && ...)>; template using any_of = bool_constant<(Ts::value || ...)>; @@ -532,7 +545,8 @@ private: class builtin_exception : public std::runtime_error { public: using std::runtime_error::runtime_error; - virtual void set_error() const = 0; /// Set the error using the Python C API + /// Set the error using the Python C API + virtual void set_error() const = 0; }; #define PYBIND11_RUNTIME_EXCEPTION(name, type) \ diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 99b1f7248..81a3d1e73 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -544,6 +544,7 @@ class module : public object { public: PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check) + /// Create a new top-level Python module with the given name and docstring explicit module(const char *name, const char *doc = nullptr) { if (!options::show_user_defined_docstrings()) doc = nullptr; #if PY_MAJOR_VERSION >= 3 @@ -562,6 +563,11 @@ public: inc_ref(); } + /** \rst + Create Python binding for a new function within the module scope. ``Func`` + can be a plain C++ function, a function pointer, or a lambda function. For + details on the ``Extra&& ... extra`` argument, see section :ref:`extras`. + \endrst */ template module &def(const char *name_, Func &&f, const Extra& ... extra) { cpp_function func(std::forward(f), name(name_), scope(*this), @@ -572,6 +578,16 @@ public: return *this; } + /** \rst + Create and return a new Python submodule with the given name and docstring. + This also works recursively, i.e. + + .. code-block:: cpp + + py::module m("example", "pybind11 example plugin"); + py::module m2 = m.def_submodule("sub", "A submodule of 'example'"); + py::module m3 = m2.def_submodule("subsub", "A submodule of 'example.sub'"); + \endrst */ module def_submodule(const char *name, const char *doc = nullptr) { std::string full_name = std::string(PyModule_GetName(m_ptr)) + std::string(".") + std::string(name); @@ -582,6 +598,7 @@ public: return result; } + /// Import and return a module or throws `error_already_set`. static module import(const char *name) { PyObject *obj = PyImport_ImportModule(name); if (!obj) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index a89aad78d..bc806de73 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -45,51 +45,130 @@ using tuple_accessor = accessor; class pyobject_tag { }; template using is_pyobject = std::is_base_of::type>; -/// Mixin which adds common functions to handle, object and various accessors. -/// The only requirement for `Derived` is to implement `PyObject *Derived::ptr() const`. +/** \rst + A mixin class which adds common functions to `handle`, `object` and various accessors. + The only requirement for `Derived` is to implement ``PyObject *Derived::ptr() const``. +\endrst */ template class object_api : public pyobject_tag { const Derived &derived() const { return static_cast(*this); } public: + /** \rst + Return an iterator equivalent to calling ``iter()`` in Python. The object + must be a collection which supports the iteration protocol. + \endrst */ iterator begin() const; + /// Return a sentinel which ends iteration. iterator end() const; - item_accessor operator[](handle key) const; - item_accessor operator[](const char *key) const; - obj_attr_accessor attr(handle key) const; - str_attr_accessor attr(const char *key) const; - args_proxy operator*() const; - template bool contains(T &&key) const; + /** \rst + Return an internal functor to invoke the object's sequence protocol. Casting + the returned ``detail::item_accessor`` instance to a `handle` or `object` + subclass causes a corresponding call to ``__getitem__``. Assigning a `handle` + or `object` subclass causes a call to ``__setitem__``. + \endrst */ + item_accessor operator[](handle key) const; + /// See above (the only difference is that they key is provided as a string literal) + item_accessor operator[](const char *key) const; + + /** \rst + Return an internal functor to access the object's attributes. Casting the + returned ``detail::obj_attr_accessor`` instance to a `handle` or `object` + subclass causes a corresponding call to ``getattr``. Assigning a `handle` + or `object` subclass causes a call to ``setattr``. + \endrst */ + obj_attr_accessor attr(handle key) const; + /// See above (the only difference is that they key is provided as a string literal) + str_attr_accessor attr(const char *key) const; + + /** \rst + Matches * unpacking in Python, e.g. to unpack arguments out of a ``tuple`` + or ``list`` for a function call. Applying another * to the result yields + ** unpacking, e.g. to unpack a dict as function keyword arguments. + See :ref:`calling_python_functions`. + \endrst */ + args_proxy operator*() const; + + /// Check if the given item is contained within this object, i.e. ``item in obj``. + template bool contains(T &&item) const; + + /** \rst + Assuming the Python object is a function or implements the ``__call__`` + protocol, ``operator()`` invokes the underlying function, passing an + arbitrary set of parameters. The result is returned as a `object` and + may need to be converted back into a Python object using `handle::cast()`. + + When some of the arguments cannot be converted to Python objects, the + function will throw a `cast_error` exception. When the Python function + call fails, a `error_already_set` exception is thrown. + \endrst */ template object operator()(Args &&...args) const; template PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)") object call(Args&&... args) const; + /// Equivalent to ``obj is None`` in Python. bool is_none() const { return derived().ptr() == Py_None; } - PYBIND11_DEPRECATED("Instead of obj.str(), use py::str(obj)") + PYBIND11_DEPRECATED("Use py::str(obj) instead") pybind11::str str() const; + /// Return the object's current reference count int ref_count() const { return static_cast(Py_REFCNT(derived().ptr())); } + /// Return a handle to the Python type object underlying the instance handle get_type() const; }; NAMESPACE_END(detail) -/// Holds a reference to a Python object (no reference counting) +/** \rst + Holds a reference to a Python object (no reference counting) + + The `handle` class is a thin wrapper around an arbitrary Python object (i.e. a + ``PyObject *`` in Python's C API). It does not perform any automatic reference + counting and merely provides a basic C++ interface to various Python API functions. + + .. seealso:: + The `object` class inherits from `handle` and adds automatic reference + counting features. +\endrst */ class handle : public detail::object_api { public: + /// The default constructor creates a handle with a ``nullptr``-valued pointer handle() = default; + /// Creates a ``handle`` from the given raw Python object pointer handle(PyObject *ptr) : m_ptr(ptr) { } // Allow implicit conversion from PyObject* + /// Return the underlying ``PyObject *`` pointer PyObject *ptr() const { return m_ptr; } PyObject *&ptr() { return m_ptr; } + + /** \rst + Manually increase the reference count of the Python object. Usually, it is + preferable to use the `object` class which derives from `handle` and calls + this function automatically. Returns a reference to itself. + \endrst */ const handle& inc_ref() const { Py_XINCREF(m_ptr); return *this; } + + /** \rst + Manually decrease the reference count of the Python object. Usually, it is + preferable to use the `object` class which derives from `handle` and calls + this function automatically. Returns a reference to itself. + \endrst */ const handle& dec_ref() const { Py_XDECREF(m_ptr); return *this; } + /** \rst + Attempt to cast the Python object into the given C++ type. A `cast_error` + will be throw upon failure. + \endrst */ template T cast() const; + /// Return ``true`` when the `handle` wraps a valid Python object explicit operator bool() const { return m_ptr != nullptr; } + /** \rst + Check that the underlying pointers are the same. + Equivalent to ``obj1 is obj2`` in Python. + \endrst */ bool operator==(const handle &h) const { return m_ptr == h.m_ptr; } bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; } PYBIND11_DEPRECATED("Use handle::operator bool() instead") @@ -98,16 +177,33 @@ protected: PyObject *m_ptr = nullptr; }; -/// Holds a reference to a Python object (with reference counting) +/** \rst + Holds a reference to a Python object (with reference counting) + + Like `handle`, the `object` class is a thin wrapper around an arbitrary Python + object (i.e. a ``PyObject *`` in Python's C API). In contrast to `handle`, it + optionally increases the object's reference count upon construction, and it + *always* decreases the reference count when the `object` instance goes out of + scope and is destructed. When using `object` instances consistently, it is much + easier to get reference counting right at the first attempt. +\endrst */ class object : public handle { public: object() = default; PYBIND11_DEPRECATED("Use reinterpret_borrow() or reinterpret_steal()") object(handle h, bool is_borrowed) : handle(h) { if (is_borrowed) inc_ref(); } + /// Copy constructor; always increases the reference count object(const object &o) : handle(o) { inc_ref(); } + /// Move constructor; steals the object from ``other`` and preserves its reference count object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; } + /// Destructor; automatically calls `handle::dec_ref()` ~object() { dec_ref(); } + /** \rst + Resets the internal pointer to ``nullptr`` without without decreasing the + object's reference count. The function returns a raw handle to the original + Python object. + \endrst */ handle release() { PyObject *tmp = m_ptr; m_ptr = nullptr; @@ -150,12 +246,41 @@ public: object(handle h, stolen_t) : handle(h) { } }; -/** The following functions don't do any kind of conversion, they simply declare - that a PyObject is a certain type and borrow or steal the reference. */ +/** \rst + Declare that a `handle` or ``PyObject *`` is a certain type and borrow the reference. + The target type ``T`` must be `object` or one of its derived classes. The function + doesn't do any conversions or checks. It's up to the user to make sure that the + target type is correct. + + .. code-block:: cpp + + PyObject *result = PySequence_GetItem(obj, index); + py::object o = reinterpret_borrow(p); + // or + py::tuple t = reinterpret_borrow(p); // <-- `p` must be already be a `tuple` +\endrst */ template T reinterpret_borrow(handle h) { return {h, object::borrowed}; } + +/** \rst + Like `reinterpret_borrow`, but steals the reference. + + .. code-block:: cpp + + PyObject *p = PyObject_Str(obj); + py::str s = reinterpret_steal(p); // <-- `p` must be already be a `str` +\endrst */ template T reinterpret_steal(handle h) { return {h, object::stolen}; } -/// Check if `obj` is an instance of type `T` +/** \defgroup python_builtins _ + Unless stated otherwise, the following C++ functions behave the same + as their Python counterparts. + */ + +/** \ingroup python_builtins + \rst + Return true if ``obj`` is an instance of ``T``. Type ``T`` must be a subclass of + `object` or a class which was exposed to Python as ``py::class_``. +\endrst */ template ::value, int> = 0> bool isinstance(handle obj) { return T::_check(obj); } @@ -165,6 +290,8 @@ bool isinstance(handle obj) { return detail::isinstance_generic(obj, typeid(T)); template <> inline bool isinstance(handle obj) = delete; template <> inline bool isinstance(handle obj) { return obj.ptr() != nullptr; } +/// \ingroup python_builtins +/// Return true if ``obj`` is an instance of the ``type``. inline bool isinstance(handle obj, handle type) { const auto result = PyObject_IsInstance(obj.ptr(), type.ptr()); if (result == -1) @@ -172,6 +299,8 @@ inline bool isinstance(handle obj, handle type) { return result != 0; } +/// \addtogroup python_builtins +/// @{ inline bool hasattr(handle obj, handle name) { return PyObject_HasAttr(obj.ptr(), name.ptr()) == 1; } @@ -217,6 +346,7 @@ inline void setattr(handle obj, handle name, handle value) { inline void setattr(handle obj, const char *name, handle value) { if (PyObject_SetAttrString(obj.ptr(), name, value.ptr()) != 0) { throw error_already_set(); } } +/// @} python_builtins NAMESPACE_BEGIN(detail) inline handle get_function(handle value) { @@ -459,6 +589,8 @@ NAMESPACE_END(detail) PYBIND11_OBJECT(Name, Parent, CheckFun) \ Name() : Parent() { } +/// \addtogroup pytypes +/// @{ class iterator : public object { public: /** Caveat: copying an iterator does not (and cannot) clone the internal @@ -528,6 +660,10 @@ public: explicit str(const bytes &b); + /** \rst + Return a string representation of the object. This is analogous to + the ``str()`` function in Python. + \endrst */ explicit str(handle h) : object(raw_str(h.ptr()), stolen) { } operator std::string() const { @@ -561,12 +697,17 @@ private: return str_value; } }; +/// @} pytypes inline namespace literals { -/// String literal version of str +/** \rst + String literal version of `str` + \endrst */ inline str operator"" _s(const char *s, size_t size) { return {s, size}; } } +/// \addtogroup pytypes +/// @{ class bytes : public object { public: PYBIND11_OBJECT(bytes, object, PYBIND11_BYTES_CHECK) @@ -870,7 +1011,10 @@ public: PYBIND11_OBJECT_CVT(memoryview, object, PyMemoryView_Check, PyMemoryView_FromObject) }; +/// @} pytypes +/// \addtogroup python_builtins +/// @{ inline size_t len(handle h) { ssize_t result = PyObject_Length(h.ptr()); if (result < 0) @@ -888,6 +1032,7 @@ inline str repr(handle h) { #endif return reinterpret_steal(str_value); } +/// @} python_builtins NAMESPACE_BEGIN(detail) template iterator object_api::begin() const { @@ -911,8 +1056,8 @@ template str_attr_accessor object_api::attr(const char *key) con template args_proxy object_api::operator*() const { return args_proxy(derived().ptr()); } -template template bool object_api::contains(T &&key) const { - return attr("__contains__")(std::forward(key)).template cast(); +template template bool object_api::contains(T &&item) const { + return attr("__contains__")(std::forward(item)).template cast(); } template