[Python-checkins] CVS: python/dist/src/Python ceval.c,2.275,2.276 compile.c,2.223,2.224 structmember.c,2.20,2.21 symtable.c,2.5,2.6

Guido van Rossum gvanrossum@users.sourceforge.net
Thu, 20 Sep 2001 13:46:21 -0700


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

Modified Files:
	ceval.c compile.c structmember.c symtable.c 
Log Message:
Add optional docstrings to member descriptors.  For backwards
compatibility, this required all places where an array of "struct
memberlist" structures was declared that is referenced from a type's
tp_members slot to change the type of the structure to PyMemberDef;
"struct memberlist" is now only used by old code that still calls
PyMember_Get/Set.  The code in PyObject_GenericGetAttr/SetAttr now
calls the new APIs PyMember_GetOne/SetOne, which take a PyMemberDef
argument.

As examples, I added actual docstrings to the attributes of a few
types: file, complex, instance method, super, and xxsubtype.spamlist.

Also converted the symtable to new style getattr.


Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.275
retrieving revision 2.276
diff -C2 -d -r2.275 -r2.276
*** ceval.c	2001/09/13 16:56:43	2.275
--- ceval.c	2001/09/20 20:46:19	2.276
***************
*** 193,197 ****
  };
  
! static struct memberlist gen_memberlist[] = {
  	{"gi_frame",	T_OBJECT, offsetof(genobject, gi_frame),	RO},
  	{"gi_running",	T_INT,    offsetof(genobject, gi_running),	RO},
--- 193,197 ----
  };
  
