## ObjectWrapper

### Introduction

This page defines two concepts used to describe classes which manage a Python objects, and which are intended to support usage with a Python-like syntax.

### ObjectWrapper Concept Requirements

Models of the ObjectWrapper concept have object as a publicly-accessible base class, and are used to supply special construction behavior and/or additional convenient functionality through (often templated) member functions. Except when the return type R is itself an TypeWrapper, a member function invocation of the form

    x.some_function(a1, a2,...an)

always has semantics equivalent to:

    extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()

(see caveat below).

### TypeWrapper Concept Requirements

TypeWrapper is a refinement of ObjectWrapper which is associated with a particular Python type `X`. For a given TypeWrapper `T`, a valid constructor expression

    T(a1, a2,...an)

builds a new T object managing the result of invoking X with arguments corresponding to

    object(a1), object(a2),...object(an)

. When used as arguments to wrapped C++ functions, or as the template parameter to extract<>, only instances of the associated Python type will be considered a match.

### Caveat

The upshot of the special member function invocation rules when the return type is a TypeWrapper is that it is possible for the returned object to manage a Python object of an inappropriate type. This is not usually a serious problem; the worst-case result is that errors will be detected at runtime a little later than they might otherwise be. For an example of how this can occur, note that the dict member function `items` returns an object of type list. Now suppose the user defines this `dict` subclass in Python:

    >>> class mydict(dict):
    ...     def items(self):
    ...         return tuple(dict.items(self)) # return a tuple

Since an instance of `mydict` is also an instance of `dict`, when used as an argument to a wrapped C++ function, boost::python::dict can accept objects of Python type `mydict`. Invoking `items()` on this object can result in an instance of boost::python::list which actually holds a Python `tuple`. Subsequent attempts to use `list` methods (e.g. `append`, or any other mutating operation) on this object will raise the same exception that would occur if you tried to do it from Python.