/src/Python-3.8.3/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_object.h" |
5 | | #include "pycore_pystate.h" |
6 | | #include "pycore_tupleobject.h" |
7 | | #include "structmember.h" /* Why is this not included in Python.h? */ |
8 | | |
9 | | /*[clinic input] |
10 | | class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type" |
11 | | class property "propertyobject *" "&PyProperty_Type" |
12 | | [clinic start generated code]*/ |
13 | | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/ |
14 | | |
15 | | static void |
16 | | descr_dealloc(PyDescrObject *descr) |
17 | 86 | { |
18 | 86 | _PyObject_GC_UNTRACK(descr); |
19 | 86 | Py_XDECREF(descr->d_type); |
20 | 86 | Py_XDECREF(descr->d_name); |
21 | 86 | Py_XDECREF(descr->d_qualname); |
22 | 86 | PyObject_GC_Del(descr); |
23 | 86 | } |
24 | | |
25 | | static PyObject * |
26 | | descr_name(PyDescrObject *descr) |
27 | 0 | { |
28 | 0 | if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) |
29 | 0 | return descr->d_name; |
30 | 0 | return NULL; |
31 | 0 | } |
32 | | |
33 | | static PyObject * |
34 | | descr_repr(PyDescrObject *descr, const char *format) |
35 | 0 | { |
36 | 0 | PyObject *name = NULL; |
37 | 0 | if (descr->d_name != NULL && PyUnicode_Check(descr->d_name)) |
38 | 0 | name = descr->d_name; |
39 | |
|
40 | 0 | return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name); |
41 | 0 | } |
42 | | |
43 | | static PyObject * |
44 | | method_repr(PyMethodDescrObject *descr) |
45 | 0 | { |
46 | 0 | return descr_repr((PyDescrObject *)descr, |
47 | 0 | "<method '%V' of '%s' objects>"); |
48 | 0 | } |
49 | | |
50 | | static PyObject * |
51 | | member_repr(PyMemberDescrObject *descr) |
52 | 0 | { |
53 | 0 | return descr_repr((PyDescrObject *)descr, |
54 | 0 | "<member '%V' of '%s' objects>"); |
55 | 0 | } |
56 | | |
57 | | static PyObject * |
58 | | getset_repr(PyGetSetDescrObject *descr) |
59 | 0 | { |
60 | 0 | return descr_repr((PyDescrObject *)descr, |
61 | 0 | "<attribute '%V' of '%s' objects>"); |
62 | 0 | } |
63 | | |
64 | | static PyObject * |
65 | | wrapperdescr_repr(PyWrapperDescrObject *descr) |
66 | 0 | { |
67 | 0 | return descr_repr((PyDescrObject *)descr, |
68 | 0 | "<slot wrapper '%V' of '%s' objects>"); |
69 | 0 | } |
70 | | |
71 | | static int |
72 | | descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres) |
73 | 18.7k | { |
74 | 18.7k | if (obj == NULL) { |
75 | 270 | Py_INCREF(descr); |
76 | 270 | *pres = (PyObject *)descr; |
77 | 270 | return 1; |
78 | 270 | } |
79 | 18.5k | if (!PyObject_TypeCheck(obj, descr->d_type)) { |
80 | 0 | PyErr_Format(PyExc_TypeError, |
81 | 0 | "descriptor '%V' for '%.100s' objects " |
82 | 0 | "doesn't apply to a '%.100s' object", |
83 | 0 | descr_name((PyDescrObject *)descr), "?", |
84 | 0 | descr->d_type->tp_name, |
85 | 0 | obj->ob_type->tp_name); |
86 | 0 | *pres = NULL; |
87 | 0 | return 1; |
88 | 0 | } |
89 | 18.5k | return 0; |
90 | 18.5k | } |
91 | | |
92 | | static PyObject * |
93 | | classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) |
94 | 3.52k | { |
95 | | /* Ensure a valid type. Class methods ignore obj. */ |
96 | 3.52k | if (type == NULL) { |
97 | 0 | if (obj != NULL) |
98 | 0 | type = (PyObject *)obj->ob_type; |
99 | 0 | else { |
100 | | /* Wot - no type?! */ |
101 | 0 | PyErr_Format(PyExc_TypeError, |
102 | 0 | "descriptor '%V' for type '%.100s' " |
103 | 0 | "needs either an object or a type", |
104 | 0 | descr_name((PyDescrObject *)descr), "?", |
105 | 0 | PyDescr_TYPE(descr)->tp_name); |
106 | 0 | return NULL; |
107 | 0 | } |
108 | 0 | } |
109 | 3.52k | if (!PyType_Check(type)) { |
110 | 0 | PyErr_Format(PyExc_TypeError, |
111 | 0 | "descriptor '%V' for type '%.100s' " |
112 | 0 | "needs a type, not a '%.100s' as arg 2", |
113 | 0 | descr_name((PyDescrObject *)descr), "?", |
114 | 0 | PyDescr_TYPE(descr)->tp_name, |
115 | 0 | type->ob_type->tp_name); |
116 | 0 | return NULL; |
117 | 0 | } |
118 | 3.52k | if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) { |
119 | 0 | PyErr_Format(PyExc_TypeError, |
120 | 0 | "descriptor '%V' requires a subtype of '%.100s' " |
121 | 0 | "but received '%.100s'", |
122 | 0 | descr_name((PyDescrObject *)descr), "?", |
123 | 0 | PyDescr_TYPE(descr)->tp_name, |
124 | 0 | ((PyTypeObject *)type)->tp_name); |
125 | 0 | return NULL; |
126 | 0 | } |
127 | 3.52k | return PyCFunction_NewEx(descr->d_method, type, NULL); |
128 | 3.52k | } |
129 | | |
130 | | static PyObject * |
131 | | method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) |
132 | 5.39k | { |
133 | 5.39k | PyObject *res; |
134 | | |
135 | 5.39k | if (descr_check((PyDescrObject *)descr, obj, &res)) |
136 | 249 | return res; |
137 | 5.15k | return PyCFunction_NewEx(descr->d_method, obj, NULL); |
138 | 5.39k | } |
139 | | |
140 | | static PyObject * |
141 | | member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) |
142 | 6.09k | { |
143 | 6.09k | PyObject *res; |
144 | | |
145 | 6.09k | if (descr_check((PyDescrObject *)descr, obj, &res)) |
146 | 1 | return res; |
147 | | |
148 | 6.09k | if (descr->d_member->flags & READ_RESTRICTED) { |
149 | 1 | if (PySys_Audit("object.__getattr__", "Os", |
150 | 1 | obj ? obj : Py_None, descr->d_member->name) < 0) { |
151 | 0 | return NULL; |
152 | 0 | } |
153 | 1 | } |
154 | | |
155 | 6.09k | return PyMember_GetOne((char *)obj, descr->d_member); |
156 | 6.09k | } |
157 | | |
158 | | static PyObject * |
159 | | getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) |
160 | 6.89k | { |
161 | 6.89k | PyObject *res; |
162 | | |
163 | 6.89k | if (descr_check((PyDescrObject *)descr, obj, &res)) |
164 | 1 | return res; |
165 | 6.89k | if (descr->d_getset->get != NULL) |
166 | 6.89k | return descr->d_getset->get(obj, descr->d_getset->closure); |
167 | 0 | PyErr_Format(PyExc_AttributeError, |
168 | 0 | "attribute '%V' of '%.100s' objects is not readable", |
169 | 0 | descr_name((PyDescrObject *)descr), "?", |
170 | 0 | PyDescr_TYPE(descr)->tp_name); |
171 | 0 | return NULL; |
172 | 6.89k | } |
173 | | |
174 | | static PyObject * |
175 | | wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type) |
176 | 402 | { |
177 | 402 | PyObject *res; |
178 | | |
179 | 402 | if (descr_check((PyDescrObject *)descr, obj, &res)) |
180 | 19 | return res; |
181 | 383 | return PyWrapper_New((PyObject *)descr, obj); |
182 | 402 | } |
183 | | |
184 | | static int |
185 | | descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, |
186 | | int *pres) |
187 | 1.24k | { |
188 | 1.24k | assert(obj != NULL); |
189 | 1.24k | if (!PyObject_TypeCheck(obj, descr->d_type)) { |
190 | 0 | PyErr_Format(PyExc_TypeError, |
191 | 0 | "descriptor '%V' for '%.100s' objects " |
192 | 0 | "doesn't apply to a '%.100s' object", |
193 | 0 | descr_name(descr), "?", |
194 | 0 | descr->d_type->tp_name, |
195 | 0 | obj->ob_type->tp_name); |
196 | 0 | *pres = -1; |
197 | 0 | return 1; |
198 | 0 | } |
199 | 1.24k | return 0; |
200 | 1.24k | } |
201 | | |
202 | | static int |
203 | | member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) |
204 | 474 | { |
205 | 474 | int res; |
206 | | |
207 | 474 | if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) |
208 | 0 | return res; |
209 | 474 | return PyMember_SetOne((char *)obj, descr->d_member, value); |
210 | 474 | } |
211 | | |
212 | | static int |
213 | | getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) |
214 | 774 | { |
215 | 774 | int res; |
216 | | |
217 | 774 | if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) |
218 | 0 | return res; |
219 | 774 | if (descr->d_getset->set != NULL) |
220 | 774 | return descr->d_getset->set(obj, value, |
221 | 774 | descr->d_getset->closure); |
222 | 0 | PyErr_Format(PyExc_AttributeError, |
223 | 0 | "attribute '%V' of '%.100s' objects is not writable", |
224 | 0 | descr_name((PyDescrObject *)descr), "?", |
225 | 0 | PyDescr_TYPE(descr)->tp_name); |
226 | 0 | return -1; |
227 | 774 | } |
228 | | |
229 | | |
230 | | /* Vectorcall functions for each of the PyMethodDescr calling conventions. |
231 | | * |
232 | | * First, common helpers |
233 | | */ |
234 | | static const char * |
235 | 0 | get_name(PyObject *func) { |
236 | 0 | assert(PyObject_TypeCheck(func, &PyMethodDescr_Type)); |
237 | 0 | return ((PyMethodDescrObject *)func)->d_method->ml_name; |
238 | 0 | } |
239 | | |
240 | | typedef void (*funcptr)(void); |
241 | | |
242 | | static inline int |
243 | | method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) |
244 | 17.4k | { |
245 | 17.4k | assert(!PyErr_Occurred()); |
246 | 17.4k | assert(PyObject_TypeCheck(func, &PyMethodDescr_Type)); |
247 | 17.4k | if (nargs < 1) { |
248 | 0 | PyErr_Format(PyExc_TypeError, |
249 | 0 | "descriptor '%.200s' of '%.100s' " |
250 | 0 | "object needs an argument", |
251 | 0 | get_name(func), PyDescr_TYPE(func)->tp_name); |
252 | 0 | return -1; |
253 | 0 | } |
254 | 17.4k | PyObject *self = args[0]; |
255 | 17.4k | if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), |
256 | 17.4k | (PyObject *)PyDescr_TYPE(func))) |
257 | 0 | { |
258 | 0 | PyErr_Format(PyExc_TypeError, |
259 | 0 | "descriptor '%.200s' for '%.100s' objects " |
260 | 0 | "doesn't apply to a '%.100s' object", |
261 | 0 | get_name(func), PyDescr_TYPE(func)->tp_name, |
262 | 0 | Py_TYPE(self)->tp_name); |
263 | 0 | return -1; |
264 | 0 | } |
265 | 17.4k | if (kwnames && PyTuple_GET_SIZE(kwnames)) { |
266 | 0 | PyErr_Format(PyExc_TypeError, |
267 | 0 | "%.200s() takes no keyword arguments", get_name(func)); |
268 | 0 | return -1; |
269 | 0 | } |
270 | 17.4k | return 0; |
271 | 17.4k | } |
272 | | |
273 | | static inline funcptr |
274 | | method_enter_call(PyObject *func) |
275 | 17.4k | { |
276 | 17.4k | if (Py_EnterRecursiveCall(" while calling a Python object")) { |
277 | 0 | return NULL; |
278 | 0 | } |
279 | 17.4k | return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth; |
280 | 17.4k | } |
281 | | |
282 | | /* Now the actual vectorcall functions */ |
283 | | static PyObject * |
284 | | method_vectorcall_VARARGS( |
285 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
286 | 1.16k | { |
287 | 1.16k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
288 | 1.16k | if (method_check_args(func, args, nargs, kwnames)) { |
289 | 0 | return NULL; |
290 | 0 | } |
291 | 1.16k | PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); |
292 | 1.16k | if (argstuple == NULL) { |
293 | 0 | return NULL; |
294 | 0 | } |
295 | 1.16k | PyCFunction meth = (PyCFunction)method_enter_call(func); |
296 | 1.16k | if (meth == NULL) { |
297 | 0 | Py_DECREF(argstuple); |
298 | 0 | return NULL; |
299 | 0 | } |
300 | 1.16k | PyObject *result = meth(args[0], argstuple); |
301 | 1.16k | Py_DECREF(argstuple); |
302 | 1.16k | Py_LeaveRecursiveCall(); |
303 | 1.16k | return result; |
304 | 1.16k | } |
305 | | |
306 | | static PyObject * |
307 | | method_vectorcall_VARARGS_KEYWORDS( |
308 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
309 | 290 | { |
310 | 290 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
311 | 290 | if (method_check_args(func, args, nargs, NULL)) { |
312 | 0 | return NULL; |
313 | 0 | } |
314 | 290 | PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); |
315 | 290 | if (argstuple == NULL) { |
316 | 0 | return NULL; |
317 | 0 | } |
318 | 290 | PyObject *result = NULL; |
319 | | /* Create a temporary dict for keyword arguments */ |
320 | 290 | PyObject *kwdict = NULL; |
321 | 290 | if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) { |
322 | 0 | kwdict = _PyStack_AsDict(args + nargs, kwnames); |
323 | 0 | if (kwdict == NULL) { |
324 | 0 | goto exit; |
325 | 0 | } |
326 | 0 | } |
327 | 290 | PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords) |
328 | 290 | method_enter_call(func); |
329 | 290 | if (meth == NULL) { |
330 | 0 | goto exit; |
331 | 0 | } |
332 | 290 | result = meth(args[0], argstuple, kwdict); |
333 | 290 | Py_LeaveRecursiveCall(); |
334 | 290 | exit: |
335 | 290 | Py_DECREF(argstuple); |
336 | 290 | Py_XDECREF(kwdict); |
337 | 290 | return result; |
338 | 290 | } |
339 | | |
340 | | static PyObject * |
341 | | method_vectorcall_FASTCALL( |
342 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
343 | 5.45k | { |
344 | 5.45k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
345 | 5.45k | if (method_check_args(func, args, nargs, kwnames)) { |
346 | 0 | return NULL; |
347 | 0 | } |
348 | 5.45k | _PyCFunctionFast meth = (_PyCFunctionFast) |
349 | 5.45k | method_enter_call(func); |
350 | 5.45k | if (meth == NULL) { |
351 | 0 | return NULL; |
352 | 0 | } |
353 | 5.45k | PyObject *result = meth(args[0], args+1, nargs-1); |
354 | 5.45k | Py_LeaveRecursiveCall(); |
355 | 5.45k | return result; |
356 | 5.45k | } |
357 | | |
358 | | static PyObject * |
359 | | method_vectorcall_FASTCALL_KEYWORDS( |
360 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
361 | 288 | { |
362 | 288 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
363 | 288 | if (method_check_args(func, args, nargs, NULL)) { |
364 | 0 | return NULL; |
365 | 0 | } |
366 | 288 | _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) |
367 | 288 | method_enter_call(func); |
368 | 288 | if (meth == NULL) { |
369 | 0 | return NULL; |
370 | 0 | } |
371 | 288 | PyObject *result = meth(args[0], args+1, nargs-1, kwnames); |
372 | 288 | Py_LeaveRecursiveCall(); |
373 | 288 | return result; |
374 | 288 | } |
375 | | |
376 | | static PyObject * |
377 | | method_vectorcall_NOARGS( |
378 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
379 | 3.14k | { |
380 | 3.14k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
381 | 3.14k | if (method_check_args(func, args, nargs, kwnames)) { |
382 | 0 | return NULL; |
383 | 0 | } |
384 | 3.14k | if (nargs != 1) { |
385 | 0 | PyErr_Format(PyExc_TypeError, |
386 | 0 | "%.200s() takes no arguments (%zd given)", get_name(func), nargs-1); |
387 | 0 | return NULL; |
388 | 0 | } |
389 | 3.14k | PyCFunction meth = (PyCFunction)method_enter_call(func); |
390 | 3.14k | if (meth == NULL) { |
391 | 0 | return NULL; |
392 | 0 | } |
393 | 3.14k | PyObject *result = meth(args[0], NULL); |
394 | 3.14k | Py_LeaveRecursiveCall(); |
395 | 3.14k | return result; |
396 | 3.14k | } |
397 | | |
398 | | static PyObject * |
399 | | method_vectorcall_O( |
400 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
401 | 7.15k | { |
402 | 7.15k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
403 | 7.15k | if (method_check_args(func, args, nargs, kwnames)) { |
404 | 0 | return NULL; |
405 | 0 | } |
406 | 7.15k | if (nargs != 2) { |
407 | 0 | PyErr_Format(PyExc_TypeError, |
408 | 0 | "%.200s() takes exactly one argument (%zd given)", |
409 | 0 | get_name(func), nargs-1); |
410 | 0 | return NULL; |
411 | 0 | } |
412 | 7.15k | PyCFunction meth = (PyCFunction)method_enter_call(func); |
413 | 7.15k | if (meth == NULL) { |
414 | 0 | return NULL; |
415 | 0 | } |
416 | 7.15k | PyObject *result = meth(args[0], args[1]); |
417 | 7.15k | Py_LeaveRecursiveCall(); |
418 | 7.15k | return result; |
419 | 7.15k | } |
420 | | |
421 | | |
422 | | static PyObject * |
423 | | classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, |
424 | | PyObject *kwds) |
425 | 0 | { |
426 | 0 | Py_ssize_t argc; |
427 | 0 | PyObject *self, *result; |
428 | | |
429 | | /* Make sure that the first argument is acceptable as 'self' */ |
430 | 0 | assert(PyTuple_Check(args)); |
431 | 0 | argc = PyTuple_GET_SIZE(args); |
432 | 0 | if (argc < 1) { |
433 | 0 | PyErr_Format(PyExc_TypeError, |
434 | 0 | "descriptor '%V' of '%.100s' " |
435 | 0 | "object needs an argument", |
436 | 0 | descr_name((PyDescrObject *)descr), "?", |
437 | 0 | PyDescr_TYPE(descr)->tp_name); |
438 | 0 | return NULL; |
439 | 0 | } |
440 | 0 | self = PyTuple_GET_ITEM(args, 0); |
441 | 0 | if (!PyType_Check(self)) { |
442 | 0 | PyErr_Format(PyExc_TypeError, |
443 | 0 | "descriptor '%V' requires a type " |
444 | 0 | "but received a '%.100s' instance", |
445 | 0 | descr_name((PyDescrObject *)descr), "?", |
446 | 0 | self->ob_type->tp_name); |
447 | 0 | return NULL; |
448 | 0 | } |
449 | 0 | if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) { |
450 | 0 | PyErr_Format(PyExc_TypeError, |
451 | 0 | "descriptor '%V' requires a subtype of '%.100s' " |
452 | 0 | "but received '%.100s'", |
453 | 0 | descr_name((PyDescrObject *)descr), "?", |
454 | 0 | PyDescr_TYPE(descr)->tp_name, |
455 | 0 | ((PyTypeObject*)self)->tp_name); |
456 | 0 | return NULL; |
457 | 0 | } |
458 | | |
459 | 0 | result = _PyMethodDef_RawFastCallDict(descr->d_method, self, |
460 | 0 | &_PyTuple_ITEMS(args)[1], argc - 1, |
461 | 0 | kwds); |
462 | 0 | result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL); |
463 | 0 | return result; |
464 | 0 | } |
465 | | |
466 | | Py_LOCAL_INLINE(PyObject *) |
467 | | wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self, |
468 | | PyObject *args, PyObject *kwds) |
469 | 397 | { |
470 | 397 | wrapperfunc wrapper = descr->d_base->wrapper; |
471 | | |
472 | 397 | if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) { |
473 | 23 | wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper; |
474 | 23 | return (*wk)(self, args, descr->d_wrapped, kwds); |
475 | 23 | } |
476 | | |
477 | 374 | if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) { |
478 | 0 | PyErr_Format(PyExc_TypeError, |
479 | 0 | "wrapper %s() takes no keyword arguments", |
480 | 0 | descr->d_base->name); |
481 | 0 | return NULL; |
482 | 0 | } |
483 | 374 | return (*wrapper)(self, args, descr->d_wrapped); |
484 | 374 | } |
485 | | |
486 | | static PyObject * |
487 | | wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) |
488 | 17 | { |
489 | 17 | Py_ssize_t argc; |
490 | 17 | PyObject *self, *result; |
491 | | |
492 | | /* Make sure that the first argument is acceptable as 'self' */ |
493 | 17 | assert(PyTuple_Check(args)); |
494 | 17 | argc = PyTuple_GET_SIZE(args); |
495 | 17 | if (argc < 1) { |
496 | 0 | PyErr_Format(PyExc_TypeError, |
497 | 0 | "descriptor '%V' of '%.100s' " |
498 | 0 | "object needs an argument", |
499 | 0 | descr_name((PyDescrObject *)descr), "?", |
500 | 0 | PyDescr_TYPE(descr)->tp_name); |
501 | 0 | return NULL; |
502 | 0 | } |
503 | 17 | self = PyTuple_GET_ITEM(args, 0); |
504 | 17 | if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), |
505 | 17 | (PyObject *)PyDescr_TYPE(descr))) { |
506 | 0 | PyErr_Format(PyExc_TypeError, |
507 | 0 | "descriptor '%V' " |
508 | 0 | "requires a '%.100s' object " |
509 | 0 | "but received a '%.100s'", |
510 | 0 | descr_name((PyDescrObject *)descr), "?", |
511 | 0 | PyDescr_TYPE(descr)->tp_name, |
512 | 0 | self->ob_type->tp_name); |
513 | 0 | return NULL; |
514 | 0 | } |
515 | | |
516 | 17 | args = PyTuple_GetSlice(args, 1, argc); |
517 | 17 | if (args == NULL) { |
518 | 0 | return NULL; |
519 | 0 | } |
520 | 17 | result = wrapperdescr_raw_call(descr, self, args, kwds); |
521 | 17 | Py_DECREF(args); |
522 | 17 | return result; |
523 | 17 | } |
524 | | |
525 | | |
526 | | static PyObject * |
527 | | method_get_doc(PyMethodDescrObject *descr, void *closure) |
528 | 0 | { |
529 | 0 | return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); |
530 | 0 | } |
531 | | |
532 | | static PyObject * |
533 | | method_get_text_signature(PyMethodDescrObject *descr, void *closure) |
534 | 0 | { |
535 | 0 | return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); |
536 | 0 | } |
537 | | |
538 | | static PyObject * |
539 | | calculate_qualname(PyDescrObject *descr) |
540 | 0 | { |
541 | 0 | PyObject *type_qualname, *res; |
542 | 0 | _Py_IDENTIFIER(__qualname__); |
543 | |
|
544 | 0 | if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) { |
545 | 0 | PyErr_SetString(PyExc_TypeError, |
546 | 0 | "<descriptor>.__name__ is not a unicode object"); |
547 | 0 | return NULL; |
548 | 0 | } |
549 | | |
550 | 0 | type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type, |
551 | 0 | &PyId___qualname__); |
552 | 0 | if (type_qualname == NULL) |
553 | 0 | return NULL; |
554 | | |
555 | 0 | if (!PyUnicode_Check(type_qualname)) { |
556 | 0 | PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__." |
557 | 0 | "__qualname__ is not a unicode object"); |
558 | 0 | Py_XDECREF(type_qualname); |
559 | 0 | return NULL; |
560 | 0 | } |
561 | | |
562 | 0 | res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name); |
563 | 0 | Py_DECREF(type_qualname); |
564 | 0 | return res; |
565 | 0 | } |
566 | | |
567 | | static PyObject * |
568 | | descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored)) |
569 | 0 | { |
570 | 0 | if (descr->d_qualname == NULL) |
571 | 0 | descr->d_qualname = calculate_qualname(descr); |
572 | 0 | Py_XINCREF(descr->d_qualname); |
573 | 0 | return descr->d_qualname; |
574 | 0 | } |
575 | | |
576 | | static PyObject * |
577 | | descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored)) |
578 | 0 | { |
579 | 0 | _Py_IDENTIFIER(getattr); |
580 | 0 | return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr), |
581 | 0 | PyDescr_TYPE(descr), PyDescr_NAME(descr)); |
582 | 0 | } |
583 | | |
584 | | static PyMethodDef descr_methods[] = { |
585 | | {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL}, |
586 | | {NULL, NULL} |
587 | | }; |
588 | | |
589 | | static PyMemberDef descr_members[] = { |
590 | | {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY}, |
591 | | {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY}, |
592 | | {0} |
593 | | }; |
594 | | |
595 | | static PyGetSetDef method_getset[] = { |
596 | | {"__doc__", (getter)method_get_doc}, |
597 | | {"__qualname__", (getter)descr_get_qualname}, |
598 | | {"__text_signature__", (getter)method_get_text_signature}, |
599 | | {0} |
600 | | }; |
601 | | |
602 | | static PyObject * |
603 | | member_get_doc(PyMemberDescrObject *descr, void *closure) |
604 | 0 | { |
605 | 0 | if (descr->d_member->doc == NULL) { |
606 | 0 | Py_RETURN_NONE; |
607 | 0 | } |
608 | 0 | return PyUnicode_FromString(descr->d_member->doc); |
609 | 0 | } |
610 | | |
611 | | static PyGetSetDef member_getset[] = { |
612 | | {"__doc__", (getter)member_get_doc}, |
613 | | {"__qualname__", (getter)descr_get_qualname}, |
614 | | {0} |
615 | | }; |
616 | | |
617 | | static PyObject * |
618 | | getset_get_doc(PyGetSetDescrObject *descr, void *closure) |
619 | 0 | { |
620 | 0 | if (descr->d_getset->doc == NULL) { |
621 | 0 | Py_RETURN_NONE; |
622 | 0 | } |
623 | 0 | return PyUnicode_FromString(descr->d_getset->doc); |
624 | 0 | } |
625 | | |
626 | | static PyGetSetDef getset_getset[] = { |
627 | | {"__doc__", (getter)getset_get_doc}, |
628 | | {"__qualname__", (getter)descr_get_qualname}, |
629 | | {0} |
630 | | }; |
631 | | |
632 | | static PyObject * |
633 | | wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) |
634 | 0 | { |
635 | 0 | return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc); |
636 | 0 | } |
637 | | |
638 | | static PyObject * |
639 | | wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure) |
640 | 0 | { |
641 | 0 | return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc); |
642 | 0 | } |
643 | | |
644 | | static PyGetSetDef wrapperdescr_getset[] = { |
645 | | {"__doc__", (getter)wrapperdescr_get_doc}, |
646 | | {"__qualname__", (getter)descr_get_qualname}, |
647 | | {"__text_signature__", (getter)wrapperdescr_get_text_signature}, |
648 | | {0} |
649 | | }; |
650 | | |
651 | | static int |
652 | | descr_traverse(PyObject *self, visitproc visit, void *arg) |
653 | 59.2k | { |
654 | 59.2k | PyDescrObject *descr = (PyDescrObject *)self; |
655 | 59.2k | Py_VISIT(descr->d_type); |
656 | 59.2k | return 0; |
657 | 59.2k | } |
658 | | |
659 | | PyTypeObject PyMethodDescr_Type = { |
660 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
661 | | "method_descriptor", |
662 | | sizeof(PyMethodDescrObject), |
663 | | 0, |
664 | | (destructor)descr_dealloc, /* tp_dealloc */ |
665 | | offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */ |
666 | | 0, /* tp_getattr */ |
667 | | 0, /* tp_setattr */ |
668 | | 0, /* tp_as_async */ |
669 | | (reprfunc)method_repr, /* tp_repr */ |
670 | | 0, /* tp_as_number */ |
671 | | 0, /* tp_as_sequence */ |
672 | | 0, /* tp_as_mapping */ |
673 | | 0, /* tp_hash */ |
674 | | PyVectorcall_Call, /* tp_call */ |
675 | | 0, /* tp_str */ |
676 | | PyObject_GenericGetAttr, /* tp_getattro */ |
677 | | 0, /* tp_setattro */ |
678 | | 0, /* tp_as_buffer */ |
679 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
680 | | _Py_TPFLAGS_HAVE_VECTORCALL | |
681 | | Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */ |
682 | | 0, /* tp_doc */ |
683 | | descr_traverse, /* tp_traverse */ |
684 | | 0, /* tp_clear */ |
685 | | 0, /* tp_richcompare */ |
686 | | 0, /* tp_weaklistoffset */ |
687 | | 0, /* tp_iter */ |
688 | | 0, /* tp_iternext */ |
689 | | descr_methods, /* tp_methods */ |
690 | | descr_members, /* tp_members */ |
691 | | method_getset, /* tp_getset */ |
692 | | 0, /* tp_base */ |
693 | | 0, /* tp_dict */ |
694 | | (descrgetfunc)method_get, /* tp_descr_get */ |
695 | | 0, /* tp_descr_set */ |
696 | | }; |
697 | | |
698 | | /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */ |
699 | | PyTypeObject PyClassMethodDescr_Type = { |
700 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
701 | | "classmethod_descriptor", |
702 | | sizeof(PyMethodDescrObject), |
703 | | 0, |
704 | | (destructor)descr_dealloc, /* tp_dealloc */ |
705 | | 0, /* tp_vectorcall_offset */ |
706 | | 0, /* tp_getattr */ |
707 | | 0, /* tp_setattr */ |
708 | | 0, /* tp_as_async */ |
709 | | (reprfunc)method_repr, /* tp_repr */ |
710 | | 0, /* tp_as_number */ |
711 | | 0, /* tp_as_sequence */ |
712 | | 0, /* tp_as_mapping */ |
713 | | 0, /* tp_hash */ |
714 | | (ternaryfunc)classmethoddescr_call, /* tp_call */ |
715 | | 0, /* tp_str */ |
716 | | PyObject_GenericGetAttr, /* tp_getattro */ |
717 | | 0, /* tp_setattro */ |
718 | | 0, /* tp_as_buffer */ |
719 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
720 | | 0, /* tp_doc */ |
721 | | descr_traverse, /* tp_traverse */ |
722 | | 0, /* tp_clear */ |
723 | | 0, /* tp_richcompare */ |
724 | | 0, /* tp_weaklistoffset */ |
725 | | 0, /* tp_iter */ |
726 | | 0, /* tp_iternext */ |
727 | | descr_methods, /* tp_methods */ |
728 | | descr_members, /* tp_members */ |
729 | | method_getset, /* tp_getset */ |
730 | | 0, /* tp_base */ |
731 | | 0, /* tp_dict */ |
732 | | (descrgetfunc)classmethod_get, /* tp_descr_get */ |
733 | | 0, /* tp_descr_set */ |
734 | | }; |
735 | | |
736 | | PyTypeObject PyMemberDescr_Type = { |
737 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
738 | | "member_descriptor", |
739 | | sizeof(PyMemberDescrObject), |
740 | | 0, |
741 | | (destructor)descr_dealloc, /* tp_dealloc */ |
742 | | 0, /* tp_vectorcall_offset */ |
743 | | 0, /* tp_getattr */ |
744 | | 0, /* tp_setattr */ |
745 | | 0, /* tp_as_async */ |
746 | | (reprfunc)member_repr, /* tp_repr */ |
747 | | 0, /* tp_as_number */ |
748 | | 0, /* tp_as_sequence */ |
749 | | 0, /* tp_as_mapping */ |
750 | | 0, /* tp_hash */ |
751 | | 0, /* tp_call */ |
752 | | 0, /* tp_str */ |
753 | | PyObject_GenericGetAttr, /* tp_getattro */ |
754 | | 0, /* tp_setattro */ |
755 | | 0, /* tp_as_buffer */ |
756 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
757 | | 0, /* tp_doc */ |
758 | | descr_traverse, /* tp_traverse */ |
759 | | 0, /* tp_clear */ |
760 | | 0, /* tp_richcompare */ |
761 | | 0, /* tp_weaklistoffset */ |
762 | | 0, /* tp_iter */ |
763 | | 0, /* tp_iternext */ |
764 | | descr_methods, /* tp_methods */ |
765 | | descr_members, /* tp_members */ |
766 | | member_getset, /* tp_getset */ |
767 | | 0, /* tp_base */ |
768 | | 0, /* tp_dict */ |
769 | | (descrgetfunc)member_get, /* tp_descr_get */ |
770 | | (descrsetfunc)member_set, /* tp_descr_set */ |
771 | | }; |
772 | | |
773 | | PyTypeObject PyGetSetDescr_Type = { |
774 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
775 | | "getset_descriptor", |
776 | | sizeof(PyGetSetDescrObject), |
777 | | 0, |
778 | | (destructor)descr_dealloc, /* tp_dealloc */ |
779 | | 0, /* tp_vectorcall_offset */ |
780 | | 0, /* tp_getattr */ |
781 | | 0, /* tp_setattr */ |
782 | | 0, /* tp_as_async */ |
783 | | (reprfunc)getset_repr, /* tp_repr */ |
784 | | 0, /* tp_as_number */ |
785 | | 0, /* tp_as_sequence */ |
786 | | 0, /* tp_as_mapping */ |
787 | | 0, /* tp_hash */ |
788 | | 0, /* tp_call */ |
789 | | 0, /* tp_str */ |
790 | | PyObject_GenericGetAttr, /* tp_getattro */ |
791 | | 0, /* tp_setattro */ |
792 | | 0, /* tp_as_buffer */ |
793 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
794 | | 0, /* tp_doc */ |
795 | | descr_traverse, /* tp_traverse */ |
796 | | 0, /* tp_clear */ |
797 | | 0, /* tp_richcompare */ |
798 | | 0, /* tp_weaklistoffset */ |
799 | | 0, /* tp_iter */ |
800 | | 0, /* tp_iternext */ |
801 | | 0, /* tp_methods */ |
802 | | descr_members, /* tp_members */ |
803 | | getset_getset, /* tp_getset */ |
804 | | 0, /* tp_base */ |
805 | | 0, /* tp_dict */ |
806 | | (descrgetfunc)getset_get, /* tp_descr_get */ |
807 | | (descrsetfunc)getset_set, /* tp_descr_set */ |
808 | | }; |
809 | | |
810 | | PyTypeObject PyWrapperDescr_Type = { |
811 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
812 | | "wrapper_descriptor", |
813 | | sizeof(PyWrapperDescrObject), |
814 | | 0, |
815 | | (destructor)descr_dealloc, /* tp_dealloc */ |
816 | | 0, /* tp_vectorcall_offset */ |
817 | | 0, /* tp_getattr */ |
818 | | 0, /* tp_setattr */ |
819 | | 0, /* tp_as_async */ |
820 | | (reprfunc)wrapperdescr_repr, /* tp_repr */ |
821 | | 0, /* tp_as_number */ |
822 | | 0, /* tp_as_sequence */ |
823 | | 0, /* tp_as_mapping */ |
824 | | 0, /* tp_hash */ |
825 | | (ternaryfunc)wrapperdescr_call, /* tp_call */ |
826 | | 0, /* tp_str */ |
827 | | PyObject_GenericGetAttr, /* tp_getattro */ |
828 | | 0, /* tp_setattro */ |
829 | | 0, /* tp_as_buffer */ |
830 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
831 | | Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */ |
832 | | 0, /* tp_doc */ |
833 | | descr_traverse, /* tp_traverse */ |
834 | | 0, /* tp_clear */ |
835 | | 0, /* tp_richcompare */ |
836 | | 0, /* tp_weaklistoffset */ |
837 | | 0, /* tp_iter */ |
838 | | 0, /* tp_iternext */ |
839 | | descr_methods, /* tp_methods */ |
840 | | descr_members, /* tp_members */ |
841 | | wrapperdescr_getset, /* tp_getset */ |
842 | | 0, /* tp_base */ |
843 | | 0, /* tp_dict */ |
844 | | (descrgetfunc)wrapperdescr_get, /* tp_descr_get */ |
845 | | 0, /* tp_descr_set */ |
846 | | }; |
847 | | |
848 | | static PyDescrObject * |
849 | | descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) |
850 | 28.8k | { |
851 | 28.8k | PyDescrObject *descr; |
852 | | |
853 | 28.8k | descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0); |
854 | 28.8k | if (descr != NULL) { |
855 | 28.8k | Py_XINCREF(type); |
856 | 28.8k | descr->d_type = type; |
857 | 28.8k | descr->d_name = PyUnicode_InternFromString(name); |
858 | 28.8k | if (descr->d_name == NULL) { |
859 | 0 | Py_DECREF(descr); |
860 | 0 | descr = NULL; |
861 | 0 | } |
862 | 28.8k | else { |
863 | 28.8k | descr->d_qualname = NULL; |
864 | 28.8k | } |
865 | 28.8k | } |
866 | 28.8k | return descr; |
867 | 28.8k | } |
868 | | |
869 | | PyObject * |
870 | | PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) |
871 | 8.82k | { |
872 | | /* Figure out correct vectorcall function to use */ |
873 | 8.82k | vectorcallfunc vectorcall; |
874 | 8.82k | switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS)) |
875 | 8.82k | { |
876 | 1.17k | case METH_VARARGS: |
877 | 1.17k | vectorcall = method_vectorcall_VARARGS; |
878 | 1.17k | break; |
879 | 154 | case METH_VARARGS | METH_KEYWORDS: |
880 | 154 | vectorcall = method_vectorcall_VARARGS_KEYWORDS; |
881 | 154 | break; |
882 | 958 | case METH_FASTCALL: |
883 | 958 | vectorcall = method_vectorcall_FASTCALL; |
884 | 958 | break; |
885 | 460 | case METH_FASTCALL | METH_KEYWORDS: |
886 | 460 | vectorcall = method_vectorcall_FASTCALL_KEYWORDS; |
887 | 460 | break; |
888 | 4.60k | case METH_NOARGS: |
889 | 4.60k | vectorcall = method_vectorcall_NOARGS; |
890 | 4.60k | break; |
891 | 1.46k | case METH_O: |
892 | 1.46k | vectorcall = method_vectorcall_O; |
893 | 1.46k | break; |
894 | 0 | default: |
895 | 0 | PyErr_Format(PyExc_SystemError, |
896 | 0 | "%s() method: bad call flags", method->ml_name); |
897 | 0 | return NULL; |
898 | 8.82k | } |
899 | | |
900 | 8.82k | PyMethodDescrObject *descr; |
901 | | |
902 | 8.82k | descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type, |
903 | 8.82k | type, method->ml_name); |
904 | 8.82k | if (descr != NULL) { |
905 | 8.82k | descr->d_method = method; |
906 | 8.82k | descr->vectorcall = vectorcall; |
907 | 8.82k | } |
908 | 8.82k | return (PyObject *)descr; |
909 | 8.82k | } |
910 | | |
911 | | PyObject * |
912 | | PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method) |
913 | 183 | { |
914 | 183 | PyMethodDescrObject *descr; |
915 | | |
916 | 183 | descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type, |
917 | 183 | type, method->ml_name); |
918 | 183 | if (descr != NULL) |
919 | 183 | descr->d_method = method; |
920 | 183 | return (PyObject *)descr; |
921 | 183 | } |
922 | | |
923 | | PyObject * |
924 | | PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member) |
925 | 3.45k | { |
926 | 3.45k | PyMemberDescrObject *descr; |
927 | | |
928 | 3.45k | descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type, |
929 | 3.45k | type, member->name); |
930 | 3.45k | if (descr != NULL) |
931 | 3.45k | descr->d_member = member; |
932 | 3.45k | return (PyObject *)descr; |
933 | 3.45k | } |
934 | | |
935 | | PyObject * |
936 | | PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset) |
937 | 2.90k | { |
938 | 2.90k | PyGetSetDescrObject *descr; |
939 | | |
940 | 2.90k | descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type, |
941 | 2.90k | type, getset->name); |
942 | 2.90k | if (descr != NULL) |
943 | 2.90k | descr->d_getset = getset; |
944 | 2.90k | return (PyObject *)descr; |
945 | 2.90k | } |
946 | | |
947 | | PyObject * |
948 | | PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) |
949 | 13.4k | { |
950 | 13.4k | PyWrapperDescrObject *descr; |
951 | | |
952 | 13.4k | descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type, |
953 | 13.4k | type, base->name); |
954 | 13.4k | if (descr != NULL) { |
955 | 13.4k | descr->d_base = base; |
956 | 13.4k | descr->d_wrapped = wrapped; |
957 | 13.4k | } |
958 | 13.4k | return (PyObject *)descr; |
959 | 13.4k | } |
960 | | |
961 | | |
962 | | /* --- mappingproxy: read-only proxy for mappings --- */ |
963 | | |
964 | | /* This has no reason to be in this file except that adding new files is a |
965 | | bit of a pain */ |
966 | | |
967 | | typedef struct { |
968 | | PyObject_HEAD |
969 | | PyObject *mapping; |
970 | | } mappingproxyobject; |
971 | | |
972 | | static Py_ssize_t |
973 | | mappingproxy_len(mappingproxyobject *pp) |
974 | 0 | { |
975 | 0 | return PyObject_Size(pp->mapping); |
976 | 0 | } |
977 | | |
978 | | static PyObject * |
979 | | mappingproxy_getitem(mappingproxyobject *pp, PyObject *key) |
980 | 578 | { |
981 | 578 | return PyObject_GetItem(pp->mapping, key); |
982 | 578 | } |
983 | | |
984 | | static PyMappingMethods mappingproxy_as_mapping = { |
985 | | (lenfunc)mappingproxy_len, /* mp_length */ |
986 | | (binaryfunc)mappingproxy_getitem, /* mp_subscript */ |
987 | | 0, /* mp_ass_subscript */ |
988 | | }; |
989 | | |
990 | | static int |
991 | | mappingproxy_contains(mappingproxyobject *pp, PyObject *key) |
992 | 576 | { |
993 | 576 | if (PyDict_CheckExact(pp->mapping)) |
994 | 576 | return PyDict_Contains(pp->mapping, key); |
995 | 0 | else |
996 | 0 | return PySequence_Contains(pp->mapping, key); |
997 | 576 | } |
998 | | |
999 | | static PySequenceMethods mappingproxy_as_sequence = { |
1000 | | 0, /* sq_length */ |
1001 | | 0, /* sq_concat */ |
1002 | | 0, /* sq_repeat */ |
1003 | | 0, /* sq_item */ |
1004 | | 0, /* sq_slice */ |
1005 | | 0, /* sq_ass_item */ |
1006 | | 0, /* sq_ass_slice */ |
1007 | | (objobjproc)mappingproxy_contains, /* sq_contains */ |
1008 | | 0, /* sq_inplace_concat */ |
1009 | | 0, /* sq_inplace_repeat */ |
1010 | | }; |
1011 | | |
1012 | | static PyObject * |
1013 | | mappingproxy_get(mappingproxyobject *pp, PyObject *args) |
1014 | 46 | { |
1015 | 46 | PyObject *key, *def = Py_None; |
1016 | 46 | _Py_IDENTIFIER(get); |
1017 | | |
1018 | 46 | if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) |
1019 | 0 | return NULL; |
1020 | 46 | return _PyObject_CallMethodIdObjArgs(pp->mapping, &PyId_get, |
1021 | 46 | key, def, NULL); |
1022 | 46 | } |
1023 | | |
1024 | | static PyObject * |
1025 | | mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) |
1026 | 1 | { |
1027 | 1 | _Py_IDENTIFIER(keys); |
1028 | 1 | return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL); |
1029 | 1 | } |
1030 | | |
1031 | | static PyObject * |
1032 | | mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) |
1033 | 0 | { |
1034 | 0 | _Py_IDENTIFIER(values); |
1035 | 0 | return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL); |
1036 | 0 | } |
1037 | | |
1038 | | static PyObject * |
1039 | | mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) |
1040 | 477 | { |
1041 | 477 | _Py_IDENTIFIER(items); |
1042 | 477 | return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL); |
1043 | 477 | } |
1044 | | |
1045 | | static PyObject * |
1046 | | mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) |
1047 | 0 | { |
1048 | 0 | _Py_IDENTIFIER(copy); |
1049 | 0 | return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL); |
1050 | 0 | } |
1051 | | |
1052 | | /* WARNING: mappingproxy methods must not give access |
1053 | | to the underlying mapping */ |
1054 | | |
1055 | | static PyMethodDef mappingproxy_methods[] = { |
1056 | | {"get", (PyCFunction)mappingproxy_get, METH_VARARGS, |
1057 | | PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." |
1058 | | " d defaults to None.")}, |
1059 | | {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS, |
1060 | | PyDoc_STR("D.keys() -> list of D's keys")}, |
1061 | | {"values", (PyCFunction)mappingproxy_values, METH_NOARGS, |
1062 | | PyDoc_STR("D.values() -> list of D's values")}, |
1063 | | {"items", (PyCFunction)mappingproxy_items, METH_NOARGS, |
1064 | | PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")}, |
1065 | | {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS, |
1066 | | PyDoc_STR("D.copy() -> a shallow copy of D")}, |
1067 | | {0} |
1068 | | }; |
1069 | | |
1070 | | static void |
1071 | | mappingproxy_dealloc(mappingproxyobject *pp) |
1072 | 1.67k | { |
1073 | 1.67k | _PyObject_GC_UNTRACK(pp); |
1074 | 1.67k | Py_DECREF(pp->mapping); |
1075 | 1.67k | PyObject_GC_Del(pp); |
1076 | 1.67k | } |
1077 | | |
1078 | | static PyObject * |
1079 | | mappingproxy_getiter(mappingproxyobject *pp) |
1080 | 0 | { |
1081 | 0 | return PyObject_GetIter(pp->mapping); |
1082 | 0 | } |
1083 | | |
1084 | | static PyObject * |
1085 | | mappingproxy_str(mappingproxyobject *pp) |
1086 | 0 | { |
1087 | 0 | return PyObject_Str(pp->mapping); |
1088 | 0 | } |
1089 | | |
1090 | | static PyObject * |
1091 | | mappingproxy_repr(mappingproxyobject *pp) |
1092 | 0 | { |
1093 | 0 | return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping); |
1094 | 0 | } |
1095 | | |
1096 | | static int |
1097 | | mappingproxy_traverse(PyObject *self, visitproc visit, void *arg) |
1098 | 0 | { |
1099 | 0 | mappingproxyobject *pp = (mappingproxyobject *)self; |
1100 | 0 | Py_VISIT(pp->mapping); |
1101 | 0 | return 0; |
1102 | 0 | } |
1103 | | |
1104 | | static PyObject * |
1105 | | mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op) |
1106 | 0 | { |
1107 | 0 | return PyObject_RichCompare(v->mapping, w, op); |
1108 | 0 | } |
1109 | | |
1110 | | static int |
1111 | | mappingproxy_check_mapping(PyObject *mapping) |
1112 | 1.67k | { |
1113 | 1.67k | if (!PyMapping_Check(mapping) |
1114 | 1.67k | || PyList_Check(mapping) |
1115 | 1.67k | || PyTuple_Check(mapping)) { |
1116 | 0 | PyErr_Format(PyExc_TypeError, |
1117 | 0 | "mappingproxy() argument must be a mapping, not %s", |
1118 | 0 | Py_TYPE(mapping)->tp_name); |
1119 | 0 | return -1; |
1120 | 0 | } |
1121 | 1.67k | return 0; |
1122 | 1.67k | } |
1123 | | |
1124 | | /*[clinic input] |
1125 | | @classmethod |
1126 | | mappingproxy.__new__ as mappingproxy_new |
1127 | | |
1128 | | mapping: object |
1129 | | |
1130 | | [clinic start generated code]*/ |
1131 | | |
1132 | | static PyObject * |
1133 | | mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping) |
1134 | | /*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/ |
1135 | 1 | { |
1136 | 1 | mappingproxyobject *mappingproxy; |
1137 | | |
1138 | 1 | if (mappingproxy_check_mapping(mapping) == -1) |
1139 | 0 | return NULL; |
1140 | | |
1141 | 1 | mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); |
1142 | 1 | if (mappingproxy == NULL) |
1143 | 0 | return NULL; |
1144 | 1 | Py_INCREF(mapping); |
1145 | 1 | mappingproxy->mapping = mapping; |
1146 | 1 | _PyObject_GC_TRACK(mappingproxy); |
1147 | 1 | return (PyObject *)mappingproxy; |
1148 | 1 | } |
1149 | | |
1150 | | PyObject * |
1151 | | PyDictProxy_New(PyObject *mapping) |
1152 | 1.67k | { |
1153 | 1.67k | mappingproxyobject *pp; |
1154 | | |
1155 | 1.67k | if (mappingproxy_check_mapping(mapping) == -1) |
1156 | 0 | return NULL; |
1157 | | |
1158 | 1.67k | pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); |
1159 | 1.67k | if (pp != NULL) { |
1160 | 1.67k | Py_INCREF(mapping); |
1161 | 1.67k | pp->mapping = mapping; |
1162 | 1.67k | _PyObject_GC_TRACK(pp); |
1163 | 1.67k | } |
1164 | 1.67k | return (PyObject *)pp; |
1165 | 1.67k | } |
1166 | | |
1167 | | |
1168 | | /* --- Wrapper object for "slot" methods --- */ |
1169 | | |
1170 | | /* This has no reason to be in this file except that adding new files is a |
1171 | | bit of a pain */ |
1172 | | |
1173 | | typedef struct { |
1174 | | PyObject_HEAD |
1175 | | PyWrapperDescrObject *descr; |
1176 | | PyObject *self; |
1177 | | } wrapperobject; |
1178 | | |
1179 | 0 | #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type) |
1180 | | |
1181 | | static void |
1182 | | wrapper_dealloc(wrapperobject *wp) |
1183 | 382 | { |
1184 | 382 | PyObject_GC_UnTrack(wp); |
1185 | 382 | Py_TRASHCAN_BEGIN(wp, wrapper_dealloc) |
1186 | 382 | Py_XDECREF(wp->descr); |
1187 | 382 | Py_XDECREF(wp->self); |
1188 | 382 | PyObject_GC_Del(wp); |
1189 | 382 | Py_TRASHCAN_END |
1190 | 382 | } |
1191 | | |
1192 | | static PyObject * |
1193 | | wrapper_richcompare(PyObject *a, PyObject *b, int op) |
1194 | 0 | { |
1195 | 0 | wrapperobject *wa, *wb; |
1196 | 0 | int eq; |
1197 | |
|
1198 | 0 | assert(a != NULL && b != NULL); |
1199 | | |
1200 | | /* both arguments should be wrapperobjects */ |
1201 | 0 | if ((op != Py_EQ && op != Py_NE) |
1202 | 0 | || !Wrapper_Check(a) || !Wrapper_Check(b)) |
1203 | 0 | { |
1204 | 0 | Py_RETURN_NOTIMPLEMENTED; |
1205 | 0 | } |
1206 | | |
1207 | 0 | wa = (wrapperobject *)a; |
1208 | 0 | wb = (wrapperobject *)b; |
1209 | 0 | eq = (wa->descr == wb->descr && wa->self == wb->self); |
1210 | 0 | if (eq == (op == Py_EQ)) { |
1211 | 0 | Py_RETURN_TRUE; |
1212 | 0 | } |
1213 | 0 | else { |
1214 | 0 | Py_RETURN_FALSE; |
1215 | 0 | } |
1216 | 0 | } |
1217 | | |
1218 | | static Py_hash_t |
1219 | | wrapper_hash(wrapperobject *wp) |
1220 | 0 | { |
1221 | 0 | Py_hash_t x, y; |
1222 | 0 | x = _Py_HashPointer(wp->self); |
1223 | 0 | y = _Py_HashPointer(wp->descr); |
1224 | 0 | x = x ^ y; |
1225 | 0 | if (x == -1) |
1226 | 0 | x = -2; |
1227 | 0 | return x; |
1228 | 0 | } |
1229 | | |
1230 | | static PyObject * |
1231 | | wrapper_repr(wrapperobject *wp) |
1232 | 0 | { |
1233 | 0 | return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>", |
1234 | 0 | wp->descr->d_base->name, |
1235 | 0 | wp->self->ob_type->tp_name, |
1236 | 0 | wp->self); |
1237 | 0 | } |
1238 | | |
1239 | | static PyObject * |
1240 | | wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored)) |
1241 | 0 | { |
1242 | 0 | _Py_IDENTIFIER(getattr); |
1243 | 0 | return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr), |
1244 | 0 | wp->self, PyDescr_NAME(wp->descr)); |
1245 | 0 | } |
1246 | | |
1247 | | static PyMethodDef wrapper_methods[] = { |
1248 | | {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL}, |
1249 | | {NULL, NULL} |
1250 | | }; |
1251 | | |
1252 | | static PyMemberDef wrapper_members[] = { |
1253 | | {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY}, |
1254 | | {0} |
1255 | | }; |
1256 | | |
1257 | | static PyObject * |
1258 | | wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored)) |
1259 | 0 | { |
1260 | 0 | PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr); |
1261 | |
|
1262 | 0 | Py_INCREF(c); |
1263 | 0 | return c; |
1264 | 0 | } |
1265 | | |
1266 | | static PyObject * |
1267 | | wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored)) |
1268 | 0 | { |
1269 | 0 | const char *s = wp->descr->d_base->name; |
1270 | |
|
1271 | 0 | return PyUnicode_FromString(s); |
1272 | 0 | } |
1273 | | |
1274 | | static PyObject * |
1275 | | wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored)) |
1276 | 0 | { |
1277 | 0 | return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); |
1278 | 0 | } |
1279 | | |
1280 | | static PyObject * |
1281 | | wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored)) |
1282 | 0 | { |
1283 | 0 | return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); |
1284 | 0 | } |
1285 | | |
1286 | | static PyObject * |
1287 | | wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored)) |
1288 | 0 | { |
1289 | 0 | return descr_get_qualname((PyDescrObject *)wp->descr, NULL); |
1290 | 0 | } |
1291 | | |
1292 | | static PyGetSetDef wrapper_getsets[] = { |
1293 | | {"__objclass__", (getter)wrapper_objclass}, |
1294 | | {"__name__", (getter)wrapper_name}, |
1295 | | {"__qualname__", (getter)wrapper_qualname}, |
1296 | | {"__doc__", (getter)wrapper_doc}, |
1297 | | {"__text_signature__", (getter)wrapper_text_signature}, |
1298 | | {0} |
1299 | | }; |
1300 | | |
1301 | | static PyObject * |
1302 | | wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) |
1303 | 380 | { |
1304 | 380 | return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds); |
1305 | 380 | } |
1306 | | |
1307 | | static int |
1308 | | wrapper_traverse(PyObject *self, visitproc visit, void *arg) |
1309 | 2 | { |
1310 | 2 | wrapperobject *wp = (wrapperobject *)self; |
1311 | 2 | Py_VISIT(wp->descr); |
1312 | 2 | Py_VISIT(wp->self); |
1313 | 2 | return 0; |
1314 | 2 | } |
1315 | | |
1316 | | PyTypeObject _PyMethodWrapper_Type = { |
1317 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1318 | | "method-wrapper", /* tp_name */ |
1319 | | sizeof(wrapperobject), /* tp_basicsize */ |
1320 | | 0, /* tp_itemsize */ |
1321 | | /* methods */ |
1322 | | (destructor)wrapper_dealloc, /* tp_dealloc */ |
1323 | | 0, /* tp_vectorcall_offset */ |
1324 | | 0, /* tp_getattr */ |
1325 | | 0, /* tp_setattr */ |
1326 | | 0, /* tp_as_async */ |
1327 | | (reprfunc)wrapper_repr, /* tp_repr */ |
1328 | | 0, /* tp_as_number */ |
1329 | | 0, /* tp_as_sequence */ |
1330 | | 0, /* tp_as_mapping */ |
1331 | | (hashfunc)wrapper_hash, /* tp_hash */ |
1332 | | (ternaryfunc)wrapper_call, /* tp_call */ |
1333 | | 0, /* tp_str */ |
1334 | | PyObject_GenericGetAttr, /* tp_getattro */ |
1335 | | 0, /* tp_setattro */ |
1336 | | 0, /* tp_as_buffer */ |
1337 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
1338 | | 0, /* tp_doc */ |
1339 | | wrapper_traverse, /* tp_traverse */ |
1340 | | 0, /* tp_clear */ |
1341 | | wrapper_richcompare, /* tp_richcompare */ |
1342 | | 0, /* tp_weaklistoffset */ |
1343 | | 0, /* tp_iter */ |
1344 | | 0, /* tp_iternext */ |
1345 | | wrapper_methods, /* tp_methods */ |
1346 | | wrapper_members, /* tp_members */ |
1347 | | wrapper_getsets, /* tp_getset */ |
1348 | | 0, /* tp_base */ |
1349 | | 0, /* tp_dict */ |
1350 | | 0, /* tp_descr_get */ |
1351 | | 0, /* tp_descr_set */ |
1352 | | }; |
1353 | | |
1354 | | PyObject * |
1355 | | PyWrapper_New(PyObject *d, PyObject *self) |
1356 | 383 | { |
1357 | 383 | wrapperobject *wp; |
1358 | 383 | PyWrapperDescrObject *descr; |
1359 | | |
1360 | 383 | assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); |
1361 | 383 | descr = (PyWrapperDescrObject *)d; |
1362 | 383 | assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), |
1363 | 383 | (PyObject *)PyDescr_TYPE(descr))); |
1364 | | |
1365 | 383 | wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type); |
1366 | 383 | if (wp != NULL) { |
1367 | 383 | Py_INCREF(descr); |
1368 | 383 | wp->descr = descr; |
1369 | 383 | Py_INCREF(self); |
1370 | 383 | wp->self = self; |
1371 | 383 | _PyObject_GC_TRACK(wp); |
1372 | 383 | } |
1373 | 383 | return (PyObject *)wp; |
1374 | 383 | } |
1375 | | |
1376 | | |
1377 | | /* A built-in 'property' type */ |
1378 | | |
1379 | | /* |
1380 | | class property(object): |
1381 | | |
1382 | | def __init__(self, fget=None, fset=None, fdel=None, doc=None): |
1383 | | if doc is None and fget is not None and hasattr(fget, "__doc__"): |
1384 | | doc = fget.__doc__ |
1385 | | self.__get = fget |
1386 | | self.__set = fset |
1387 | | self.__del = fdel |
1388 | | self.__doc__ = doc |
1389 | | |
1390 | | def __get__(self, inst, type=None): |
1391 | | if inst is None: |
1392 | | return self |
1393 | | if self.__get is None: |
1394 | | raise AttributeError, "unreadable attribute" |
1395 | | return self.__get(inst) |
1396 | | |
1397 | | def __set__(self, inst, value): |
1398 | | if self.__set is None: |
1399 | | raise AttributeError, "can't set attribute" |
1400 | | return self.__set(inst, value) |
1401 | | |
1402 | | def __delete__(self, inst): |
1403 | | if self.__del is None: |
1404 | | raise AttributeError, "can't delete attribute" |
1405 | | return self.__del(inst) |
1406 | | |
1407 | | */ |
1408 | | |
1409 | | typedef struct { |
1410 | | PyObject_HEAD |
1411 | | PyObject *prop_get; |
1412 | | PyObject *prop_set; |
1413 | | PyObject *prop_del; |
1414 | | PyObject *prop_doc; |
1415 | | int getter_doc; |
1416 | | } propertyobject; |
1417 | | |
1418 | | static PyObject * property_copy(PyObject *, PyObject *, PyObject *, |
1419 | | PyObject *); |
1420 | | |
1421 | | static PyMemberDef property_members[] = { |
1422 | | {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY}, |
1423 | | {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY}, |
1424 | | {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY}, |
1425 | | {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0}, |
1426 | | {0} |
1427 | | }; |
1428 | | |
1429 | | |
1430 | | PyDoc_STRVAR(getter_doc, |
1431 | | "Descriptor to change the getter on a property."); |
1432 | | |
1433 | | static PyObject * |
1434 | | property_getter(PyObject *self, PyObject *getter) |
1435 | 0 | { |
1436 | 0 | return property_copy(self, getter, NULL, NULL); |
1437 | 0 | } |
1438 | | |
1439 | | |
1440 | | PyDoc_STRVAR(setter_doc, |
1441 | | "Descriptor to change the setter on a property."); |
1442 | | |
1443 | | static PyObject * |
1444 | | property_setter(PyObject *self, PyObject *setter) |
1445 | 32 | { |
1446 | 32 | return property_copy(self, NULL, setter, NULL); |
1447 | 32 | } |
1448 | | |
1449 | | |
1450 | | PyDoc_STRVAR(deleter_doc, |
1451 | | "Descriptor to change the deleter on a property."); |
1452 | | |
1453 | | static PyObject * |
1454 | | property_deleter(PyObject *self, PyObject *deleter) |
1455 | 0 | { |
1456 | 0 | return property_copy(self, NULL, NULL, deleter); |
1457 | 0 | } |
1458 | | |
1459 | | |
1460 | | static PyMethodDef property_methods[] = { |
1461 | | {"getter", property_getter, METH_O, getter_doc}, |
1462 | | {"setter", property_setter, METH_O, setter_doc}, |
1463 | | {"deleter", property_deleter, METH_O, deleter_doc}, |
1464 | | {0} |
1465 | | }; |
1466 | | |
1467 | | |
1468 | | static void |
1469 | | property_dealloc(PyObject *self) |
1470 | 32 | { |
1471 | 32 | propertyobject *gs = (propertyobject *)self; |
1472 | | |
1473 | 32 | _PyObject_GC_UNTRACK(self); |
1474 | 32 | Py_XDECREF(gs->prop_get); |
1475 | 32 | Py_XDECREF(gs->prop_set); |
1476 | 32 | Py_XDECREF(gs->prop_del); |
1477 | 32 | Py_XDECREF(gs->prop_doc); |
1478 | 32 | self->ob_type->tp_free(self); |
1479 | 32 | } |
1480 | | |
1481 | | static PyObject * |
1482 | | property_descr_get(PyObject *self, PyObject *obj, PyObject *type) |
1483 | 1.64k | { |
1484 | 1.64k | if (obj == NULL || obj == Py_None) { |
1485 | 0 | Py_INCREF(self); |
1486 | 0 | return self; |
1487 | 0 | } |
1488 | | |
1489 | 1.64k | propertyobject *gs = (propertyobject *)self; |
1490 | 1.64k | if (gs->prop_get == NULL) { |
1491 | 0 | PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); |
1492 | 0 | return NULL; |
1493 | 0 | } |
1494 | | |
1495 | 1.64k | PyObject *args[1] = {obj}; |
1496 | 1.64k | return _PyObject_FastCall(gs->prop_get, args, 1); |
1497 | 1.64k | } |
1498 | | |
1499 | | static int |
1500 | | property_descr_set(PyObject *self, PyObject *obj, PyObject *value) |
1501 | 56 | { |
1502 | 56 | propertyobject *gs = (propertyobject *)self; |
1503 | 56 | PyObject *func, *res; |
1504 | | |
1505 | 56 | if (value == NULL) |
1506 | 0 | func = gs->prop_del; |
1507 | 56 | else |
1508 | 56 | func = gs->prop_set; |
1509 | 56 | if (func == NULL) { |
1510 | 0 | PyErr_SetString(PyExc_AttributeError, |
1511 | 0 | value == NULL ? |
1512 | 0 | "can't delete attribute" : |
1513 | 0 | "can't set attribute"); |
1514 | 0 | return -1; |
1515 | 0 | } |
1516 | 56 | if (value == NULL) |
1517 | 0 | res = PyObject_CallFunctionObjArgs(func, obj, NULL); |
1518 | 56 | else |
1519 | 56 | res = PyObject_CallFunctionObjArgs(func, obj, value, NULL); |
1520 | 56 | if (res == NULL) |
1521 | 0 | return -1; |
1522 | 56 | Py_DECREF(res); |
1523 | 56 | return 0; |
1524 | 56 | } |
1525 | | |
1526 | | static PyObject * |
1527 | | property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) |
1528 | 32 | { |
1529 | 32 | propertyobject *pold = (propertyobject *)old; |
1530 | 32 | PyObject *new, *type, *doc; |
1531 | | |
1532 | 32 | type = PyObject_Type(old); |
1533 | 32 | if (type == NULL) |
1534 | 0 | return NULL; |
1535 | | |
1536 | 32 | if (get == NULL || get == Py_None) { |
1537 | 32 | Py_XDECREF(get); |
1538 | 32 | get = pold->prop_get ? pold->prop_get : Py_None; |
1539 | 32 | } |
1540 | 32 | if (set == NULL || set == Py_None) { |
1541 | 0 | Py_XDECREF(set); |
1542 | 0 | set = pold->prop_set ? pold->prop_set : Py_None; |
1543 | 0 | } |
1544 | 32 | if (del == NULL || del == Py_None) { |
1545 | 32 | Py_XDECREF(del); |
1546 | 32 | del = pold->prop_del ? pold->prop_del : Py_None; |
1547 | 32 | } |
1548 | 32 | if (pold->getter_doc && get != Py_None) { |
1549 | | /* make _init use __doc__ from getter */ |
1550 | 32 | doc = Py_None; |
1551 | 32 | } |
1552 | 0 | else { |
1553 | 0 | doc = pold->prop_doc ? pold->prop_doc : Py_None; |
1554 | 0 | } |
1555 | | |
1556 | 32 | new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL); |
1557 | 32 | Py_DECREF(type); |
1558 | 32 | if (new == NULL) |
1559 | 0 | return NULL; |
1560 | 32 | return new; |
1561 | 32 | } |
1562 | | |
1563 | | /*[clinic input] |
1564 | | property.__init__ as property_init |
1565 | | |
1566 | | fget: object(c_default="NULL") = None |
1567 | | function to be used for getting an attribute value |
1568 | | fset: object(c_default="NULL") = None |
1569 | | function to be used for setting an attribute value |
1570 | | fdel: object(c_default="NULL") = None |
1571 | | function to be used for del'ing an attribute |
1572 | | doc: object(c_default="NULL") = None |
1573 | | docstring |
1574 | | |
1575 | | Property attribute. |
1576 | | |
1577 | | Typical use is to define a managed attribute x: |
1578 | | |
1579 | | class C(object): |
1580 | | def getx(self): return self._x |
1581 | | def setx(self, value): self._x = value |
1582 | | def delx(self): del self._x |
1583 | | x = property(getx, setx, delx, "I'm the 'x' property.") |
1584 | | |
1585 | | Decorators make defining new properties or modifying existing ones easy: |
1586 | | |
1587 | | class C(object): |
1588 | | @property |
1589 | | def x(self): |
1590 | | "I am the 'x' property." |
1591 | | return self._x |
1592 | | @x.setter |
1593 | | def x(self, value): |
1594 | | self._x = value |
1595 | | @x.deleter |
1596 | | def x(self): |
1597 | | del self._x |
1598 | | [clinic start generated code]*/ |
1599 | | |
1600 | | static int |
1601 | | property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, |
1602 | | PyObject *fdel, PyObject *doc) |
1603 | | /*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/ |
1604 | 99 | { |
1605 | 99 | if (fget == Py_None) |
1606 | 0 | fget = NULL; |
1607 | 99 | if (fset == Py_None) |
1608 | 0 | fset = NULL; |
1609 | 99 | if (fdel == Py_None) |
1610 | 32 | fdel = NULL; |
1611 | | |
1612 | 99 | Py_XINCREF(fget); |
1613 | 99 | Py_XINCREF(fset); |
1614 | 99 | Py_XINCREF(fdel); |
1615 | 99 | Py_XINCREF(doc); |
1616 | | |
1617 | 99 | Py_XSETREF(self->prop_get, fget); |
1618 | 99 | Py_XSETREF(self->prop_set, fset); |
1619 | 99 | Py_XSETREF(self->prop_del, fdel); |
1620 | 99 | Py_XSETREF(self->prop_doc, doc); |
1621 | 99 | self->getter_doc = 0; |
1622 | | |
1623 | | /* if no docstring given and the getter has one, use that one */ |
1624 | 99 | if ((doc == NULL || doc == Py_None) && fget != NULL) { |
1625 | 99 | _Py_IDENTIFIER(__doc__); |
1626 | 99 | PyObject *get_doc; |
1627 | 99 | int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc); |
1628 | 99 | if (rc <= 0) { |
1629 | 0 | return rc; |
1630 | 0 | } |
1631 | 99 | if (Py_TYPE(self) == &PyProperty_Type) { |
1632 | 99 | Py_XSETREF(self->prop_doc, get_doc); |
1633 | 99 | } |
1634 | 0 | else { |
1635 | | /* If this is a property subclass, put __doc__ |
1636 | | in dict of the subclass instance instead, |
1637 | | otherwise it gets shadowed by __doc__ in the |
1638 | | class's dict. */ |
1639 | 0 | int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc); |
1640 | 0 | Py_DECREF(get_doc); |
1641 | 0 | if (err < 0) |
1642 | 0 | return -1; |
1643 | 0 | } |
1644 | 99 | self->getter_doc = 1; |
1645 | 99 | } |
1646 | | |
1647 | 99 | return 0; |
1648 | 99 | } |
1649 | | |
1650 | | static PyObject * |
1651 | | property_get___isabstractmethod__(propertyobject *prop, void *closure) |
1652 | 1 | { |
1653 | 1 | int res = _PyObject_IsAbstract(prop->prop_get); |
1654 | 1 | if (res == -1) { |
1655 | 0 | return NULL; |
1656 | 0 | } |
1657 | 1 | else if (res) { |
1658 | 0 | Py_RETURN_TRUE; |
1659 | 0 | } |
1660 | | |
1661 | 1 | res = _PyObject_IsAbstract(prop->prop_set); |
1662 | 1 | if (res == -1) { |
1663 | 0 | return NULL; |
1664 | 0 | } |
1665 | 1 | else if (res) { |
1666 | 0 | Py_RETURN_TRUE; |
1667 | 0 | } |
1668 | | |
1669 | 1 | res = _PyObject_IsAbstract(prop->prop_del); |
1670 | 1 | if (res == -1) { |
1671 | 0 | return NULL; |
1672 | 0 | } |
1673 | 1 | else if (res) { |
1674 | 0 | Py_RETURN_TRUE; |
1675 | 0 | } |
1676 | 1 | Py_RETURN_FALSE; |
1677 | 1 | } |
1678 | | |
1679 | | static PyGetSetDef property_getsetlist[] = { |
1680 | | {"__isabstractmethod__", |
1681 | | (getter)property_get___isabstractmethod__, NULL, |
1682 | | NULL, |
1683 | | NULL}, |
1684 | | {NULL} /* Sentinel */ |
1685 | | }; |
1686 | | |
1687 | | static int |
1688 | | property_traverse(PyObject *self, visitproc visit, void *arg) |
1689 | 146 | { |
1690 | 146 | propertyobject *pp = (propertyobject *)self; |
1691 | 146 | Py_VISIT(pp->prop_get); |
1692 | 146 | Py_VISIT(pp->prop_set); |
1693 | 146 | Py_VISIT(pp->prop_del); |
1694 | 146 | Py_VISIT(pp->prop_doc); |
1695 | 146 | return 0; |
1696 | 146 | } |
1697 | | |
1698 | | static int |
1699 | | property_clear(PyObject *self) |
1700 | 0 | { |
1701 | 0 | propertyobject *pp = (propertyobject *)self; |
1702 | 0 | Py_CLEAR(pp->prop_doc); |
1703 | 0 | return 0; |
1704 | 0 | } |
1705 | | |
1706 | | #include "clinic/descrobject.c.h" |
1707 | | |
1708 | | PyTypeObject PyDictProxy_Type = { |
1709 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1710 | | "mappingproxy", /* tp_name */ |
1711 | | sizeof(mappingproxyobject), /* tp_basicsize */ |
1712 | | 0, /* tp_itemsize */ |
1713 | | /* methods */ |
1714 | | (destructor)mappingproxy_dealloc, /* tp_dealloc */ |
1715 | | 0, /* tp_vectorcall_offset */ |
1716 | | 0, /* tp_getattr */ |
1717 | | 0, /* tp_setattr */ |
1718 | | 0, /* tp_as_async */ |
1719 | | (reprfunc)mappingproxy_repr, /* tp_repr */ |
1720 | | 0, /* tp_as_number */ |
1721 | | &mappingproxy_as_sequence, /* tp_as_sequence */ |
1722 | | &mappingproxy_as_mapping, /* tp_as_mapping */ |
1723 | | 0, /* tp_hash */ |
1724 | | 0, /* tp_call */ |
1725 | | (reprfunc)mappingproxy_str, /* tp_str */ |
1726 | | PyObject_GenericGetAttr, /* tp_getattro */ |
1727 | | 0, /* tp_setattro */ |
1728 | | 0, /* tp_as_buffer */ |
1729 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
1730 | | 0, /* tp_doc */ |
1731 | | mappingproxy_traverse, /* tp_traverse */ |
1732 | | 0, /* tp_clear */ |
1733 | | (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */ |
1734 | | 0, /* tp_weaklistoffset */ |
1735 | | (getiterfunc)mappingproxy_getiter, /* tp_iter */ |
1736 | | 0, /* tp_iternext */ |
1737 | | mappingproxy_methods, /* tp_methods */ |
1738 | | 0, /* tp_members */ |
1739 | | 0, /* tp_getset */ |
1740 | | 0, /* tp_base */ |
1741 | | 0, /* tp_dict */ |
1742 | | 0, /* tp_descr_get */ |
1743 | | 0, /* tp_descr_set */ |
1744 | | 0, /* tp_dictoffset */ |
1745 | | 0, /* tp_init */ |
1746 | | 0, /* tp_alloc */ |
1747 | | mappingproxy_new, /* tp_new */ |
1748 | | }; |
1749 | | |
1750 | | PyTypeObject PyProperty_Type = { |
1751 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1752 | | "property", /* tp_name */ |
1753 | | sizeof(propertyobject), /* tp_basicsize */ |
1754 | | 0, /* tp_itemsize */ |
1755 | | /* methods */ |
1756 | | property_dealloc, /* tp_dealloc */ |
1757 | | 0, /* tp_vectorcall_offset */ |
1758 | | 0, /* tp_getattr */ |
1759 | | 0, /* tp_setattr */ |
1760 | | 0, /* tp_as_async */ |
1761 | | 0, /* tp_repr */ |
1762 | | 0, /* tp_as_number */ |
1763 | | 0, /* tp_as_sequence */ |
1764 | | 0, /* tp_as_mapping */ |
1765 | | 0, /* tp_hash */ |
1766 | | 0, /* tp_call */ |
1767 | | 0, /* tp_str */ |
1768 | | PyObject_GenericGetAttr, /* tp_getattro */ |
1769 | | 0, /* tp_setattro */ |
1770 | | 0, /* tp_as_buffer */ |
1771 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
1772 | | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
1773 | | property_init__doc__, /* tp_doc */ |
1774 | | property_traverse, /* tp_traverse */ |
1775 | | (inquiry)property_clear, /* tp_clear */ |
1776 | | 0, /* tp_richcompare */ |
1777 | | 0, /* tp_weaklistoffset */ |
1778 | | 0, /* tp_iter */ |
1779 | | 0, /* tp_iternext */ |
1780 | | property_methods, /* tp_methods */ |
1781 | | property_members, /* tp_members */ |
1782 | | property_getsetlist, /* tp_getset */ |
1783 | | 0, /* tp_base */ |
1784 | | 0, /* tp_dict */ |
1785 | | property_descr_get, /* tp_descr_get */ |
1786 | | property_descr_set, /* tp_descr_set */ |
1787 | | 0, /* tp_dictoffset */ |
1788 | | property_init, /* tp_init */ |
1789 | | PyType_GenericAlloc, /* tp_alloc */ |
1790 | | PyType_GenericNew, /* tp_new */ |
1791 | | PyObject_GC_Del, /* tp_free */ |
1792 | | }; |