symbian-qemu-0.9.1-12/python-2.6.1/Objects/descrobject.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* Descriptors -- a new, flexible way to describe attributes */
       
     2 
       
     3 #include "Python.h"
       
     4 #include "structmember.h" /* Why is this not included in Python.h? */
       
     5 
       
     6 static void
       
     7 descr_dealloc(PyDescrObject *descr)
       
     8 {
       
     9 	_PyObject_GC_UNTRACK(descr);
       
    10 	Py_XDECREF(descr->d_type);
       
    11 	Py_XDECREF(descr->d_name);
       
    12 	PyObject_GC_Del(descr);
       
    13 }
       
    14 
       
    15 static char *
       
    16 descr_name(PyDescrObject *descr)
       
    17 {
       
    18 	if (descr->d_name != NULL && PyString_Check(descr->d_name))
       
    19 		return PyString_AS_STRING(descr->d_name);
       
    20 	else
       
    21 		return "?";
       
    22 }
       
    23 
       
    24 static PyObject *
       
    25 descr_repr(PyDescrObject *descr, char *format)
       
    26 {
       
    27 	return PyString_FromFormat(format, descr_name(descr),
       
    28 				   descr->d_type->tp_name);
       
    29 }
       
    30 
       
    31 static PyObject *
       
    32 method_repr(PyMethodDescrObject *descr)
       
    33 {
       
    34 	return descr_repr((PyDescrObject *)descr, 
       
    35 			  "<method '%s' of '%s' objects>");
       
    36 }
       
    37 
       
    38 static PyObject *
       
    39 member_repr(PyMemberDescrObject *descr)
       
    40 {
       
    41 	return descr_repr((PyDescrObject *)descr, 
       
    42 			  "<member '%s' of '%s' objects>");
       
    43 }
       
    44 
       
    45 static PyObject *
       
    46 getset_repr(PyGetSetDescrObject *descr)
       
    47 {
       
    48 	return descr_repr((PyDescrObject *)descr, 
       
    49 			  "<attribute '%s' of '%s' objects>");
       
    50 }
       
    51 
       
    52 static PyObject *
       
    53 wrapperdescr_repr(PyWrapperDescrObject *descr)
       
    54 {
       
    55 	return descr_repr((PyDescrObject *)descr, 
       
    56 			  "<slot wrapper '%s' of '%s' objects>");
       
    57 }
       
    58 
       
    59 static int
       
    60 descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
       
    61 {
       
    62 	if (obj == NULL) {
       
    63 		Py_INCREF(descr);
       
    64 		*pres = (PyObject *)descr;
       
    65 		return 1;
       
    66 	}
       
    67 	if (!PyObject_TypeCheck(obj, descr->d_type)) {
       
    68 		PyErr_Format(PyExc_TypeError,
       
    69 			     "descriptor '%s' for '%s' objects "
       
    70 			     "doesn't apply to '%s' object",
       
    71 			     descr_name((PyDescrObject *)descr),
       
    72 			     descr->d_type->tp_name,
       
    73 			     obj->ob_type->tp_name);
       
    74 		*pres = NULL;
       
    75 		return 1;
       
    76 	}
       
    77 	return 0;
       
    78 }
       
    79 
       
    80 static PyObject *
       
    81 classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
       
    82 {
       
    83 	/* Ensure a valid type.  Class methods ignore obj. */
       
    84 	if (type == NULL) {
       
    85 		if (obj != NULL)
       
    86 			type = (PyObject *)obj->ob_type;
       
    87 		else {
       
    88 			/* Wot - no type?! */
       
    89 			PyErr_Format(PyExc_TypeError,
       
    90 				     "descriptor '%s' for type '%s' "
       
    91 				     "needs either an object or a type",
       
    92 				     descr_name((PyDescrObject *)descr),
       
    93 				     descr->d_type->tp_name);
       
    94 			return NULL;
       
    95 		}
       
    96 	}
       
    97 	if (!PyType_Check(type)) {
       
    98 		PyErr_Format(PyExc_TypeError,
       
    99 			     "descriptor '%s' for type '%s' "
       
   100 			     "needs a type, not a '%s' as arg 2",
       
   101 			     descr_name((PyDescrObject *)descr),
       
   102 			     descr->d_type->tp_name,
       
   103 			     type->ob_type->tp_name);
       
   104 		return NULL;
       
   105 	}
       
   106 	if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) {
       
   107 		PyErr_Format(PyExc_TypeError,
       
   108 			     "descriptor '%s' for type '%s' "
       
   109 			     "doesn't apply to type '%s'",
       
   110 			     descr_name((PyDescrObject *)descr),
       
   111 			     descr->d_type->tp_name,
       
   112 			     ((PyTypeObject *)type)->tp_name);
       
   113 		return NULL;
       
   114 	}
       
   115 	return PyCFunction_New(descr->d_method, type);
       
   116 }
       
   117 
       
   118 static PyObject *
       
   119 method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
       
   120 {
       
   121 	PyObject *res;
       
   122 
       
   123 	if (descr_check((PyDescrObject *)descr, obj, &res))
       
   124 		return res;
       
   125 	return PyCFunction_New(descr->d_method, obj);
       
   126 }
       
   127 
       
   128 static PyObject *
       
   129 member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
       
   130 {
       
   131 	PyObject *res;
       
   132 
       
   133 	if (descr_check((PyDescrObject *)descr, obj, &res))
       
   134 		return res;
       
   135 	return PyMember_GetOne((char *)obj, descr->d_member);
       
   136 }
       
   137 
       
   138 static PyObject *
       
   139 getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
       
   140 {
       
   141 	PyObject *res;
       
   142 
       
   143 	if (descr_check((PyDescrObject *)descr, obj, &res))
       
   144 		return res;
       
   145 	if (descr->d_getset->get != NULL)
       
   146 		return descr->d_getset->get(obj, descr->d_getset->closure);
       
   147 	PyErr_Format(PyExc_AttributeError,
       
   148 		     "attribute '%.300s' of '%.100s' objects is not readable",
       
   149 		     descr_name((PyDescrObject *)descr),
       
   150 		     descr->d_type->tp_name);
       
   151 	return NULL;
       
   152 }
       
   153 
       
   154 static PyObject *
       
   155 wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
       
   156 {
       
   157 	PyObject *res;
       
   158 
       
   159 	if (descr_check((PyDescrObject *)descr, obj, &res))
       
   160 		return res;
       
   161 	return PyWrapper_New((PyObject *)descr, obj);
       
   162 }
       
   163 
       
   164 static int
       
   165 descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
       
   166 	       int *pres)
       
   167 {
       
   168 	assert(obj != NULL);
       
   169 	if (!PyObject_TypeCheck(obj, descr->d_type)) {
       
   170 		PyErr_Format(PyExc_TypeError,
       
   171 			     "descriptor '%.200s' for '%.100s' objects "
       
   172 			     "doesn't apply to '%.100s' object",
       
   173 			     descr_name(descr),
       
   174 			     descr->d_type->tp_name,
       
   175 			     obj->ob_type->tp_name);
       
   176 		*pres = -1;
       
   177 		return 1;
       
   178 	}
       
   179 	return 0;
       
   180 }
       
   181 
       
   182 static int
       
   183 member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
       
   184 {
       
   185 	int res;
       
   186 
       
   187 	if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
       
   188 		return res;
       
   189 	return PyMember_SetOne((char *)obj, descr->d_member, value);
       
   190 }
       
   191 
       
   192 static int
       
   193 getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
       
   194 {
       
   195 	int res;
       
   196 
       
   197 	if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
       
   198 		return res;
       
   199 	if (descr->d_getset->set != NULL)
       
   200 		return descr->d_getset->set(obj, value,
       
   201 					    descr->d_getset->closure);
       
   202 	PyErr_Format(PyExc_AttributeError,
       
   203 		     "attribute '%.300s' of '%.100s' objects is not writable",
       
   204 		     descr_name((PyDescrObject *)descr),
       
   205 		     descr->d_type->tp_name);
       
   206 	return -1;
       
   207 }
       
   208 
       
   209 static PyObject *
       
   210 methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
       
   211 {
       
   212 	Py_ssize_t argc;
       
   213 	PyObject *self, *func, *result;
       
   214 
       
   215 	/* Make sure that the first argument is acceptable as 'self' */
       
   216 	assert(PyTuple_Check(args));
       
   217 	argc = PyTuple_GET_SIZE(args);
       
   218 	if (argc < 1) {
       
   219 		PyErr_Format(PyExc_TypeError,
       
   220 			     "descriptor '%.300s' of '%.100s' "
       
   221 			     "object needs an argument",
       
   222 			     descr_name((PyDescrObject *)descr),
       
   223 			     descr->d_type->tp_name);
       
   224 		return NULL;
       
   225 	}
       
   226 	self = PyTuple_GET_ITEM(args, 0);
       
   227 	if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
       
   228 		PyErr_Format(PyExc_TypeError,
       
   229 			     "descriptor '%.200s' "
       
   230 			     "requires a '%.100s' object "
       
   231 			     "but received a '%.100s'",
       
   232 			     descr_name((PyDescrObject *)descr),
       
   233 			     descr->d_type->tp_name,
       
   234 			     self->ob_type->tp_name);
       
   235 		return NULL;
       
   236 	}
       
   237 
       
   238 	func = PyCFunction_New(descr->d_method, self);
       
   239 	if (func == NULL)
       
   240 		return NULL;
       
   241 	args = PyTuple_GetSlice(args, 1, argc);
       
   242 	if (args == NULL) {
       
   243 		Py_DECREF(func);
       
   244 		return NULL;
       
   245 	}
       
   246 	result = PyEval_CallObjectWithKeywords(func, args, kwds);
       
   247 	Py_DECREF(args);
       
   248 	Py_DECREF(func);
       
   249 	return result;
       
   250 }
       
   251 
       
   252 static PyObject *
       
   253 classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
       
   254 		      PyObject *kwds)
       
   255 {
       
   256 	PyObject *func, *result;
       
   257 
       
   258 	func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
       
   259 	if (func == NULL)
       
   260 		return NULL;
       
   261 
       
   262 	result = PyEval_CallObjectWithKeywords(func, args, kwds);
       
   263 	Py_DECREF(func);
       
   264 	return result;
       
   265 }
       
   266 
       
   267 static PyObject *
       
   268 wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
       
   269 {
       
   270 	Py_ssize_t argc;
       
   271 	PyObject *self, *func, *result;
       
   272 
       
   273 	/* Make sure that the first argument is acceptable as 'self' */
       
   274 	assert(PyTuple_Check(args));
       
   275 	argc = PyTuple_GET_SIZE(args);
       
   276 	if (argc < 1) {
       
   277 		PyErr_Format(PyExc_TypeError,
       
   278 			     "descriptor '%.300s' of '%.100s' "
       
   279 			     "object needs an argument",
       
   280 			     descr_name((PyDescrObject *)descr),
       
   281 			     descr->d_type->tp_name);
       
   282 		return NULL;
       
   283 	}
       
   284 	self = PyTuple_GET_ITEM(args, 0);
       
   285 	if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
       
   286 		PyErr_Format(PyExc_TypeError,
       
   287 			     "descriptor '%.200s' "
       
   288 			     "requires a '%.100s' object "
       
   289 			     "but received a '%.100s'",
       
   290 			     descr_name((PyDescrObject *)descr),
       
   291 			     descr->d_type->tp_name,
       
   292 			     self->ob_type->tp_name);
       
   293 		return NULL;
       
   294 	}
       
   295 
       
   296 	func = PyWrapper_New((PyObject *)descr, self);
       
   297 	if (func == NULL)
       
   298 		return NULL;
       
   299 	args = PyTuple_GetSlice(args, 1, argc);
       
   300 	if (args == NULL) {
       
   301 		Py_DECREF(func);
       
   302 		return NULL;
       
   303 	}
       
   304 	result = PyEval_CallObjectWithKeywords(func, args, kwds);
       
   305 	Py_DECREF(args);
       
   306 	Py_DECREF(func);
       
   307 	return result;
       
   308 }
       
   309 
       
   310 static PyObject *
       
   311 method_get_doc(PyMethodDescrObject *descr, void *closure)
       
   312 {
       
   313 	if (descr->d_method->ml_doc == NULL) {
       
   314 		Py_INCREF(Py_None);
       
   315 		return Py_None;
       
   316 	}
       
   317 	return PyString_FromString(descr->d_method->ml_doc);
       
   318 }
       
   319 
       
   320 static PyMemberDef descr_members[] = {
       
   321 	{"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
       
   322 	{"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
       
   323 	{0}
       
   324 };
       
   325 
       
   326 static PyGetSetDef method_getset[] = {
       
   327 	{"__doc__", (getter)method_get_doc},
       
   328 	{0}
       
   329 };
       
   330 
       
   331 static PyObject *
       
   332 member_get_doc(PyMemberDescrObject *descr, void *closure)
       
   333 {
       
   334 	if (descr->d_member->doc == NULL) {
       
   335 		Py_INCREF(Py_None);
       
   336 		return Py_None;
       
   337 	}
       
   338 	return PyString_FromString(descr->d_member->doc);
       
   339 }
       
   340 
       
   341 static PyGetSetDef member_getset[] = {
       
   342 	{"__doc__", (getter)member_get_doc},
       
   343 	{0}
       
   344 };
       
   345 
       
   346 static PyObject *
       
   347 getset_get_doc(PyGetSetDescrObject *descr, void *closure)
       
   348 {
       
   349 	if (descr->d_getset->doc == NULL) {
       
   350 		Py_INCREF(Py_None);
       
   351 		return Py_None;
       
   352 	}
       
   353 	return PyString_FromString(descr->d_getset->doc);
       
   354 }
       
   355 
       
   356 static PyGetSetDef getset_getset[] = {
       
   357 	{"__doc__", (getter)getset_get_doc},
       
   358 	{0}
       
   359 };
       
   360 
       
   361 static PyObject *
       
   362 wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
       
   363 {
       
   364 	if (descr->d_base->doc == NULL) {
       
   365 		Py_INCREF(Py_None);
       
   366 		return Py_None;
       
   367 	}
       
   368 	return PyString_FromString(descr->d_base->doc);
       
   369 }
       
   370 
       
   371 static PyGetSetDef wrapperdescr_getset[] = {
       
   372 	{"__doc__", (getter)wrapperdescr_get_doc},
       
   373 	{0}
       
   374 };
       
   375 
       
   376 static int
       
   377 descr_traverse(PyObject *self, visitproc visit, void *arg)
       
   378 {
       
   379 	PyDescrObject *descr = (PyDescrObject *)self;
       
   380 	Py_VISIT(descr->d_type);
       
   381 	return 0;
       
   382 }
       
   383 
       
   384 static PyTypeObject PyMethodDescr_Type = {
       
   385 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   386 	"method_descriptor",
       
   387 	sizeof(PyMethodDescrObject),
       
   388 	0,
       
   389 	(destructor)descr_dealloc,		/* tp_dealloc */
       
   390 	0,					/* tp_print */
       
   391 	0,					/* tp_getattr */
       
   392 	0,					/* tp_setattr */
       
   393 	0,					/* tp_compare */
       
   394 	(reprfunc)method_repr,			/* tp_repr */
       
   395 	0,					/* tp_as_number */
       
   396 	0,					/* tp_as_sequence */
       
   397 	0,					/* tp_as_mapping */
       
   398 	0,					/* tp_hash */
       
   399 	(ternaryfunc)methoddescr_call,		/* tp_call */
       
   400 	0,					/* tp_str */
       
   401 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   402 	0,					/* tp_setattro */
       
   403 	0,					/* tp_as_buffer */
       
   404 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   405 	0,					/* tp_doc */
       
   406 	descr_traverse,				/* tp_traverse */
       
   407 	0,					/* tp_clear */
       
   408 	0,					/* tp_richcompare */
       
   409 	0,					/* tp_weaklistoffset */
       
   410 	0,					/* tp_iter */
       
   411 	0,					/* tp_iternext */
       
   412 	0,					/* tp_methods */
       
   413 	descr_members,				/* tp_members */
       
   414 	method_getset,				/* tp_getset */
       
   415 	0,					/* tp_base */
       
   416 	0,					/* tp_dict */
       
   417 	(descrgetfunc)method_get,		/* tp_descr_get */
       
   418 	0,					/* tp_descr_set */
       
   419 };
       
   420 
       
   421 /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
       
   422 static PyTypeObject PyClassMethodDescr_Type = {
       
   423 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   424 	"classmethod_descriptor",
       
   425 	sizeof(PyMethodDescrObject),
       
   426 	0,
       
   427 	(destructor)descr_dealloc,		/* tp_dealloc */
       
   428 	0,					/* tp_print */
       
   429 	0,					/* tp_getattr */
       
   430 	0,					/* tp_setattr */
       
   431 	0,					/* tp_compare */
       
   432 	(reprfunc)method_repr,			/* tp_repr */
       
   433 	0,					/* tp_as_number */
       
   434 	0,					/* tp_as_sequence */
       
   435 	0,					/* tp_as_mapping */
       
   436 	0,					/* tp_hash */
       
   437 	(ternaryfunc)classmethoddescr_call,	/* tp_call */
       
   438 	0,					/* tp_str */
       
   439 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   440 	0,					/* tp_setattro */
       
   441 	0,					/* tp_as_buffer */
       
   442 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   443 	0,					/* tp_doc */
       
   444 	descr_traverse,				/* tp_traverse */
       
   445 	0,					/* tp_clear */
       
   446 	0,					/* tp_richcompare */
       
   447 	0,					/* tp_weaklistoffset */
       
   448 	0,					/* tp_iter */
       
   449 	0,					/* tp_iternext */
       
   450 	0,					/* tp_methods */
       
   451 	descr_members,				/* tp_members */
       
   452 	method_getset,				/* tp_getset */
       
   453 	0,					/* tp_base */
       
   454 	0,					/* tp_dict */
       
   455 	(descrgetfunc)classmethod_get,		/* tp_descr_get */
       
   456 	0,					/* tp_descr_set */
       
   457 };
       
   458 
       
   459 static PyTypeObject PyMemberDescr_Type = {
       
   460 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   461 	"member_descriptor",
       
   462 	sizeof(PyMemberDescrObject),
       
   463 	0,
       
   464 	(destructor)descr_dealloc,		/* tp_dealloc */
       
   465 	0,					/* tp_print */
       
   466 	0,					/* tp_getattr */
       
   467 	0,					/* tp_setattr */
       
   468 	0,					/* tp_compare */
       
   469 	(reprfunc)member_repr,			/* tp_repr */
       
   470 	0,					/* tp_as_number */
       
   471 	0,					/* tp_as_sequence */
       
   472 	0,					/* tp_as_mapping */
       
   473 	0,					/* tp_hash */
       
   474 	0,					/* tp_call */
       
   475 	0,					/* tp_str */
       
   476 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   477 	0,					/* tp_setattro */
       
   478 	0,					/* tp_as_buffer */
       
   479 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   480 	0,					/* tp_doc */
       
   481 	descr_traverse,				/* tp_traverse */
       
   482 	0,					/* tp_clear */
       
   483 	0,					/* tp_richcompare */
       
   484 	0,					/* tp_weaklistoffset */
       
   485 	0,					/* tp_iter */
       
   486 	0,					/* tp_iternext */
       
   487 	0,					/* tp_methods */
       
   488 	descr_members,				/* tp_members */
       
   489 	member_getset,				/* tp_getset */
       
   490 	0,					/* tp_base */
       
   491 	0,					/* tp_dict */
       
   492 	(descrgetfunc)member_get,		/* tp_descr_get */
       
   493 	(descrsetfunc)member_set,		/* tp_descr_set */
       
   494 };
       
   495 
       
   496 static PyTypeObject PyGetSetDescr_Type = {
       
   497 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   498 	"getset_descriptor",
       
   499 	sizeof(PyGetSetDescrObject),
       
   500 	0,
       
   501 	(destructor)descr_dealloc,		/* tp_dealloc */
       
   502 	0,					/* tp_print */
       
   503 	0,					/* tp_getattr */
       
   504 	0,					/* tp_setattr */
       
   505 	0,					/* tp_compare */
       
   506 	(reprfunc)getset_repr,			/* tp_repr */
       
   507 	0,					/* tp_as_number */
       
   508 	0,					/* tp_as_sequence */
       
   509 	0,					/* tp_as_mapping */
       
   510 	0,					/* tp_hash */
       
   511 	0,					/* tp_call */
       
   512 	0,					/* tp_str */
       
   513 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   514 	0,					/* tp_setattro */
       
   515 	0,					/* tp_as_buffer */
       
   516 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   517 	0,					/* tp_doc */
       
   518 	descr_traverse,				/* tp_traverse */
       
   519 	0,					/* tp_clear */
       
   520 	0,					/* tp_richcompare */
       
   521 	0,					/* tp_weaklistoffset */
       
   522 	0,					/* tp_iter */
       
   523 	0,					/* tp_iternext */
       
   524 	0,					/* tp_methods */
       
   525 	descr_members,				/* tp_members */
       
   526 	getset_getset,				/* tp_getset */
       
   527 	0,					/* tp_base */
       
   528 	0,					/* tp_dict */
       
   529 	(descrgetfunc)getset_get,		/* tp_descr_get */
       
   530 	(descrsetfunc)getset_set,		/* tp_descr_set */
       
   531 };
       
   532 
       
   533 PyTypeObject PyWrapperDescr_Type = {
       
   534 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   535 	"wrapper_descriptor",
       
   536 	sizeof(PyWrapperDescrObject),
       
   537 	0,
       
   538 	(destructor)descr_dealloc,		/* tp_dealloc */
       
   539 	0,					/* tp_print */
       
   540 	0,					/* tp_getattr */
       
   541 	0,					/* tp_setattr */
       
   542 	0,					/* tp_compare */
       
   543 	(reprfunc)wrapperdescr_repr,		/* tp_repr */
       
   544 	0,					/* tp_as_number */
       
   545 	0,					/* tp_as_sequence */
       
   546 	0,					/* tp_as_mapping */
       
   547 	0,					/* tp_hash */
       
   548 	(ternaryfunc)wrapperdescr_call,		/* tp_call */
       
   549 	0,					/* tp_str */
       
   550 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   551 	0,					/* tp_setattro */
       
   552 	0,					/* tp_as_buffer */
       
   553 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   554 	0,					/* tp_doc */
       
   555 	descr_traverse,				/* tp_traverse */
       
   556 	0,					/* tp_clear */
       
   557 	0,					/* tp_richcompare */
       
   558 	0,					/* tp_weaklistoffset */
       
   559 	0,					/* tp_iter */
       
   560 	0,					/* tp_iternext */
       
   561 	0,					/* tp_methods */
       
   562 	descr_members,				/* tp_members */
       
   563 	wrapperdescr_getset,			/* tp_getset */
       
   564 	0,					/* tp_base */
       
   565 	0,					/* tp_dict */
       
   566 	(descrgetfunc)wrapperdescr_get,		/* tp_descr_get */
       
   567 	0,					/* tp_descr_set */
       
   568 };
       
   569 
       
   570 static PyDescrObject *
       
   571 descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
       
   572 {
       
   573 	PyDescrObject *descr;
       
   574 
       
   575 	descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
       
   576 	if (descr != NULL) {
       
   577 		Py_XINCREF(type);
       
   578 		descr->d_type = type;
       
   579 		descr->d_name = PyString_InternFromString(name);
       
   580 		if (descr->d_name == NULL) {
       
   581 			Py_DECREF(descr);
       
   582 			descr = NULL;
       
   583 		}
       
   584 	}
       
   585 	return descr;
       
   586 }
       
   587 
       
   588 PyObject *
       
   589 PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
       
   590 {
       
   591 	PyMethodDescrObject *descr;
       
   592 
       
   593 	descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
       
   594 						 type, method->ml_name);
       
   595 	if (descr != NULL)
       
   596 		descr->d_method = method;
       
   597 	return (PyObject *)descr;
       
   598 }
       
   599 
       
   600 PyObject *
       
   601 PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
       
   602 {
       
   603 	PyMethodDescrObject *descr;
       
   604 
       
   605 	descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
       
   606 						 type, method->ml_name);
       
   607 	if (descr != NULL)
       
   608 		descr->d_method = method;
       
   609 	return (PyObject *)descr;
       
   610 }
       
   611 
       
   612 PyObject *
       
   613 PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
       
   614 {
       
   615 	PyMemberDescrObject *descr;
       
   616 
       
   617 	descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
       
   618 						 type, member->name);
       
   619 	if (descr != NULL)
       
   620 		descr->d_member = member;
       
   621 	return (PyObject *)descr;
       
   622 }
       
   623 
       
   624 PyObject *
       
   625 PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
       
   626 {
       
   627 	PyGetSetDescrObject *descr;
       
   628 
       
   629 	descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
       
   630 						 type, getset->name);
       
   631 	if (descr != NULL)
       
   632 		descr->d_getset = getset;
       
   633 	return (PyObject *)descr;
       
   634 }
       
   635 
       
   636 PyObject *
       
   637 PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
       
   638 {
       
   639 	PyWrapperDescrObject *descr;
       
   640 
       
   641 	descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
       
   642 						 type, base->name);
       
   643 	if (descr != NULL) {
       
   644 		descr->d_base = base;
       
   645 		descr->d_wrapped = wrapped;
       
   646 	}
       
   647 	return (PyObject *)descr;
       
   648 }
       
   649 
       
   650 
       
   651 /* --- Readonly proxy for dictionaries (actually any mapping) --- */
       
   652 
       
   653 /* This has no reason to be in this file except that adding new files is a
       
   654    bit of a pain */
       
   655 
       
   656 typedef struct {
       
   657 	PyObject_HEAD
       
   658 	PyObject *dict;
       
   659 } proxyobject;
       
   660 
       
   661 static Py_ssize_t
       
   662 proxy_len(proxyobject *pp)
       
   663 {
       
   664 	return PyObject_Size(pp->dict);
       
   665 }
       
   666 
       
   667 static PyObject *
       
   668 proxy_getitem(proxyobject *pp, PyObject *key)
       
   669 {
       
   670 	return PyObject_GetItem(pp->dict, key);
       
   671 }
       
   672 
       
   673 static PyMappingMethods proxy_as_mapping = {
       
   674 	(lenfunc)proxy_len,			/* mp_length */
       
   675 	(binaryfunc)proxy_getitem,		/* mp_subscript */
       
   676 	0,					/* mp_ass_subscript */
       
   677 };
       
   678 
       
   679 static int
       
   680 proxy_contains(proxyobject *pp, PyObject *key)
       
   681 {
       
   682 	return PyDict_Contains(pp->dict, key);
       
   683 }
       
   684 
       
   685 static PySequenceMethods proxy_as_sequence = {
       
   686 	0,					/* sq_length */
       
   687 	0,					/* sq_concat */
       
   688 	0,					/* sq_repeat */
       
   689 	0,					/* sq_item */
       
   690 	0,					/* sq_slice */
       
   691 	0,					/* sq_ass_item */
       
   692 	0,					/* sq_ass_slice */
       
   693 	(objobjproc)proxy_contains,		/* sq_contains */
       
   694 	0,					/* sq_inplace_concat */
       
   695 	0,					/* sq_inplace_repeat */
       
   696 };
       
   697 
       
   698 static PyObject *
       
   699 proxy_has_key(proxyobject *pp, PyObject *key)
       
   700 {
       
   701 	int res = PyDict_Contains(pp->dict, key);
       
   702 	if (res < 0)
       
   703 		return NULL;
       
   704 	return PyBool_FromLong(res);
       
   705 }
       
   706 
       
   707 static PyObject *
       
   708 proxy_get(proxyobject *pp, PyObject *args)
       
   709 {
       
   710 	PyObject *key, *def = Py_None;
       
   711 
       
   712 	if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
       
   713 		return NULL;
       
   714 	return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);
       
   715 }
       
   716 
       
   717 static PyObject *
       
   718 proxy_keys(proxyobject *pp)
       
   719 {
       
   720 	return PyMapping_Keys(pp->dict);
       
   721 }
       
   722 
       
   723 static PyObject *
       
   724 proxy_values(proxyobject *pp)
       
   725 {
       
   726 	return PyMapping_Values(pp->dict);
       
   727 }
       
   728 
       
   729 static PyObject *
       
   730 proxy_items(proxyobject *pp)
       
   731 {
       
   732 	return PyMapping_Items(pp->dict);
       
   733 }
       
   734 
       
   735 static PyObject *
       
   736 proxy_iterkeys(proxyobject *pp)
       
   737 {
       
   738 	return PyObject_CallMethod(pp->dict, "iterkeys", NULL);
       
   739 }
       
   740 
       
   741 static PyObject *
       
   742 proxy_itervalues(proxyobject *pp)
       
   743 {
       
   744 	return PyObject_CallMethod(pp->dict, "itervalues", NULL);
       
   745 }
       
   746 
       
   747 static PyObject *
       
   748 proxy_iteritems(proxyobject *pp)
       
   749 {
       
   750 	return PyObject_CallMethod(pp->dict, "iteritems", NULL);
       
   751 }
       
   752 static PyObject *
       
   753 proxy_copy(proxyobject *pp)
       
   754 {
       
   755 	return PyObject_CallMethod(pp->dict, "copy", NULL);
       
   756 }
       
   757 
       
   758 static PyMethodDef proxy_methods[] = {
       
   759 	{"has_key",   (PyCFunction)proxy_has_key,    METH_O,
       
   760 	 PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")},
       
   761 	{"get",       (PyCFunction)proxy_get,        METH_VARARGS,
       
   762 	 PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d."
       
   763 	 				"  d defaults to None.")},
       
   764 	{"keys",      (PyCFunction)proxy_keys,       METH_NOARGS,
       
   765 	 PyDoc_STR("D.keys() -> list of D's keys")},
       
   766 	{"values",    (PyCFunction)proxy_values,     METH_NOARGS,
       
   767 	 PyDoc_STR("D.values() -> list of D's values")},
       
   768 	{"items",     (PyCFunction)proxy_items,      METH_NOARGS,
       
   769 	 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
       
   770 	{"iterkeys",  (PyCFunction)proxy_iterkeys,   METH_NOARGS,
       
   771 	 PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")},
       
   772 	{"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS,
       
   773 	 PyDoc_STR("D.itervalues() -> an iterator over the values of D")},
       
   774 	{"iteritems", (PyCFunction)proxy_iteritems,  METH_NOARGS,
       
   775 	 PyDoc_STR("D.iteritems() ->"
       
   776 	 	   " an iterator over the (key, value) items of D")},
       
   777 	{"copy",      (PyCFunction)proxy_copy,       METH_NOARGS,
       
   778 	 PyDoc_STR("D.copy() -> a shallow copy of D")},
       
   779 	{0}
       
   780 };
       
   781 
       
   782 static void
       
   783 proxy_dealloc(proxyobject *pp)
       
   784 {
       
   785 	_PyObject_GC_UNTRACK(pp);
       
   786 	Py_DECREF(pp->dict);
       
   787 	PyObject_GC_Del(pp);
       
   788 }
       
   789 
       
   790 static PyObject *
       
   791 proxy_getiter(proxyobject *pp)
       
   792 {
       
   793 	return PyObject_GetIter(pp->dict);
       
   794 }
       
   795 
       
   796 static PyObject *
       
   797 proxy_str(proxyobject *pp)
       
   798 {
       
   799 	return PyObject_Str(pp->dict);
       
   800 }
       
   801 
       
   802 static int
       
   803 proxy_traverse(PyObject *self, visitproc visit, void *arg)
       
   804 {
       
   805 	proxyobject *pp = (proxyobject *)self;
       
   806 	Py_VISIT(pp->dict);
       
   807 	return 0;
       
   808 }
       
   809 
       
   810 static int
       
   811 proxy_compare(proxyobject *v, PyObject *w)
       
   812 {
       
   813 	return PyObject_Compare(v->dict, w);
       
   814 }
       
   815 
       
   816 static PyObject *
       
   817 proxy_richcompare(proxyobject *v, PyObject *w, int op)
       
   818 {
       
   819 	return PyObject_RichCompare(v->dict, w, op);
       
   820 }
       
   821 
       
   822 static PyTypeObject proxytype = {
       
   823 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   824 	"dictproxy",				/* tp_name */
       
   825 	sizeof(proxyobject),			/* tp_basicsize */
       
   826 	0,					/* tp_itemsize */
       
   827 	/* methods */
       
   828 	(destructor)proxy_dealloc, 		/* tp_dealloc */
       
   829 	0,					/* tp_print */
       
   830 	0,					/* tp_getattr */
       
   831 	0,					/* tp_setattr */
       
   832 	(cmpfunc)proxy_compare,			/* tp_compare */
       
   833 	0,					/* tp_repr */
       
   834 	0,					/* tp_as_number */
       
   835 	&proxy_as_sequence,			/* tp_as_sequence */
       
   836 	&proxy_as_mapping,			/* tp_as_mapping */
       
   837 	0,					/* tp_hash */
       
   838 	0,					/* tp_call */
       
   839 	(reprfunc)proxy_str,			/* tp_str */
       
   840 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   841 	0,					/* tp_setattro */
       
   842 	0,					/* tp_as_buffer */
       
   843 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
   844  	0,					/* tp_doc */
       
   845 	proxy_traverse,				/* tp_traverse */
       
   846  	0,					/* tp_clear */
       
   847 	(richcmpfunc)proxy_richcompare,		/* tp_richcompare */
       
   848 	0,					/* tp_weaklistoffset */
       
   849 	(getiterfunc)proxy_getiter,		/* tp_iter */
       
   850 	0,					/* tp_iternext */
       
   851 	proxy_methods,				/* tp_methods */
       
   852 	0,					/* tp_members */
       
   853 	0,					/* tp_getset */
       
   854 	0,					/* tp_base */
       
   855 	0,					/* tp_dict */
       
   856 	0,					/* tp_descr_get */
       
   857 	0,					/* tp_descr_set */
       
   858 };
       
   859 
       
   860 PyObject *
       
   861 PyDictProxy_New(PyObject *dict)
       
   862 {
       
   863 	proxyobject *pp;
       
   864 
       
   865 	pp = PyObject_GC_New(proxyobject, &proxytype);
       
   866 	if (pp != NULL) {
       
   867 		Py_INCREF(dict);
       
   868 		pp->dict = dict;
       
   869 		_PyObject_GC_TRACK(pp);
       
   870 	}
       
   871 	return (PyObject *)pp;
       
   872 }
       
   873 
       
   874 
       
   875 /* --- Wrapper object for "slot" methods --- */
       
   876 
       
   877 /* This has no reason to be in this file except that adding new files is a
       
   878    bit of a pain */
       
   879 
       
   880 typedef struct {
       
   881 	PyObject_HEAD
       
   882 	PyWrapperDescrObject *descr;
       
   883 	PyObject *self;
       
   884 } wrapperobject;
       
   885 
       
   886 static void
       
   887 wrapper_dealloc(wrapperobject *wp)
       
   888 {
       
   889 	PyObject_GC_UnTrack(wp);
       
   890 	Py_TRASHCAN_SAFE_BEGIN(wp)
       
   891 	Py_XDECREF(wp->descr);
       
   892 	Py_XDECREF(wp->self);
       
   893 	PyObject_GC_Del(wp);
       
   894 	Py_TRASHCAN_SAFE_END(wp)
       
   895 }
       
   896 
       
   897 static int
       
   898 wrapper_compare(wrapperobject *a, wrapperobject *b)
       
   899 {
       
   900 	if (a->descr == b->descr)
       
   901 		return PyObject_Compare(a->self, b->self);
       
   902 	else
       
   903 		return (a->descr < b->descr) ? -1 : 1;
       
   904 }
       
   905 
       
   906 static long
       
   907 wrapper_hash(wrapperobject *wp)
       
   908 {
       
   909 	int x, y;
       
   910 	x = _Py_HashPointer(wp->descr);
       
   911 	if (x == -1)
       
   912 		return -1;
       
   913 	y = PyObject_Hash(wp->self);
       
   914 	if (y == -1)
       
   915 		return -1;
       
   916 	x = x ^ y;
       
   917 	if (x == -1)
       
   918 		x = -2;
       
   919 	return x;
       
   920 }
       
   921 
       
   922 static PyObject *
       
   923 wrapper_repr(wrapperobject *wp)
       
   924 {
       
   925 	return PyString_FromFormat("<method-wrapper '%s' of %s object at %p>",
       
   926 				   wp->descr->d_base->name,
       
   927 				   wp->self->ob_type->tp_name,
       
   928 				   wp->self);
       
   929 }
       
   930 
       
   931 static PyMemberDef wrapper_members[] = {
       
   932 	{"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
       
   933 	{0}
       
   934 };
       
   935 
       
   936 static PyObject *
       
   937 wrapper_objclass(wrapperobject *wp)
       
   938 {
       
   939 	PyObject *c = (PyObject *)wp->descr->d_type;
       
   940 
       
   941 	Py_INCREF(c);
       
   942 	return c;
       
   943 }
       
   944 
       
   945 static PyObject *
       
   946 wrapper_name(wrapperobject *wp)
       
   947 {
       
   948 	char *s = wp->descr->d_base->name;
       
   949 
       
   950 	return PyString_FromString(s);
       
   951 }
       
   952 
       
   953 static PyObject *
       
   954 wrapper_doc(wrapperobject *wp)
       
   955 {
       
   956 	char *s = wp->descr->d_base->doc;
       
   957 
       
   958 	if (s == NULL) {
       
   959 		Py_INCREF(Py_None);
       
   960 		return Py_None;
       
   961 	}
       
   962 	else {
       
   963 		return PyString_FromString(s);
       
   964 	}
       
   965 }
       
   966 
       
   967 static PyGetSetDef wrapper_getsets[] = {
       
   968 	{"__objclass__", (getter)wrapper_objclass},
       
   969 	{"__name__", (getter)wrapper_name},
       
   970 	{"__doc__", (getter)wrapper_doc},
       
   971 	{0}
       
   972 };
       
   973 
       
   974 static PyObject *
       
   975 wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
       
   976 {
       
   977 	wrapperfunc wrapper = wp->descr->d_base->wrapper;
       
   978 	PyObject *self = wp->self;
       
   979 
       
   980 	if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
       
   981 		wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
       
   982 		return (*wk)(self, args, wp->descr->d_wrapped, kwds);
       
   983 	}
       
   984 
       
   985 	if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {
       
   986 		PyErr_Format(PyExc_TypeError,
       
   987 			     "wrapper %s doesn't take keyword arguments",
       
   988 			     wp->descr->d_base->name);
       
   989 		return NULL;
       
   990 	}
       
   991 	return (*wrapper)(self, args, wp->descr->d_wrapped);
       
   992 }
       
   993 
       
   994 static int
       
   995 wrapper_traverse(PyObject *self, visitproc visit, void *arg)
       
   996 {
       
   997 	wrapperobject *wp = (wrapperobject *)self;
       
   998 	Py_VISIT(wp->descr);
       
   999 	Py_VISIT(wp->self);
       
  1000 	return 0;
       
  1001 }
       
  1002 
       
  1003 static PyTypeObject wrappertype = {
       
  1004 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
  1005 	"method-wrapper",			/* tp_name */
       
  1006 	sizeof(wrapperobject),			/* tp_basicsize */
       
  1007 	0,					/* tp_itemsize */
       
  1008 	/* methods */
       
  1009 	(destructor)wrapper_dealloc, 		/* tp_dealloc */
       
  1010 	0,					/* tp_print */
       
  1011 	0,					/* tp_getattr */
       
  1012 	0,					/* tp_setattr */
       
  1013 	(cmpfunc)wrapper_compare,		/* tp_compare */
       
  1014 	(reprfunc)wrapper_repr,			/* tp_repr */
       
  1015 	0,					/* tp_as_number */
       
  1016 	0,					/* tp_as_sequence */
       
  1017 	0,		       			/* tp_as_mapping */
       
  1018 	(hashfunc)wrapper_hash,			/* tp_hash */
       
  1019 	(ternaryfunc)wrapper_call,		/* tp_call */
       
  1020 	0,					/* tp_str */
       
  1021 	PyObject_GenericGetAttr,		/* tp_getattro */
       
  1022 	0,					/* tp_setattro */
       
  1023 	0,					/* tp_as_buffer */
       
  1024 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
       
  1025  	0,					/* tp_doc */
       
  1026 	wrapper_traverse,			/* tp_traverse */
       
  1027  	0,					/* tp_clear */
       
  1028 	0,					/* tp_richcompare */
       
  1029 	0,					/* tp_weaklistoffset */
       
  1030 	0,					/* tp_iter */
       
  1031 	0,					/* tp_iternext */
       
  1032 	0,					/* tp_methods */
       
  1033 	wrapper_members,			/* tp_members */
       
  1034 	wrapper_getsets,			/* tp_getset */
       
  1035 	0,					/* tp_base */
       
  1036 	0,					/* tp_dict */
       
  1037 	0,					/* tp_descr_get */
       
  1038 	0,					/* tp_descr_set */
       
  1039 };
       
  1040 
       
  1041 PyObject *
       
  1042 PyWrapper_New(PyObject *d, PyObject *self)
       
  1043 {
       
  1044 	wrapperobject *wp;
       
  1045 	PyWrapperDescrObject *descr;
       
  1046 
       
  1047 	assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
       
  1048 	descr = (PyWrapperDescrObject *)d;
       
  1049 	assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
       
  1050 
       
  1051 	wp = PyObject_GC_New(wrapperobject, &wrappertype);
       
  1052 	if (wp != NULL) {
       
  1053 		Py_INCREF(descr);
       
  1054 		wp->descr = descr;
       
  1055 		Py_INCREF(self);
       
  1056 		wp->self = self;
       
  1057 		_PyObject_GC_TRACK(wp);
       
  1058 	}
       
  1059 	return (PyObject *)wp;
       
  1060 }
       
  1061 
       
  1062 
       
  1063 /* A built-in 'property' type */
       
  1064 
       
  1065 /*
       
  1066     class property(object):
       
  1067 
       
  1068         def __init__(self, fget=None, fset=None, fdel=None, doc=None):
       
  1069             if doc is None and fget is not None and hasattr(fget, "__doc__"):
       
  1070                 doc = fget.__doc__
       
  1071             self.__get = fget
       
  1072             self.__set = fset
       
  1073             self.__del = fdel
       
  1074             self.__doc__ = doc
       
  1075 
       
  1076         def __get__(self, inst, type=None):
       
  1077             if inst is None:
       
  1078                 return self
       
  1079             if self.__get is None:
       
  1080                 raise AttributeError, "unreadable attribute"
       
  1081             return self.__get(inst)
       
  1082 
       
  1083         def __set__(self, inst, value):
       
  1084             if self.__set is None:
       
  1085                 raise AttributeError, "can't set attribute"
       
  1086             return self.__set(inst, value)
       
  1087 
       
  1088         def __delete__(self, inst):
       
  1089             if self.__del is None:
       
  1090                 raise AttributeError, "can't delete attribute"
       
  1091             return self.__del(inst)
       
  1092 
       
  1093 */
       
  1094 
       
  1095 typedef struct {
       
  1096 	PyObject_HEAD
       
  1097 	PyObject *prop_get;
       
  1098 	PyObject *prop_set;
       
  1099 	PyObject *prop_del;
       
  1100 	PyObject *prop_doc;
       
  1101 	int getter_doc;
       
  1102 } propertyobject;
       
  1103 
       
  1104 static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
       
  1105 				  PyObject *, PyObject *);
       
  1106 
       
  1107 static PyMemberDef property_members[] = {
       
  1108 	{"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
       
  1109 	{"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
       
  1110 	{"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
       
  1111 	{"__doc__",  T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
       
  1112 	{0}
       
  1113 };
       
  1114 
       
  1115 
       
  1116 PyDoc_STRVAR(getter_doc,
       
  1117 	     "Descriptor to change the getter on a property.");
       
  1118 
       
  1119 static PyObject *
       
  1120 property_getter(PyObject *self, PyObject *getter)
       
  1121 {
       
  1122 	return property_copy(self, getter, NULL, NULL, NULL);
       
  1123 }
       
  1124 
       
  1125 
       
  1126 PyDoc_STRVAR(setter_doc,
       
  1127 	     "Descriptor to change the setter on a property.");
       
  1128 
       
  1129 static PyObject *
       
  1130 property_setter(PyObject *self, PyObject *setter)
       
  1131 {
       
  1132 	return property_copy(self, NULL, setter, NULL, NULL);
       
  1133 }
       
  1134 
       
  1135 
       
  1136 PyDoc_STRVAR(deleter_doc,
       
  1137 	     "Descriptor to change the deleter on a property.");
       
  1138 
       
  1139 static PyObject *
       
  1140 property_deleter(PyObject *self, PyObject *deleter)
       
  1141 {
       
  1142 	return property_copy(self, NULL, NULL, deleter, NULL);
       
  1143 }
       
  1144 
       
  1145 
       
  1146 static PyMethodDef property_methods[] = {
       
  1147 	{"getter", property_getter, METH_O, getter_doc},
       
  1148 	{"setter", property_setter, METH_O, setter_doc},
       
  1149 	{"deleter", property_deleter, METH_O, deleter_doc},
       
  1150 	{0}
       
  1151 };
       
  1152 
       
  1153 
       
  1154 static void
       
  1155 property_dealloc(PyObject *self)
       
  1156 {
       
  1157 	propertyobject *gs = (propertyobject *)self;
       
  1158 
       
  1159 	_PyObject_GC_UNTRACK(self);
       
  1160 	Py_XDECREF(gs->prop_get);
       
  1161 	Py_XDECREF(gs->prop_set);
       
  1162 	Py_XDECREF(gs->prop_del);
       
  1163 	Py_XDECREF(gs->prop_doc);
       
  1164 	self->ob_type->tp_free(self);
       
  1165 }
       
  1166 
       
  1167 static PyObject *
       
  1168 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
       
  1169 {
       
  1170 	propertyobject *gs = (propertyobject *)self;
       
  1171 
       
  1172 	if (obj == NULL || obj == Py_None) {
       
  1173 		Py_INCREF(self);
       
  1174 		return self;
       
  1175 	}
       
  1176 	if (gs->prop_get == NULL) {
       
  1177 		PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
       
  1178 		return NULL;
       
  1179 	}
       
  1180 	return PyObject_CallFunction(gs->prop_get, "(O)", obj);
       
  1181 }
       
  1182 
       
  1183 static int
       
  1184 property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
       
  1185 {
       
  1186 	propertyobject *gs = (propertyobject *)self;
       
  1187 	PyObject *func, *res;
       
  1188 
       
  1189 	if (value == NULL)
       
  1190 		func = gs->prop_del;
       
  1191 	else
       
  1192 		func = gs->prop_set;
       
  1193 	if (func == NULL) {
       
  1194 		PyErr_SetString(PyExc_AttributeError,
       
  1195 				value == NULL ?
       
  1196 				"can't delete attribute" :
       
  1197 				"can't set attribute");
       
  1198 		return -1;
       
  1199 	}
       
  1200 	if (value == NULL)
       
  1201 		res = PyObject_CallFunction(func, "(O)", obj);
       
  1202 	else
       
  1203 		res = PyObject_CallFunction(func, "(OO)", obj, value);
       
  1204 	if (res == NULL)
       
  1205 		return -1;
       
  1206 	Py_DECREF(res);
       
  1207 	return 0;
       
  1208 }
       
  1209 
       
  1210 static PyObject *
       
  1211 property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del,
       
  1212 		PyObject *doc)
       
  1213 {
       
  1214 	propertyobject *pold = (propertyobject *)old;
       
  1215 	propertyobject *pnew = NULL;
       
  1216 	PyObject *new, *type;
       
  1217 
       
  1218 	type = PyObject_Type(old);
       
  1219 	if (type == NULL)
       
  1220 		return NULL;
       
  1221 
       
  1222 	if (get == NULL || get == Py_None) {
       
  1223 		Py_XDECREF(get);
       
  1224 		get = pold->prop_get ? pold->prop_get : Py_None;
       
  1225 	}
       
  1226 	if (set == NULL || set == Py_None) {
       
  1227 		Py_XDECREF(set);
       
  1228 		set = pold->prop_set ? pold->prop_set : Py_None;
       
  1229 	}
       
  1230 	if (del == NULL || del == Py_None) {
       
  1231 		Py_XDECREF(del);
       
  1232 		del = pold->prop_del ? pold->prop_del : Py_None;
       
  1233 	}
       
  1234 	if (doc == NULL || doc == Py_None) {
       
  1235 		Py_XDECREF(doc);
       
  1236 		doc = pold->prop_doc ? pold->prop_doc : Py_None;
       
  1237 	}
       
  1238 	
       
  1239 	new =  PyObject_CallFunction(type, "OOOO", get, set, del, doc);
       
  1240 	Py_DECREF(type);
       
  1241 	if (new == NULL)
       
  1242 		return NULL;
       
  1243 	pnew = (propertyobject *)new;
       
  1244 	
       
  1245 	if (pold->getter_doc && get != Py_None) {
       
  1246 		PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");
       
  1247 		if (get_doc != NULL) {
       
  1248 			Py_XDECREF(pnew->prop_doc);
       
  1249 			pnew->prop_doc = get_doc;  /* get_doc already INCREF'd by GetAttr */
       
  1250 			pnew->getter_doc = 1;
       
  1251 		} else {
       
  1252 			PyErr_Clear();
       
  1253 		}
       
  1254 	}
       
  1255 	return new;
       
  1256 }
       
  1257 
       
  1258 static int
       
  1259 property_init(PyObject *self, PyObject *args, PyObject *kwds)
       
  1260 {
       
  1261 	PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
       
  1262 	static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
       
  1263 	propertyobject *prop = (propertyobject *)self;
       
  1264 	
       
  1265 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
       
  1266 					 kwlist, &get, &set, &del, &doc))
       
  1267 		return -1;
       
  1268 
       
  1269 	if (get == Py_None)
       
  1270 		get = NULL;
       
  1271 	if (set == Py_None)
       
  1272 		set = NULL;
       
  1273 	if (del == Py_None)
       
  1274 		del = NULL;
       
  1275 
       
  1276 	Py_XINCREF(get);
       
  1277 	Py_XINCREF(set);
       
  1278 	Py_XINCREF(del);
       
  1279 	Py_XINCREF(doc);
       
  1280 
       
  1281 	prop->prop_get = get;
       
  1282 	prop->prop_set = set;
       
  1283 	prop->prop_del = del;
       
  1284 	prop->prop_doc = doc;
       
  1285 	prop->getter_doc = 0;
       
  1286 
       
  1287 	/* if no docstring given and the getter has one, use that one */
       
  1288 	if ((doc == NULL || doc == Py_None) && get != NULL) {
       
  1289 		PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");
       
  1290 		if (get_doc != NULL) {
       
  1291 			Py_XDECREF(prop->prop_doc);
       
  1292 			prop->prop_doc = get_doc;  /* get_doc already INCREF'd by GetAttr */
       
  1293 			prop->getter_doc = 1;
       
  1294 		} else {
       
  1295 			PyErr_Clear();
       
  1296 		}
       
  1297 	}
       
  1298 
       
  1299 	return 0;
       
  1300 }
       
  1301 
       
  1302 PyDoc_STRVAR(property_doc,
       
  1303 "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
       
  1304 "\n"
       
  1305 "fget is a function to be used for getting an attribute value, and likewise\n"
       
  1306 "fset is a function for setting, and fdel a function for del'ing, an\n"
       
  1307 "attribute.  Typical use is to define a managed attribute x:\n"
       
  1308 "class C(object):\n"
       
  1309 "    def getx(self): return self._x\n"
       
  1310 "    def setx(self, value): self._x = value\n"
       
  1311 "    def delx(self): del self._x\n"
       
  1312 "    x = property(getx, setx, delx, \"I'm the 'x' property.\")\n"
       
  1313 "\n"
       
  1314 "Decorators make defining new properties or modifying existing ones easy:\n"
       
  1315 "class C(object):\n"
       
  1316 "    @property\n"
       
  1317 "    def x(self): return self._x\n"
       
  1318 "    @x.setter\n"
       
  1319 "    def x(self, value): self._x = value\n"
       
  1320 "    @x.deleter\n"
       
  1321 "    def x(self): del self._x\n"
       
  1322 );
       
  1323 
       
  1324 static int
       
  1325 property_traverse(PyObject *self, visitproc visit, void *arg)
       
  1326 {
       
  1327 	propertyobject *pp = (propertyobject *)self;
       
  1328 	Py_VISIT(pp->prop_get);
       
  1329 	Py_VISIT(pp->prop_set);
       
  1330 	Py_VISIT(pp->prop_del);
       
  1331 	Py_VISIT(pp->prop_doc);
       
  1332 	return 0;
       
  1333 }
       
  1334 
       
  1335 PyTypeObject PyProperty_Type = {
       
  1336 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
  1337 	"property",				/* tp_name */
       
  1338 	sizeof(propertyobject),			/* tp_basicsize */
       
  1339 	0,					/* tp_itemsize */
       
  1340 	/* methods */
       
  1341 	property_dealloc,	 		/* tp_dealloc */
       
  1342 	0,					/* tp_print */
       
  1343 	0,					/* tp_getattr */
       
  1344 	0,					/* tp_setattr */
       
  1345 	0,					/* tp_compare */
       
  1346 	0,					/* tp_repr */
       
  1347 	0,					/* tp_as_number */
       
  1348 	0,					/* tp_as_sequence */
       
  1349 	0,		       			/* tp_as_mapping */
       
  1350 	0,					/* tp_hash */
       
  1351 	0,					/* tp_call */
       
  1352 	0,					/* tp_str */
       
  1353 	PyObject_GenericGetAttr,		/* tp_getattro */
       
  1354 	0,					/* tp_setattro */
       
  1355 	0,					/* tp_as_buffer */
       
  1356 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
       
  1357 		Py_TPFLAGS_BASETYPE,		/* tp_flags */
       
  1358  	property_doc,				/* tp_doc */
       
  1359 	property_traverse,			/* tp_traverse */
       
  1360  	0,					/* tp_clear */
       
  1361 	0,					/* tp_richcompare */
       
  1362 	0,					/* tp_weaklistoffset */
       
  1363 	0,					/* tp_iter */
       
  1364 	0,					/* tp_iternext */
       
  1365 	property_methods,			/* tp_methods */
       
  1366 	property_members,			/* tp_members */
       
  1367 	0,					/* tp_getset */
       
  1368 	0,					/* tp_base */
       
  1369 	0,					/* tp_dict */
       
  1370 	property_descr_get,			/* tp_descr_get */
       
  1371 	property_descr_set,			/* tp_descr_set */
       
  1372 	0,					/* tp_dictoffset */
       
  1373 	property_init,				/* tp_init */
       
  1374 	PyType_GenericAlloc,			/* tp_alloc */
       
  1375 	PyType_GenericNew,			/* tp_new */
       
  1376 	PyObject_GC_Del,               		/* tp_free */
       
  1377 };