blob: edead26a7d5d176feb979504ed4fe09917f4cc96 [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001/* Descriptors -- a new, flexible way to describe attributes */
2
3#include "Python.h"
Eric Snow2ebc5ce2017-09-07 23:51:28 -06004#include "internal/pystate.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +00005#include "structmember.h" /* Why is this not included in Python.h? */
6
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02007/*[clinic input]
8class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
9class property "propertyobject *" "&PyProperty_Type"
10[clinic start generated code]*/
11/*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
12
Tim Peters6d6c1a32001-08-02 04:15:00 +000013static void
14descr_dealloc(PyDescrObject *descr)
15{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000016 _PyObject_GC_UNTRACK(descr);
17 Py_XDECREF(descr->d_type);
18 Py_XDECREF(descr->d_name);
Antoine Pitrou9d574812011-12-12 13:47:25 +010019 Py_XDECREF(descr->d_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 PyObject_GC_Del(descr);
Tim Peters6d6c1a32001-08-02 04:15:00 +000021}
22
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000023static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +000024descr_name(PyDescrObject *descr)
25{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000026 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
27 return descr->d_name;
28 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +000029}
30
31static PyObject *
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020032descr_repr(PyDescrObject *descr, const char *format)
Tim Peters6d6c1a32001-08-02 04:15:00 +000033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 PyObject *name = NULL;
35 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
36 name = descr->d_name;
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000037
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
Tim Peters6d6c1a32001-08-02 04:15:00 +000039}
40
41static PyObject *
42method_repr(PyMethodDescrObject *descr)
43{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 return descr_repr((PyDescrObject *)descr,
45 "<method '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000046}
47
48static PyObject *
49member_repr(PyMemberDescrObject *descr)
50{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 return descr_repr((PyDescrObject *)descr,
52 "<member '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000053}
54
55static PyObject *
56getset_repr(PyGetSetDescrObject *descr)
57{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000058 return descr_repr((PyDescrObject *)descr,
59 "<attribute '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000060}
61
62static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +000063wrapperdescr_repr(PyWrapperDescrObject *descr)
Tim Peters6d6c1a32001-08-02 04:15:00 +000064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 return descr_repr((PyDescrObject *)descr,
66 "<slot wrapper '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000067}
68
69static int
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000070descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +000071{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 if (obj == NULL) {
73 Py_INCREF(descr);
74 *pres = (PyObject *)descr;
75 return 1;
76 }
77 if (!PyObject_TypeCheck(obj, descr->d_type)) {
78 PyErr_Format(PyExc_TypeError,
79 "descriptor '%V' for '%s' objects "
80 "doesn't apply to '%s' object",
81 descr_name((PyDescrObject *)descr), "?",
82 descr->d_type->tp_name,
83 obj->ob_type->tp_name);
84 *pres = NULL;
85 return 1;
86 }
87 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000088}
89
90static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000091classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Petersbca1cbc2002-12-09 22:56:13 +000092{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 /* Ensure a valid type. Class methods ignore obj. */
94 if (type == NULL) {
95 if (obj != NULL)
96 type = (PyObject *)obj->ob_type;
97 else {
98 /* Wot - no type?! */
99 PyErr_Format(PyExc_TypeError,
100 "descriptor '%V' for type '%s' "
101 "needs either an object or a type",
102 descr_name((PyDescrObject *)descr), "?",
103 PyDescr_TYPE(descr)->tp_name);
104 return NULL;
105 }
106 }
107 if (!PyType_Check(type)) {
108 PyErr_Format(PyExc_TypeError,
109 "descriptor '%V' for type '%s' "
110 "needs a type, not a '%s' as arg 2",
111 descr_name((PyDescrObject *)descr), "?",
112 PyDescr_TYPE(descr)->tp_name,
113 type->ob_type->tp_name);
114 return NULL;
115 }
116 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
117 PyErr_Format(PyExc_TypeError,
118 "descriptor '%V' for type '%s' "
119 "doesn't apply to type '%s'",
120 descr_name((PyDescrObject *)descr), "?",
121 PyDescr_TYPE(descr)->tp_name,
122 ((PyTypeObject *)type)->tp_name);
123 return NULL;
124 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200125 return PyCFunction_NewEx(descr->d_method, type, NULL);
Tim Petersbca1cbc2002-12-09 22:56:13 +0000126}
127
128static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000129method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000131 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 if (descr_check((PyDescrObject *)descr, obj, &res))
134 return res;
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200135 return PyCFunction_NewEx(descr->d_method, obj, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000136}
137
138static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000139member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000140{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 if (descr_check((PyDescrObject *)descr, obj, &res))
144 return res;
145 return PyMember_GetOne((char *)obj, descr->d_member);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000146}
147
148static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000149getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 if (descr_check((PyDescrObject *)descr, obj, &res))
154 return res;
155 if (descr->d_getset->get != NULL)
156 return descr->d_getset->get(obj, descr->d_getset->closure);
157 PyErr_Format(PyExc_AttributeError,
158 "attribute '%V' of '%.100s' objects is not readable",
159 descr_name((PyDescrObject *)descr), "?",
160 PyDescr_TYPE(descr)->tp_name);
161 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000162}
163
164static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000165wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000166{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 if (descr_check((PyDescrObject *)descr, obj, &res))
170 return res;
171 return PyWrapper_New((PyObject *)descr, obj);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000172}
173
174static int
175descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 int *pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 assert(obj != NULL);
179 if (!PyObject_TypeCheck(obj, descr->d_type)) {
180 PyErr_Format(PyExc_TypeError,
181 "descriptor '%V' for '%.100s' objects "
182 "doesn't apply to '%.100s' object",
183 descr_name(descr), "?",
184 descr->d_type->tp_name,
185 obj->ob_type->tp_name);
186 *pres = -1;
187 return 1;
188 }
189 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000190}
191
192static int
193member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000196
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
198 return res;
199 return PyMember_SetOne((char *)obj, descr->d_member, value);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000200}
201
202static int
203getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
204{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
208 return res;
209 if (descr->d_getset->set != NULL)
210 return descr->d_getset->set(obj, value,
211 descr->d_getset->closure);
212 PyErr_Format(PyExc_AttributeError,
213 "attribute '%V' of '%.100s' objects is not writable",
214 descr_name((PyDescrObject *)descr), "?",
215 PyDescr_TYPE(descr)->tp_name);
216 return -1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000217}
218
219static PyObject *
Victor Stinnerc5257232017-01-18 10:38:09 +0100220methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000221{
Victor Stinnerc5257232017-01-18 10:38:09 +0100222 Py_ssize_t nargs;
223 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 /* Make sure that the first argument is acceptable as 'self' */
226 assert(PyTuple_Check(args));
Victor Stinnerc5257232017-01-18 10:38:09 +0100227 nargs = PyTuple_GET_SIZE(args);
228 if (nargs < 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 PyErr_Format(PyExc_TypeError,
230 "descriptor '%V' of '%.100s' "
231 "object needs an argument",
232 descr_name((PyDescrObject *)descr), "?",
233 PyDescr_TYPE(descr)->tp_name);
234 return NULL;
235 }
236 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200237 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200238 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 PyErr_Format(PyExc_TypeError,
240 "descriptor '%V' "
241 "requires a '%.100s' object "
242 "but received a '%.100s'",
243 descr_name((PyDescrObject *)descr), "?",
244 PyDescr_TYPE(descr)->tp_name,
245 self->ob_type->tp_name);
246 return NULL;
247 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000248
Victor Stinnerc5257232017-01-18 10:38:09 +0100249 result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
250 &PyTuple_GET_ITEM(args, 1), nargs - 1,
251 kwargs);
252 result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000254}
255
INADA Naoki5566bbb2017-02-03 07:43:03 +0900256// same to methoddescr_call(), but use FASTCALL convention.
257PyObject *
258_PyMethodDescr_FastCallKeywords(PyObject *descrobj,
259 PyObject **args, Py_ssize_t nargs,
260 PyObject *kwnames)
261{
262 assert(Py_TYPE(descrobj) == &PyMethodDescr_Type);
263 PyMethodDescrObject *descr = (PyMethodDescrObject *)descrobj;
264 PyObject *self, *result;
265
266 /* Make sure that the first argument is acceptable as 'self' */
267 if (nargs < 1) {
268 PyErr_Format(PyExc_TypeError,
269 "descriptor '%V' of '%.100s' "
270 "object needs an argument",
271 descr_name((PyDescrObject *)descr), "?",
272 PyDescr_TYPE(descr)->tp_name);
273 return NULL;
274 }
275 self = args[0];
276 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
277 (PyObject *)PyDescr_TYPE(descr))) {
278 PyErr_Format(PyExc_TypeError,
279 "descriptor '%V' "
280 "requires a '%.100s' object "
281 "but received a '%.100s'",
282 descr_name((PyDescrObject *)descr), "?",
283 PyDescr_TYPE(descr)->tp_name,
284 self->ob_type->tp_name);
285 return NULL;
286 }
287
288 result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self,
289 args+1, nargs-1, kwnames);
290 result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
291 return result;
292}
293
Tim Peters6d6c1a32001-08-02 04:15:00 +0000294static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000295classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000297{
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400298 Py_ssize_t argc;
Victor Stinner2990fa12016-08-22 23:21:55 +0200299 PyObject *self, *func, *result, **stack;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000300
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400301 /* Make sure that the first argument is acceptable as 'self' */
302 assert(PyTuple_Check(args));
303 argc = PyTuple_GET_SIZE(args);
304 if (argc < 1) {
305 PyErr_Format(PyExc_TypeError,
306 "descriptor '%V' of '%.100s' "
307 "object needs an argument",
308 descr_name((PyDescrObject *)descr), "?",
309 PyDescr_TYPE(descr)->tp_name);
310 return NULL;
311 }
312 self = PyTuple_GET_ITEM(args, 0);
313 if (!PyType_Check(self)) {
314 PyErr_Format(PyExc_TypeError,
315 "descriptor '%V' requires a type "
316 "but received a '%.100s'",
317 descr_name((PyDescrObject *)descr), "?",
318 PyDescr_TYPE(descr)->tp_name,
319 self->ob_type->tp_name);
320 return NULL;
321 }
322 if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
323 PyErr_Format(PyExc_TypeError,
324 "descriptor '%V' "
325 "requires a subtype of '%.100s' "
326 "but received '%.100s",
327 descr_name((PyDescrObject *)descr), "?",
328 PyDescr_TYPE(descr)->tp_name,
329 self->ob_type->tp_name);
330 return NULL;
331 }
332
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200333 func = PyCFunction_NewEx(descr->d_method, self, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 if (func == NULL)
335 return NULL;
Victor Stinner2990fa12016-08-22 23:21:55 +0200336 stack = &PyTuple_GET_ITEM(args, 1);
337 result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 Py_DECREF(func);
339 return result;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000340}
341
342static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000343wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 Py_ssize_t argc;
Victor Stinner2990fa12016-08-22 23:21:55 +0200346 PyObject *self, *func, *result, **stack;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 /* Make sure that the first argument is acceptable as 'self' */
349 assert(PyTuple_Check(args));
350 argc = PyTuple_GET_SIZE(args);
351 if (argc < 1) {
352 PyErr_Format(PyExc_TypeError,
353 "descriptor '%V' of '%.100s' "
354 "object needs an argument",
355 descr_name((PyDescrObject *)descr), "?",
356 PyDescr_TYPE(descr)->tp_name);
357 return NULL;
358 }
359 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200360 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200361 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 PyErr_Format(PyExc_TypeError,
363 "descriptor '%V' "
364 "requires a '%.100s' object "
365 "but received a '%.100s'",
366 descr_name((PyDescrObject *)descr), "?",
367 PyDescr_TYPE(descr)->tp_name,
368 self->ob_type->tp_name);
369 return NULL;
370 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 func = PyWrapper_New((PyObject *)descr, self);
373 if (func == NULL)
374 return NULL;
Victor Stinner2990fa12016-08-22 23:21:55 +0200375
376 stack = &PyTuple_GET_ITEM(args, 1);
377 result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 Py_DECREF(func);
379 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000380}
381
382static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000383method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000384{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800385 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800386}
387
388static PyObject *
389method_get_text_signature(PyMethodDescrObject *descr, void *closure)
390{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800391 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000392}
393
Antoine Pitrou9d574812011-12-12 13:47:25 +0100394static PyObject *
395calculate_qualname(PyDescrObject *descr)
396{
397 PyObject *type_qualname, *res;
398 _Py_IDENTIFIER(__qualname__);
399
400 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
401 PyErr_SetString(PyExc_TypeError,
402 "<descriptor>.__name__ is not a unicode object");
403 return NULL;
404 }
405
406 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
407 &PyId___qualname__);
408 if (type_qualname == NULL)
409 return NULL;
410
411 if (!PyUnicode_Check(type_qualname)) {
412 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
413 "__qualname__ is not a unicode object");
414 Py_XDECREF(type_qualname);
415 return NULL;
416 }
417
418 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
419 Py_DECREF(type_qualname);
420 return res;
421}
422
423static PyObject *
424descr_get_qualname(PyDescrObject *descr)
425{
426 if (descr->d_qualname == NULL)
427 descr->d_qualname = calculate_qualname(descr);
428 Py_XINCREF(descr->d_qualname);
429 return descr->d_qualname;
430}
431
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100432static PyObject *
433descr_reduce(PyDescrObject *descr)
434{
435 PyObject *builtins;
436 PyObject *getattr;
437 _Py_IDENTIFIER(getattr);
438
439 builtins = PyEval_GetBuiltins();
440 getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
441 return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
442 PyDescr_NAME(descr));
443}
444
445static PyMethodDef descr_methods[] = {
446 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
447 {NULL, NULL}
448};
449
Guido van Rossum6f799372001-09-20 20:46:19 +0000450static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
452 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
453 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000454};
455
Guido van Rossum32d34c82001-09-20 21:45:26 +0000456static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100458 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800459 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000461};
462
463static PyObject *
464member_get_doc(PyMemberDescrObject *descr, void *closure)
465{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200467 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 }
469 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000470}
471
Guido van Rossum32d34c82001-09-20 21:45:26 +0000472static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100474 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000476};
477
478static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000479getset_get_doc(PyGetSetDescrObject *descr, void *closure)
480{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200482 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 }
484 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000485}
486
487static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100489 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000491};
492
493static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000494wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000495{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800496 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800497}
498
499static PyObject *
500wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
501{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800502 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000503}
504
Armin Rigoc6686b72005-11-07 08:38:00 +0000505static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100507 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800508 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000509 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000510};
511
Guido van Rossum048eb752001-10-02 21:24:57 +0000512static int
513descr_traverse(PyObject *self, visitproc visit, void *arg)
514{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 PyDescrObject *descr = (PyDescrObject *)self;
516 Py_VISIT(descr->d_type);
517 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000518}
519
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000520PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 PyVarObject_HEAD_INIT(&PyType_Type, 0)
522 "method_descriptor",
523 sizeof(PyMethodDescrObject),
524 0,
525 (destructor)descr_dealloc, /* tp_dealloc */
526 0, /* tp_print */
527 0, /* tp_getattr */
528 0, /* tp_setattr */
529 0, /* tp_reserved */
530 (reprfunc)method_repr, /* tp_repr */
531 0, /* tp_as_number */
532 0, /* tp_as_sequence */
533 0, /* tp_as_mapping */
534 0, /* tp_hash */
535 (ternaryfunc)methoddescr_call, /* tp_call */
536 0, /* tp_str */
537 PyObject_GenericGetAttr, /* tp_getattro */
538 0, /* tp_setattro */
539 0, /* tp_as_buffer */
540 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
541 0, /* tp_doc */
542 descr_traverse, /* tp_traverse */
543 0, /* tp_clear */
544 0, /* tp_richcompare */
545 0, /* tp_weaklistoffset */
546 0, /* tp_iter */
547 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100548 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 descr_members, /* tp_members */
550 method_getset, /* tp_getset */
551 0, /* tp_base */
552 0, /* tp_dict */
553 (descrgetfunc)method_get, /* tp_descr_get */
554 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000555};
556
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000557/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000558PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 PyVarObject_HEAD_INIT(&PyType_Type, 0)
560 "classmethod_descriptor",
561 sizeof(PyMethodDescrObject),
562 0,
563 (destructor)descr_dealloc, /* tp_dealloc */
564 0, /* tp_print */
565 0, /* tp_getattr */
566 0, /* tp_setattr */
567 0, /* tp_reserved */
568 (reprfunc)method_repr, /* tp_repr */
569 0, /* tp_as_number */
570 0, /* tp_as_sequence */
571 0, /* tp_as_mapping */
572 0, /* tp_hash */
573 (ternaryfunc)classmethoddescr_call, /* tp_call */
574 0, /* tp_str */
575 PyObject_GenericGetAttr, /* tp_getattro */
576 0, /* tp_setattro */
577 0, /* tp_as_buffer */
578 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
579 0, /* tp_doc */
580 descr_traverse, /* tp_traverse */
581 0, /* tp_clear */
582 0, /* tp_richcompare */
583 0, /* tp_weaklistoffset */
584 0, /* tp_iter */
585 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100586 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 descr_members, /* tp_members */
588 method_getset, /* tp_getset */
589 0, /* tp_base */
590 0, /* tp_dict */
591 (descrgetfunc)classmethod_get, /* tp_descr_get */
592 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000593};
594
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000595PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 PyVarObject_HEAD_INIT(&PyType_Type, 0)
597 "member_descriptor",
598 sizeof(PyMemberDescrObject),
599 0,
600 (destructor)descr_dealloc, /* tp_dealloc */
601 0, /* tp_print */
602 0, /* tp_getattr */
603 0, /* tp_setattr */
604 0, /* tp_reserved */
605 (reprfunc)member_repr, /* tp_repr */
606 0, /* tp_as_number */
607 0, /* tp_as_sequence */
608 0, /* tp_as_mapping */
609 0, /* tp_hash */
610 0, /* tp_call */
611 0, /* tp_str */
612 PyObject_GenericGetAttr, /* tp_getattro */
613 0, /* tp_setattro */
614 0, /* tp_as_buffer */
615 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
616 0, /* tp_doc */
617 descr_traverse, /* tp_traverse */
618 0, /* tp_clear */
619 0, /* tp_richcompare */
620 0, /* tp_weaklistoffset */
621 0, /* tp_iter */
622 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100623 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 descr_members, /* tp_members */
625 member_getset, /* tp_getset */
626 0, /* tp_base */
627 0, /* tp_dict */
628 (descrgetfunc)member_get, /* tp_descr_get */
629 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000630};
631
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000632PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 PyVarObject_HEAD_INIT(&PyType_Type, 0)
634 "getset_descriptor",
635 sizeof(PyGetSetDescrObject),
636 0,
637 (destructor)descr_dealloc, /* tp_dealloc */
638 0, /* tp_print */
639 0, /* tp_getattr */
640 0, /* tp_setattr */
641 0, /* tp_reserved */
642 (reprfunc)getset_repr, /* tp_repr */
643 0, /* tp_as_number */
644 0, /* tp_as_sequence */
645 0, /* tp_as_mapping */
646 0, /* tp_hash */
647 0, /* tp_call */
648 0, /* tp_str */
649 PyObject_GenericGetAttr, /* tp_getattro */
650 0, /* tp_setattro */
651 0, /* tp_as_buffer */
652 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
653 0, /* tp_doc */
654 descr_traverse, /* tp_traverse */
655 0, /* tp_clear */
656 0, /* tp_richcompare */
657 0, /* tp_weaklistoffset */
658 0, /* tp_iter */
659 0, /* tp_iternext */
660 0, /* tp_methods */
661 descr_members, /* tp_members */
662 getset_getset, /* tp_getset */
663 0, /* tp_base */
664 0, /* tp_dict */
665 (descrgetfunc)getset_get, /* tp_descr_get */
666 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000667};
668
Guido van Rossumf4593e02001-10-03 12:09:30 +0000669PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 PyVarObject_HEAD_INIT(&PyType_Type, 0)
671 "wrapper_descriptor",
672 sizeof(PyWrapperDescrObject),
673 0,
674 (destructor)descr_dealloc, /* tp_dealloc */
675 0, /* tp_print */
676 0, /* tp_getattr */
677 0, /* tp_setattr */
678 0, /* tp_reserved */
679 (reprfunc)wrapperdescr_repr, /* tp_repr */
680 0, /* tp_as_number */
681 0, /* tp_as_sequence */
682 0, /* tp_as_mapping */
683 0, /* tp_hash */
684 (ternaryfunc)wrapperdescr_call, /* tp_call */
685 0, /* tp_str */
686 PyObject_GenericGetAttr, /* tp_getattro */
687 0, /* tp_setattro */
688 0, /* tp_as_buffer */
689 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
690 0, /* tp_doc */
691 descr_traverse, /* tp_traverse */
692 0, /* tp_clear */
693 0, /* tp_richcompare */
694 0, /* tp_weaklistoffset */
695 0, /* tp_iter */
696 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100697 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 descr_members, /* tp_members */
699 wrapperdescr_getset, /* tp_getset */
700 0, /* tp_base */
701 0, /* tp_dict */
702 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
703 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000704};
705
706static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000707descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
712 if (descr != NULL) {
713 Py_XINCREF(type);
714 descr->d_type = type;
715 descr->d_name = PyUnicode_InternFromString(name);
716 if (descr->d_name == NULL) {
717 Py_DECREF(descr);
718 descr = NULL;
719 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500720 else {
721 descr->d_qualname = NULL;
722 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 }
724 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000725}
726
727PyObject *
728PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
729{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
733 type, method->ml_name);
734 if (descr != NULL)
735 descr->d_method = method;
736 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000737}
738
739PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000740PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
745 type, method->ml_name);
746 if (descr != NULL)
747 descr->d_method = method;
748 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000749}
750
751PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000752PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
757 type, member->name);
758 if (descr != NULL)
759 descr->d_member = member;
760 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000761}
762
763PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000764PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
769 type, getset->name);
770 if (descr != NULL)
771 descr->d_getset = getset;
772 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000773}
774
775PyObject *
776PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
777{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000778 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000780 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
781 type, base->name);
782 if (descr != NULL) {
783 descr->d_base = base;
784 descr->d_wrapped = wrapped;
785 }
786 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000787}
788
Tim Peters6d6c1a32001-08-02 04:15:00 +0000789
Victor Stinner0db176f2012-04-16 00:16:30 +0200790/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000791
792/* This has no reason to be in this file except that adding new files is a
793 bit of a pain */
794
795typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +0200797 PyObject *mapping;
798} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000799
Martin v. Löwis18e16552006-02-15 17:27:45 +0000800static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +0200801mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000802{
Victor Stinner0db176f2012-04-16 00:16:30 +0200803 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000804}
805
806static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200807mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000808{
Victor Stinner0db176f2012-04-16 00:16:30 +0200809 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000810}
811
Victor Stinner0db176f2012-04-16 00:16:30 +0200812static PyMappingMethods mappingproxy_as_mapping = {
813 (lenfunc)mappingproxy_len, /* mp_length */
814 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000816};
817
818static int
Victor Stinner0db176f2012-04-16 00:16:30 +0200819mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000820{
Victor Stinner0db176f2012-04-16 00:16:30 +0200821 if (PyDict_CheckExact(pp->mapping))
822 return PyDict_Contains(pp->mapping, key);
823 else
824 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000825}
826
Victor Stinner0db176f2012-04-16 00:16:30 +0200827static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 0, /* sq_length */
829 0, /* sq_concat */
830 0, /* sq_repeat */
831 0, /* sq_item */
832 0, /* sq_slice */
833 0, /* sq_ass_item */
834 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +0200835 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000836 0, /* sq_inplace_concat */
837 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000838};
839
840static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200841mappingproxy_get(mappingproxyobject *pp, PyObject *args)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000842{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 PyObject *key, *def = Py_None;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200844 _Py_IDENTIFIER(get);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
847 return NULL;
Victor Stinner7e425412016-12-09 00:36:19 +0100848 return _PyObject_CallMethodIdObjArgs(pp->mapping, &PyId_get,
849 key, def, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000850}
851
852static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200853mappingproxy_keys(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000854{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200855 _Py_IDENTIFIER(keys);
Victor Stinner0db176f2012-04-16 00:16:30 +0200856 return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000857}
858
859static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200860mappingproxy_values(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000861{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200862 _Py_IDENTIFIER(values);
Victor Stinner0db176f2012-04-16 00:16:30 +0200863 return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000864}
865
866static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200867mappingproxy_items(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000868{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200869 _Py_IDENTIFIER(items);
Victor Stinner0db176f2012-04-16 00:16:30 +0200870 return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000871}
872
873static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200874mappingproxy_copy(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000875{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200876 _Py_IDENTIFIER(copy);
Victor Stinner0db176f2012-04-16 00:16:30 +0200877 return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000878}
879
Victor Stinner0db176f2012-04-16 00:16:30 +0200880/* WARNING: mappingproxy methods must not give access
881 to the underlying mapping */
882
883static PyMethodDef mappingproxy_methods[] = {
884 {"get", (PyCFunction)mappingproxy_get, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +0200886 " d defaults to None.")},
887 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000888 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +0200889 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +0200891 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000892 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +0200893 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000894 PyDoc_STR("D.copy() -> a shallow copy of D")},
895 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000896};
897
898static void
Victor Stinner0db176f2012-04-16 00:16:30 +0200899mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000900{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +0200902 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000904}
905
906static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200907mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000908{
Victor Stinner0db176f2012-04-16 00:16:30 +0200909 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000910}
911
Neil Schemenauer26775122001-10-21 22:26:43 +0000912static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200913mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000914{
Victor Stinner0db176f2012-04-16 00:16:30 +0200915 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000916}
917
Ezio Melottiac53ab62010-12-18 14:59:43 +0000918static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200919mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +0000920{
Victor Stinner0db176f2012-04-16 00:16:30 +0200921 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +0000922}
923
Guido van Rossum048eb752001-10-02 21:24:57 +0000924static int
Victor Stinner0db176f2012-04-16 00:16:30 +0200925mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +0000926{
Victor Stinner0db176f2012-04-16 00:16:30 +0200927 mappingproxyobject *pp = (mappingproxyobject *)self;
928 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000930}
931
Raymond Hettinger29a6d442002-08-31 15:51:04 +0000932static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200933mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +0000934{
Victor Stinner0db176f2012-04-16 00:16:30 +0200935 return PyObject_RichCompare(v->mapping, w, op);
936}
937
938static int
939mappingproxy_check_mapping(PyObject *mapping)
940{
941 if (!PyMapping_Check(mapping)
942 || PyList_Check(mapping)
943 || PyTuple_Check(mapping)) {
944 PyErr_Format(PyExc_TypeError,
945 "mappingproxy() argument must be a mapping, not %s",
946 Py_TYPE(mapping)->tp_name);
947 return -1;
948 }
949 return 0;
950}
951
Serhiy Storchaka18b250f2017-03-19 08:51:07 +0200952/*[clinic input]
953@classmethod
954mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +0200955
Serhiy Storchaka18b250f2017-03-19 08:51:07 +0200956 mapping: object
957
958[clinic start generated code]*/
959
960static PyObject *
961mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
962/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
963{
964 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +0200965
966 if (mappingproxy_check_mapping(mapping) == -1)
967 return NULL;
968
969 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
970 if (mappingproxy == NULL)
971 return NULL;
972 Py_INCREF(mapping);
973 mappingproxy->mapping = mapping;
974 _PyObject_GC_TRACK(mappingproxy);
975 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +0000976}
977
Tim Peters6d6c1a32001-08-02 04:15:00 +0000978PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200979PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000980{
Victor Stinner0db176f2012-04-16 00:16:30 +0200981 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000982
Victor Stinner0db176f2012-04-16 00:16:30 +0200983 if (mappingproxy_check_mapping(mapping) == -1)
984 return NULL;
985
986 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000987 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +0200988 Py_INCREF(mapping);
989 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 _PyObject_GC_TRACK(pp);
991 }
992 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000993}
994
995
996/* --- Wrapper object for "slot" methods --- */
997
998/* This has no reason to be in this file except that adding new files is a
999 bit of a pain */
1000
1001typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 PyObject_HEAD
1003 PyWrapperDescrObject *descr;
1004 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001005} wrapperobject;
1006
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001007#define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001008
Tim Peters6d6c1a32001-08-02 04:15:00 +00001009static void
1010wrapper_dealloc(wrapperobject *wp)
1011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 PyObject_GC_UnTrack(wp);
1013 Py_TRASHCAN_SAFE_BEGIN(wp)
1014 Py_XDECREF(wp->descr);
1015 Py_XDECREF(wp->self);
1016 PyObject_GC_Del(wp);
1017 Py_TRASHCAN_SAFE_END(wp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001018}
1019
Mark Dickinson211c6252009-02-01 10:28:51 +00001020#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
1021
1022static PyObject *
1023wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001024{
Benjamin Petersonca470632016-09-06 13:47:26 -07001025 intptr_t result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 PyObject *v;
1027 PyWrapperDescrObject *a_descr, *b_descr;
Mark Dickinson211c6252009-02-01 10:28:51 +00001028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 /* both arguments should be wrapperobjects */
1032 if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
1033 v = Py_NotImplemented;
1034 Py_INCREF(v);
1035 return v;
1036 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001037
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001038 /* compare by descriptor address; if the descriptors are the same,
1039 compare by the objects they're bound to */
1040 a_descr = ((wrapperobject *)a)->descr;
1041 b_descr = ((wrapperobject *)b)->descr;
1042 if (a_descr == b_descr) {
1043 a = ((wrapperobject *)a)->self;
1044 b = ((wrapperobject *)b)->self;
1045 return PyObject_RichCompare(a, b, op);
1046 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 result = a_descr - b_descr;
1049 switch (op) {
1050 case Py_EQ:
1051 v = TEST_COND(result == 0);
1052 break;
1053 case Py_NE:
1054 v = TEST_COND(result != 0);
1055 break;
1056 case Py_LE:
1057 v = TEST_COND(result <= 0);
1058 break;
1059 case Py_GE:
1060 v = TEST_COND(result >= 0);
1061 break;
1062 case Py_LT:
1063 v = TEST_COND(result < 0);
1064 break;
1065 case Py_GT:
1066 v = TEST_COND(result > 0);
1067 break;
1068 default:
1069 PyErr_BadArgument();
1070 return NULL;
1071 }
1072 Py_INCREF(v);
1073 return v;
Armin Rigoc6686b72005-11-07 08:38:00 +00001074}
1075
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001076static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001077wrapper_hash(wrapperobject *wp)
1078{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001079 Py_hash_t x, y;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 x = _Py_HashPointer(wp->descr);
1081 if (x == -1)
1082 return -1;
1083 y = PyObject_Hash(wp->self);
1084 if (y == -1)
1085 return -1;
1086 x = x ^ y;
1087 if (x == -1)
1088 x = -2;
1089 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001090}
1091
Armin Rigoc6686b72005-11-07 08:38:00 +00001092static PyObject *
1093wrapper_repr(wrapperobject *wp)
1094{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001095 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1096 wp->descr->d_base->name,
1097 wp->self->ob_type->tp_name,
1098 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001099}
1100
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001101static PyObject *
1102wrapper_reduce(wrapperobject *wp)
1103{
1104 PyObject *builtins;
1105 PyObject *getattr;
1106 _Py_IDENTIFIER(getattr);
1107
1108 builtins = PyEval_GetBuiltins();
1109 getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
1110 return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
1111}
1112
1113static PyMethodDef wrapper_methods[] = {
1114 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1115 {NULL, NULL}
1116};
1117
Armin Rigoc6686b72005-11-07 08:38:00 +00001118static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1120 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001121};
1122
1123static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +00001124wrapper_objclass(wrapperobject *wp)
1125{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001126 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001127
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 Py_INCREF(c);
1129 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001130}
1131
1132static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +00001133wrapper_name(wrapperobject *wp)
1134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001138}
1139
1140static PyObject *
Larry Hastings5c661892014-01-24 06:17:25 -08001141wrapper_doc(wrapperobject *wp, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001142{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001143 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001144}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001145
Larry Hastings5c661892014-01-24 06:17:25 -08001146static PyObject *
1147wrapper_text_signature(wrapperobject *wp, void *closure)
1148{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001149 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001150}
1151
Antoine Pitrou9d574812011-12-12 13:47:25 +01001152static PyObject *
1153wrapper_qualname(wrapperobject *wp)
1154{
1155 return descr_get_qualname((PyDescrObject *)wp->descr);
1156}
1157
Guido van Rossum32d34c82001-09-20 21:45:26 +00001158static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 {"__objclass__", (getter)wrapper_objclass},
1160 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001161 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001163 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001165};
1166
1167static PyObject *
1168wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 wrapperfunc wrapper = wp->descr->d_base->wrapper;
1171 PyObject *self = wp->self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
1174 wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
1175 return (*wk)(self, args, wp->descr->d_wrapped, kwds);
1176 }
Guido van Rossumc8e56452001-10-22 00:43:43 +00001177
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001178 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka5eb788b2017-06-06 18:45:22 +03001180 "wrapper %s() takes no keyword arguments",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 wp->descr->d_base->name);
1182 return NULL;
1183 }
1184 return (*wrapper)(self, args, wp->descr->d_wrapped);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001185}
1186
Guido van Rossum048eb752001-10-02 21:24:57 +00001187static int
1188wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 wrapperobject *wp = (wrapperobject *)self;
1191 Py_VISIT(wp->descr);
1192 Py_VISIT(wp->self);
1193 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001194}
1195
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001196PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1198 "method-wrapper", /* tp_name */
1199 sizeof(wrapperobject), /* tp_basicsize */
1200 0, /* tp_itemsize */
1201 /* methods */
1202 (destructor)wrapper_dealloc, /* tp_dealloc */
1203 0, /* tp_print */
1204 0, /* tp_getattr */
1205 0, /* tp_setattr */
1206 0, /* tp_reserved */
1207 (reprfunc)wrapper_repr, /* tp_repr */
1208 0, /* tp_as_number */
1209 0, /* tp_as_sequence */
1210 0, /* tp_as_mapping */
1211 (hashfunc)wrapper_hash, /* tp_hash */
1212 (ternaryfunc)wrapper_call, /* tp_call */
1213 0, /* tp_str */
1214 PyObject_GenericGetAttr, /* tp_getattro */
1215 0, /* tp_setattro */
1216 0, /* tp_as_buffer */
1217 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1218 0, /* tp_doc */
1219 wrapper_traverse, /* tp_traverse */
1220 0, /* tp_clear */
1221 wrapper_richcompare, /* tp_richcompare */
1222 0, /* tp_weaklistoffset */
1223 0, /* tp_iter */
1224 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001225 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 wrapper_members, /* tp_members */
1227 wrapper_getsets, /* tp_getset */
1228 0, /* tp_base */
1229 0, /* tp_dict */
1230 0, /* tp_descr_get */
1231 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001232};
1233
1234PyObject *
1235PyWrapper_New(PyObject *d, PyObject *self)
1236{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 wrapperobject *wp;
1238 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1241 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001242 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001243 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001244
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001245 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 if (wp != NULL) {
1247 Py_INCREF(descr);
1248 wp->descr = descr;
1249 Py_INCREF(self);
1250 wp->self = self;
1251 _PyObject_GC_TRACK(wp);
1252 }
1253 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001254}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001255
1256
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001257/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001258
1259/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001260class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1263 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001264 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 self.__get = fget
1266 self.__set = fset
1267 self.__del = fdel
1268 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 def __get__(self, inst, type=None):
1271 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001272 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001274 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 def __set__(self, inst, value):
1278 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001279 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 def __delete__(self, inst):
1283 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001284 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001286
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001287*/
1288
1289typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 PyObject_HEAD
1291 PyObject *prop_get;
1292 PyObject *prop_set;
1293 PyObject *prop_del;
1294 PyObject *prop_doc;
1295 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001296} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001297
Christian Heimes0449f632007-12-15 01:27:15 +00001298static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001299 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001300
Tim Peters66c1a522001-09-24 21:17:50 +00001301static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1303 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1304 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001305 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001307};
1308
Christian Heimes0449f632007-12-15 01:27:15 +00001309
Guido van Rossum58da9312007-11-10 23:39:45 +00001310PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001312
Neal Norwitz32dde222008-04-15 06:43:13 +00001313static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001314property_getter(PyObject *self, PyObject *getter)
1315{
Benjamin Peterson93964832010-06-28 03:07:10 +00001316 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001317}
1318
Christian Heimes0449f632007-12-15 01:27:15 +00001319
Guido van Rossum58da9312007-11-10 23:39:45 +00001320PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001322
Neal Norwitz32dde222008-04-15 06:43:13 +00001323static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001324property_setter(PyObject *self, PyObject *setter)
1325{
Benjamin Peterson93964832010-06-28 03:07:10 +00001326 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001327}
1328
Christian Heimes0449f632007-12-15 01:27:15 +00001329
Guido van Rossum58da9312007-11-10 23:39:45 +00001330PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001332
Neal Norwitz32dde222008-04-15 06:43:13 +00001333static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001334property_deleter(PyObject *self, PyObject *deleter)
1335{
Benjamin Peterson93964832010-06-28 03:07:10 +00001336 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001337}
1338
1339
Guido van Rossum58da9312007-11-10 23:39:45 +00001340static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 {"getter", property_getter, METH_O, getter_doc},
1342 {"setter", property_setter, METH_O, setter_doc},
1343 {"deleter", property_deleter, METH_O, deleter_doc},
1344 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001345};
1346
Tim Peters66c1a522001-09-24 21:17:50 +00001347
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001348static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001349property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001350{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 _PyObject_GC_UNTRACK(self);
1354 Py_XDECREF(gs->prop_get);
1355 Py_XDECREF(gs->prop_set);
1356 Py_XDECREF(gs->prop_del);
1357 Py_XDECREF(gs->prop_doc);
1358 self->ob_type->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001359}
1360
1361static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001362property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001363{
Serhiy Storchakaa7a0ad62015-05-24 21:38:06 +03001364 static PyObject * volatile cached_args = NULL;
1365 PyObject *args;
Raymond Hettingerc4e335b2015-04-30 08:08:13 -07001366 PyObject *ret;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 if (obj == NULL || obj == Py_None) {
1370 Py_INCREF(self);
1371 return self;
1372 }
1373 if (gs->prop_get == NULL) {
1374 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1375 return NULL;
1376 }
Serhiy Storchakaa7a0ad62015-05-24 21:38:06 +03001377 args = cached_args;
Serhiy Storchaka7822f152016-05-04 21:42:05 +03001378 cached_args = NULL;
1379 if (!args) {
1380 args = PyTuple_New(1);
1381 if (!args)
Serhiy Storchakaa7a0ad62015-05-24 21:38:06 +03001382 return NULL;
Serhiy Storchaka7822f152016-05-04 21:42:05 +03001383 _PyObject_GC_UNTRACK(args);
Raymond Hettingerc4e335b2015-04-30 08:08:13 -07001384 }
Serhiy Storchakaa7a0ad62015-05-24 21:38:06 +03001385 Py_INCREF(obj);
Raymond Hettingerc4e335b2015-04-30 08:08:13 -07001386 PyTuple_SET_ITEM(args, 0, obj);
1387 ret = PyObject_Call(gs->prop_get, args, NULL);
Serhiy Storchaka7822f152016-05-04 21:42:05 +03001388 if (cached_args == NULL && Py_REFCNT(args) == 1) {
Serhiy Storchakafff9a312017-03-21 08:53:25 +02001389 assert(PyTuple_GET_SIZE(args) == 1);
Serhiy Storchaka7822f152016-05-04 21:42:05 +03001390 assert(PyTuple_GET_ITEM(args, 0) == obj);
1391 cached_args = args;
1392 Py_DECREF(obj);
Serhiy Storchakaa7a0ad62015-05-24 21:38:06 +03001393 }
Serhiy Storchaka7822f152016-05-04 21:42:05 +03001394 else {
1395 assert(Py_REFCNT(args) >= 1);
1396 _PyObject_GC_TRACK(args);
1397 Py_DECREF(args);
1398 }
Raymond Hettingerc4e335b2015-04-30 08:08:13 -07001399 return ret;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001400}
1401
1402static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001403property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001404{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 propertyobject *gs = (propertyobject *)self;
1406 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 if (value == NULL)
1409 func = gs->prop_del;
1410 else
1411 func = gs->prop_set;
1412 if (func == NULL) {
1413 PyErr_SetString(PyExc_AttributeError,
1414 value == NULL ?
1415 "can't delete attribute" :
1416 "can't set attribute");
1417 return -1;
1418 }
1419 if (value == NULL)
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001420 res = PyObject_CallFunctionObjArgs(func, obj, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001422 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 if (res == NULL)
1424 return -1;
1425 Py_DECREF(res);
1426 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001427}
1428
Christian Heimes0449f632007-12-15 01:27:15 +00001429static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001430property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001433 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 type = PyObject_Type(old);
1436 if (type == NULL)
1437 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 if (get == NULL || get == Py_None) {
1440 Py_XDECREF(get);
1441 get = pold->prop_get ? pold->prop_get : Py_None;
1442 }
1443 if (set == NULL || set == Py_None) {
1444 Py_XDECREF(set);
1445 set = pold->prop_set ? pold->prop_set : Py_None;
1446 }
1447 if (del == NULL || del == Py_None) {
1448 Py_XDECREF(del);
1449 del = pold->prop_del ? pold->prop_del : Py_None;
1450 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001451 if (pold->getter_doc && get != Py_None) {
1452 /* make _init use __doc__ from getter */
1453 doc = Py_None;
1454 }
1455 else {
1456 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001458
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001459 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 Py_DECREF(type);
1461 if (new == NULL)
1462 return NULL;
1463 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001464}
1465
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001466/*[clinic input]
1467property.__init__ as property_init
1468
1469 fget: object(c_default="NULL") = None
1470 function to be used for getting an attribute value
1471 fset: object(c_default="NULL") = None
1472 function to be used for setting an attribute value
1473 fdel: object(c_default="NULL") = None
1474 function to be used for del'ing an attribute
1475 doc: object(c_default="NULL") = None
1476 docstring
1477
1478Property attribute.
1479
1480Typical use is to define a managed attribute x:
1481
1482class C(object):
1483 def getx(self): return self._x
1484 def setx(self, value): self._x = value
1485 def delx(self): del self._x
1486 x = property(getx, setx, delx, "I'm the 'x' property.")
1487
1488Decorators make defining new properties or modifying existing ones easy:
1489
1490class C(object):
1491 @property
1492 def x(self):
1493 "I am the 'x' property."
1494 return self._x
1495 @x.setter
1496 def x(self, value):
1497 self._x = value
1498 @x.deleter
1499 def x(self):
1500 del self._x
1501[clinic start generated code]*/
1502
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001503static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001504property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1505 PyObject *fdel, PyObject *doc)
1506/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001507{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001508 if (fget == Py_None)
1509 fget = NULL;
1510 if (fset == Py_None)
1511 fset = NULL;
1512 if (fdel == Py_None)
1513 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001514
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001515 Py_XINCREF(fget);
1516 Py_XINCREF(fset);
1517 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001519
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001520 self->prop_get = fget;
1521 self->prop_set = fset;
1522 self->prop_del = fdel;
1523 self->prop_doc = doc;
1524 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001527 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001528 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001529 PyObject *get_doc = _PyObject_GetAttrId(fget, &PyId___doc__);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 if (get_doc) {
1531 if (Py_TYPE(self) == &PyProperty_Type) {
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001532 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 }
1534 else {
1535 /* If this is a property subclass, put __doc__
1536 in dict of the subclass instance instead,
1537 otherwise it gets shadowed by __doc__ in the
1538 class's dict. */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001539 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 Py_DECREF(get_doc);
1541 if (err < 0)
1542 return -1;
1543 }
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001544 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 }
1546 else if (PyErr_ExceptionMatches(PyExc_Exception)) {
1547 PyErr_Clear();
1548 }
1549 else {
1550 return -1;
1551 }
1552 }
1553
1554 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001555}
1556
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001557static PyObject *
1558property_get___isabstractmethod__(propertyobject *prop, void *closure)
1559{
1560 int res = _PyObject_IsAbstract(prop->prop_get);
1561 if (res == -1) {
1562 return NULL;
1563 }
1564 else if (res) {
1565 Py_RETURN_TRUE;
1566 }
1567
1568 res = _PyObject_IsAbstract(prop->prop_set);
1569 if (res == -1) {
1570 return NULL;
1571 }
1572 else if (res) {
1573 Py_RETURN_TRUE;
1574 }
1575
1576 res = _PyObject_IsAbstract(prop->prop_del);
1577 if (res == -1) {
1578 return NULL;
1579 }
1580 else if (res) {
1581 Py_RETURN_TRUE;
1582 }
1583 Py_RETURN_FALSE;
1584}
1585
1586static PyGetSetDef property_getsetlist[] = {
1587 {"__isabstractmethod__",
1588 (getter)property_get___isabstractmethod__, NULL,
1589 NULL,
1590 NULL},
1591 {NULL} /* Sentinel */
1592};
1593
Guido van Rossum048eb752001-10-02 21:24:57 +00001594static int
1595property_traverse(PyObject *self, visitproc visit, void *arg)
1596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 propertyobject *pp = (propertyobject *)self;
1598 Py_VISIT(pp->prop_get);
1599 Py_VISIT(pp->prop_set);
1600 Py_VISIT(pp->prop_del);
1601 Py_VISIT(pp->prop_doc);
1602 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001603}
1604
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001605static int
1606property_clear(PyObject *self)
1607{
1608 propertyobject *pp = (propertyobject *)self;
1609 Py_CLEAR(pp->prop_doc);
1610 return 0;
1611}
1612
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001613#include "clinic/descrobject.c.h"
1614
1615PyTypeObject PyDictProxy_Type = {
1616 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1617 "mappingproxy", /* tp_name */
1618 sizeof(mappingproxyobject), /* tp_basicsize */
1619 0, /* tp_itemsize */
1620 /* methods */
1621 (destructor)mappingproxy_dealloc, /* tp_dealloc */
1622 0, /* tp_print */
1623 0, /* tp_getattr */
1624 0, /* tp_setattr */
1625 0, /* tp_reserved */
1626 (reprfunc)mappingproxy_repr, /* tp_repr */
1627 0, /* tp_as_number */
1628 &mappingproxy_as_sequence, /* tp_as_sequence */
1629 &mappingproxy_as_mapping, /* tp_as_mapping */
1630 0, /* tp_hash */
1631 0, /* tp_call */
1632 (reprfunc)mappingproxy_str, /* tp_str */
1633 PyObject_GenericGetAttr, /* tp_getattro */
1634 0, /* tp_setattro */
1635 0, /* tp_as_buffer */
1636 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1637 0, /* tp_doc */
1638 mappingproxy_traverse, /* tp_traverse */
1639 0, /* tp_clear */
1640 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1641 0, /* tp_weaklistoffset */
1642 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1643 0, /* tp_iternext */
1644 mappingproxy_methods, /* tp_methods */
1645 0, /* tp_members */
1646 0, /* tp_getset */
1647 0, /* tp_base */
1648 0, /* tp_dict */
1649 0, /* tp_descr_get */
1650 0, /* tp_descr_set */
1651 0, /* tp_dictoffset */
1652 0, /* tp_init */
1653 0, /* tp_alloc */
1654 mappingproxy_new, /* tp_new */
1655};
1656
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001657PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1659 "property", /* tp_name */
1660 sizeof(propertyobject), /* tp_basicsize */
1661 0, /* tp_itemsize */
1662 /* methods */
1663 property_dealloc, /* tp_dealloc */
1664 0, /* tp_print */
1665 0, /* tp_getattr */
1666 0, /* tp_setattr */
1667 0, /* tp_reserved */
1668 0, /* tp_repr */
1669 0, /* tp_as_number */
1670 0, /* tp_as_sequence */
1671 0, /* tp_as_mapping */
1672 0, /* tp_hash */
1673 0, /* tp_call */
1674 0, /* tp_str */
1675 PyObject_GenericGetAttr, /* tp_getattro */
1676 0, /* tp_setattro */
1677 0, /* tp_as_buffer */
1678 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1679 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001680 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001681 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001682 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 0, /* tp_richcompare */
1684 0, /* tp_weaklistoffset */
1685 0, /* tp_iter */
1686 0, /* tp_iternext */
1687 property_methods, /* tp_methods */
1688 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001689 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690 0, /* tp_base */
1691 0, /* tp_dict */
1692 property_descr_get, /* tp_descr_get */
1693 property_descr_set, /* tp_descr_set */
1694 0, /* tp_dictoffset */
1695 property_init, /* tp_init */
1696 PyType_GenericAlloc, /* tp_alloc */
1697 PyType_GenericNew, /* tp_new */
1698 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001699};