/src/cpython/Objects/descrobject.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Descriptors -- a new, flexible way to describe attributes */ |
2 | | |
3 | | #include "Python.h" |
4 | | #include "pycore_abstract.h" // _PyObject_RealIsSubclass() |
5 | | #include "pycore_call.h" // _PyStack_AsDict() |
6 | | #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate() |
7 | | #include "pycore_emscripten_trampoline.h" // descr_set_trampoline_call(), descr_get_trampoline_call() |
8 | | #include "pycore_descrobject.h" // _PyMethodWrapper_Type |
9 | | #include "pycore_modsupport.h" // _PyArg_UnpackStack() |
10 | | #include "pycore_object.h" // _PyObject_GC_UNTRACK() |
11 | | #include "pycore_object_deferred.h" // _PyObject_SetDeferredRefcount() |
12 | | #include "pycore_pystate.h" // _PyThreadState_GET() |
13 | | #include "pycore_tuple.h" // _PyTuple_ITEMS() |
14 | | |
15 | | |
16 | | /*[clinic input] |
17 | | class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type" |
18 | | class property "propertyobject *" "&PyProperty_Type" |
19 | | [clinic start generated code]*/ |
20 | | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/ |
21 | | |
22 | | static void |
23 | | descr_dealloc(PyObject *self) |
24 | 865 | { |
25 | 865 | PyDescrObject *descr = (PyDescrObject *)self; |
26 | 865 | _PyObject_GC_UNTRACK(descr); |
27 | 865 | Py_XDECREF(descr->d_type); |
28 | 865 | Py_XDECREF(descr->d_name); |
29 | 865 | Py_XDECREF(descr->d_qualname); |
30 | 865 | PyObject_GC_Del(descr); |
31 | 865 | } |
32 | | |
33 | | static PyObject * |
34 | | descr_name(PyDescrObject *descr) |
35 | 0 | { |
36 | 0 | if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) |
37 | 0 | return descr->d_name; |
38 | 0 | return NULL; |
39 | 0 | } |
40 | | |
41 | | static PyObject * |
42 | | descr_repr(PyDescrObject *descr, const char *format) |
43 | 0 | { |
44 | 0 | PyObject *name = NULL; |
45 | 0 | if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) |
46 | 0 | name = descr->d_name; |
47 | |
|
48 | 0 | return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name); |
49 | 0 | } |
50 | | |
51 | | static PyObject * |
52 | | method_repr(PyObject *descr) |
53 | 0 | { |
54 | 0 | return descr_repr((PyDescrObject *)descr, |
55 | 0 | "<method '%V' of '%s' objects>"); |
56 | 0 | } |
57 | | |
58 | | static PyObject * |
59 | | member_repr(PyObject *descr) |
60 | 0 | { |
61 | 0 | return descr_repr((PyDescrObject *)descr, |
62 | 0 | "<member '%V' of '%s' objects>"); |
63 | 0 | } |
64 | | |
65 | | static PyObject * |
66 | | getset_repr(PyObject *descr) |
67 | 0 | { |
68 | 0 | return descr_repr((PyDescrObject *)descr, |
69 | 0 | "<attribute '%V' of '%s' objects>"); |
70 | 0 | } |
71 | | |
72 | | static PyObject * |
73 | | wrapperdescr_repr(PyObject *descr) |
74 | 0 | { |
75 | 0 | return descr_repr((PyDescrObject *)descr, |
76 | 0 | "<slot wrapper '%V' of '%s' objects>"); |
77 | 0 | } |
78 | | |
79 | | static int |
80 | | descr_check(PyDescrObject *descr, PyObject *obj) |
81 | 477M | { |
82 | 477M | if (!PyObject_TypeCheck(obj, descr->d_type)) { |
83 | 0 | PyErr_Format(PyExc_TypeError, |
84 | 0 | "descriptor '%V' for '%.100s' objects " |
85 | 0 | "doesn't apply to a '%.100s' object", |
86 | 0 | descr_name((PyDescrObject *)descr), "?", |
87 | 0 | descr->d_type->tp_name, |
88 | 0 | Py_TYPE(obj)->tp_name); |
89 | 0 | return -1; |
90 | 0 | } |
91 | 477M | return 0; |
92 | 477M | } |
93 | | |
94 | | static PyObject * |
95 | | classmethod_get(PyObject *self, PyObject *obj, PyObject *type) |
96 | 280k | { |
97 | 280k | PyMethodDescrObject *descr = (PyMethodDescrObject *)self; |
98 | | /* Ensure a valid type. Class methods ignore obj. */ |
99 | 280k | if (type == NULL) { |
100 | 0 | if (obj != NULL) |
101 | 0 | type = (PyObject *)Py_TYPE(obj); |
102 | 0 | else { |
103 | | /* Wot - no type?! */ |
104 | 0 | PyErr_Format(PyExc_TypeError, |
105 | 0 | "descriptor '%V' for type '%.100s' " |
106 | 0 | "needs either an object or a type", |
107 | 0 | descr_name((PyDescrObject *)descr), "?", |
108 | 0 | PyDescr_TYPE(descr)->tp_name); |
109 | 0 | return NULL; |
110 | 0 | } |
111 | 0 | } |
112 | 280k | if (!PyType_Check(type)) { |
113 | 0 | PyErr_Format(PyExc_TypeError, |
114 | 0 | "descriptor '%V' for type '%.100s' " |
115 | 0 | "needs a type, not a '%.100s' as arg 2", |
116 | 0 | descr_name((PyDescrObject *)descr), "?", |
117 | 0 | PyDescr_TYPE(descr)->tp_name, |
118 | 0 | Py_TYPE(type)->tp_name); |
119 | 0 | return NULL; |
120 | 0 | } |
121 | 280k | if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) { |
122 | 0 | PyErr_Format(PyExc_TypeError, |
123 | 0 | "descriptor '%V' requires a subtype of '%.100s' " |
124 | 0 | "but received '%.100s'", |
125 | 0 | descr_name((PyDescrObject *)descr), "?", |
126 | 0 | PyDescr_TYPE(descr)->tp_name, |
127 | 0 | ((PyTypeObject *)type)->tp_name); |
128 | 0 | return NULL; |
129 | 0 | } |
130 | 280k | PyTypeObject *cls = NULL; |
131 | 280k | if (descr->d_method->ml_flags & METH_METHOD) { |
132 | 0 | cls = descr->d_common.d_type; |
133 | 0 | } |
134 | 280k | return PyCMethod_New(descr->d_method, type, NULL, cls); |
135 | 280k | } |
136 | | |
137 | | static PyObject * |
138 | | method_get(PyObject *self, PyObject *obj, PyObject *type) |
139 | 273M | { |
140 | 273M | PyMethodDescrObject *descr = (PyMethodDescrObject *)self; |
141 | 273M | if (obj == NULL) { |
142 | 1.97k | return Py_NewRef(descr); |
143 | 1.97k | } |
144 | 273M | if (descr_check((PyDescrObject *)descr, obj) < 0) { |
145 | 0 | return NULL; |
146 | 0 | } |
147 | 273M | if (descr->d_method->ml_flags & METH_METHOD) { |
148 | 6.97M | if (type == NULL || PyType_Check(type)) { |
149 | 6.97M | return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type); |
150 | 6.97M | } else { |
151 | 0 | PyErr_Format(PyExc_TypeError, |
152 | 0 | "descriptor '%V' needs a type, not '%s', as arg 2", |
153 | 0 | descr_name((PyDescrObject *)descr), |
154 | 0 | Py_TYPE(type)->tp_name); |
155 | 0 | return NULL; |
156 | 0 | } |
157 | 266M | } else { |
158 | 266M | return PyCFunction_NewEx(descr->d_method, obj, NULL); |
159 | 266M | } |
160 | 273M | } |
161 | | |
162 | | static PyObject * |
163 | | member_get(PyObject *self, PyObject *obj, PyObject *type) |
164 | 102k | { |
165 | 102k | PyMemberDescrObject *descr = (PyMemberDescrObject *)self; |
166 | 102k | if (obj == NULL) { |
167 | 0 | return Py_NewRef(descr); |
168 | 0 | } |
169 | 102k | if (descr_check((PyDescrObject *)descr, obj) < 0) { |
170 | 0 | return NULL; |
171 | 0 | } |
172 | | |
173 | 102k | if (descr->d_member->flags & Py_AUDIT_READ) { |
174 | 0 | if (PySys_Audit("object.__getattr__", "Os", |
175 | 0 | obj ? obj : Py_None, descr->d_member->name) < 0) { |
176 | 0 | return NULL; |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | 102k | return PyMember_GetOne((char *)obj, descr->d_member); |
181 | 102k | } |
182 | | |
183 | | static PyObject * |
184 | | getset_get(PyObject *self, PyObject *obj, PyObject *type) |
185 | 12.8M | { |
186 | 12.8M | PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; |
187 | 12.8M | if (obj == NULL) { |
188 | 4 | return Py_NewRef(descr); |
189 | 4 | } |
190 | 12.8M | if (descr_check((PyDescrObject *)descr, obj) < 0) { |
191 | 0 | return NULL; |
192 | 0 | } |
193 | 12.8M | if (descr->d_getset->get != NULL) |
194 | 12.8M | return descr_get_trampoline_call( |
195 | 12.8M | descr->d_getset->get, obj, descr->d_getset->closure); |
196 | 0 | PyErr_Format(PyExc_AttributeError, |
197 | 0 | "attribute '%V' of '%.100s' objects is not readable", |
198 | 0 | descr_name((PyDescrObject *)descr), "?", |
199 | 0 | PyDescr_TYPE(descr)->tp_name); |
200 | 0 | return NULL; |
201 | 12.8M | } |
202 | | |
203 | | static PyObject * |
204 | | wrapperdescr_get(PyObject *self, PyObject *obj, PyObject *type) |
205 | 11.2M | { |
206 | 11.2M | PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; |
207 | 11.2M | if (obj == NULL) { |
208 | 956 | return Py_NewRef(descr); |
209 | 956 | } |
210 | 11.2M | if (descr_check((PyDescrObject *)descr, obj) < 0) { |
211 | 0 | return NULL; |
212 | 0 | } |
213 | 11.2M | return PyWrapper_New((PyObject *)descr, obj); |
214 | 11.2M | } |
215 | | |
216 | | static int |
217 | | descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value) |
218 | 13.7k | { |
219 | 13.7k | assert(obj != NULL); |
220 | 13.7k | if (!PyObject_TypeCheck(obj, descr->d_type)) { |
221 | 0 | PyErr_Format(PyExc_TypeError, |
222 | 0 | "descriptor '%V' for '%.100s' objects " |
223 | 0 | "doesn't apply to a '%.100s' object", |
224 | 0 | descr_name(descr), "?", |
225 | 0 | descr->d_type->tp_name, |
226 | 0 | Py_TYPE(obj)->tp_name); |
227 | 0 | return -1; |
228 | 0 | } |
229 | 13.7k | return 0; |
230 | 13.7k | } |
231 | | |
232 | | static int |
233 | | member_set(PyObject *self, PyObject *obj, PyObject *value) |
234 | 7.11k | { |
235 | 7.11k | PyMemberDescrObject *descr = (PyMemberDescrObject *)self; |
236 | 7.11k | if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { |
237 | 0 | return -1; |
238 | 0 | } |
239 | 7.11k | return PyMember_SetOne((char *)obj, descr->d_member, value); |
240 | 7.11k | } |
241 | | |
242 | | static int |
243 | | getset_set(PyObject *self, PyObject *obj, PyObject *value) |
244 | 6.62k | { |
245 | 6.62k | PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; |
246 | 6.62k | if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { |
247 | 0 | return -1; |
248 | 0 | } |
249 | 6.62k | if (descr->d_getset->set != NULL) { |
250 | 6.62k | return descr_set_trampoline_call( |
251 | 6.62k | descr->d_getset->set, obj, value, |
252 | 6.62k | descr->d_getset->closure); |
253 | 6.62k | } |
254 | 0 | PyErr_Format(PyExc_AttributeError, |
255 | 0 | "attribute '%V' of '%.100s' objects is not writable", |
256 | 0 | descr_name((PyDescrObject *)descr), "?", |
257 | 0 | PyDescr_TYPE(descr)->tp_name); |
258 | 0 | return -1; |
259 | 6.62k | } |
260 | | |
261 | | |
262 | | /* Vectorcall functions for each of the PyMethodDescr calling conventions. |
263 | | * |
264 | | * First, common helpers |
265 | | */ |
266 | | static inline int |
267 | | method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) |
268 | 179M | { |
269 | 179M | assert(!PyErr_Occurred()); |
270 | 179M | if (nargs < 1) { |
271 | 0 | PyObject *funcstr = _PyObject_FunctionStr(func); |
272 | 0 | if (funcstr != NULL) { |
273 | 0 | PyErr_Format(PyExc_TypeError, |
274 | 0 | "unbound method %U needs an argument", funcstr); |
275 | 0 | Py_DECREF(funcstr); |
276 | 0 | } |
277 | 0 | return -1; |
278 | 0 | } |
279 | 179M | PyObject *self = args[0]; |
280 | 179M | if (descr_check((PyDescrObject *)func, self) < 0) { |
281 | 0 | return -1; |
282 | 0 | } |
283 | 179M | if (kwnames && PyTuple_GET_SIZE(kwnames)) { |
284 | 0 | PyObject *funcstr = _PyObject_FunctionStr(func); |
285 | 0 | if (funcstr != NULL) { |
286 | 0 | PyErr_Format(PyExc_TypeError, |
287 | 0 | "%U takes no keyword arguments", funcstr); |
288 | 0 | Py_DECREF(funcstr); |
289 | 0 | } |
290 | 0 | return -1; |
291 | 0 | } |
292 | 179M | return 0; |
293 | 179M | } |
294 | | |
295 | | typedef void (*funcptr)(void); |
296 | | |
297 | | static inline funcptr |
298 | | method_enter_call(PyThreadState *tstate, PyObject *func) |
299 | 179M | { |
300 | 179M | if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { |
301 | 0 | return NULL; |
302 | 0 | } |
303 | 179M | return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth; |
304 | 179M | } |
305 | | |
306 | | /* Now the actual vectorcall functions */ |
307 | | static PyObject * |
308 | | method_vectorcall_VARARGS( |
309 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
310 | 67.3M | { |
311 | 67.3M | PyThreadState *tstate = _PyThreadState_GET(); |
312 | 67.3M | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
313 | 67.3M | if (method_check_args(func, args, nargs, kwnames)) { |
314 | 0 | return NULL; |
315 | 0 | } |
316 | 67.3M | PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); |
317 | 67.3M | if (argstuple == NULL) { |
318 | 0 | return NULL; |
319 | 0 | } |
320 | 67.3M | PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); |
321 | 67.3M | if (meth == NULL) { |
322 | 0 | Py_DECREF(argstuple); |
323 | 0 | return NULL; |
324 | 0 | } |
325 | 67.3M | PyObject *result = _PyCFunction_TrampolineCall( |
326 | 67.3M | meth, args[0], argstuple); |
327 | 67.3M | Py_DECREF(argstuple); |
328 | 67.3M | _Py_LeaveRecursiveCallTstate(tstate); |
329 | 67.3M | return result; |
330 | 67.3M | } |
331 | | |
332 | | static PyObject * |
333 | | method_vectorcall_VARARGS_KEYWORDS( |
334 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
335 | 8.79M | { |
336 | 8.79M | PyThreadState *tstate = _PyThreadState_GET(); |
337 | 8.79M | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
338 | 8.79M | if (method_check_args(func, args, nargs, NULL)) { |
339 | 0 | return NULL; |
340 | 0 | } |
341 | 8.79M | PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); |
342 | 8.79M | if (argstuple == NULL) { |
343 | 0 | return NULL; |
344 | 0 | } |
345 | 8.79M | PyObject *result = NULL; |
346 | | /* Create a temporary dict for keyword arguments */ |
347 | 8.79M | PyObject *kwdict = NULL; |
348 | 8.79M | if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) { |
349 | 28 | kwdict = _PyStack_AsDict(args + nargs, kwnames); |
350 | 28 | if (kwdict == NULL) { |
351 | 0 | goto exit; |
352 | 0 | } |
353 | 28 | } |
354 | 8.79M | PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords) |
355 | 8.79M | method_enter_call(tstate, func); |
356 | 8.79M | if (meth == NULL) { |
357 | 0 | goto exit; |
358 | 0 | } |
359 | 8.79M | result = _PyCFunctionWithKeywords_TrampolineCall( |
360 | 8.79M | meth, args[0], argstuple, kwdict); |
361 | 8.79M | _Py_LeaveRecursiveCallTstate(tstate); |
362 | 8.79M | exit: |
363 | 8.79M | Py_DECREF(argstuple); |
364 | 8.79M | Py_XDECREF(kwdict); |
365 | 8.79M | return result; |
366 | 8.79M | } |
367 | | |
368 | | static PyObject * |
369 | | method_vectorcall_FASTCALL_KEYWORDS_METHOD( |
370 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
371 | 79.0M | { |
372 | 79.0M | PyThreadState *tstate = _PyThreadState_GET(); |
373 | 79.0M | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
374 | 79.0M | if (method_check_args(func, args, nargs, NULL)) { |
375 | 0 | return NULL; |
376 | 0 | } |
377 | 79.0M | PyCMethod meth = (PyCMethod) method_enter_call(tstate, func); |
378 | 79.0M | if (meth == NULL) { |
379 | 0 | return NULL; |
380 | 0 | } |
381 | 79.0M | PyObject *result = meth(args[0], |
382 | 79.0M | ((PyMethodDescrObject *)func)->d_common.d_type, |
383 | 79.0M | args+1, nargs-1, kwnames); |
384 | 79.0M | _Py_LeaveRecursiveCall(); |
385 | 79.0M | return result; |
386 | 79.0M | } |
387 | | |
388 | | static PyObject * |
389 | | method_vectorcall_FASTCALL( |
390 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
391 | 44.2k | { |
392 | 44.2k | PyThreadState *tstate = _PyThreadState_GET(); |
393 | 44.2k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
394 | 44.2k | if (method_check_args(func, args, nargs, kwnames)) { |
395 | 0 | return NULL; |
396 | 0 | } |
397 | 44.2k | PyCFunctionFast meth = (PyCFunctionFast) |
398 | 44.2k | method_enter_call(tstate, func); |
399 | 44.2k | if (meth == NULL) { |
400 | 0 | return NULL; |
401 | 0 | } |
402 | 44.2k | PyObject *result = meth(args[0], args+1, nargs-1); |
403 | 44.2k | _Py_LeaveRecursiveCallTstate(tstate); |
404 | 44.2k | return result; |
405 | 44.2k | } |
406 | | |
407 | | static PyObject * |
408 | | method_vectorcall_FASTCALL_KEYWORDS( |
409 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
410 | 4.37M | { |
411 | 4.37M | PyThreadState *tstate = _PyThreadState_GET(); |
412 | 4.37M | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
413 | 4.37M | if (method_check_args(func, args, nargs, NULL)) { |
414 | 0 | return NULL; |
415 | 0 | } |
416 | 4.37M | PyCFunctionFastWithKeywords meth = (PyCFunctionFastWithKeywords) |
417 | 4.37M | method_enter_call(tstate, func); |
418 | 4.37M | if (meth == NULL) { |
419 | 0 | return NULL; |
420 | 0 | } |
421 | 4.37M | PyObject *result = meth(args[0], args+1, nargs-1, kwnames); |
422 | 4.37M | _Py_LeaveRecursiveCallTstate(tstate); |
423 | 4.37M | return result; |
424 | 4.37M | } |
425 | | |
426 | | static PyObject * |
427 | | method_vectorcall_NOARGS( |
428 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
429 | 32.5k | { |
430 | 32.5k | PyThreadState *tstate = _PyThreadState_GET(); |
431 | 32.5k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
432 | 32.5k | if (method_check_args(func, args, nargs, kwnames)) { |
433 | 0 | return NULL; |
434 | 0 | } |
435 | 32.5k | if (nargs != 1) { |
436 | 0 | PyObject *funcstr = _PyObject_FunctionStr(func); |
437 | 0 | if (funcstr != NULL) { |
438 | 0 | PyErr_Format(PyExc_TypeError, |
439 | 0 | "%U takes no arguments (%zd given)", funcstr, nargs-1); |
440 | 0 | Py_DECREF(funcstr); |
441 | 0 | } |
442 | 0 | return NULL; |
443 | 0 | } |
444 | 32.5k | PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); |
445 | 32.5k | if (meth == NULL) { |
446 | 0 | return NULL; |
447 | 0 | } |
448 | 32.5k | PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], NULL); |
449 | 32.5k | _Py_LeaveRecursiveCallTstate(tstate); |
450 | 32.5k | return result; |
451 | 32.5k | } |
452 | | |
453 | | static PyObject * |
454 | | method_vectorcall_O( |
455 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
456 | 20.2M | { |
457 | 20.2M | PyThreadState *tstate = _PyThreadState_GET(); |
458 | 20.2M | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
459 | 20.2M | if (method_check_args(func, args, nargs, kwnames)) { |
460 | 0 | return NULL; |
461 | 0 | } |
462 | 20.2M | if (nargs != 2) { |
463 | 0 | PyObject *funcstr = _PyObject_FunctionStr(func); |
464 | 0 | if (funcstr != NULL) { |
465 | 0 | PyErr_Format(PyExc_TypeError, |
466 | 0 | "%U takes exactly one argument (%zd given)", |
467 | 0 | funcstr, nargs-1); |
468 | 0 | Py_DECREF(funcstr); |
469 | 0 | } |
470 | 0 | return NULL; |
471 | 0 | } |
472 | 20.2M | PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); |
473 | 20.2M | if (meth == NULL) { |
474 | 0 | return NULL; |
475 | 0 | } |
476 | 20.2M | PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], args[1]); |
477 | 20.2M | _Py_LeaveRecursiveCallTstate(tstate); |
478 | 20.2M | return result; |
479 | 20.2M | } |
480 | | |
481 | | |
482 | | /* Instances of classmethod_descriptor are unlikely to be called directly. |
483 | | For one, the analogous class "classmethod" (for Python classes) is not |
484 | | callable. Second, users are not likely to access a classmethod_descriptor |
485 | | directly, since it means pulling it from the class __dict__. |
486 | | |
487 | | This is just an excuse to say that this doesn't need to be optimized: |
488 | | we implement this simply by calling __get__ and then calling the result. |
489 | | */ |
490 | | static PyObject * |
491 | | classmethoddescr_call(PyObject *_descr, PyObject *args, |
492 | | PyObject *kwds) |
493 | 0 | { |
494 | 0 | PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; |
495 | 0 | Py_ssize_t argc = PyTuple_GET_SIZE(args); |
496 | 0 | if (argc < 1) { |
497 | 0 | PyErr_Format(PyExc_TypeError, |
498 | 0 | "descriptor '%V' of '%.100s' " |
499 | 0 | "object needs an argument", |
500 | 0 | descr_name((PyDescrObject *)descr), "?", |
501 | 0 | PyDescr_TYPE(descr)->tp_name); |
502 | 0 | return NULL; |
503 | 0 | } |
504 | 0 | PyObject *self = PyTuple_GET_ITEM(args, 0); |
505 | 0 | PyObject *bound = classmethod_get((PyObject *)descr, NULL, self); |
506 | 0 | if (bound == NULL) { |
507 | 0 | return NULL; |
508 | 0 | } |
509 | 0 | PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1, |
510 | 0 | argc-1, kwds); |
511 | 0 | Py_DECREF(bound); |
512 | 0 | return res; |
513 | 0 | } |
514 | | |
515 | | Py_LOCAL_INLINE(PyObject *) |
516 | | wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self, |
517 | | PyObject *args, PyObject *kwds) |
518 | 25.1M | { |
519 | 25.1M | wrapperfunc wrapper = descr->d_base->wrapper; |
520 | | |
521 | 25.1M | if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) { |
522 | 17.5M | wrapperfunc_kwds wk = _Py_FUNC_CAST(wrapperfunc_kwds, wrapper); |
523 | 17.5M | return (*wk)(self, args, descr->d_wrapped, kwds); |
524 | 17.5M | } |
525 | | |
526 | 7.57M | if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) { |
527 | 0 | PyErr_Format(PyExc_TypeError, |
528 | 0 | "wrapper %s() takes no keyword arguments", |
529 | 0 | descr->d_base->name); |
530 | 0 | return NULL; |
531 | 0 | } |
532 | 7.57M | return (*wrapper)(self, args, descr->d_wrapped); |
533 | 7.57M | } |
534 | | |
535 | | static PyObject * |
536 | | wrapperdescr_call(PyObject *_descr, PyObject *args, PyObject *kwds) |
537 | 13.8M | { |
538 | 13.8M | PyWrapperDescrObject *descr = (PyWrapperDescrObject *)_descr; |
539 | 13.8M | Py_ssize_t argc; |
540 | 13.8M | PyObject *self, *result; |
541 | | |
542 | | /* Make sure that the first argument is acceptable as 'self' */ |
543 | 13.8M | assert(PyTuple_Check(args)); |
544 | 13.8M | argc = PyTuple_GET_SIZE(args); |
545 | 13.8M | if (argc < 1) { |
546 | 0 | PyErr_Format(PyExc_TypeError, |
547 | 0 | "descriptor '%V' of '%.100s' " |
548 | 0 | "object needs an argument", |
549 | 0 | descr_name((PyDescrObject *)descr), "?", |
550 | 0 | PyDescr_TYPE(descr)->tp_name); |
551 | 0 | return NULL; |
552 | 0 | } |
553 | 13.8M | self = PyTuple_GET_ITEM(args, 0); |
554 | 13.8M | if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), |
555 | 13.8M | (PyObject *)PyDescr_TYPE(descr))) { |
556 | 0 | PyErr_Format(PyExc_TypeError, |
557 | 0 | "descriptor '%V' " |
558 | 0 | "requires a '%.100s' object " |
559 | 0 | "but received a '%.100s'", |
560 | 0 | descr_name((PyDescrObject *)descr), "?", |
561 | 0 | PyDescr_TYPE(descr)->tp_name, |
562 | 0 | Py_TYPE(self)->tp_name); |
563 | 0 | return NULL; |
564 | 0 | } |
565 | | |
566 | 13.8M | args = PyTuple_GetSlice(args, 1, argc); |
567 | 13.8M | if (args == NULL) { |
568 | 0 | return NULL; |
569 | 0 | } |
570 | 13.8M | result = wrapperdescr_raw_call(descr, self, args, kwds); |
571 | 13.8M | Py_DECREF(args); |
572 | 13.8M | return result; |
573 | 13.8M | } |
574 | | |
575 | | |
576 | | static PyObject * |
577 | | method_get_doc(PyObject *_descr, void *closure) |
578 | 0 | { |
579 | 0 | PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; |
580 | 0 | return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); |
581 | 0 | } |
582 | | |
583 | | static PyObject * |
584 | | method_get_text_signature(PyObject *_descr, void *closure) |
585 | 0 | { |
586 | 0 | PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; |
587 | 0 | return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, |
588 | 0 | descr->d_method->ml_doc, |
589 | 0 | descr->d_method->ml_flags); |
590 | 0 | } |
591 | | |
592 | | static PyObject * |
593 | | calculate_qualname(PyDescrObject *descr) |
594 | 0 | { |
595 | 0 | PyObject *type_qualname, *res; |
596 | |
|
597 | 0 | if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) { |
598 | 0 | PyErr_SetString(PyExc_TypeError, |
599 | 0 | "<descriptor>.__name__ is not a unicode object"); |
600 | 0 | return NULL; |
601 | 0 | } |
602 | | |
603 | 0 | type_qualname = PyObject_GetAttr( |
604 | 0 | (PyObject *)descr->d_type, &_Py_ID(__qualname__)); |
605 | 0 | if (type_qualname == NULL) |
606 | 0 | return NULL; |
607 | | |
608 | 0 | if (!PyUnicode_Check(type_qualname)) { |
609 | 0 | PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__." |
610 | 0 | "__qualname__ is not a unicode object"); |
611 | 0 | Py_XDECREF(type_qualname); |
612 | 0 | return NULL; |
613 | 0 | } |
614 | | |
615 | 0 | res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name); |
616 | 0 | Py_DECREF(type_qualname); |
617 | 0 | return res; |
618 | 0 | } |
619 | | |
620 | | static PyObject * |
621 | | descr_get_qualname(PyObject *self, void *Py_UNUSED(ignored)) |
622 | 0 | { |
623 | 0 | PyDescrObject *descr = (PyDescrObject *)self; |
624 | 0 | if (descr->d_qualname == NULL) |
625 | 0 | descr->d_qualname = calculate_qualname(descr); |
626 | 0 | return Py_XNewRef(descr->d_qualname); |
627 | 0 | } |
628 | | |
629 | | static PyObject * |
630 | | descr_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) |
631 | 0 | { |
632 | 0 | PyDescrObject *descr = (PyDescrObject *)self; |
633 | 0 | return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)), |
634 | 0 | PyDescr_TYPE(descr), PyDescr_NAME(descr)); |
635 | 0 | } |
636 | | |
637 | | static PyMethodDef descr_methods[] = { |
638 | | {"__reduce__", descr_reduce, METH_NOARGS, NULL}, |
639 | | {NULL, NULL} |
640 | | }; |
641 | | |
642 | | static PyMemberDef descr_members[] = { |
643 | | {"__objclass__", _Py_T_OBJECT, offsetof(PyDescrObject, d_type), Py_READONLY}, |
644 | | {"__name__", _Py_T_OBJECT, offsetof(PyDescrObject, d_name), Py_READONLY}, |
645 | | {0} |
646 | | }; |
647 | | |
648 | | static PyGetSetDef method_getset[] = { |
649 | | {"__doc__", method_get_doc}, |
650 | | {"__qualname__", descr_get_qualname}, |
651 | | {"__text_signature__", method_get_text_signature}, |
652 | | {0} |
653 | | }; |
654 | | |
655 | | static PyObject * |
656 | | member_get_doc(PyObject *_descr, void *closure) |
657 | 0 | { |
658 | 0 | PyMemberDescrObject *descr = (PyMemberDescrObject *)_descr; |
659 | 0 | if (descr->d_member->doc == NULL) { |
660 | 0 | Py_RETURN_NONE; |
661 | 0 | } |
662 | 0 | return PyUnicode_FromString(descr->d_member->doc); |
663 | 0 | } |
664 | | |
665 | | static PyGetSetDef member_getset[] = { |
666 | | {"__doc__", member_get_doc}, |
667 | | {"__qualname__", descr_get_qualname}, |
668 | | {0} |
669 | | }; |
670 | | |
671 | | static PyObject * |
672 | | getset_get_doc(PyObject *self, void *closure) |
673 | 0 | { |
674 | 0 | PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; |
675 | 0 | if (descr->d_getset->doc == NULL) { |
676 | 0 | Py_RETURN_NONE; |
677 | 0 | } |
678 | 0 | return PyUnicode_FromString(descr->d_getset->doc); |
679 | 0 | } |
680 | | |
681 | | static PyGetSetDef getset_getset[] = { |
682 | | {"__doc__", getset_get_doc}, |
683 | | {"__qualname__", descr_get_qualname}, |
684 | | {0} |
685 | | }; |
686 | | |
687 | | static PyObject * |
688 | | wrapperdescr_get_doc(PyObject *self, void *closure) |
689 | 0 | { |
690 | 0 | PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; |
691 | 0 | return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc); |
692 | 0 | } |
693 | | |
694 | | static PyObject * |
695 | | wrapperdescr_get_text_signature(PyObject *self, void *closure) |
696 | 0 | { |
697 | 0 | PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; |
698 | 0 | return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, |
699 | 0 | descr->d_base->doc, 0); |
700 | 0 | } |
701 | | |
702 | | static PyGetSetDef wrapperdescr_getset[] = { |
703 | | {"__doc__", wrapperdescr_get_doc}, |
704 | | {"__qualname__", descr_get_qualname}, |
705 | | {"__text_signature__", wrapperdescr_get_text_signature}, |
706 | | {0} |
707 | | }; |
708 | | |
709 | | static int |
710 | | descr_traverse(PyObject *self, visitproc visit, void *arg) |
711 | 17.2M | { |
712 | 17.2M | PyDescrObject *descr = (PyDescrObject *)self; |
713 | 17.2M | Py_VISIT(descr->d_type); |
714 | 17.2M | return 0; |
715 | 17.2M | } |
716 | | |
717 | | PyTypeObject PyMethodDescr_Type = { |
718 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
719 | | "method_descriptor", |
720 | | sizeof(PyMethodDescrObject), |
721 | | 0, |
722 | | descr_dealloc, /* tp_dealloc */ |
723 | | offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */ |
724 | | 0, /* tp_getattr */ |
725 | | 0, /* tp_setattr */ |
726 | | 0, /* tp_as_async */ |
727 | | method_repr, /* tp_repr */ |
728 | | 0, /* tp_as_number */ |
729 | | 0, /* tp_as_sequence */ |
730 | | 0, /* tp_as_mapping */ |
731 | | 0, /* tp_hash */ |
732 | | PyVectorcall_Call, /* tp_call */ |
733 | | 0, /* tp_str */ |
734 | | PyObject_GenericGetAttr, /* tp_getattro */ |
735 | | 0, /* tp_setattro */ |
736 | | 0, /* tp_as_buffer */ |
737 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
738 | | Py_TPFLAGS_HAVE_VECTORCALL | |
739 | | Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */ |
740 | | 0, /* tp_doc */ |
741 | | descr_traverse, /* tp_traverse */ |
742 | | 0, /* tp_clear */ |
743 | | 0, /* tp_richcompare */ |
744 | | 0, /* tp_weaklistoffset */ |
745 | | 0, /* tp_iter */ |
746 | | 0, /* tp_iternext */ |
747 | | descr_methods, /* tp_methods */ |
748 | | descr_members, /* tp_members */ |
749 | | method_getset, /* tp_getset */ |
750 | | 0, /* tp_base */ |
751 | | 0, /* tp_dict */ |
752 | | method_get, /* tp_descr_get */ |
753 | | 0, /* tp_descr_set */ |
754 | | }; |
755 | | |
756 | | /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */ |
757 | | PyTypeObject PyClassMethodDescr_Type = { |
758 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
759 | | "classmethod_descriptor", |
760 | | sizeof(PyMethodDescrObject), |
761 | | 0, |
762 | | descr_dealloc, /* tp_dealloc */ |
763 | | 0, /* tp_vectorcall_offset */ |
764 | | 0, /* tp_getattr */ |
765 | | 0, /* tp_setattr */ |
766 | | 0, /* tp_as_async */ |
767 | | method_repr, /* tp_repr */ |
768 | | 0, /* tp_as_number */ |
769 | | 0, /* tp_as_sequence */ |
770 | | 0, /* tp_as_mapping */ |
771 | | 0, /* tp_hash */ |
772 | | classmethoddescr_call, /* tp_call */ |
773 | | 0, /* tp_str */ |
774 | | PyObject_GenericGetAttr, /* tp_getattro */ |
775 | | 0, /* tp_setattro */ |
776 | | 0, /* tp_as_buffer */ |
777 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
778 | | 0, /* tp_doc */ |
779 | | descr_traverse, /* tp_traverse */ |
780 | | 0, /* tp_clear */ |
781 | | 0, /* tp_richcompare */ |
782 | | 0, /* tp_weaklistoffset */ |
783 | | 0, /* tp_iter */ |
784 | | 0, /* tp_iternext */ |
785 | | 0, /* tp_methods */ |
786 | | descr_members, /* tp_members */ |
787 | | method_getset, /* tp_getset */ |
788 | | 0, /* tp_base */ |
789 | | 0, /* tp_dict */ |
790 | | classmethod_get, /* tp_descr_get */ |
791 | | 0, /* tp_descr_set */ |
792 | | }; |
793 | | |
794 | | PyTypeObject PyMemberDescr_Type = { |
795 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
796 | | "member_descriptor", |
797 | | sizeof(PyMemberDescrObject), |
798 | | 0, |
799 | | descr_dealloc, /* tp_dealloc */ |
800 | | 0, /* tp_vectorcall_offset */ |
801 | | 0, /* tp_getattr */ |
802 | | 0, /* tp_setattr */ |
803 | | 0, /* tp_as_async */ |
804 | | member_repr, /* tp_repr */ |
805 | | 0, /* tp_as_number */ |
806 | | 0, /* tp_as_sequence */ |
807 | | 0, /* tp_as_mapping */ |
808 | | 0, /* tp_hash */ |
809 | | 0, /* tp_call */ |
810 | | 0, /* tp_str */ |
811 | | PyObject_GenericGetAttr, /* tp_getattro */ |
812 | | 0, /* tp_setattro */ |
813 | | 0, /* tp_as_buffer */ |
814 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
815 | | 0, /* tp_doc */ |
816 | | descr_traverse, /* tp_traverse */ |
817 | | 0, /* tp_clear */ |
818 | | 0, /* tp_richcompare */ |
819 | | 0, /* tp_weaklistoffset */ |
820 | | 0, /* tp_iter */ |
821 | | 0, /* tp_iternext */ |
822 | | descr_methods, /* tp_methods */ |
823 | | descr_members, /* tp_members */ |
824 | | member_getset, /* tp_getset */ |
825 | | 0, /* tp_base */ |
826 | | 0, /* tp_dict */ |
827 | | member_get, /* tp_descr_get */ |
828 | | member_set, /* tp_descr_set */ |
829 | | }; |
830 | | |
831 | | PyTypeObject PyGetSetDescr_Type = { |
832 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
833 | | "getset_descriptor", |
834 | | sizeof(PyGetSetDescrObject), |
835 | | 0, |
836 | | descr_dealloc, /* tp_dealloc */ |
837 | | 0, /* tp_vectorcall_offset */ |
838 | | 0, /* tp_getattr */ |
839 | | 0, /* tp_setattr */ |
840 | | 0, /* tp_as_async */ |
841 | | getset_repr, /* tp_repr */ |
842 | | 0, /* tp_as_number */ |
843 | | 0, /* tp_as_sequence */ |
844 | | 0, /* tp_as_mapping */ |
845 | | 0, /* tp_hash */ |
846 | | 0, /* tp_call */ |
847 | | 0, /* tp_str */ |
848 | | PyObject_GenericGetAttr, /* tp_getattro */ |
849 | | 0, /* tp_setattro */ |
850 | | 0, /* tp_as_buffer */ |
851 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
852 | | 0, /* tp_doc */ |
853 | | descr_traverse, /* tp_traverse */ |
854 | | 0, /* tp_clear */ |
855 | | 0, /* tp_richcompare */ |
856 | | 0, /* tp_weaklistoffset */ |
857 | | 0, /* tp_iter */ |
858 | | 0, /* tp_iternext */ |
859 | | 0, /* tp_methods */ |
860 | | descr_members, /* tp_members */ |
861 | | getset_getset, /* tp_getset */ |
862 | | 0, /* tp_base */ |
863 | | 0, /* tp_dict */ |
864 | | getset_get, /* tp_descr_get */ |
865 | | getset_set, /* tp_descr_set */ |
866 | | }; |
867 | | |
868 | | PyTypeObject PyWrapperDescr_Type = { |
869 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
870 | | "wrapper_descriptor", |
871 | | sizeof(PyWrapperDescrObject), |
872 | | 0, |
873 | | descr_dealloc, /* tp_dealloc */ |
874 | | 0, /* tp_vectorcall_offset */ |
875 | | 0, /* tp_getattr */ |
876 | | 0, /* tp_setattr */ |
877 | | 0, /* tp_as_async */ |
878 | | wrapperdescr_repr, /* tp_repr */ |
879 | | 0, /* tp_as_number */ |
880 | | 0, /* tp_as_sequence */ |
881 | | 0, /* tp_as_mapping */ |
882 | | 0, /* tp_hash */ |
883 | | wrapperdescr_call, /* tp_call */ |
884 | | 0, /* tp_str */ |
885 | | PyObject_GenericGetAttr, /* tp_getattro */ |
886 | | 0, /* tp_setattro */ |
887 | | 0, /* tp_as_buffer */ |
888 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
889 | | Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */ |
890 | | 0, /* tp_doc */ |
891 | | descr_traverse, /* tp_traverse */ |
892 | | 0, /* tp_clear */ |
893 | | 0, /* tp_richcompare */ |
894 | | 0, /* tp_weaklistoffset */ |
895 | | 0, /* tp_iter */ |
896 | | 0, /* tp_iternext */ |
897 | | descr_methods, /* tp_methods */ |
898 | | descr_members, /* tp_members */ |
899 | | wrapperdescr_getset, /* tp_getset */ |
900 | | 0, /* tp_base */ |
901 | | 0, /* tp_dict */ |
902 | | wrapperdescr_get, /* tp_descr_get */ |
903 | | 0, /* tp_descr_set */ |
904 | | }; |
905 | | |
906 | | static PyDescrObject * |
907 | | descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) |
908 | 42.9k | { |
909 | 42.9k | PyDescrObject *descr; |
910 | | |
911 | 42.9k | descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0); |
912 | 42.9k | if (descr != NULL) { |
913 | 42.9k | _PyObject_SetDeferredRefcount((PyObject *)descr); |
914 | 42.9k | descr->d_type = (PyTypeObject*)Py_XNewRef(type); |
915 | 42.9k | descr->d_name = PyUnicode_InternFromString(name); |
916 | 42.9k | if (descr->d_name == NULL) { |
917 | 0 | Py_SETREF(descr, NULL); |
918 | 0 | } |
919 | 42.9k | else { |
920 | 42.9k | descr->d_qualname = NULL; |
921 | 42.9k | } |
922 | 42.9k | } |
923 | 42.9k | return descr; |
924 | 42.9k | } |
925 | | |
926 | | PyObject * |
927 | | PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) |
928 | 12.9k | { |
929 | | /* Figure out correct vectorcall function to use */ |
930 | 12.9k | vectorcallfunc vectorcall; |
931 | 12.9k | switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | |
932 | 12.9k | METH_O | METH_KEYWORDS | METH_METHOD)) |
933 | 12.9k | { |
934 | 433 | case METH_VARARGS: |
935 | 433 | vectorcall = method_vectorcall_VARARGS; |
936 | 433 | break; |
937 | 484 | case METH_VARARGS | METH_KEYWORDS: |
938 | 484 | vectorcall = method_vectorcall_VARARGS_KEYWORDS; |
939 | 484 | break; |
940 | 1.83k | case METH_FASTCALL: |
941 | 1.83k | vectorcall = method_vectorcall_FASTCALL; |
942 | 1.83k | break; |
943 | 770 | case METH_FASTCALL | METH_KEYWORDS: |
944 | 770 | vectorcall = method_vectorcall_FASTCALL_KEYWORDS; |
945 | 770 | break; |
946 | 6.59k | case METH_NOARGS: |
947 | 6.59k | vectorcall = method_vectorcall_NOARGS; |
948 | 6.59k | break; |
949 | 2.31k | case METH_O: |
950 | 2.31k | vectorcall = method_vectorcall_O; |
951 | 2.31k | break; |
952 | 556 | case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: |
953 | 556 | vectorcall = method_vectorcall_FASTCALL_KEYWORDS_METHOD; |
954 | 556 | break; |
955 | 0 | default: |
956 | 0 | PyErr_Format(PyExc_SystemError, |
957 | 0 | "%s() method: bad call flags", method->ml_name); |
958 | 0 | return NULL; |
959 | 12.9k | } |
960 | | |
961 | 12.9k | PyMethodDescrObject *descr; |
962 | | |
963 | 12.9k | descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type, |
964 | 12.9k | type, method->ml_name); |
965 | 12.9k | if (descr != NULL) { |
966 | 12.9k | descr->d_method = method; |
967 | 12.9k | descr->vectorcall = vectorcall; |
968 | 12.9k | } |
969 | 12.9k | return (PyObject *)descr; |
970 | 12.9k | } |
971 | | |
972 | | PyObject * |
973 | | PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method) |
974 | 747 | { |
975 | 747 | PyMethodDescrObject *descr; |
976 | | |
977 | 747 | descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type, |
978 | 747 | type, method->ml_name); |
979 | 747 | if (descr != NULL) |
980 | 747 | descr->d_method = method; |
981 | 747 | return (PyObject *)descr; |
982 | 747 | } |
983 | | |
984 | | PyObject * |
985 | | PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member) |
986 | 5.47k | { |
987 | 5.47k | PyMemberDescrObject *descr; |
988 | | |
989 | 5.47k | if (member->flags & Py_RELATIVE_OFFSET) { |
990 | 0 | PyErr_SetString( |
991 | 0 | PyExc_SystemError, |
992 | 0 | "PyDescr_NewMember used with Py_RELATIVE_OFFSET"); |
993 | 0 | return NULL; |
994 | 0 | } |
995 | 5.47k | descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type, |
996 | 5.47k | type, member->name); |
997 | 5.47k | if (descr != NULL) |
998 | 5.47k | descr->d_member = member; |
999 | 5.47k | return (PyObject *)descr; |
1000 | 5.47k | } |
1001 | | |
1002 | | PyObject * |
1003 | | PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset) |
1004 | 6.78k | { |
1005 | 6.78k | PyGetSetDescrObject *descr; |
1006 | | |
1007 | 6.78k | descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type, |
1008 | 6.78k | type, getset->name); |
1009 | 6.78k | if (descr != NULL) |
1010 | 6.78k | descr->d_getset = getset; |
1011 | 6.78k | return (PyObject *)descr; |
1012 | 6.78k | } |
1013 | | |
1014 | | PyObject * |
1015 | | PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) |
1016 | 16.9k | { |
1017 | 16.9k | PyWrapperDescrObject *descr; |
1018 | | |
1019 | 16.9k | descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type, |
1020 | 16.9k | type, base->name); |
1021 | 16.9k | if (descr != NULL) { |
1022 | 16.9k | descr->d_base = base; |
1023 | 16.9k | descr->d_wrapped = wrapped; |
1024 | 16.9k | } |
1025 | 16.9k | return (PyObject *)descr; |
1026 | 16.9k | } |
1027 | | |
1028 | | int |
1029 | | PyDescr_IsData(PyObject *ob) |
1030 | 270M | { |
1031 | 270M | return Py_TYPE(ob)->tp_descr_set != NULL; |
1032 | 270M | } |
1033 | | |
1034 | | /* --- mappingproxy: read-only proxy for mappings --- */ |
1035 | | |
1036 | | /* This has no reason to be in this file except that adding new files is a |
1037 | | bit of a pain */ |
1038 | | |
1039 | | typedef struct { |
1040 | | PyObject_HEAD |
1041 | | PyObject *mapping; |
1042 | | } mappingproxyobject; |
1043 | | |
1044 | | static Py_ssize_t |
1045 | | mappingproxy_len(PyObject *self) |
1046 | 0 | { |
1047 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1048 | 0 | return PyObject_Size(pp->mapping); |
1049 | 0 | } |
1050 | | |
1051 | | static PyObject * |
1052 | | mappingproxy_getitem(PyObject *self, PyObject *key) |
1053 | 3.74k | { |
1054 | 3.74k | mappingproxyobject *pp = (mappingproxyobject *)self; |
1055 | 3.74k | return PyObject_GetItem(pp->mapping, key); |
1056 | 3.74k | } |
1057 | | |
1058 | | static PyMappingMethods mappingproxy_as_mapping = { |
1059 | | mappingproxy_len, /* mp_length */ |
1060 | | mappingproxy_getitem, /* mp_subscript */ |
1061 | | 0, /* mp_ass_subscript */ |
1062 | | }; |
1063 | | |
1064 | | static PyObject * |
1065 | | mappingproxy_or(PyObject *left, PyObject *right) |
1066 | 0 | { |
1067 | 0 | if (PyObject_TypeCheck(left, &PyDictProxy_Type)) { |
1068 | 0 | left = ((mappingproxyobject*)left)->mapping; |
1069 | 0 | } |
1070 | 0 | if (PyObject_TypeCheck(right, &PyDictProxy_Type)) { |
1071 | 0 | right = ((mappingproxyobject*)right)->mapping; |
1072 | 0 | } |
1073 | 0 | return PyNumber_Or(left, right); |
1074 | 0 | } |
1075 | | |
1076 | | static PyObject * |
1077 | | mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other)) |
1078 | 0 | { |
1079 | 0 | return PyErr_Format(PyExc_TypeError, |
1080 | 0 | "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name); |
1081 | 0 | } |
1082 | | |
1083 | | static PyNumberMethods mappingproxy_as_number = { |
1084 | | .nb_or = mappingproxy_or, |
1085 | | .nb_inplace_or = mappingproxy_ior, |
1086 | | }; |
1087 | | |
1088 | | static int |
1089 | | mappingproxy_contains(PyObject *self, PyObject *key) |
1090 | 796 | { |
1091 | 796 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1092 | 796 | if (PyDict_CheckExact(pp->mapping)) |
1093 | 796 | return PyDict_Contains(pp->mapping, key); |
1094 | 0 | else |
1095 | 0 | return PySequence_Contains(pp->mapping, key); |
1096 | 796 | } |
1097 | | |
1098 | | static PySequenceMethods mappingproxy_as_sequence = { |
1099 | | 0, /* sq_length */ |
1100 | | 0, /* sq_concat */ |
1101 | | 0, /* sq_repeat */ |
1102 | | 0, /* sq_item */ |
1103 | | 0, /* sq_slice */ |
1104 | | 0, /* sq_ass_item */ |
1105 | | 0, /* sq_ass_slice */ |
1106 | | mappingproxy_contains, /* sq_contains */ |
1107 | | 0, /* sq_inplace_concat */ |
1108 | | 0, /* sq_inplace_repeat */ |
1109 | | }; |
1110 | | |
1111 | | static PyObject * |
1112 | | mappingproxy_get(PyObject *self, PyObject *const *args, Py_ssize_t nargs) |
1113 | 3.00k | { |
1114 | 3.00k | mappingproxyobject *pp = (mappingproxyobject *)self; |
1115 | | /* newargs: mapping, key, default=None */ |
1116 | 3.00k | PyObject *newargs[3]; |
1117 | 3.00k | newargs[0] = pp->mapping; |
1118 | 3.00k | newargs[2] = Py_None; |
1119 | | |
1120 | 3.00k | if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2, |
1121 | 3.00k | &newargs[1], &newargs[2])) |
1122 | 0 | { |
1123 | 0 | return NULL; |
1124 | 0 | } |
1125 | 3.00k | return PyObject_VectorcallMethod(&_Py_ID(get), newargs, |
1126 | 3.00k | 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, |
1127 | 3.00k | NULL); |
1128 | 3.00k | } |
1129 | | |
1130 | | static PyObject * |
1131 | | mappingproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1132 | 136 | { |
1133 | 136 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1134 | 136 | return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(keys)); |
1135 | 136 | } |
1136 | | |
1137 | | static PyObject * |
1138 | | mappingproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1139 | 4 | { |
1140 | 4 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1141 | 4 | return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(values)); |
1142 | 4 | } |
1143 | | |
1144 | | static PyObject * |
1145 | | mappingproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1146 | 773 | { |
1147 | 773 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1148 | 773 | return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(items)); |
1149 | 773 | } |
1150 | | |
1151 | | static PyObject * |
1152 | | mappingproxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1153 | 0 | { |
1154 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1155 | 0 | return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(copy)); |
1156 | 0 | } |
1157 | | |
1158 | | static PyObject * |
1159 | | mappingproxy_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1160 | 0 | { |
1161 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1162 | 0 | return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(__reversed__)); |
1163 | 0 | } |
1164 | | |
1165 | | /* WARNING: mappingproxy methods must not give access |
1166 | | to the underlying mapping */ |
1167 | | |
1168 | | static PyMethodDef mappingproxy_methods[] = { |
1169 | | {"get", _PyCFunction_CAST(mappingproxy_get), METH_FASTCALL, |
1170 | | PyDoc_STR("get($self, key, default=None, /)\n--\n\n" |
1171 | | "Return the value for key if key is in the mapping, else default.")}, |
1172 | | {"keys", mappingproxy_keys, METH_NOARGS, |
1173 | | PyDoc_STR("D.keys() -> a set-like object providing a view on D's keys")}, |
1174 | | {"values", mappingproxy_values, METH_NOARGS, |
1175 | | PyDoc_STR("D.values() -> an object providing a view on D's values")}, |
1176 | | {"items", mappingproxy_items, METH_NOARGS, |
1177 | | PyDoc_STR("D.items() -> a set-like object providing a view on D's items")}, |
1178 | | {"copy", mappingproxy_copy, METH_NOARGS, |
1179 | | PyDoc_STR("D.copy() -> a shallow copy of D")}, |
1180 | | {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, |
1181 | | PyDoc_STR("See PEP 585")}, |
1182 | | {"__reversed__", mappingproxy_reversed, METH_NOARGS, |
1183 | | PyDoc_STR("D.__reversed__() -> reverse iterator")}, |
1184 | | {0} |
1185 | | }; |
1186 | | |
1187 | | static void |
1188 | | mappingproxy_dealloc(PyObject *self) |
1189 | 5.40k | { |
1190 | 5.40k | mappingproxyobject *pp = (mappingproxyobject *)self; |
1191 | 5.40k | _PyObject_GC_UNTRACK(pp); |
1192 | 5.40k | Py_DECREF(pp->mapping); |
1193 | 5.40k | PyObject_GC_Del(pp); |
1194 | 5.40k | } |
1195 | | |
1196 | | static PyObject * |
1197 | | mappingproxy_getiter(PyObject *self) |
1198 | 0 | { |
1199 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1200 | 0 | return PyObject_GetIter(pp->mapping); |
1201 | 0 | } |
1202 | | |
1203 | | static Py_hash_t |
1204 | | mappingproxy_hash(PyObject *self) |
1205 | 0 | { |
1206 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1207 | 0 | return PyObject_Hash(pp->mapping); |
1208 | 0 | } |
1209 | | |
1210 | | static PyObject * |
1211 | | mappingproxy_str(PyObject *self) |
1212 | 0 | { |
1213 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1214 | 0 | return PyObject_Str(pp->mapping); |
1215 | 0 | } |
1216 | | |
1217 | | static PyObject * |
1218 | | mappingproxy_repr(PyObject *self) |
1219 | 0 | { |
1220 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1221 | 0 | return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping); |
1222 | 0 | } |
1223 | | |
1224 | | static int |
1225 | | mappingproxy_traverse(PyObject *self, visitproc visit, void *arg) |
1226 | 3.99k | { |
1227 | 3.99k | mappingproxyobject *pp = (mappingproxyobject *)self; |
1228 | 3.99k | Py_VISIT(pp->mapping); |
1229 | 3.99k | return 0; |
1230 | 3.99k | } |
1231 | | |
1232 | | static PyObject * |
1233 | | mappingproxy_richcompare(PyObject *self, PyObject *w, int op) |
1234 | 0 | { |
1235 | 0 | mappingproxyobject *v = (mappingproxyobject *)self; |
1236 | 0 | if (op == Py_EQ || op == Py_NE) { |
1237 | 0 | return PyObject_RichCompare(v->mapping, w, op); |
1238 | 0 | } |
1239 | 0 | Py_RETURN_NOTIMPLEMENTED; |
1240 | 0 | } |
1241 | | |
1242 | | static int |
1243 | | mappingproxy_check_mapping(PyObject *mapping) |
1244 | 5.40k | { |
1245 | 5.40k | if (!PyMapping_Check(mapping) |
1246 | 5.40k | || PyList_Check(mapping) |
1247 | 5.40k | || PyTuple_Check(mapping)) { |
1248 | 0 | PyErr_Format(PyExc_TypeError, |
1249 | 0 | "mappingproxy() argument must be a mapping, not %s", |
1250 | 0 | Py_TYPE(mapping)->tp_name); |
1251 | 0 | return -1; |
1252 | 0 | } |
1253 | 5.40k | return 0; |
1254 | 5.40k | } |
1255 | | |
1256 | | /*[clinic input] |
1257 | | @classmethod |
1258 | | mappingproxy.__new__ as mappingproxy_new |
1259 | | |
1260 | | mapping: object |
1261 | | |
1262 | | Read-only proxy of a mapping. |
1263 | | [clinic start generated code]*/ |
1264 | | |
1265 | | static PyObject * |
1266 | | mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping) |
1267 | | /*[clinic end generated code: output=65f27f02d5b68fa7 input=c156df096ef7590c]*/ |
1268 | 63 | { |
1269 | 63 | mappingproxyobject *mappingproxy; |
1270 | | |
1271 | 63 | if (mappingproxy_check_mapping(mapping) == -1) |
1272 | 0 | return NULL; |
1273 | | |
1274 | 63 | mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); |
1275 | 63 | if (mappingproxy == NULL) |
1276 | 0 | return NULL; |
1277 | 63 | mappingproxy->mapping = Py_NewRef(mapping); |
1278 | 63 | _PyObject_GC_TRACK(mappingproxy); |
1279 | 63 | return (PyObject *)mappingproxy; |
1280 | 63 | } |
1281 | | |
1282 | | PyObject * |
1283 | | PyDictProxy_New(PyObject *mapping) |
1284 | 5.34k | { |
1285 | 5.34k | mappingproxyobject *pp; |
1286 | | |
1287 | 5.34k | if (mappingproxy_check_mapping(mapping) == -1) |
1288 | 0 | return NULL; |
1289 | | |
1290 | 5.34k | pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); |
1291 | 5.34k | if (pp != NULL) { |
1292 | 5.34k | pp->mapping = Py_NewRef(mapping); |
1293 | 5.34k | _PyObject_GC_TRACK(pp); |
1294 | 5.34k | } |
1295 | 5.34k | return (PyObject *)pp; |
1296 | 5.34k | } |
1297 | | |
1298 | | |
1299 | | /* --- Wrapper object for "slot" methods --- */ |
1300 | | |
1301 | | /* This has no reason to be in this file except that adding new files is a |
1302 | | bit of a pain */ |
1303 | | |
1304 | | typedef struct { |
1305 | | PyObject_HEAD |
1306 | | PyWrapperDescrObject *descr; |
1307 | | PyObject *self; |
1308 | | } wrapperobject; |
1309 | | |
1310 | 0 | #define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type) |
1311 | | |
1312 | | static void |
1313 | | wrapper_dealloc(PyObject *self) |
1314 | 11.2M | { |
1315 | 11.2M | wrapperobject *wp = (wrapperobject *)self; |
1316 | 11.2M | PyObject_GC_UnTrack(wp); |
1317 | 11.2M | Py_XDECREF(wp->descr); |
1318 | 11.2M | Py_XDECREF(wp->self); |
1319 | 11.2M | PyObject_GC_Del(wp); |
1320 | 11.2M | } |
1321 | | |
1322 | | static PyObject * |
1323 | | wrapper_richcompare(PyObject *a, PyObject *b, int op) |
1324 | 0 | { |
1325 | 0 | wrapperobject *wa, *wb; |
1326 | 0 | int eq; |
1327 | |
|
1328 | 0 | assert(a != NULL && b != NULL); |
1329 | | |
1330 | | /* both arguments should be wrapperobjects */ |
1331 | 0 | if ((op != Py_EQ && op != Py_NE) |
1332 | 0 | || !Wrapper_Check(a) || !Wrapper_Check(b)) |
1333 | 0 | { |
1334 | 0 | Py_RETURN_NOTIMPLEMENTED; |
1335 | 0 | } |
1336 | | |
1337 | 0 | wa = (wrapperobject *)a; |
1338 | 0 | wb = (wrapperobject *)b; |
1339 | 0 | eq = (wa->descr == wb->descr && wa->self == wb->self); |
1340 | 0 | if (eq == (op == Py_EQ)) { |
1341 | 0 | Py_RETURN_TRUE; |
1342 | 0 | } |
1343 | 0 | else { |
1344 | 0 | Py_RETURN_FALSE; |
1345 | 0 | } |
1346 | 0 | } |
1347 | | |
1348 | | static Py_hash_t |
1349 | | wrapper_hash(PyObject *self) |
1350 | 0 | { |
1351 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1352 | 0 | Py_hash_t x, y; |
1353 | 0 | x = PyObject_GenericHash(wp->self); |
1354 | 0 | y = Py_HashPointer(wp->descr); |
1355 | 0 | x = x ^ y; |
1356 | 0 | if (x == -1) |
1357 | 0 | x = -2; |
1358 | 0 | return x; |
1359 | 0 | } |
1360 | | |
1361 | | static PyObject * |
1362 | | wrapper_repr(PyObject *self) |
1363 | 0 | { |
1364 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1365 | 0 | return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>", |
1366 | 0 | wp->descr->d_base->name, |
1367 | 0 | Py_TYPE(wp->self)->tp_name, |
1368 | 0 | wp->self); |
1369 | 0 | } |
1370 | | |
1371 | | static PyObject * |
1372 | | wrapper_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) |
1373 | 0 | { |
1374 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1375 | 0 | return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)), |
1376 | 0 | wp->self, PyDescr_NAME(wp->descr)); |
1377 | 0 | } |
1378 | | |
1379 | | static PyMethodDef wrapper_methods[] = { |
1380 | | {"__reduce__", wrapper_reduce, METH_NOARGS, NULL}, |
1381 | | {NULL, NULL} |
1382 | | }; |
1383 | | |
1384 | | static PyMemberDef wrapper_members[] = { |
1385 | | {"__self__", _Py_T_OBJECT, offsetof(wrapperobject, self), Py_READONLY}, |
1386 | | {0} |
1387 | | }; |
1388 | | |
1389 | | static PyObject * |
1390 | | wrapper_objclass(PyObject *wp, void *Py_UNUSED(ignored)) |
1391 | 0 | { |
1392 | 0 | PyObject *c = (PyObject *)PyDescr_TYPE(((wrapperobject *)wp)->descr); |
1393 | |
|
1394 | 0 | return Py_NewRef(c); |
1395 | 0 | } |
1396 | | |
1397 | | static PyObject * |
1398 | | wrapper_name(PyObject *wp, void *Py_UNUSED(ignored)) |
1399 | 0 | { |
1400 | 0 | const char *s = ((wrapperobject *)wp)->descr->d_base->name; |
1401 | |
|
1402 | 0 | return PyUnicode_FromString(s); |
1403 | 0 | } |
1404 | | |
1405 | | static PyObject * |
1406 | | wrapper_doc(PyObject *self, void *Py_UNUSED(ignored)) |
1407 | 0 | { |
1408 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1409 | 0 | return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); |
1410 | 0 | } |
1411 | | |
1412 | | static PyObject * |
1413 | | wrapper_text_signature(PyObject *self, void *Py_UNUSED(ignored)) |
1414 | 0 | { |
1415 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1416 | 0 | return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, |
1417 | 0 | wp->descr->d_base->doc, 0); |
1418 | 0 | } |
1419 | | |
1420 | | static PyObject * |
1421 | | wrapper_qualname(PyObject *self, void *Py_UNUSED(ignored)) |
1422 | 0 | { |
1423 | 0 | wrapperobject *wp = (wrapperobject *)self; |
1424 | 0 | return descr_get_qualname((PyObject *)wp->descr, NULL); |
1425 | 0 | } |
1426 | | |
1427 | | static PyGetSetDef wrapper_getsets[] = { |
1428 | | {"__objclass__", wrapper_objclass}, |
1429 | | {"__name__", wrapper_name}, |
1430 | | {"__qualname__", wrapper_qualname}, |
1431 | | {"__doc__", wrapper_doc}, |
1432 | | {"__text_signature__", wrapper_text_signature}, |
1433 | | {0} |
1434 | | }; |
1435 | | |
1436 | | static PyObject * |
1437 | | wrapper_call(PyObject *self, PyObject *args, PyObject *kwds) |
1438 | 11.2M | { |
1439 | 11.2M | wrapperobject *wp = (wrapperobject *)self; |
1440 | 11.2M | return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds); |
1441 | 11.2M | } |
1442 | | |
1443 | | static int |
1444 | | wrapper_traverse(PyObject *self, visitproc visit, void *arg) |
1445 | 3.09k | { |
1446 | 3.09k | wrapperobject *wp = (wrapperobject *)self; |
1447 | 3.09k | Py_VISIT(wp->descr); |
1448 | 3.09k | Py_VISIT(wp->self); |
1449 | 3.09k | return 0; |
1450 | 3.09k | } |
1451 | | |
1452 | | PyTypeObject _PyMethodWrapper_Type = { |
1453 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1454 | | "method-wrapper", /* tp_name */ |
1455 | | sizeof(wrapperobject), /* tp_basicsize */ |
1456 | | 0, /* tp_itemsize */ |
1457 | | /* methods */ |
1458 | | wrapper_dealloc, /* tp_dealloc */ |
1459 | | 0, /* tp_vectorcall_offset */ |
1460 | | 0, /* tp_getattr */ |
1461 | | 0, /* tp_setattr */ |
1462 | | 0, /* tp_as_async */ |
1463 | | wrapper_repr, /* tp_repr */ |
1464 | | 0, /* tp_as_number */ |
1465 | | 0, /* tp_as_sequence */ |
1466 | | 0, /* tp_as_mapping */ |
1467 | | wrapper_hash, /* tp_hash */ |
1468 | | wrapper_call, /* tp_call */ |
1469 | | 0, /* tp_str */ |
1470 | | PyObject_GenericGetAttr, /* tp_getattro */ |
1471 | | 0, /* tp_setattro */ |
1472 | | 0, /* tp_as_buffer */ |
1473 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
1474 | | 0, /* tp_doc */ |
1475 | | wrapper_traverse, /* tp_traverse */ |
1476 | | 0, /* tp_clear */ |
1477 | | wrapper_richcompare, /* tp_richcompare */ |
1478 | | 0, /* tp_weaklistoffset */ |
1479 | | 0, /* tp_iter */ |
1480 | | 0, /* tp_iternext */ |
1481 | | wrapper_methods, /* tp_methods */ |
1482 | | wrapper_members, /* tp_members */ |
1483 | | wrapper_getsets, /* tp_getset */ |
1484 | | 0, /* tp_base */ |
1485 | | 0, /* tp_dict */ |
1486 | | 0, /* tp_descr_get */ |
1487 | | 0, /* tp_descr_set */ |
1488 | | }; |
1489 | | |
1490 | | PyObject * |
1491 | | PyWrapper_New(PyObject *d, PyObject *self) |
1492 | 11.2M | { |
1493 | 11.2M | wrapperobject *wp; |
1494 | 11.2M | PyWrapperDescrObject *descr; |
1495 | | |
1496 | 11.2M | assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); |
1497 | 11.2M | descr = (PyWrapperDescrObject *)d; |
1498 | 11.2M | assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), |
1499 | 11.2M | (PyObject *)PyDescr_TYPE(descr))); |
1500 | | |
1501 | 11.2M | wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type); |
1502 | 11.2M | if (wp != NULL) { |
1503 | 11.2M | wp->descr = (PyWrapperDescrObject*)Py_NewRef(descr); |
1504 | 11.2M | wp->self = Py_NewRef(self); |
1505 | 11.2M | _PyObject_GC_TRACK(wp); |
1506 | 11.2M | } |
1507 | 11.2M | return (PyObject *)wp; |
1508 | 11.2M | } |
1509 | | |
1510 | | |
1511 | | /* A built-in 'property' type */ |
1512 | | |
1513 | 44 | #define _propertyobject_CAST(op) ((propertyobject *)(op)) |
1514 | | |
1515 | | /* |
1516 | | class property(object): |
1517 | | |
1518 | | def __init__(self, fget=None, fset=None, fdel=None, doc=None): |
1519 | | if doc is None and fget is not None and hasattr(fget, "__doc__"): |
1520 | | doc = fget.__doc__ |
1521 | | self.__get = fget |
1522 | | self.__set = fset |
1523 | | self.__del = fdel |
1524 | | try: |
1525 | | self.__doc__ = doc |
1526 | | except AttributeError: # read-only or dict-less class |
1527 | | pass |
1528 | | self.__name = None |
1529 | | |
1530 | | def __set_name__(self, owner, name): |
1531 | | self.__name = name |
1532 | | |
1533 | | @property |
1534 | | def __name__(self): |
1535 | | return self.__name if self.__name is not None else self.fget.__name__ |
1536 | | |
1537 | | @__name__.setter |
1538 | | def __name__(self, value): |
1539 | | self.__name = value |
1540 | | |
1541 | | def __get__(self, inst, type=None): |
1542 | | if inst is None: |
1543 | | return self |
1544 | | if self.__get is None: |
1545 | | raise AttributeError("property has no getter") |
1546 | | return self.__get(inst) |
1547 | | |
1548 | | def __set__(self, inst, value): |
1549 | | if self.__set is None: |
1550 | | raise AttributeError("property has no setter") |
1551 | | return self.__set(inst, value) |
1552 | | |
1553 | | def __delete__(self, inst): |
1554 | | if self.__del is None: |
1555 | | raise AttributeError("property has no deleter") |
1556 | | return self.__del(inst) |
1557 | | |
1558 | | */ |
1559 | | |
1560 | | static PyObject * property_copy(PyObject *, PyObject *, PyObject *, |
1561 | | PyObject *); |
1562 | | |
1563 | | static PyMemberDef property_members[] = { |
1564 | | {"fget", _Py_T_OBJECT, offsetof(propertyobject, prop_get), Py_READONLY}, |
1565 | | {"fset", _Py_T_OBJECT, offsetof(propertyobject, prop_set), Py_READONLY}, |
1566 | | {"fdel", _Py_T_OBJECT, offsetof(propertyobject, prop_del), Py_READONLY}, |
1567 | | {"__doc__", _Py_T_OBJECT, offsetof(propertyobject, prop_doc), 0}, |
1568 | | {0} |
1569 | | }; |
1570 | | |
1571 | | |
1572 | | PyDoc_STRVAR(getter_doc, |
1573 | | "Descriptor to obtain a copy of the property with a different getter."); |
1574 | | |
1575 | | static PyObject * |
1576 | | property_getter(PyObject *self, PyObject *getter) |
1577 | 0 | { |
1578 | 0 | return property_copy(self, getter, NULL, NULL); |
1579 | 0 | } |
1580 | | |
1581 | | |
1582 | | PyDoc_STRVAR(setter_doc, |
1583 | | "Descriptor to obtain a copy of the property with a different setter."); |
1584 | | |
1585 | | static PyObject * |
1586 | | property_setter(PyObject *self, PyObject *setter) |
1587 | 86 | { |
1588 | 86 | return property_copy(self, NULL, setter, NULL); |
1589 | 86 | } |
1590 | | |
1591 | | |
1592 | | PyDoc_STRVAR(deleter_doc, |
1593 | | "Descriptor to obtain a copy of the property with a different deleter."); |
1594 | | |
1595 | | static PyObject * |
1596 | | property_deleter(PyObject *self, PyObject *deleter) |
1597 | 4 | { |
1598 | 4 | return property_copy(self, NULL, NULL, deleter); |
1599 | 4 | } |
1600 | | |
1601 | | |
1602 | | PyDoc_STRVAR(set_name_doc, |
1603 | | "__set_name__($self, owner, name, /)\n" |
1604 | | "--\n" |
1605 | | "\n" |
1606 | | "Method to set name of a property."); |
1607 | | |
1608 | | static PyObject * |
1609 | 943 | property_set_name(PyObject *self, PyObject *args) { |
1610 | 943 | if (PyTuple_GET_SIZE(args) != 2) { |
1611 | 0 | PyErr_Format( |
1612 | 0 | PyExc_TypeError, |
1613 | 0 | "__set_name__() takes 2 positional arguments but %d were given", |
1614 | 0 | PyTuple_GET_SIZE(args)); |
1615 | 0 | return NULL; |
1616 | 0 | } |
1617 | | |
1618 | 943 | propertyobject *prop = (propertyobject *)self; |
1619 | 943 | PyObject *name = PyTuple_GET_ITEM(args, 1); |
1620 | | |
1621 | 943 | Py_XSETREF(prop->prop_name, Py_XNewRef(name)); |
1622 | | |
1623 | 943 | Py_RETURN_NONE; |
1624 | 943 | } |
1625 | | |
1626 | | static PyMethodDef property_methods[] = { |
1627 | | {"getter", property_getter, METH_O, getter_doc}, |
1628 | | {"setter", property_setter, METH_O, setter_doc}, |
1629 | | {"deleter", property_deleter, METH_O, deleter_doc}, |
1630 | | {"__set_name__", property_set_name, METH_VARARGS, set_name_doc}, |
1631 | | {0} |
1632 | | }; |
1633 | | |
1634 | | |
1635 | | static void |
1636 | | property_dealloc(PyObject *self) |
1637 | 90 | { |
1638 | 90 | propertyobject *gs = (propertyobject *)self; |
1639 | | |
1640 | 90 | _PyObject_GC_UNTRACK(self); |
1641 | 90 | Py_XDECREF(gs->prop_get); |
1642 | 90 | Py_XDECREF(gs->prop_set); |
1643 | 90 | Py_XDECREF(gs->prop_del); |
1644 | 90 | Py_XDECREF(gs->prop_doc); |
1645 | 90 | Py_XDECREF(gs->prop_name); |
1646 | 90 | Py_TYPE(self)->tp_free(self); |
1647 | 90 | } |
1648 | | |
1649 | | static int |
1650 | | property_name(propertyobject *prop, PyObject **name) |
1651 | 0 | { |
1652 | 0 | if (prop->prop_name != NULL) { |
1653 | 0 | *name = Py_NewRef(prop->prop_name); |
1654 | 0 | return 1; |
1655 | 0 | } |
1656 | 0 | if (prop->prop_get == NULL) { |
1657 | 0 | *name = NULL; |
1658 | 0 | return 0; |
1659 | 0 | } |
1660 | 0 | return PyObject_GetOptionalAttr(prop->prop_get, &_Py_ID(__name__), name); |
1661 | 0 | } |
1662 | | |
1663 | | static PyObject * |
1664 | | property_descr_get(PyObject *self, PyObject *obj, PyObject *type) |
1665 | 10.8M | { |
1666 | 10.8M | if (obj == NULL || obj == Py_None) { |
1667 | 12 | return Py_NewRef(self); |
1668 | 12 | } |
1669 | | |
1670 | 10.8M | propertyobject *gs = (propertyobject *)self; |
1671 | 10.8M | if (gs->prop_get == NULL) { |
1672 | 0 | PyObject *propname; |
1673 | 0 | if (property_name(gs, &propname) < 0) { |
1674 | 0 | return NULL; |
1675 | 0 | } |
1676 | 0 | PyObject *qualname = PyType_GetQualName(Py_TYPE(obj)); |
1677 | 0 | if (propname != NULL && qualname != NULL) { |
1678 | 0 | PyErr_Format(PyExc_AttributeError, |
1679 | 0 | "property %R of %R object has no getter", |
1680 | 0 | propname, |
1681 | 0 | qualname); |
1682 | 0 | } |
1683 | 0 | else if (qualname != NULL) { |
1684 | 0 | PyErr_Format(PyExc_AttributeError, |
1685 | 0 | "property of %R object has no getter", |
1686 | 0 | qualname); |
1687 | 0 | } else { |
1688 | 0 | PyErr_SetString(PyExc_AttributeError, |
1689 | 0 | "property has no getter"); |
1690 | 0 | } |
1691 | 0 | Py_XDECREF(propname); |
1692 | 0 | Py_XDECREF(qualname); |
1693 | 0 | return NULL; |
1694 | 0 | } |
1695 | | |
1696 | 10.8M | return PyObject_CallOneArg(gs->prop_get, obj); |
1697 | 10.8M | } |
1698 | | |
1699 | | static int |
1700 | | property_descr_set(PyObject *self, PyObject *obj, PyObject *value) |
1701 | 64 | { |
1702 | 64 | propertyobject *gs = (propertyobject *)self; |
1703 | 64 | PyObject *func, *res; |
1704 | | |
1705 | 64 | if (value == NULL) { |
1706 | 0 | func = gs->prop_del; |
1707 | 0 | } |
1708 | 64 | else { |
1709 | 64 | func = gs->prop_set; |
1710 | 64 | } |
1711 | | |
1712 | 64 | if (func == NULL) { |
1713 | 0 | PyObject *propname; |
1714 | 0 | if (property_name(gs, &propname) < 0) { |
1715 | 0 | return -1; |
1716 | 0 | } |
1717 | 0 | PyObject *qualname = NULL; |
1718 | 0 | if (obj != NULL) { |
1719 | 0 | qualname = PyType_GetQualName(Py_TYPE(obj)); |
1720 | 0 | } |
1721 | 0 | if (propname != NULL && qualname != NULL) { |
1722 | 0 | PyErr_Format(PyExc_AttributeError, |
1723 | 0 | value == NULL ? |
1724 | 0 | "property %R of %R object has no deleter" : |
1725 | 0 | "property %R of %R object has no setter", |
1726 | 0 | propname, |
1727 | 0 | qualname); |
1728 | 0 | } |
1729 | 0 | else if (qualname != NULL) { |
1730 | 0 | PyErr_Format(PyExc_AttributeError, |
1731 | 0 | value == NULL ? |
1732 | 0 | "property of %R object has no deleter" : |
1733 | 0 | "property of %R object has no setter", |
1734 | 0 | qualname); |
1735 | 0 | } |
1736 | 0 | else { |
1737 | 0 | PyErr_SetString(PyExc_AttributeError, |
1738 | 0 | value == NULL ? |
1739 | 0 | "property has no deleter" : |
1740 | 0 | "property has no setter"); |
1741 | 0 | } |
1742 | 0 | Py_XDECREF(propname); |
1743 | 0 | Py_XDECREF(qualname); |
1744 | 0 | return -1; |
1745 | 0 | } |
1746 | | |
1747 | 64 | if (value == NULL) { |
1748 | 0 | res = PyObject_CallOneArg(func, obj); |
1749 | 0 | } |
1750 | 64 | else { |
1751 | 64 | EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); |
1752 | 64 | PyObject *args[] = { obj, value }; |
1753 | 64 | res = PyObject_Vectorcall(func, args, 2, NULL); |
1754 | 64 | } |
1755 | | |
1756 | 64 | if (res == NULL) { |
1757 | 0 | return -1; |
1758 | 0 | } |
1759 | | |
1760 | 64 | Py_DECREF(res); |
1761 | 64 | return 0; |
1762 | 64 | } |
1763 | | |
1764 | | static PyObject * |
1765 | | property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) |
1766 | 90 | { |
1767 | 90 | propertyobject *pold = (propertyobject *)old; |
1768 | 90 | PyObject *new, *type, *doc; |
1769 | | |
1770 | 90 | type = PyObject_Type(old); |
1771 | 90 | if (type == NULL) |
1772 | 0 | return NULL; |
1773 | | |
1774 | 90 | if (get == NULL || get == Py_None) { |
1775 | 90 | get = pold->prop_get ? pold->prop_get : Py_None; |
1776 | 90 | } |
1777 | 90 | if (set == NULL || set == Py_None) { |
1778 | 4 | set = pold->prop_set ? pold->prop_set : Py_None; |
1779 | 4 | } |
1780 | 90 | if (del == NULL || del == Py_None) { |
1781 | 86 | del = pold->prop_del ? pold->prop_del : Py_None; |
1782 | 86 | } |
1783 | 90 | if (pold->getter_doc && get != Py_None) { |
1784 | | /* make _init use __doc__ from getter */ |
1785 | 22 | doc = Py_None; |
1786 | 22 | } |
1787 | 68 | else { |
1788 | 68 | doc = pold->prop_doc ? pold->prop_doc : Py_None; |
1789 | 68 | } |
1790 | | |
1791 | 90 | new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL); |
1792 | 90 | Py_DECREF(type); |
1793 | 90 | if (new == NULL) |
1794 | 0 | return NULL; |
1795 | | |
1796 | 90 | if (PyObject_TypeCheck((new), &PyProperty_Type)) { |
1797 | 90 | Py_XSETREF(((propertyobject *) new)->prop_name, Py_XNewRef(pold->prop_name)); |
1798 | 90 | } |
1799 | 90 | return new; |
1800 | 90 | } |
1801 | | |
1802 | | /*[clinic input] |
1803 | | property.__init__ as property_init |
1804 | | |
1805 | | fget: object(c_default="NULL") = None |
1806 | | function to be used for getting an attribute value |
1807 | | fset: object(c_default="NULL") = None |
1808 | | function to be used for setting an attribute value |
1809 | | fdel: object(c_default="NULL") = None |
1810 | | function to be used for del'ing an attribute |
1811 | | doc: object(c_default="NULL") = None |
1812 | | docstring |
1813 | | |
1814 | | Property attribute. |
1815 | | |
1816 | | Typical use is to define a managed attribute x: |
1817 | | |
1818 | | class C(object): |
1819 | | def getx(self): return self._x |
1820 | | def setx(self, value): self._x = value |
1821 | | def delx(self): del self._x |
1822 | | x = property(getx, setx, delx, "I'm the 'x' property.") |
1823 | | |
1824 | | Decorators make defining new properties or modifying existing ones easy: |
1825 | | |
1826 | | class C(object): |
1827 | | @property |
1828 | | def x(self): |
1829 | | "I am the 'x' property." |
1830 | | return self._x |
1831 | | @x.setter |
1832 | | def x(self, value): |
1833 | | self._x = value |
1834 | | @x.deleter |
1835 | | def x(self): |
1836 | | del self._x |
1837 | | [clinic start generated code]*/ |
1838 | | |
1839 | | static int |
1840 | | property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, |
1841 | | PyObject *fdel, PyObject *doc) |
1842 | | /*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/ |
1843 | 951 | { |
1844 | 951 | if (fget == Py_None) |
1845 | 0 | fget = NULL; |
1846 | 951 | if (fset == Py_None) |
1847 | 0 | fset = NULL; |
1848 | 951 | if (fdel == Py_None) |
1849 | 86 | fdel = NULL; |
1850 | | |
1851 | 951 | Py_XSETREF(self->prop_get, Py_XNewRef(fget)); |
1852 | 951 | Py_XSETREF(self->prop_set, Py_XNewRef(fset)); |
1853 | 951 | Py_XSETREF(self->prop_del, Py_XNewRef(fdel)); |
1854 | 951 | Py_XSETREF(self->prop_doc, NULL); |
1855 | 951 | Py_XSETREF(self->prop_name, NULL); |
1856 | | |
1857 | 951 | self->getter_doc = 0; |
1858 | 951 | PyObject *prop_doc = NULL; |
1859 | | |
1860 | 951 | if (doc != NULL && doc != Py_None) { |
1861 | 0 | prop_doc = Py_XNewRef(doc); |
1862 | 0 | } |
1863 | | /* if no docstring given and the getter has one, use that one */ |
1864 | 951 | else if (fget != NULL) { |
1865 | 951 | int rc = PyObject_GetOptionalAttr(fget, &_Py_ID(__doc__), &prop_doc); |
1866 | 951 | if (rc < 0) { |
1867 | 0 | return rc; |
1868 | 0 | } |
1869 | 951 | if (prop_doc == Py_None) { |
1870 | 622 | prop_doc = NULL; |
1871 | 622 | Py_DECREF(Py_None); |
1872 | 622 | } |
1873 | 951 | if (prop_doc != NULL){ |
1874 | 329 | self->getter_doc = 1; |
1875 | 329 | } |
1876 | 951 | } |
1877 | | |
1878 | | /* At this point `prop_doc` is either NULL or |
1879 | | a non-None object with incremented ref counter */ |
1880 | | |
1881 | 951 | if (Py_IS_TYPE(self, &PyProperty_Type)) { |
1882 | 951 | Py_XSETREF(self->prop_doc, prop_doc); |
1883 | 951 | } else { |
1884 | | /* If this is a property subclass, put __doc__ in the dict |
1885 | | or designated slot of the subclass instance instead, otherwise |
1886 | | it gets shadowed by __doc__ in the class's dict. */ |
1887 | |
|
1888 | 0 | if (prop_doc == NULL) { |
1889 | 0 | prop_doc = Py_NewRef(Py_None); |
1890 | 0 | } |
1891 | 0 | int err = PyObject_SetAttr( |
1892 | 0 | (PyObject *)self, &_Py_ID(__doc__), prop_doc); |
1893 | 0 | Py_DECREF(prop_doc); |
1894 | 0 | if (err < 0) { |
1895 | 0 | assert(PyErr_Occurred()); |
1896 | 0 | if (!self->getter_doc && |
1897 | 0 | PyErr_ExceptionMatches(PyExc_AttributeError)) |
1898 | 0 | { |
1899 | 0 | PyErr_Clear(); |
1900 | | // https://github.com/python/cpython/issues/98963#issuecomment-1574413319 |
1901 | | // Python silently dropped this doc assignment through 3.11. |
1902 | | // We preserve that behavior for backwards compatibility. |
1903 | | // |
1904 | | // If we ever want to deprecate this behavior, only raise a |
1905 | | // warning or error when proc_doc is not None so that |
1906 | | // property without a specific doc= still works. |
1907 | 0 | return 0; |
1908 | 0 | } else { |
1909 | 0 | return -1; |
1910 | 0 | } |
1911 | 0 | } |
1912 | 0 | } |
1913 | | |
1914 | 951 | return 0; |
1915 | 951 | } |
1916 | | |
1917 | | static PyObject * |
1918 | | property_get__name__(PyObject *op, void *Py_UNUSED(ignored)) |
1919 | 0 | { |
1920 | 0 | propertyobject *prop = _propertyobject_CAST(op); |
1921 | 0 | PyObject *name; |
1922 | 0 | if (property_name(prop, &name) < 0) { |
1923 | 0 | return NULL; |
1924 | 0 | } |
1925 | 0 | if (name == NULL) { |
1926 | 0 | PyErr_SetString(PyExc_AttributeError, |
1927 | 0 | "'property' object has no attribute '__name__'"); |
1928 | 0 | } |
1929 | 0 | return name; |
1930 | 0 | } |
1931 | | |
1932 | | static int |
1933 | | property_set__name__(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) |
1934 | 0 | { |
1935 | 0 | propertyobject *prop = _propertyobject_CAST(op); |
1936 | 0 | Py_XSETREF(prop->prop_name, Py_XNewRef(value)); |
1937 | 0 | return 0; |
1938 | 0 | } |
1939 | | |
1940 | | static PyObject * |
1941 | | property_get___isabstractmethod__(PyObject *op, void *closure) |
1942 | 44 | { |
1943 | 44 | propertyobject *prop = _propertyobject_CAST(op); |
1944 | 44 | int res = _PyObject_IsAbstract(prop->prop_get); |
1945 | 44 | if (res == -1) { |
1946 | 0 | return NULL; |
1947 | 0 | } |
1948 | 44 | else if (res) { |
1949 | 0 | Py_RETURN_TRUE; |
1950 | 0 | } |
1951 | | |
1952 | 44 | res = _PyObject_IsAbstract(prop->prop_set); |
1953 | 44 | if (res == -1) { |
1954 | 0 | return NULL; |
1955 | 0 | } |
1956 | 44 | else if (res) { |
1957 | 0 | Py_RETURN_TRUE; |
1958 | 0 | } |
1959 | | |
1960 | 44 | res = _PyObject_IsAbstract(prop->prop_del); |
1961 | 44 | if (res == -1) { |
1962 | 0 | return NULL; |
1963 | 0 | } |
1964 | 44 | else if (res) { |
1965 | 0 | Py_RETURN_TRUE; |
1966 | 0 | } |
1967 | 44 | Py_RETURN_FALSE; |
1968 | 44 | } |
1969 | | |
1970 | | static PyGetSetDef property_getsetlist[] = { |
1971 | | {"__name__", property_get__name__, property_set__name__, NULL, NULL}, |
1972 | | {"__isabstractmethod__", property_get___isabstractmethod__, NULL, |
1973 | | NULL, |
1974 | | NULL}, |
1975 | | {NULL} /* Sentinel */ |
1976 | | }; |
1977 | | |
1978 | | static int |
1979 | | property_traverse(PyObject *self, visitproc visit, void *arg) |
1980 | 582k | { |
1981 | 582k | propertyobject *pp = (propertyobject *)self; |
1982 | 582k | Py_VISIT(pp->prop_get); |
1983 | 582k | Py_VISIT(pp->prop_set); |
1984 | 582k | Py_VISIT(pp->prop_del); |
1985 | 582k | Py_VISIT(pp->prop_doc); |
1986 | 582k | Py_VISIT(pp->prop_name); |
1987 | 582k | return 0; |
1988 | 582k | } |
1989 | | |
1990 | | static int |
1991 | | property_clear(PyObject *self) |
1992 | 0 | { |
1993 | 0 | propertyobject *pp = (propertyobject *)self; |
1994 | 0 | Py_CLEAR(pp->prop_doc); |
1995 | 0 | return 0; |
1996 | 0 | } |
1997 | | |
1998 | | #include "clinic/descrobject.c.h" |
1999 | | |
2000 | | PyTypeObject PyDictProxy_Type = { |
2001 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
2002 | | "mappingproxy", /* tp_name */ |
2003 | | sizeof(mappingproxyobject), /* tp_basicsize */ |
2004 | | 0, /* tp_itemsize */ |
2005 | | /* methods */ |
2006 | | mappingproxy_dealloc, /* tp_dealloc */ |
2007 | | 0, /* tp_vectorcall_offset */ |
2008 | | 0, /* tp_getattr */ |
2009 | | 0, /* tp_setattr */ |
2010 | | 0, /* tp_as_async */ |
2011 | | mappingproxy_repr, /* tp_repr */ |
2012 | | &mappingproxy_as_number, /* tp_as_number */ |
2013 | | &mappingproxy_as_sequence, /* tp_as_sequence */ |
2014 | | &mappingproxy_as_mapping, /* tp_as_mapping */ |
2015 | | mappingproxy_hash, /* tp_hash */ |
2016 | | 0, /* tp_call */ |
2017 | | mappingproxy_str, /* tp_str */ |
2018 | | PyObject_GenericGetAttr, /* tp_getattro */ |
2019 | | 0, /* tp_setattro */ |
2020 | | 0, /* tp_as_buffer */ |
2021 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
2022 | | Py_TPFLAGS_MAPPING, /* tp_flags */ |
2023 | | mappingproxy_new__doc__, /* tp_doc */ |
2024 | | mappingproxy_traverse, /* tp_traverse */ |
2025 | | 0, /* tp_clear */ |
2026 | | mappingproxy_richcompare, /* tp_richcompare */ |
2027 | | 0, /* tp_weaklistoffset */ |
2028 | | mappingproxy_getiter, /* tp_iter */ |
2029 | | 0, /* tp_iternext */ |
2030 | | mappingproxy_methods, /* tp_methods */ |
2031 | | 0, /* tp_members */ |
2032 | | 0, /* tp_getset */ |
2033 | | 0, /* tp_base */ |
2034 | | 0, /* tp_dict */ |
2035 | | 0, /* tp_descr_get */ |
2036 | | 0, /* tp_descr_set */ |
2037 | | 0, /* tp_dictoffset */ |
2038 | | 0, /* tp_init */ |
2039 | | 0, /* tp_alloc */ |
2040 | | mappingproxy_new, /* tp_new */ |
2041 | | }; |
2042 | | |
2043 | | PyTypeObject PyProperty_Type = { |
2044 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
2045 | | "property", /* tp_name */ |
2046 | | sizeof(propertyobject), /* tp_basicsize */ |
2047 | | 0, /* tp_itemsize */ |
2048 | | /* methods */ |
2049 | | property_dealloc, /* tp_dealloc */ |
2050 | | 0, /* tp_vectorcall_offset */ |
2051 | | 0, /* tp_getattr */ |
2052 | | 0, /* tp_setattr */ |
2053 | | 0, /* tp_as_async */ |
2054 | | 0, /* tp_repr */ |
2055 | | 0, /* tp_as_number */ |
2056 | | 0, /* tp_as_sequence */ |
2057 | | 0, /* tp_as_mapping */ |
2058 | | 0, /* tp_hash */ |
2059 | | 0, /* tp_call */ |
2060 | | 0, /* tp_str */ |
2061 | | PyObject_GenericGetAttr, /* tp_getattro */ |
2062 | | 0, /* tp_setattro */ |
2063 | | 0, /* tp_as_buffer */ |
2064 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
2065 | | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
2066 | | property_init__doc__, /* tp_doc */ |
2067 | | property_traverse, /* tp_traverse */ |
2068 | | property_clear, /* tp_clear */ |
2069 | | 0, /* tp_richcompare */ |
2070 | | 0, /* tp_weaklistoffset */ |
2071 | | 0, /* tp_iter */ |
2072 | | 0, /* tp_iternext */ |
2073 | | property_methods, /* tp_methods */ |
2074 | | property_members, /* tp_members */ |
2075 | | property_getsetlist, /* tp_getset */ |
2076 | | 0, /* tp_base */ |
2077 | | 0, /* tp_dict */ |
2078 | | property_descr_get, /* tp_descr_get */ |
2079 | | property_descr_set, /* tp_descr_set */ |
2080 | | 0, /* tp_dictoffset */ |
2081 | | property_init, /* tp_init */ |
2082 | | PyType_GenericAlloc, /* tp_alloc */ |
2083 | | PyType_GenericNew, /* tp_new */ |
2084 | | PyObject_GC_Del, /* tp_free */ |
2085 | | }; |