[Python-checkins] CVS: python/dist/src/Objects descrobject.c,2.13,2.14

Tim Peters tim_one@users.sourceforge.net
Mon, 24 Sep 2001 14:17:52 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv32355/python/Objects

Modified Files:
	descrobject.c 
Log Message:
Make properties discoverable from Python:

- property() now takes 4 keyword arguments:  fget, fset, fdel, doc.
  Note that the real purpose of the 'f' prefix is to make fdel fit in
  ('del' is a keyword, so can't used as a keyword argument name).

- These map to visible readonly attributes 'fget', 'fset', 'fdel',
  and '__doc__' in the property object.

- fget/fset/fdel weren't discoverable from Python before.

- __doc__ is new, and allows to associate a docstring with a property.


Index: descrobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v
retrieving revision 2.13
retrieving revision 2.14
diff -C2 -d -r2.13 -r2.14
*** descrobject.c	2001/09/20 21:45:26	2.13
--- descrobject.c	2001/09/24 21:17:50	2.14
***************
*** 874,880 ****
      class property(object):
  
! 	def __init__(self, get=None, set=None):
! 	    self.__get = get
! 	    self.__set = set
  
  	def __get__(self, inst, type=None):
--- 874,882 ----
      class property(object):
  
! 	def __init__(self, fget=None, fset=None, fdel=None, doc=None):
! 	    self.__get = fget
! 	    self.__set = fset
! 	    self.__del = fdel
! 	    self.__doc__ = doc
  
  	def __get__(self, inst, type=None):
***************
*** 886,901 ****
  
  	def __set__(self, inst, value):
! 	    if self.__set is None:
! 		raise AttributeError, "unsettable attribute"
! 	    return self.__set(inst, value)
  */
  
  typedef struct {
  	PyObject_HEAD
! 	PyObject *get;
! 	PyObject *set;
! 	PyObject *del;
  } propertyobject;
  
  static void
  property_dealloc(PyObject *self)
--- 888,918 ----
  
  	def __set__(self, inst, value):
! 	    if value is None:
! 	    	if self.__del is None:
! 	    	    raise AttributeError, "can't delete attribute"
! 	    	return self.__del(inst)
! 	    else:
! 	        if self.__set is None:
! 	            raise AttributeError, "can't set attribute"
! 	        return self.__set(inst, value)
  */
  
  typedef struct {
  	PyObject_HEAD
! 	PyObject *prop_get;
! 	PyObject *prop_set;
! 	PyObject *prop_del;
! 	PyObject *prop_doc;
  } propertyobject;
  
+ static PyMemberDef property_members[] = {
+ 	{"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
+ 	{"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
+ 	{"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
+ 	{"__doc__",  T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
+ 	{0}
+ };
+ 
+ 
  static void
  property_dealloc(PyObject *self)
***************
*** 903,909 ****
  	propertyobject *gs = (propertyobject *)self;
  
! 	Py_XDECREF(gs->get);
! 	Py_XDECREF(gs->set);
! 	Py_XDECREF(gs->del);
  	self->ob_type->tp_free(self);
  }
--- 920,927 ----
  	propertyobject *gs = (propertyobject *)self;
  
! 	Py_XDECREF(gs->prop_get);
! 	Py_XDECREF(gs->prop_set);
! 	Py_XDECREF(gs->prop_del);
! 	Py_XDECREF(gs->prop_doc);
  	self->ob_type->tp_free(self);
  }
***************
*** 914,918 ****
  	propertyobject *gs = (propertyobject *)self;
  
! 	if (gs->get == NULL) {
  		PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
  		return NULL;
--- 932,936 ----
  	propertyobject *gs = (propertyobject *)self;
  
! 	if (gs->prop_get == NULL) {
  		PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
  		return NULL;
***************
*** 922,926 ****
  		return self;
  	}
! 	return PyObject_CallFunction(gs->get, "(O)", obj);
  }
  
--- 940,944 ----
  		return self;
  	}
! 	return PyObject_CallFunction(gs->prop_get, "(O)", obj);
  }
  
***************
*** 932,938 ****
  
  	if (value == NULL)
! 		func = gs->del;
  	else
! 		func = gs->set;
  	if (func == NULL) {
  		PyErr_SetString(PyExc_AttributeError,
--- 950,956 ----
  
  	if (value == NULL)
! 		func = gs->prop_del;
  	else
! 		func = gs->prop_set;
  	if (func == NULL) {
  		PyErr_SetString(PyExc_AttributeError,
***************
*** 955,984 ****
  property_init(PyObject *self, PyObject *args, PyObject *kwds)
  {
! 	PyObject *get = NULL, *set = NULL, *del = NULL;
  	propertyobject *gs = (propertyobject *)self;
  
! 	if (!PyArg_ParseTuple(args, "|OOO:property", &get, &set, &del))
  		return -1;
  	if (get == Py_None)
  		get = NULL;
  	if (set == Py_None)
  		set = NULL;
  	Py_XINCREF(get);
  	Py_XINCREF(set);
  	Py_XINCREF(del);
! 	gs->get = get;
! 	gs->set = set;
! 	gs->del = del;
  	return 0;
  }
  
  static char property_doc[] =
! "property([getfunc[, setfunc[, delfunc]]]) -> property attribute\n"
! "Typical use to define a managed attribute x of C instances:\n"
  "class C(object):\n"
  "    def getx(self): return self.__x\n"
  "    def setx(self, value): self.__x = value\n"
  "    def delx(self): del self.__x\n"
! "    x = property(getx, setx, delx)";
  
  PyTypeObject PyProperty_Type = {
--- 973,1015 ----
  property_init(PyObject *self, PyObject *args, PyObject *kwds)
  {
! 	PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
! 	static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
  	propertyobject *gs = (propertyobject *)self;
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
! 	     				 kwlist, &get, &set, &del, &doc))
  		return -1;
+ 
  	if (get == Py_None)
  		get = NULL;
  	if (set == Py_None)
  		set = NULL;
+ 	if (del == Py_None)
+ 		del = NULL;
+ 
  	Py_XINCREF(get);
  	Py_XINCREF(set);
  	Py_XINCREF(del);
! 	Py_XINCREF(doc);
! 
! 	gs->prop_get = get;
! 	gs->prop_set = set;
! 	gs->prop_del = del;
! 	gs->prop_doc = doc;
! 
  	return 0;
  }
  
  static char property_doc[] =
! "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
! "\n"
! "fget is a function to be used for getting an attribute value, and likewise\n"
! "fset is a function for setting, and fdel a function for del'ing, an\n"
! "attribute.  Typical use is to define a managed attribute x:\n"
  "class C(object):\n"
  "    def getx(self): return self.__x\n"
  "    def setx(self, value): self.__x = value\n"
  "    def delx(self): del self.__x\n"
! "    x = property(getx, setx, delx, \"I'm the 'x' property.\")";
  
  PyTypeObject PyProperty_Type = {
***************
*** 1013,1017 ****
  	0,					/* tp_iternext */
  	0,					/* tp_methods */
! 	0,					/* tp_members */
  	0,					/* tp_getset */
  	0,					/* tp_base */
--- 1044,1048 ----
  	0,					/* tp_iternext */
  	0,					/* tp_methods */
! 	property_members,			/* tp_members */
  	0,					/* tp_getset */
  	0,					/* tp_base */