! static PyMemberDef gen_memberlist[] = {
  	{"gi_frame",	T_OBJECT, offsetof(genobject, gi_frame),	RO},
  	{"gi_running",	T_INT,    offsetof(genobject, gi_running),	RO},

Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.223
retrieving revision 2.224
diff -C2 -d -r2.223 -r2.224
*** compile.c	2001/09/14 20:08:07	2.223
--- compile.c	2001/09/20 20:46:19	2.224
***************
*** 74,78 ****
  #define OFF(x) offsetof(PyCodeObject, x)
  
! static struct memberlist code_memberlist[] = {
  	{"co_argcount",	T_INT,		OFF(co_argcount),	READONLY},
  	{"co_nlocals",	T_INT,		OFF(co_nlocals),	READONLY},
--- 74,78 ----
  #define OFF(x) offsetof(PyCodeObject, x)
  
! static PyMemberDef code_memberlist[] = {
  	{"co_argcount",	T_INT,		OFF(co_argcount),	READONLY},
  	{"co_nlocals",	T_INT,		OFF(co_nlocals),	READONLY},

Index: structmember.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/structmember.c,v
retrieving revision 2.20
retrieving revision 2.21
diff -C2 -d -r2.20 -r2.21
*** structmember.c	2001/09/17 19:28:08	2.20
--- structmember.c	2001/09/20 20:46:19	2.21
***************
*** 33,257 ****
  {
  	struct memberlist *l;
! 	
  	if (strcmp(name, "__members__") == 0)
  		return listmembers(mlist);
  	for (l = mlist; l->name != NULL; l++) {
  		if (strcmp(l->name, name) == 0) {
! 			PyObject *v;
! 			if ((l->flags & READ_RESTRICTED) &&
! 			    PyEval_GetRestricted()) {
! 				PyErr_SetString(PyExc_RuntimeError,
! 						"restricted attribute");
! 				return NULL;
! 			}
! 			addr += l->offset;
! 			switch (l->type) {
! 			case T_BYTE:
! 				v = PyInt_FromLong((long)
! 						 (((*(char*)addr & 0xff)
! 						   ^ 0x80) - 0x80));
! 				break;
! 			case T_UBYTE:
! 				v = PyInt_FromLong((long) *(char*)addr & 0xff);
! 				break;
! 			case T_SHORT:
! 				v = PyInt_FromLong((long) *(short*)addr);
! 				break;
! 			case T_USHORT:
! 				v = PyInt_FromLong((long)
! 						 *(unsigned short*)addr);
! 				break;
! 			case T_INT:
! 				v = PyInt_FromLong((long) *(int*)addr);
! 				break;
! 			case T_UINT:
! 				v = PyInt_FromLong((long)
! 						   *(unsigned int*)addr);
! 				break;
! 			case T_LONG:
! 				v = PyInt_FromLong(*(long*)addr);
! 				break;
! 			case T_ULONG:
! 				v = PyLong_FromDouble((double)
! 						   *(unsigned long*)addr);
! 				break;
! 			case T_FLOAT:
! 				v = PyFloat_FromDouble((double)*(float*)addr);
! 				break;
! 			case T_DOUBLE:
! 				v = PyFloat_FromDouble(*(double*)addr);
! 				break;
! 			case T_STRING:
! 				if (*(char**)addr == NULL) {
! 					Py_INCREF(Py_None);
! 					v = Py_None;
! 				}
! 				else
! 					v = PyString_FromString(*(char**)addr);
! 				break;
! 			case T_STRING_INPLACE:
! 				v = PyString_FromString((char*)addr);
! 				break;
! #ifdef macintosh
! 			case T_PSTRING:
! 				if (*(char**)addr == NULL) {
! 					Py_INCREF(Py_None);
! 					v = Py_None;
! 				}
! 				else
! 					v = PyString_FromStringAndSize(
! 						(*(char**)addr)+1,
! 						**(unsigned char**)addr);
! 				break;
! 			case T_PSTRING_INPLACE:
! 				v = PyString_FromStringAndSize(
! 					((char*)addr)+1,
! 					*(unsigned char*)addr);
! 				break;
! #endif /* macintosh */
! 			case T_CHAR:
! 				v = PyString_FromStringAndSize((char*)addr, 1);
! 				break;
! 			case T_OBJECT:
! 				v = *(PyObject **)addr;
! 				if (v == NULL)
! 					v = Py_None;
! 				Py_INCREF(v);
! 				break;
! 			default:
! 				PyErr_SetString(PyExc_SystemError,
! 						"bad memberlist type");
! 				v = NULL;
! 			}
! 			return v;
  		}
  	}
- 	
  	PyErr_SetString(PyExc_AttributeError, name);
  	return NULL;
  }
  
  int
  PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
  {
  	struct memberlist *l;
! 	PyObject *oldv;
! 	
  	for (l = mlist; l->name != NULL; l++) {
  		if (strcmp(l->name, name) == 0) {
! 			if ((l->flags & READONLY) || l->type == T_STRING
! #ifdef macintosh
! 			    || l->type == T_PSTRING
! #endif
! 				)
! 			{
! 				PyErr_SetString(PyExc_TypeError,
! 						"readonly attribute");
! 				return -1;
! 			}
! 			if ((l->flags & WRITE_RESTRICTED) &&
! 			    PyEval_GetRestricted()) {
! 				PyErr_SetString(PyExc_RuntimeError,
! 						"restricted attribute");
! 				return -1;
! 			}
! 			if (v == NULL && l->type != T_OBJECT) {
! 				PyErr_SetString(PyExc_TypeError,
! 				  "can't delete numeric/char attribute");
! 				return -1;
! 			}
! 			addr += l->offset;
! 			switch (l->type) {
! 			case T_BYTE:
! 			case T_UBYTE:
! 				if (!PyInt_Check(v)) {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				*(char*)addr = (char) PyInt_AsLong(v);
! 				break;
! 			case T_SHORT:
! 			case T_USHORT:
! 				if (!PyInt_Check(v)) {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				*(short*)addr = (short) PyInt_AsLong(v);
! 				break;
! 			case T_UINT:
! 			case T_INT:
! 				if (!PyInt_Check(v)) {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				*(int*)addr = (int) PyInt_AsLong(v);
! 				break;
! 			case T_LONG:
! 				if (!PyInt_Check(v)) {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				*(long*)addr = PyInt_AsLong(v);
! 				break;
! 			case T_ULONG:
! 				if (PyInt_Check(v))
! 					*(long*)addr = PyInt_AsLong(v);
! 				else if (PyLong_Check(v))
! 					*(long*)addr = PyLong_AsLong(v);
! 				else {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				break;
! 			case T_FLOAT:
! 				if (PyInt_Check(v))
! 					*(float*)addr =
! 						(float) PyInt_AsLong(v);
! 				else if (PyFloat_Check(v))
! 					*(float*)addr =
! 						(float) PyFloat_AsDouble(v);
! 				else {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				break;
! 			case T_DOUBLE:
! 				if (PyInt_Check(v))
! 					*(double*)addr =
! 						(double) PyInt_AsLong(v);
! 				else if (PyFloat_Check(v))
! 					*(double*)addr = PyFloat_AsDouble(v);
! 				else {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				break;
! 			case T_OBJECT:
! 				Py_XINCREF(v);
! 				oldv = *(PyObject **)addr;
! 				*(PyObject **)addr = v;
! 				Py_XDECREF(oldv);
! 				break;
! 			case T_CHAR:
! 				if (PyString_Check(v) &&
! 				    PyString_Size(v) == 1) {
! 					*(char*)addr =
! 						PyString_AsString(v)[0];
! 				}
! 				else {
! 					PyErr_BadArgument();
! 					return -1;
! 				}
! 				break;
! 			default:
! 				PyErr_SetString(PyExc_SystemError,
! 						"bad memberlist type");
! 				return -1;
! 			}
! 			return 0;
  		}
  	}
! 	
  	PyErr_SetString(PyExc_AttributeError, name);
  	return -1;
  }
--- 33,268 ----
  {
  	struct memberlist *l;
! 
  	if (strcmp(name, "__members__") == 0)
  		return listmembers(mlist);
  	for (l = mlist; l->name != NULL; l++) {
  		if (strcmp(l->name, name) == 0) {
! 			PyMemberDef copy;
! 			copy.name = l->name;
! 			copy.type = l->type;
! 			copy.offset = l->offset;
! 			copy.flags = l->flags;
! 			copy.doc = NULL;
! 			return PyMember_GetOne(addr, &copy);
  		}
  	}
  	PyErr_SetString(PyExc_AttributeError, name);
  	return NULL;
  }
  
+ PyObject *
+ PyMember_GetOne(char *addr, PyMemberDef *l)
+ {
+ 	PyObject *v;
+ 	if ((l->flags & READ_RESTRICTED) &&
+ 	    PyEval_GetRestricted()) {
+ 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
+ 		return NULL;
+ 	}
+ 	addr += l->offset;
+ 	switch (l->type) {
+ 	case T_BYTE:
+ 		v = PyInt_FromLong(
+ 			(long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80));
+ 		break;
+ 	case T_UBYTE:
+ 		v = PyInt_FromLong((long) *(char*)addr & 0xff);
+ 		break;
+ 	case T_SHORT:
+ 		v = PyInt_FromLong((long) *(short*)addr);
+ 		break;
+ 	case T_USHORT:
+ 		v = PyInt_FromLong((long) *(unsigned short*)addr);
+ 		break;
+ 	case T_INT:
+ 		v = PyInt_FromLong((long) *(int*)addr);
+ 		break;
+ 	case T_UINT:
+ 		v = PyInt_FromLong((long) *(unsigned int*)addr);
+ 		break;
+ 	case T_LONG:
+ 		v = PyInt_FromLong(*(long*)addr);
+ 		break;
+ 	case T_ULONG:
+ 		v = PyLong_FromDouble((double) *(unsigned long*)addr);
+ 		break;
+ 	case T_FLOAT:
+ 		v = PyFloat_FromDouble((double)*(float*)addr);
+ 		break;
+ 	case T_DOUBLE:
+ 		v = PyFloat_FromDouble(*(double*)addr);
+ 		break;
+ 	case T_STRING:
+ 		if (*(char**)addr == NULL) {
+ 			Py_INCREF(Py_None);
+ 			v = Py_None;
+ 		}
+ 		else
+ 			v = PyString_FromString(*(char**)addr);
+ 		break;
+ 	case T_STRING_INPLACE:
+ 		v = PyString_FromString((char*)addr);
+ 		break;
+ #ifdef macintosh
+ 	case T_PSTRING:
+ 		if (*(char**)addr == NULL) {
+ 			Py_INCREF(Py_None);
+ 			v = Py_None;
+ 		}
+ 		else
+ 			v = PyString_FromStringAndSize(
+ 				(*(char**)addr)+1,
+ 				**(unsigned char**)addr);
+ 		break;
+ 	case T_PSTRING_INPLACE:
+ 		v = PyString_FromStringAndSize(
+ 			((char*)addr)+1,
+ 			*(unsigned char*)addr);
+ 		break;
+ #endif /* macintosh */
+ 	case T_CHAR:
+ 		v = PyString_FromStringAndSize((char*)addr, 1);
+ 		break;
+ 	case T_OBJECT:
+ 		v = *(PyObject **)addr;
+ 		if (v == NULL)
+ 			v = Py_None;
+ 		Py_INCREF(v);
+ 		break;
+ 	default:
+ 		PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
+ 		v = NULL;
+ 	}
+ 	return v;
+ }
+ 
  int
  PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
  {
  	struct memberlist *l;
! 
  	for (l = mlist; l->name != NULL; l++) {
  		if (strcmp(l->name, name) == 0) {
! 			PyMemberDef copy;
! 			copy.name = l->name;
! 			copy.type = l->type;
! 			copy.offset = l->offset;
! 			copy.flags = l->flags;
! 			copy.doc = NULL;
! 			return PyMember_SetOne(addr, &copy, v);
  		}
  	}
! 
  	PyErr_SetString(PyExc_AttributeError, name);
  	return -1;
+ }
+ 
+ int
+ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
+ {
+ 	PyObject *oldv;
+ 
+ 	if ((l->flags & READONLY) || l->type == T_STRING
+ #ifdef macintosh
+ 	    || l->type == T_PSTRING
+ #endif
+ 		)
+ 	{
+ 		PyErr_SetString(PyExc_TypeError, "readonly attribute");
+ 		return -1;
+ 	}
+ 	if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) {
+ 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
+ 		return -1;
+ 	}
+ 	if (v == NULL && l->type != T_OBJECT) {
+ 		PyErr_SetString(PyExc_TypeError,
+ 				"can't delete numeric/char attribute");
+ 		return -1;
+ 	}
+ 	addr += l->offset;
+ 	switch (l->type) {
+ 	case T_BYTE:
+ 	case T_UBYTE:
+ 		if (!PyInt_Check(v)) {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		*(char*)addr = (char) PyInt_AsLong(v);
+ 		break;
+ 	case T_SHORT:
+ 	case T_USHORT:
+ 		if (!PyInt_Check(v)) {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		*(short*)addr = (short) PyInt_AsLong(v);
+ 		break;
+ 	case T_UINT:
+ 	case T_INT:
+ 		if (!PyInt_Check(v)) {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		*(int*)addr = (int) PyInt_AsLong(v);
+ 		break;
+ 	case T_LONG:
+ 		if (!PyInt_Check(v)) {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		*(long*)addr = PyInt_AsLong(v);
+ 		break;
+ 	case T_ULONG:
+ 		if (PyInt_Check(v))
+ 			*(long*)addr = PyInt_AsLong(v);
+ 		else if (PyLong_Check(v))
+ 			*(long*)addr = PyLong_AsLong(v);
+ 		else {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		break;
+ 	case T_FLOAT:
+ 		if (PyInt_Check(v))
+ 			*(float*)addr =
+ 				(float) PyInt_AsLong(v);
+ 		else if (PyFloat_Check(v))
+ 			*(float*)addr =
+ 				(float) PyFloat_AsDouble(v);
+ 		else {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		break;
+ 	case T_DOUBLE:
+ 		if (PyInt_Check(v))
+ 			*(double*)addr = (double) PyInt_AsLong(v);
+ 		else if (PyFloat_Check(v))
+ 			*(double*)addr = PyFloat_AsDouble(v);
+ 		else {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		break;
+ 	case T_OBJECT:
+ 		Py_XINCREF(v);
+ 		oldv = *(PyObject **)addr;
+ 		*(PyObject **)addr = v;
+ 		Py_XDECREF(oldv);
+ 		break;
+ 	case T_CHAR:
+ 		if (PyString_Check(v) && PyString_Size(v) == 1) {
+ 			*(char*)addr = PyString_AsString(v)[0];
+ 		}
+ 		else {
+ 			PyErr_BadArgument();
+ 			return -1;
+ 		}
+ 		break;
+ 	default:
+ 		PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
+ 		return -1;
+ 	}
+ 	return 0;
  }

Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.5
retrieving revision 2.6
diff -C2 -d -r2.5 -r2.6
*** symtable.c	2001/06/18 22:08:13	2.5
--- symtable.c	2001/09/20 20:46:19	2.6
***************
*** 107,111 ****
  #define OFF(x) offsetof(PySymtableEntryObject, x)
  
! static struct memberlist ste_memberlist[] = {
  	{"id",       T_OBJECT, OFF(ste_id), READONLY},
  	{"name",     T_OBJECT, OFF(ste_name), READONLY},
--- 107,111 ----
  #define OFF(x) offsetof(PySymtableEntryObject, x)
  
! static PyMemberDef ste_memberlist[] = {
  	{"id",       T_OBJECT, OFF(ste_id), READONLY},
  	{"name",     T_OBJECT, OFF(ste_name), READONLY},
***************
*** 120,129 ****
  };
  
- static PyObject *
- ste_getattr(PySymtableEntryObject *ste, char *name)
- {
- 	return PyMember_Get((char *)ste, ste_memberlist, name);
- }
- 
  PyTypeObject PySymtableEntry_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
--- 120,123 ----
***************
*** 134,138 ****
  	(destructor)ste_dealloc,                /* tp_dealloc */
  	0,                                      /* tp_print */
! 	(getattrfunc)ste_getattr,               /* tp_getattr */
  	0,					/* tp_setattr */
  	0,			                /* tp_compare */
--- 128,132 ----
  	(destructor)ste_dealloc,                /* tp_dealloc */
  	0,                                      /* tp_print */
! 	0,			               /* tp_getattr */
  	0,					/* tp_setattr */
  	0,			                /* tp_compare */
***************
*** 144,151 ****
  	0,					/* tp_call */
  	0,					/* tp_str */
! 	0,					/* tp_getattro */
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT,	                /* tp_flags */
   	0,					/* tp_doc */
  };
--- 138,162 ----
  	0,					/* tp_call */
  	0,					/* tp_str */
! 	PyObject_GenericGetAttr,		/* tp_getattro */
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT,	                /* tp_flags */
   	0,					/* tp_doc */
+ 	0,					/* tp_traverse */
+ 	0,					/* tp_clear */
+ 	0,					/* tp_richcompare */
+ 	0,					/* tp_weaklistoffset */
+ 	0,					/* tp_iter */
+ 	0,					/* tp_iternext */
+ 	0,					/* tp_methods */
+ 	ste_memberlist,				/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
+ 	0,					/* tp_descr_get */
+ 	0,					/* tp_descr_set */
+ 	0,					/* tp_dictoffset */
+ 	0,					/* tp_init */
+ 	0,					/* tp_alloc */
+ 	0,					/* tp_new */
  };