Skip to content

Commit 0f76cbb

Browse files
committed
Document wrapper stuff as internal.
1 parent 97030dc commit 0f76cbb

1 file changed

Lines changed: 25 additions & 189 deletions

File tree

‎Doc/c-api/descriptor.rst‎

Lines changed: 25 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -73,195 +73,6 @@ found in the dictionary of type objects.
7373
objects in Python.
7474
7575
76-
.. c:struct:: wrapperbase
77-
78-
Describes how a type slot is exposed to Python as a special method.
79-
80-
This is the structure behind the *slot wrapper* objects found in the
81-
dictionaries of built-in and extension types, such as ``int.__add__`` or
82-
``object.__repr__``. CPython keeps an internal table of these records, one
83-
for each special method name that corresponds to a slot of
84-
:c:type:`PyTypeObject` or one of its sub-structures (such as
85-
:c:type:`PyNumberMethods`).
86-
87-
Extensions do not normally need this structure, because CPython creates
88-
wrapper descriptors for the slots of every type automatically. It is useful
89-
when a C function with a slot-like signature should be exposed as a
90-
special method without being installed in a type slot, or when a slot
91-
function needs to be exposed under a different name or with a different
92-
docstring than the default one.
93-
94-
A ``wrapperbase`` is not copied by :c:func:`PyDescr_NewWrapper`; it must
95-
stay valid for as long as any descriptor created from it exists.
96-
It is usually a static variable.
97-
98-
.. c:member:: const char *name
99-
100-
The name of the special method, such as ``"__add__"``.
101-
This becomes the descriptor's :attr:`~definition.__name__` and is
102-
used in error messages.
103-
104-
.. c:member:: int offset
105-
106-
Offset of the slot that this record describes, relative to
107-
the start of :c:type:`!PyHeapTypeObject`.
108-
This is generally not useful to extensions, as :c:func:`PyDescr_NewWrapper`
109-
does not use this; set this to 0 when using that function.
110-
111-
.. c:member:: void *function
112-
113-
The generic slot implementation that CPython installs in a type's slot
114-
when the corresponding special method is defined in Python, for example
115-
in a subclass. Like :c:member:`~wrapperbase.offset`, it is only used by
116-
CPython's internal table; set it to ``NULL`` for records that are only
117-
used with :c:func:`PyDescr_NewWrapper`.
118-
119-
.. c:member:: wrapperfunc wrapper
120-
121-
The function that adapts the slot's C calling convention to a Python
122-
call. It receives the instance the special method was called on, a
123-
tuple of the remaining positional arguments, and the wrapped slot
124-
function pointer. It must check that the number and types of arguments
125-
are suitable for the slot function, call it, and convert the result
126-
to a Python object.
127-
128-
If :c:member:`~wrapperbase.flags` includes
129-
:c:macro:`PyWrapperFlag_KEYWORDS`, this field must instead point to a
130-
:c:type:`wrapperfunc_kwds` function, cast to :c:type:`wrapperfunc`.
131-
132-
.. c:member:: const char *doc
133-
134-
The docstring of the special method, or ``NULL``.
135-
136-
.. c:member:: int flags
137-
138-
Bitwise OR of flags that describe the wrapper function. Currently, the
139-
only flag is :c:macro:`PyWrapperFlag_KEYWORDS`; all other bits must be
140-
zero.
141-
142-
.. c:member:: PyObject *name_strobj
143-
144-
Reserved for internal use. Initialize it to ``NULL``.
145-
146-
.. c:type:: PyObject *(*wrapperfunc)(PyObject *self, PyObject *args, void *wrapped)
147-
148-
The type of the :c:member:`~wrapperbase.wrapper` function of a
149-
:c:struct:`wrapperbase`. *self* is the instance the special method is called
150-
on, *args* is a tuple of the positional arguments that follow it, and
151-
*wrapped* is the slot function pointer that was passed to
152-
:c:func:`PyDescr_NewWrapper`.
153-
154-
On success, return a :term:`strong reference` to the result. Return ``NULL``
155-
with an exception set on failure.
156-
157-
.. c:type:: PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)
158-
159-
Like :c:type:`wrapperfunc`, but with an additional *kwds* argument holding
160-
a dictionary of keyword arguments, or ``NULL`` if no keyword arguments were
161-
passed. Used for wrappers whose :c:member:`~wrapperbase.flags` include
162-
:c:macro:`PyWrapperFlag_KEYWORDS`.
163-
164-
.. c:macro:: PyWrapperFlag_KEYWORDS
165-
166-
Flag that can be set in the :c:member:`~wrapperbase.flags` field of a
167-
:c:struct:`wrapperbase` structure.
168-
When set, the :c:member:`~wrapperbase.wrapper` function has the
169-
:c:type:`wrapperfunc_kwds` signature and is passed the keyword arguments
170-
of the call as a :class:`dict`.
171-
When not set, calling the wrapper descriptor with keyword arguments
172-
raises :exc:`TypeError`.
173-
174-
.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
175-
176-
Create a new wrapper descriptor for extension type *type* from the
177-
:c:struct:`wrapperbase` structure *base* and the slot function pointer
178-
*wrapped*.
179-
180-
Wrapper descriptors expose special methods implemented by type slots. This
181-
is the same kind of descriptor that CPython creates for slot-based special
182-
methods such as ``__repr__`` or ``__add__``, and it appears in Python as a
183-
:class:`types.WrapperDescriptorType` object.
184-
185-
The descriptor only references *base*; see :c:struct:`wrapperbase` for the
186-
lifetime requirements.
187-
188-
On success, return a :term:`strong reference` to the descriptor. Return
189-
``NULL`` with an exception set on failure.
190-
191-
For example, the following gives the ``__len__`` method of a static type a
192-
custom docstring. :c:func:`PyType_Ready` would normally create the
193-
``__len__`` descriptor itself from the
194-
:c:member:`~PySequenceMethods.sq_length` slot, but it leaves the entry
195-
alone if the type's dictionary already contains one::
196-
197-
static Py_ssize_t
198-
my_len(PyObject *self)
199-
{
200-
/* ... */
201-
}
202-
203-
static PyObject *
204-
wrap_lenfunc(PyObject *self, PyObject *args, void *wrapped)
205-
{
206-
lenfunc func = (lenfunc)wrapped;
207-
if (PyTuple_GET_SIZE(args) != 0) {
208-
PyErr_SetString(PyExc_TypeError,
209-
"__len__() takes no arguments");
210-
return NULL;
211-
}
212-
Py_ssize_t result = func(self);
213-
if (result == -1 && PyErr_Occurred()) {
214-
return NULL;
215-
}
216-
return PyLong_FromSsize_t(result);
217-
}
218-
219-
static struct wrapperbase len_wrapper = {
220-
.name = "__len__",
221-
.wrapper = wrap_lenfunc,
222-
.doc = "__len__($self, /)\n--\n\nReturn the number of items.",
223-
};
224-
225-
static PySequenceMethods my_as_sequence = {
226-
.sq_length = my_len,
227-
};
228-
229-
static PyTypeObject MyType = {
230-
PyVarObject_HEAD_INIT(NULL, 0)
231-
.tp_name = "mymodule.MyType",
232-
.tp_as_sequence = &my_as_sequence,
233-
/* ... */
234-
};
235-
236-
static int
237-
ready_my_type(void)
238-
{
239-
MyType.tp_dict = PyDict_New();
240-
if (MyType.tp_dict == NULL) {
241-
return -1;
242-
}
243-
PyObject *descr = PyDescr_NewWrapper(&MyType, &len_wrapper,
244-
(void *)my_len);
245-
if (descr == NULL) {
246-
return -1;
247-
}
248-
int result = PyDict_SetItemString(MyType.tp_dict, "__len__", descr);
249-
Py_DECREF(descr);
250-
if (result < 0) {
251-
return -1;
252-
}
253-
return PyType_Ready(&MyType);
254-
}
255-
256-
.. c:var:: PyTypeObject PyWrapperDescr_Type
257-
258-
The type object for wrapper descriptor objects created by
259-
:c:func:`PyDescr_NewWrapper` and :c:func:`PyWrapper_New`. Wrapper
260-
descriptors are used internally to expose special methods implemented
261-
via wrapper structures, and appear in Python as
262-
:class:`types.WrapperDescriptorType` objects.
263-
264-
26576
.. c:function:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
26677
26778
Create a new class method descriptor for extension type *type* from the
@@ -332,6 +143,31 @@ found in the dictionary of type objects.
332143
.. soft-deprecated:: 3.15
333144
334145
146+
.. c:struct:: wrapperbase
147+
:no-contents-entry:
148+
:no-index-entry:
149+
:no-typesetting:
150+
.. c:type:: PyObject *(*wrapperfunc)(PyObject *self, PyObject *args, void *wrapped)
151+
:no-contents-entry:
152+
:no-index-entry:
153+
:no-typesetting:
154+
.. c:type:: PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)
155+
:no-contents-entry:
156+
:no-index-entry:
157+
:no-typesetting:
158+
.. c:macro:: PyWrapperFlag_KEYWORDS
159+
:no-contents-entry:
160+
:no-index-entry:
161+
:no-typesetting:
162+
.. c:var:: PyTypeObject PyWrapperDescr_Type
163+
:no-contents-entry:
164+
:no-index-entry:
165+
:no-typesetting:
166+
.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
167+
168+
For internal use only; do not use in extensions.
169+
170+
335171
Built-in descriptors
336172
^^^^^^^^^^^^^^^^^^^^
337173

0 commit comments

Comments
 (0)