@@ -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+
335171Built-in descriptors
336172^^^^^^^^^^^^^^^^^^^^
337173
0 commit comments