[Python-checkins] CVS: python/dist/src/Objects descrobject.c,NONE,1.1.2.1 complexobject.c,2.35,2.35.4.1 dictobject.c,2.80,2.80.2.1 fileobject.c,2.112,2.112.2.1 frameobject.c,2.49,2.49.4.1 listobject.c,2.92,2.92.6.1 methodobject.c,2.33,2.33.8.1 object.c,2.124,2.124.4.1 rangeobject.c,2.24,2.24.6.1 sliceobject.c,2.7,2.7.4.1 stringobject.c,2.103,2.103.2.1 typeobject.c,2.16,2.16.8.1 unicodeobject.c,2.87,2.87.2.1

Guido van Rossum gvanrossum@users.sourceforge.net
Mon, 23 Apr 2001 17:43:32 -0700


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

Modified Files:
      Tag: descr-branch
	complexobject.c dictobject.c fileobject.c frameobject.c 
	listobject.c methodobject.c object.c rangeobject.c 
	sliceobject.c stringobject.c typeobject.c unicodeobject.c 
Added Files:
      Tag: descr-branch
	descrobject.c 
Log Message:
Interim commit to descriptors prototype; see PEP 252.

--- NEW FILE: descrobject.c ---
/* Descriptors -- a new, flexible way to describe attributes */

#include "Python.h"
#include "structmember.h" /* Why is this not included in Python.h? */

/* Descriptor object */
struct PyDescrObject {
	PyObject_HEAD
	int d_flavor;
	PyTypeObject *d_type;
	union {
		PyMethodDef *d_method;
		struct memberlist *d_member;
		struct getsetlist *d_getset;
	} d_union;
};

/* Descriptor flavors */
#define DF_NULL		0
#define DF_METHOD	1
#define DF_MEMBER	2
#define DF_GETSET	3

static void
descr_dealloc(PyDescrObject *descr)
{
	PyObject_DEL(descr);
}

static char *
descr_name(PyDescrObject *descr)
{
	switch (descr->d_flavor) {
	case DF_METHOD:
		return descr->d_union.d_method->ml_name;
	case DF_MEMBER:
		return descr->d_union.d_member->name;
	case DF_GETSET:
		return descr->d_union.d_getset->name;
	default:
		return NULL;
	}
}

static PyObject *
descr_repr(PyDescrObject *descr)
{
	char buffer[500];

	switch (descr->d_flavor) {
	case DF_NULL:
		sprintf(buffer,
			"<null descriptor of '%.100s' objects>",
			descr->d_type->tp_name);
		break;
	case DF_METHOD:
		sprintf(buffer,
			"<method '%.300s' of '%.100s' objects>",
			descr->d_union.d_method->ml_name,
			descr->d_type->tp_name);
		break;
	case DF_MEMBER:
		sprintf(buffer,
			"<member '%.300s' of '%.100s' objects>",
			descr->d_union.d_member->name,
			descr->d_type->tp_name);
		break;
	case DF_GETSET:
		sprintf(buffer,
			"<attribute '%.300s' of '%.100s' objects>",
			descr->d_union.d_getset->name,
			descr->d_type->tp_name);
		break;
	default:
		sprintf(buffer, "<flavor %d attribute of '%.100s' objects>",
			descr->d_flavor,
			descr->d_type->tp_name);
		break;
	}

	return PyString_FromString(buffer);
}

static PyObject *
descr_call(PyDescrObject *descr, PyObject *args, PyObject *kwds)
{
	int argc;
	PyObject *self;

	/* Make sure that the first argument is acceptable as 'self' */
	assert(PyTuple_Check(args));
	argc = PyTuple_GET_SIZE(args);
	if (argc < 1) {
		PyErr_SetString(PyExc_TypeError,
				"descriptor call needs 'self' argument");
		return NULL;
	}
	self = PyTuple_GET_ITEM(args, 0);
	if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor call 'self' is type '%.100s', "
			     "expected type '%.100s'",
			     self->ob_type->tp_name,
			     descr->d_type->tp_name);
		return NULL;
	}

	if (descr->d_flavor == DF_METHOD) {
		PyObject *func, *result;
		func = PyCFunction_New(descr->d_union.d_method, self);
		if (func == NULL)
			return NULL;
		args = PyTuple_GetSlice(args, 1, argc);
		if (args == NULL)
			return NULL;
		result = PyEval_CallObjectWithKeywords(func, args, kwds);
		Py_DECREF(args);
		return result;
	}

	/* Make sure there are no keyword arguments */
	if (kwds != NULL) {
		assert(PyDict_Check(kwds));
		if (PyDict_Size(kwds) > 0) {
			PyErr_SetString(PyExc_TypeError,
					"this descriptor object can't called "
					"called with keyword arguments");
			return NULL;
		}
	}

	if (argc == 1)
		return PyDescr_Get((PyObject *)descr, self);
	if (argc == 2) {
		PyObject *value = PyTuple_GET_ITEM(args, 1);
		if (PyDescr_Set((PyObject *)descr, self, value) < 0)
			return NULL;
		Py_INCREF(Py_None);
		return Py_None;
	}
	PyErr_SetString(PyExc_TypeError,
			"too many arguments to descriptor call");
	return NULL;
}

static PyObject *
descr_getattr(PyDescrObject *descr, char *name)
{
	char *s;

	if (strcmp(name, "__name__") == 0) {
		s = NULL;

		switch (descr->d_flavor) {
		case DF_METHOD:
			s = descr->d_union.d_method->ml_name;
			break;
		case DF_MEMBER:
			s = descr->d_union.d_member->name;
			break;
		case DF_GETSET:
			s = descr->d_union.d_getset->name;
			break;
		}
		if (s != NULL)
			return PyString_FromString(s);
	}
	if (strcmp(name, "__doc__") == 0) {
		if (descr->d_flavor == DF_METHOD) {
			s = descr->d_union.d_method->ml_doc;

			if (s == NULL) {
				Py_INCREF(Py_None);
				return Py_None;
			}
			else {
				return PyString_FromString(s);
			}
		}
	}

	s = descr_name(descr);
	if (s == NULL)
		s = "?";
	PyErr_Format(PyExc_AttributeError,
		     "descriptor '%.100s' of '%.100s' objects has no "
		     "'%.100s' attribute",
		     s, descr->d_type->tp_name, name);
	return NULL;
}

PyTypeObject PyDescr_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
	0,
	"descriptor",
	sizeof(PyDescrObject),
	0,
	(destructor)descr_dealloc,		/* tp_dealloc */
	0,					/* tp_print */
	(getattrfunc)descr_getattr,		/* tp_getattr */
	0,					/* tp_setattr */
	0,					/* tp_compare */
	(reprfunc)descr_repr,			/* tp_repr */
	0,					/* tp_as_number */
	0,					/* tp_as_sequence */
	0,					/* tp_as_mapping */
	0,					/* tp_hash */
	(ternaryfunc)descr_call,		/* tp_call */
	0,					/* tp_str */
	0,					/* 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 */
	0,					/* tp_members */
	0,					/* tp_getset */
	0,					/* tp_base */
	0,					/* tp_dict */
};

static PyDescrObject *
PyDescr_New(PyTypeObject *type)
{
	PyDescrObject *descr =  PyObject_NEW(PyDescrObject, &PyDescr_Type);

	if (descr == NULL)
		return NULL;
	descr->d_type = type;
	descr->d_flavor = DF_NULL;
	return descr;
}

PyObject *
PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
{
	PyDescrObject *descr = PyDescr_New(type);

	if (descr == NULL)
		return NULL;
	descr->d_union.d_method = method;
	descr->d_flavor = DF_METHOD;
	return (PyObject *)descr;
}

PyObject *
PyDescr_NewMember(PyTypeObject *type, struct memberlist *member)
{
	PyDescrObject *descr = PyDescr_New(type);

	if (descr == NULL)
		return NULL;
	descr->d_union.d_member = member;
	descr->d_flavor = DF_MEMBER;
	return (PyObject *)descr;
}

PyObject *
PyDescr_NewGetSet(PyTypeObject *type, struct getsetlist *getset)
{
	PyDescrObject *descr = PyDescr_New(type);

	if (descr == NULL)
		return NULL;
	descr->d_union.d_getset = getset;
	descr->d_flavor = DF_GETSET;
	return (PyObject *)descr;
}

PyObject *
PyDescr_Get(PyObject *d, PyObject *obj)
{
	PyDescrObject *descr;

	if (obj == NULL || !PyDescr_Check(d)) {
		Py_INCREF(d);
		return d;
	}

	descr = (PyDescrObject *)d;
 
	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor for '%.100s' objects "
			     "doesn't apply to '%.100s' object",
			     descr->d_type->tp_name,
			     obj->ob_type->tp_name);
		return NULL;
	}

	switch (descr->d_flavor) {

	case DF_METHOD:
		return PyCFunction_New(descr->d_union.d_method, obj);

	case DF_MEMBER:
		return PyMember_Get((char *)obj,
				    descr->d_union.d_member,
				    descr->d_union.d_member->name);

	case DF_GETSET:
		if (descr->d_union.d_getset->get != NULL)
			return descr->d_union.d_getset->get(
				obj, descr->d_union.d_getset->closure);

	}

	PyErr_Format(PyExc_NotImplementedError,
		     "PyDescr_Get() not implemented for descriptor type %d "
		     "of '%.50s' object",
		     descr->d_flavor, obj->ob_type->tp_name);
	return NULL;
}

int
PyDescr_Set(PyObject *d, PyObject *obj, PyObject *value)
{
	PyDescrObject *descr = (PyDescrObject *)d;

	assert(PyDescr_Check(d));

	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor for '%.100s' objects "
			     "doesn't apply to '%.100s' object",
			     descr->d_type->tp_name,
			     obj->ob_type->tp_name);
		return -1;
	}

	switch (descr->d_flavor) {

	case DF_METHOD:
		PyErr_Format(PyExc_TypeError,
			     "can't %s method attribute '%.400s' "
			     "of '%.50s' object",
			     value==NULL ? "delete" : "assign to",
			     descr->d_union.d_method->ml_name,
			     obj->ob_type->tp_name);
		return -1;

	case DF_MEMBER:
		return PyMember_Set((char *)obj,
				    descr->d_union.d_member,
				    descr->d_union.d_member->name,
				    value);

	case DF_GETSET:
		if (descr->d_union.d_getset->set == NULL) {
			PyErr_Format(PyExc_TypeError,
				     "can't %s read-only attribute "
				     "'%.400s' of '%.50s' object",
				     value==NULL ? "delete" : "assign to",
				     descr->d_union.d_getset->name,
				     obj->ob_type->tp_name);
			return -1;
		}
		return descr->d_union.d_getset->set(
			obj, value, descr->d_union.d_getset->closure);

	}

	PyErr_Format(PyExc_NotImplementedError,
		     "PyDescr_Set() not implemented for descriptor type %d "
		     "of '%.50s' object",
		     descr->d_flavor, obj->ob_type->tp_name);
	return -1;
}


/* Initialize the __dict__ in a type object */

static struct PyMethodDef intrinsic_methods[] = {
	{0}
};

static struct memberlist intrinsic_members[] = {
	{"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY},
	{0}
};

static struct getsetlist intrinsic_getsets[] = {
	{0}
};

static int
add_methods(PyTypeObject *type, PyMethodDef *meth)
{
	PyObject *dict = type->tp_dict;

	for (; meth->ml_name != NULL; meth++) {
		PyObject *descr = PyDescr_NewMethod(type, meth);
		if (descr == NULL)
			return -1;
		if (PyDict_SetItemString(dict,meth->ml_name,descr) < 0)
			return -1;
		Py_DECREF(descr);
	}
	return 0;
}

static int
add_members(PyTypeObject *type, struct memberlist *memb)
{
	PyObject *dict = type->tp_dict;

	for (; memb->name != NULL; memb++) {
		PyObject *descr = PyDescr_NewMember(type, memb);
		if (descr == NULL)
			return -1;
		if (PyDict_SetItemString(dict, memb->name, descr) < 0)
			return -1;
		Py_DECREF(descr);
	}
	return 0;
}

static int
add_getset(PyTypeObject *type, struct getsetlist *gsp)
{
	PyObject *dict = type->tp_dict;

	for (; gsp->name != NULL; gsp++) {
		PyObject *descr = PyDescr_NewGetSet(type, gsp);

		if (descr == NULL)
			return -1;
		if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
			return -1;
		Py_DECREF(descr);
	}
	return 0;
}

int
PyType_InitDict(PyTypeObject *type)
{
	PyObject *dict;

	if (type->tp_dict != NULL)
		return 0;
	dict = PyDict_New();
	if (dict == NULL)
		return -1;
	type->tp_dict = dict;
	if (type->tp_methods != NULL) {
		if (add_methods(type, type->tp_methods) < 0)
			return -1;
	}
	if (type->tp_members != NULL) {
		if (add_members(type, type->tp_members) < 0)
			return -1;
	}
	if (type->tp_getset != NULL) {
		if (add_getset(type, type->tp_getset) < 0)
			return -1;
	}
	/* Add intrinsics */
	if (add_methods(type, intrinsic_methods) < 0)
		return -1;
	if (add_members(type, intrinsic_members) < 0)
		return -1;
	if (add_getset(type, intrinsic_getsets) < 0)
		return -1;
	return 0;
}

Index: complexobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v
retrieving revision 2.35
retrieving revision 2.35.4.1
diff -C2 -r2.35 -r2.35.4.1
*** complexobject.c	2001/03/18 08:21:57	2.35
--- complexobject.c	2001/04/24 00:43:30	2.35.4.1
***************
*** 9,12 ****
--- 9,13 ----
  
  #include "Python.h"
+ #include "structmember.h"
  
  /* Precisions used by repr() and str(), respectively.
***************
*** 560,575 ****
  };
  
! 
! static PyObject *
! complex_getattr(PyComplexObject *self, char *name)
! {
! 	if (strcmp(name, "real") == 0)
! 		return (PyObject *)PyFloat_FromDouble(self->cval.real);
! 	else if (strcmp(name, "imag") == 0)
! 		return (PyObject *)PyFloat_FromDouble(self->cval.imag);
! 	else if (strcmp(name, "__members__") == 0)
! 		return Py_BuildValue("[ss]", "imag", "real");
! 	return Py_FindMethod(complex_methods, (PyObject *)self, name);
! }
  
  static PyNumberMethods complex_as_number = {
--- 561,569 ----
  };
  
! static struct memberlist complex_members[] = {
! 	{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0},
! 	{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0},
! 	{0},
! };
  
  static PyNumberMethods complex_as_number = {
***************
*** 607,611 ****
  	(destructor)complex_dealloc,		/* tp_dealloc */
  	(printfunc)complex_print,		/* tp_print */
! 	(getattrfunc)complex_getattr,		/* tp_getattr */
  	0,					/* tp_setattr */
  	0,					/* tp_compare */
--- 601,605 ----
  	(destructor)complex_dealloc,		/* tp_dealloc */
  	(printfunc)complex_print,		/* tp_print */
! 	0,					/* tp_getattr */
  	0,					/* tp_setattr */
  	0,					/* tp_compare */
***************
*** 625,628 ****
--- 619,630 ----
  	0,					/* tp_clear */
  	complex_richcompare,			/* tp_richcompare */
+ 	0,					/* tp_weaklistoffset */
+ 	0,					/* tp_iter */
+ 	0,					/* tp_iternext */
+ 	complex_methods,			/* tp_methods */
+ 	complex_members,			/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  

Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.80
retrieving revision 2.80.2.1
diff -C2 -r2.80 -r2.80.2.1
*** dictobject.c	2001/04/23 14:08:49	2.80
--- dictobject.c	2001/04/24 00:43:30	2.80.2.1
***************
*** 1287,1296 ****
  };
  
- static PyObject *
- dict_getattr(dictobject *mp, char *name)
- {
- 	return Py_FindMethod(mapp_methods, (PyObject *)mp, name);
- }
- 
  static int
  dict_contains(dictobject *mp, PyObject *key)
--- 1287,1290 ----
***************
*** 1335,1339 ****
  	(destructor)dict_dealloc,		/* tp_dealloc */
  	(printfunc)dict_print,			/* tp_print */
! 	(getattrfunc)dict_getattr,		/* tp_getattr */
  	0,					/* tp_setattr */
  	(cmpfunc)dict_compare,			/* tp_compare */
--- 1329,1333 ----
  	(destructor)dict_dealloc,		/* tp_dealloc */
  	(printfunc)dict_print,			/* tp_print */
! 	0,					/* tp_getattr */
  	0,					/* tp_setattr */
  	(cmpfunc)dict_compare,			/* tp_compare */
***************
*** 1356,1359 ****
--- 1350,1358 ----
  	(getiterfunc)dictiter_new,		/* tp_iter */
  	0,					/* tp_iternext */
+ 	mapp_methods,				/* tp_methods */
+ 	0,					/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  

Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.112
retrieving revision 2.112.2.1
diff -C2 -r2.112 -r2.112.2.1
*** fileobject.c	2001/04/23 14:08:49	2.112
--- fileobject.c	2001/04/24 00:43:30	2.112.2.1
***************
*** 1274,1300 ****
  
  static PyObject *
! file_getattr(PyFileObject *f, char *name)
  {
! 	PyObject *res;
! 
! 	res = Py_FindMethod(file_methods, (PyObject *)f, name);
! 	if (res != NULL)
! 		return res;
! 	PyErr_Clear();
! 	if (strcmp(name, "closed") == 0)
! 		return PyInt_FromLong((long)(f->f_fp == 0));
! 	return PyMember_Get((char *)f, file_memberlist, name);
  }
  
! static int
! file_setattr(PyFileObject *f, char *name, PyObject *v)
! {
! 	if (v == NULL) {
! 		PyErr_SetString(PyExc_AttributeError,
! 				"can't delete file attributes");
! 		return -1;
! 	}
! 	return PyMember_Set((char *)f, file_memberlist, name, v);
! }
  
  static PyObject *
--- 1274,1286 ----
  
  static PyObject *
! get_closed(PyFileObject *f, void *closure)
  {
! 	return PyInt_FromLong((long)(f->f_fp == 0));
  }
  
! static struct getsetlist file_getsetlist[] = {
! 	{"closed", (getter)get_closed, NULL, NULL},
! 	{0},
! };
  
  static PyObject *
***************
*** 1321,1328 ****
  	(destructor)file_dealloc,		/* tp_dealloc */
  	0,					/* tp_print */
! 	(getattrfunc)file_getattr,		/* tp_getattr */
! 	(setattrfunc)file_setattr,		/* tp_setattr */
  	0,					/* tp_compare */
! 	(reprfunc)file_repr,			/* tp_repr */
  	0,					/* tp_as_number */
  	0,					/* tp_as_sequence */
--- 1307,1314 ----
  	(destructor)file_dealloc,		/* tp_dealloc */
  	0,					/* tp_print */
! 	0,			 		/* tp_getattr */
! 	0,			 		/* tp_setattr */
  	0,					/* tp_compare */
! 	(reprfunc)file_repr, 			/* tp_repr */
  	0,					/* tp_as_number */
  	0,					/* tp_as_sequence */
***************
*** 1335,1345 ****
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT,			/* tp_flags */
!  	0,					/* tp_doc */
!  	0,					/* tp_traverse */
!  	0,					/* tp_clear */
  	0,					/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
  	(getiterfunc)file_getiter,		/* tp_iter */
  	0,					/* tp_iternext */
  };
  
--- 1321,1336 ----
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT,			/* tp_flags */
! 	0,					/* tp_doc */
! 	0,					/* tp_traverse */
! 	0,					/* tp_clear */
  	0,					/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
  	(getiterfunc)file_getiter,		/* tp_iter */
  	0,					/* tp_iternext */
+ 	file_methods,				/* tp_methods */
+ 	file_memberlist,			/* tp_members */
+ 	file_getsetlist,			/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  

Index: frameobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v
retrieving revision 2.49
retrieving revision 2.49.4.1
diff -C2 -r2.49 -r2.49.4.1
*** frameobject.c	2001/04/14 17:55:41	2.49
--- frameobject.c	2001/04/24 00:43:30	2.49.4.1
***************
*** 28,43 ****
  
  static PyObject *
! frame_getattr(PyFrameObject *f, char *name)
  {
! 	if (strcmp(name, "f_locals") == 0)
! 		PyFrame_FastToLocals(f);
! 	return PyMember_Get((char *)f, frame_memberlist, name);
  }
  
! static int
! frame_setattr(PyFrameObject *f, char *name, PyObject *value)
! {
! 	return PyMember_Set((char *)f, frame_memberlist, name, value);
! }
  
  /* Stack frames are allocated and deallocated at a considerable rate.
--- 28,42 ----
  
  static PyObject *
! frame_getlocals(PyFrameObject *f, void *closure)
  {
! 	PyFrame_FastToLocals(f);
! 	Py_INCREF(f->f_locals);
! 	return f->f_locals;
  }
  
! static struct getsetlist frame_getsetlist[] = {
! 	{"f_locals",	(getter)frame_getlocals, NULL, NULL},
! 	{0}
! };
  
  /* Stack frames are allocated and deallocated at a considerable rate.
***************
*** 99,104 ****
  	(destructor)frame_dealloc, /*tp_dealloc*/
  	0,		/*tp_print*/
! 	(getattrfunc)frame_getattr, /*tp_getattr*/
! 	(setattrfunc)frame_setattr, /*tp_setattr*/
  	0,		/*tp_compare*/
  	0,		/*tp_repr*/
--- 98,103 ----
  	(destructor)frame_dealloc, /*tp_dealloc*/
  	0,		/*tp_print*/
! 	0,		/*tp_getattr*/
! 	0,		/*tp_setattr*/
  	0,		/*tp_compare*/
  	0,		/*tp_repr*/
***************
*** 106,109 ****
--- 105,127 ----
  	0,		/*tp_as_sequence*/
  	0,		/*tp_as_mapping*/
+ 	0,					/* tp_hash */
+ 	0,					/* tp_call */
+ 	0,					/* tp_str */
+ 	0,					/* 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 */
+ 	frame_memberlist,			/* tp_members */
+ 	frame_getsetlist,			/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  

Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92
retrieving revision 2.92.6.1
diff -C2 -r2.92 -r2.92.6.1
*** listobject.c	2001/02/12 22:06:02	2.92
--- listobject.c	2001/04/24 00:43:30	2.92.6.1
***************
*** 1523,1532 ****
  };
  
- static PyObject *
- list_getattr(PyListObject *f, char *name)
- {
- 	return Py_FindMethod(list_methods, (PyObject *)f, name);
- }
- 
  static PySequenceMethods list_as_sequence = {
  	(inquiry)list_length,			/* sq_length */
--- 1523,1526 ----
***************
*** 1550,1554 ****
  	(destructor)list_dealloc,		/* tp_dealloc */
  	(printfunc)list_print,			/* tp_print */
! 	(getattrfunc)list_getattr,		/* tp_getattr */
  	0,					/* tp_setattr */
  	0,					/* tp_compare */
--- 1544,1548 ----
  	(destructor)list_dealloc,		/* tp_dealloc */
  	(printfunc)list_print,			/* tp_print */
! 	0,					/* tp_getattr */
  	0,					/* tp_setattr */
  	0,					/* tp_compare */
***************
*** 1568,1571 ****
--- 1562,1573 ----
   	(inquiry)list_clear,			/* tp_clear */
  	list_richcompare,			/* tp_richcompare */
+ 	0,					/* tp_weaklistoffset */
+ 	0,					/* tp_iter */
+ 	0,					/* tp_iternext */
+ 	list_methods,				/* tp_methods */
+ 	0,					/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  
***************
*** 1596,1605 ****
  };
  
- static PyObject *
- immutable_list_getattr(PyListObject *f, char *name)
- {
- 	return Py_FindMethod(immutable_list_methods, (PyObject *)f, name);
- }
- 
  static int
  immutable_list_ass(void)
--- 1598,1601 ----
***************
*** 1628,1632 ****
  	0, /* Cannot happen */			/* tp_dealloc */
  	(printfunc)list_print,			/* tp_print */
! 	(getattrfunc)immutable_list_getattr,	/* tp_getattr */
  	0,					/* tp_setattr */
  	0, /* Won't be called */		/* tp_compare */
--- 1624,1628 ----
  	0, /* Cannot happen */			/* tp_dealloc */
  	(printfunc)list_print,			/* tp_print */
! 	0,					/* tp_getattr */
  	0,					/* tp_setattr */
  	0, /* Won't be called */		/* tp_compare */
***************
*** 1646,1649 ****
--- 1642,1653 ----
  	0,					/* tp_clear */
  	list_richcompare,			/* tp_richcompare */
+ 	0,					/* tp_weaklistoffset */
+ 	0,					/* tp_iter */
+ 	0,					/* tp_iternext */
+ 	immutable_list_methods,			/* tp_methods */
+ 	0,					/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  	/* NOTE: This is *not* the standard list_type struct! */
  };

Index: methodobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v
retrieving revision 2.33
retrieving revision 2.33.8.1
diff -C2 -r2.33 -r2.33.8.1
*** methodobject.c	2000/09/01 23:29:27	2.33
--- methodobject.c	2001/04/24 00:43:30	2.33.8.1
***************
*** 4,9 ****
  #include "Python.h"
  
- #include "token.h"
- 
  static PyCFunctionObject *free_list = NULL;
  
--- 4,7 ----
***************
*** 69,105 ****
  
  static PyObject *
! meth_getattr(PyCFunctionObject *m, char *name)
  {
! 	if (strcmp(name, "__name__") == 0) {
! 		return PyString_FromString(m->m_ml->ml_name);
! 	}
! 	if (strcmp(name, "__doc__") == 0) {
! 		char *doc = m->m_ml->ml_doc;
! 		if (doc != NULL)
! 			return PyString_FromString(doc);
! 		Py_INCREF(Py_None);
! 		return Py_None;
! 	}
! 	if (strcmp(name, "__self__") == 0) {
! 		PyObject *self;
! 		if (PyEval_GetRestricted()) {
! 			PyErr_SetString(PyExc_RuntimeError,
! 			 "method.__self__ not accessible in restricted mode");
! 			return NULL;
! 		}
! 		self = m->m_self;
! 		if (self == NULL)
! 			self = Py_None;
! 		Py_INCREF(self);
! 		return self;
! 	}
! 	if (strcmp(name, "__members__") == 0) {
! 		return Py_BuildValue("[sss]",
! 				     "__doc__", "__name__", "__self__");
  	}
! 	PyErr_SetString(PyExc_AttributeError, name);
! 	return NULL;
  }
  
  static PyObject *
  meth_repr(PyCFunctionObject *m)
--- 67,109 ----
  
  static PyObject *
! meth_get__doc__(PyCFunctionObject *m, void *closure)
  {
! 	char *doc = m->m_ml->ml_doc;
! 
! 	if (doc != NULL)
! 		return PyString_FromString(doc);
! 	Py_INCREF(Py_None);
! 	return Py_None;
! }
! 
! static PyObject *
! meth_get__name__(PyCFunctionObject *m, void *closure)
! {
! 	return PyString_FromString(m->m_ml->ml_name);
! }
! 
! static PyObject *
! meth_get__self__(PyCFunctionObject *m, void *closure)
! {
! 	PyObject *self;
! 	if (PyEval_GetRestricted()) {
! 		PyErr_SetString(PyExc_RuntimeError,
! 			"method.__self__ not accessible in restricted mode");
! 		return NULL;
  	}
! 	self = m->m_self;
! 	if (self == NULL)
! 		self = Py_None;
! 	Py_INCREF(self);
! 	return self;
  }
  
+ static struct getsetlist meth_getsets [] = {
+ 	{"__doc__",  (getter)meth_get__doc__,  NULL, NULL},
+ 	{"__name__", (getter)meth_get__name__, NULL, NULL},
+ 	{"__self__", (getter)meth_get__self__, NULL, NULL},
+ 	{0}
+ };
+ 
  static PyObject *
  meth_repr(PyCFunctionObject *m)
***************
*** 155,168 ****
  	sizeof(PyCFunctionObject),
  	0,
! 	(destructor)meth_dealloc, /*tp_dealloc*/
! 	0,		/*tp_print*/
! 	(getattrfunc)meth_getattr, /*tp_getattr*/
! 	0,		/*tp_setattr*/
! 	(cmpfunc)meth_compare, /*tp_compare*/
! 	(reprfunc)meth_repr, /*tp_repr*/
! 	0,		/*tp_as_number*/
! 	0,		/*tp_as_sequence*/
! 	0,		/*tp_as_mapping*/
! 	(hashfunc)meth_hash, /*tp_hash*/
  };
  
--- 159,189 ----
  	sizeof(PyCFunctionObject),
  	0,
! 	(destructor)meth_dealloc,		/* tp_dealloc */
! 	0,					/* tp_print */
! 	0,					/* tp_getattr */
! 	0,					/* tp_setattr */
! 	(cmpfunc)meth_compare,			/* tp_compare */
! 	(reprfunc)meth_repr, 			/* tp_repr */
! 	0,					/* tp_as_number */
! 	0,					/* tp_as_sequence */
! 	0,					/* tp_as_mapping */
! 	(hashfunc)meth_hash,			/* tp_hash */
! 	0,					/* tp_call */
! 	0,					/* tp_str */
! 	0,					/* 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_methods */
! 	0,					/* tp_members */
! 	meth_getsets,				/* tp_getset */
! 	0,					/* tp_base */
! 	0,					/* tp_dict */
  };
  

Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.124
retrieving revision 2.124.4.1
diff -C2 -r2.124 -r2.124.4.1
*** object.c	2001/03/25 19:16:13	2.124
--- object.c	2001/04/24 00:43:30	2.124.4.1
***************
*** 982,1005 ****
  PyObject_GetAttrString(PyObject *v, char *name)
  {
! 	if (v->ob_type->tp_getattro != NULL) {
! 		PyObject *w, *res;
! 		w = PyString_InternFromString(name);
! 		if (w == NULL)
! 			return NULL;
! 		res = (*v->ob_type->tp_getattro)(v, w);
! 		Py_XDECREF(w);
! 		return res;
! 	}
  
! 	if (v->ob_type->tp_getattr == NULL) {
! 		PyErr_Format(PyExc_AttributeError,
! 			     "'%.50s' object has no attribute '%.400s'",
! 			     v->ob_type->tp_name,
! 			     name);
! 		return NULL;
! 	}
! 	else {
  		return (*v->ob_type->tp_getattr)(v, name);
! 	}
  }
  
--- 982,995 ----
  PyObject_GetAttrString(PyObject *v, char *name)
  {
! 	PyObject *w, *res;
  
! 	if (v->ob_type->tp_getattr != NULL)
  		return (*v->ob_type->tp_getattr)(v, name);
! 	w = PyString_InternFromString(name);
! 	if (w == NULL)
! 		return NULL;
! 	res = PyObject_GetAttr(v, w);
! 	Py_XDECREF(w);
! 	return res;
  }
  
***************
*** 1019,1033 ****
  PyObject_SetAttrString(PyObject *v, char *name, PyObject *w)
  {
! 	if (v->ob_type->tp_setattro != NULL) {
! 		PyObject *s;
! 		int res;
! 		s = PyString_InternFromString(name);
! 		if (s == NULL)
! 			return -1;
! 		res = (*v->ob_type->tp_setattro)(v, s, w);
! 		Py_XDECREF(s);
! 		return res;
! 	}
  
  	if (v->ob_type->tp_setattr == NULL) {
  		if (v->ob_type->tp_getattr == NULL)
--- 1009,1026 ----
  PyObject_SetAttrString(PyObject *v, char *name, PyObject *w)
  {
! 	PyObject *s;
! 	int res;
! 
! 	if (v->ob_type->tp_setattr != NULL)
! 		return (*v->ob_type->tp_setattr)(v, name, w);
! 	s = PyString_InternFromString(name);
! 	if (s == NULL)
! 		return -1;
! 	res = PyObject_SetAttr(v, s, w);
! 	Py_XDECREF(s);
! 	return res;
! }
  
+ /*
  	if (v->ob_type->tp_setattr == NULL) {
  		if (v->ob_type->tp_getattr == NULL)
***************
*** 1042,1046 ****
  		return (*v->ob_type->tp_setattr)(v, name, w);
  	}
! }
  
  /* Internal API needed by PyObject_GetAttr(): */
--- 1035,1039 ----
  		return (*v->ob_type->tp_setattr)(v, name, w);
  	}
! */
  
  /* Internal API needed by PyObject_GetAttr(): */
***************
*** 1052,1055 ****
--- 1045,1050 ----
  PyObject_GetAttr(PyObject *v, PyObject *name)
  {
+ 	PyTypeObject *tp = v->ob_type;
+ 
  	/* The Unicode to string conversion is done here because the
  	   existing tp_getattro slots expect a string object as name
***************
*** 1060,1064 ****
  			return NULL;
  	}
- 
  	if (!PyString_Check(name)) {
  		PyErr_SetString(PyExc_TypeError,
--- 1055,1058 ----
***************
*** 1066,1073 ****
  		return NULL;
  	}
! 	if (v->ob_type->tp_getattro != NULL)
! 		return (*v->ob_type->tp_getattro)(v, name);
! 	else
! 	return PyObject_GetAttrString(v, PyString_AS_STRING(name));
  }
  
--- 1060,1081 ----
  		return NULL;
  	}
! 	if (tp->tp_getattro != NULL)
! 		return (*tp->tp_getattro)(v, name);
! 	if (tp->tp_getattr != NULL)
! 		return (*tp->tp_getattr)(v, PyString_AS_STRING(name));
! 	if (tp->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
! 		PyObject *descr;
! 		if (tp->tp_dict == NULL) {
! 			if (PyType_InitDict(tp) < 0)
! 				return NULL;
! 		}
! 		descr = PyDict_GetItem(tp->tp_dict, name);
! 		if (descr != NULL)
! 			return PyDescr_Get(descr, v);
! 	}
! 	PyErr_Format(PyExc_AttributeError,
! 		     "'%.50s' object has no attribute '%.400s'",
! 		     tp->tp_name, PyString_AS_STRING(name));
! 	return NULL;
  }
  
***************
*** 1087,1090 ****
--- 1095,1099 ----
  PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
  {
+ 	PyTypeObject *tp = v->ob_type;
  	int err;
  
***************
*** 1097,1119 ****
  			return -1;
  	}
! 	else
! 		Py_INCREF(name);
! 	
! 	if (!PyString_Check(name)){
  		PyErr_SetString(PyExc_TypeError,
  				"attribute name must be string");
! 		err = -1;
  	}
! 	else {
! 		PyString_InternInPlace(&name);
! 		if (v->ob_type->tp_setattro != NULL)
! 			err = (*v->ob_type->tp_setattro)(v, name, value);
! 		else
! 			err = PyObject_SetAttrString(v, 
! 				        PyString_AS_STRING(name), value);
  	}
- 	
  	Py_DECREF(name);
! 	return err;
  }
  
--- 1106,1146 ----
  			return -1;
  	}
! 	else if (!PyString_Check(name)){
  		PyErr_SetString(PyExc_TypeError,
  				"attribute name must be string");
! 		return -1;
  	}
! 	else
! 		Py_INCREF(name);
! 
! 	PyString_InternInPlace(&name);
! 	if (tp->tp_setattro != NULL) {
! 		err = (*tp->tp_setattro)(v, name, value);
! 		Py_DECREF(name);
! 		return err;
! 	}
! 	if (tp->tp_setattr != NULL) {
! 		err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);
! 		Py_DECREF(name);
! 		return err;
! 	}
! 	if (tp->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
! 		PyObject *descr;
! 		if (tp->tp_dict == NULL) {
! 			if (PyType_InitDict(tp) < 0)
! 				return -1;
! 		}
! 		descr = PyDict_GetItem(tp->tp_dict, name);
! 		if (descr != NULL) {
! 			err = PyDescr_Set(descr, v, value);
! 			Py_DECREF(name);
! 			return err;
! 		}
  	}
  	Py_DECREF(name);
! 	PyErr_Format(PyExc_AttributeError,
! 		     "'%.50s' object has no attribute '%.400s'",
! 		     tp->tp_name, PyString_AS_STRING(name));
! 	return -1;
  }
  

Index: rangeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/rangeobject.c,v
retrieving revision 2.24
retrieving revision 2.24.6.1
diff -C2 -r2.24 -r2.24.6.1
*** rangeobject.c	2001/01/15 18:58:56	2.24
--- rangeobject.c	2001/04/24 00:43:30	2.24.6.1
***************
*** 249,280 ****
  
  static PyObject *
! range_getattr(rangeobject *r, char *name)
  {
! 	PyObject *result;
! 
! 	static PyMethodDef range_methods[] = {
! 		{"tolist",	(PyCFunction)range_tolist, METH_VARARGS,
!                  "tolist() -> list\n"
!                  "Return a list object with the same values."},
! 		{NULL,		NULL}
! 	};
! 	static struct memberlist range_members[] = {
! 		{"step",  T_LONG, offsetof(rangeobject, step), RO},
! 		{"start", T_LONG, offsetof(rangeobject, start), RO},
! 		{"stop",  T_LONG, 0, RO},
! 		{NULL, 0, 0, 0}
! 	};
! 
! 	result = Py_FindMethod(range_methods, (PyObject *) r, name);
! 	if (result == NULL) {
! 		PyErr_Clear();
! 		if (strcmp("stop", name) == 0)
! 			result = PyInt_FromLong(r->start + (r->len * r->step));
! 		else
! 			result = PyMember_Get((char *)r, range_members, name);
! 	}
! 	return result;
  }
  
  static int
  range_contains(rangeobject *r, PyObject *obj)
--- 249,274 ----
  
  static PyObject *
! range_getstop(rangeobject *r, void *closure)
  {
! 	return PyInt_FromLong(r->start + (r->len * r->step));
  }
  
+ static PyMethodDef range_methods[] = {
+ 	{"tolist",	(PyCFunction)range_tolist, METH_VARARGS,
+ 	 "tolist() -> list\n"
+ 	 "Return a list object with the same values."},
+ 	{NULL,		NULL}
+ };
+ static struct memberlist range_members[] = {
+ 	{"step",  T_LONG, offsetof(rangeobject, step), RO},
+ 	{"start", T_LONG, offsetof(rangeobject, start), RO},
+ 	{NULL, 0, 0, 0}
+ };
+ 
+ static struct getsetlist range_getsets[] = {
+ 	{"stop", (getter)range_getstop, NULL, NULL},
+ 	{0}
+ };
+ 
  static int
  range_contains(rangeobject *r, PyObject *obj)
***************
*** 319,323 ****
  	(destructor)range_dealloc, /*tp_dealloc*/
  	0,			/*tp_print*/
! 	(getattrfunc)range_getattr, /*tp_getattr*/
  	0,			/*tp_setattr*/
  	(cmpfunc)range_compare, /*tp_compare*/
--- 313,317 ----
  	(destructor)range_dealloc, /*tp_dealloc*/
  	0,			/*tp_print*/
! 	0, 			/*tp_getattr*/
  	0,			/*tp_setattr*/
  	(cmpfunc)range_compare, /*tp_compare*/
***************
*** 333,335 ****
--- 327,341 ----
  	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 */
+ 	range_methods,				/* tp_methods */
+ 	range_members,				/* tp_members */
+ 	range_getsets,				/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };

Index: sliceobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/sliceobject.c,v
retrieving revision 2.7
retrieving revision 2.7.4.1
diff -C2 -r2.7 -r2.7.4.1
*** sliceobject.c	2001/03/20 12:41:34	2.7
--- sliceobject.c	2001/04/24 00:43:30	2.7.4.1
***************
*** 15,18 ****
--- 15,19 ----
  
  #include "Python.h"
+ #include "structmember.h"
  
  static PyObject *
***************
*** 129,158 ****
  }
  
! 
! static PyObject *slice_getattr(PySliceObject *self, char *name)
! {
! 	PyObject *ret;
!   
! 	ret = NULL;
! 	if (strcmp(name, "start") == 0) {
! 		ret = self->start;
! 	}
! 	else if (strcmp(name, "stop") == 0) {
! 		ret = self->stop;
! 	}
! 	else if (strcmp(name, "step") == 0) {
! 		ret = self->step;
! 	}
! 	else if (strcmp(name, "__members__") == 0) {
! 		return Py_BuildValue("[sss]",
! 				     "start", "stop", "step");
! 	}
! 	else {
! 		PyErr_SetString(PyExc_AttributeError, name);
! 		return NULL;
! 	}
! 	Py_INCREF(ret);
! 	return ret;
! }
  
  static int
--- 130,139 ----
  }
  
! static struct memberlist slice_members[] = {
! 	{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
! 	{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
! 	{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
! 	{0}
! };
  
  static int
***************
*** 183,194 ****
  	sizeof(PySliceObject),	/* Basic object size */
  	0,			/* Item size for varobject */
! 	(destructor)slice_dealloc, /*tp_dealloc*/
! 	0,			/*tp_print*/
! 	(getattrfunc)slice_getattr, /*tp_getattr*/
! 	0,			/*tp_setattr*/
! 	(cmpfunc)slice_compare, /*tp_compare*/
! 	(reprfunc)slice_repr,   /*tp_repr*/
! 	0,			/*tp_as_number*/
! 	0,	    		/*tp_as_sequence*/
! 	0,			/*tp_as_mapping*/
  };
--- 164,194 ----
  	sizeof(PySliceObject),	/* Basic object size */
  	0,			/* Item size for varobject */
! 	(destructor)slice_dealloc,		/* tp_dealloc */
! 	0,					/* tp_print */
! 	0,					/* tp_getattr */
! 	0,					/* tp_setattr */
! 	(cmpfunc)slice_compare, 		/* tp_compare */
! 	(reprfunc)slice_repr,   		/* tp_repr */
! 	0,					/* tp_as_number */
! 	0,	    				/* tp_as_sequence */
! 	0,					/* tp_as_mapping */
! 	0,					/* tp_hash */
! 	0,					/* tp_call */
! 	0,					/* tp_str */
! 	0,					/* 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 */
! 	slice_members,				/* tp_members */
! 	0,					/* tp_getset */
! 	0,					/* tp_base */
! 	0,					/* tp_dict */
  };

Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.103
retrieving revision 2.103.2.1
diff -C2 -r2.103 -r2.103.2.1
*** stringobject.c	2001/04/20 19:13:02	2.103
--- stringobject.c	2001/04/24 00:43:30	2.103.2.1
***************
*** 2351,2361 ****
  };
  
- static PyObject *
- string_getattr(PyStringObject *s, char *name)
- {
- 	return Py_FindMethod(string_methods, (PyObject*)s, name);
- }
  
- 
  PyTypeObject PyString_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
--- 2351,2355 ----
***************
*** 2366,2370 ****
  	(destructor)string_dealloc, /*tp_dealloc*/
  	(printfunc)string_print, /*tp_print*/
! 	(getattrfunc)string_getattr,		/*tp_getattr*/
  	0,		/*tp_setattr*/
  	(cmpfunc)string_compare, /*tp_compare*/
--- 2360,2364 ----
  	(destructor)string_dealloc, /*tp_dealloc*/
  	(printfunc)string_print, /*tp_print*/
! 	0,		/*tp_getattr*/
  	0,		/*tp_setattr*/
  	(cmpfunc)string_compare, /*tp_compare*/
***************
*** 2381,2384 ****
--- 2375,2389 ----
  	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 */
+ 	string_methods,				/* tp_methods */
+ 	0,					/* tp_members */
+ 	0,					/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
  };
  

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16
retrieving revision 2.16.8.1
diff -C2 -r2.16 -r2.16.8.1
*** typeobject.c	2000/09/01 23:29:27	2.16
--- typeobject.c	2001/04/24 00:43:30	2.16.8.1
***************
*** 3,35 ****
  
  #include "Python.h"
  
! /* Type object implementation */
  
  static PyObject *
! type_getattr(PyTypeObject *t, char *name)
  {
! 	if (strcmp(name, "__name__") == 0)
! 		return PyString_FromString(t->tp_name);
! 	if (strcmp(name, "__doc__") == 0) {
! 		char *doc = t->tp_doc;
! 		if (doc != NULL)
! 			return PyString_FromString(doc);
! 		Py_INCREF(Py_None);
! 		return Py_None;
! 	}
! 	if (strcmp(name, "__members__") == 0)
! 		return Py_BuildValue("[ss]", "__doc__", "__name__");
! 	PyErr_SetString(PyExc_AttributeError, name);
! 	return NULL;
  }
  
  static PyObject *
! type_repr(PyTypeObject *v)
  {
  	char buf[100];
! 	sprintf(buf, "<type '%.80s'>", v->tp_name);
  	return PyString_FromString(buf);
  }
  
  PyTypeObject PyType_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
--- 3,71 ----
  
  #include "Python.h"
+ #include "structmember.h"
  
! struct memberlist type_members[] = {
! 	{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
! 	{"__doc__", T_STRING, offsetof(PyTypeObject, tp_doc), READONLY},
! 	{"__dict__", T_OBJECT, offsetof(PyTypeObject, tp_dict), READONLY},
! 	{0}
! };
  
  static PyObject *
! type_bases(PyObject *type, void *context)
  {
! 	return PyTuple_New(0);
  }
  
+ struct getsetlist type_getsets[] = {
+ 	{"__bases__", type_bases, NULL, NULL},
+ 	{0}
+ };
+ 
  static PyObject *
! type_repr(PyTypeObject *type)
  {
  	char buf[100];
! 	sprintf(buf, "<type '%.80s'>", type->tp_name);
  	return PyString_FromString(buf);
  }
  
+ static PyObject *
+ type_getattro(PyTypeObject *type, PyObject *name)
+ {
+ 	PyTypeObject *tp = type->ob_type; /* Usually == &PyType_Type below */
+ 	PyObject *descr;
+ 
+ 	assert(PyString_Check(name));
+ 
+ 	if (type->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
+ 		if (type->tp_dict == NULL) {
+ 			if (PyType_InitDict(type) < 0)
+ 				return NULL;
+ 		}
+ 	}
+ 
+ 	if (tp->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
+ 		if (tp->tp_dict == NULL) {
+ 			if (PyType_InitDict(tp) < 0)
+ 				return NULL;
+ 		}
+ 		descr = PyDict_GetItem(tp->tp_dict, name);
+ 		if (descr != NULL)
+ 			return PyDescr_Get(descr, (PyObject *)type);
+ 	}
+ 
+ 	if (type->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
+ 		descr = PyDict_GetItem(type->tp_dict, name);
+ 		if (descr != NULL)
+ 			return PyDescr_Get(descr, NULL);
+ 	}
+ 
+ 	PyErr_Format(PyExc_AttributeError,
+ 		     "type '%.50s' has no attribute '%.400s'",
+ 		     type->tp_name, PyString_AS_STRING(name));
+ 	return NULL;
+ }
+ 
  PyTypeObject PyType_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
***************
*** 38,57 ****
  	sizeof(PyTypeObject),	/* Basic object size */
  	0,			/* Item size for varobject */
! 	0,			/*tp_dealloc*/
! 	0,			/*tp_print*/
! 	(getattrfunc)type_getattr, /*tp_getattr*/
! 	0,			/*tp_setattr*/
! 	0,			/*tp_compare*/
! 	(reprfunc)type_repr,	/*tp_repr*/
! 	0,			/*tp_as_number*/
! 	0,			/*tp_as_sequence*/
! 	0,			/*tp_as_mapping*/
! 	0,			/*tp_hash*/
! 	0,			/*tp_call*/
! 	0,			/*tp_str*/
! 	0,			/*tp_xxx1*/
! 	0,			/*tp_xxx2*/
! 	0,			/*tp_xxx3*/
! 	0,			/*tp_xxx4*/
! 	"Define the behavior of a particular type of object.",
  };
--- 74,104 ----
  	sizeof(PyTypeObject),	/* Basic object size */
  	0,			/* Item size for varobject */
! 	0,					/* tp_dealloc */
! 	0,					/* tp_print */
! 	0,			 		/* tp_getattr */
! 	0,					/* tp_setattr */
! 	0,					/* tp_compare */
! 	(reprfunc)type_repr,			/* tp_repr */
! 	0,					/* tp_as_number */
! 	0,					/* tp_as_sequence */
! 	0,					/* tp_as_mapping */
! 	0,					/* tp_hash */
! 	0,					/* tp_call */
! 	0,					/* tp_str */
! 	(getattrofunc)type_getattro,		/* tp_getattro */
! 	0,					/* tp_setattro */
! 	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
! 	"Define the behavior of a particular type of object.", /* tp_doc */
! 	0,					/* tp_traverse */
! 	0,					/* tp_clear */
! 	0,					/* tp_richcompare */
! 	0,					/* tp_weaklistoffset */
! 	0,					/* tp_iter */
! 	0,					/* tp_iternext */
! 	0,					/* tp_methods */
! 	type_members,				/* tp_members */
! 	type_getsets,				/* tp_getset */
! 	0,					/* tp_base */
! 	0,					/* tp_dict */
  };

Index: unicodeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v
retrieving revision 2.87
retrieving revision 2.87.2.1
diff -C2 -r2.87 -r2.87.2.1
*** unicodeobject.c	2001/04/23 14:44:21	2.87
--- unicodeobject.c	2001/04/24 00:43:30	2.87.2.1
***************
*** 4558,4567 ****
  };
  
- static PyObject * 
- unicode_getattr(PyUnicodeObject *self, char *name)
- {
-     return Py_FindMethod(unicode_methods, (PyObject*) self, name);
- }
- 
  static PySequenceMethods unicode_as_sequence = {
      (inquiry) unicode_length, 		/* sq_length */
--- 4558,4561 ----
***************
*** 5235,5239 ****
      (destructor)_PyUnicode_Free, 	/* tp_dealloc */
      0, 					/* tp_print */
!     (getattrfunc)unicode_getattr, 	/* tp_getattr */
      0, 					/* tp_setattr */
      (cmpfunc) unicode_compare, 		/* tp_compare */
--- 5229,5233 ----
      (destructor)_PyUnicode_Free, 	/* tp_dealloc */
      0, 					/* tp_print */
!     0,				 	/* tp_getattr */
      0, 					/* tp_setattr */
      (cmpfunc) unicode_compare, 		/* tp_compare */
***************
*** 5245,5252 ****
      0, 					/* tp_call*/
      (reprfunc) unicode_str,	 	/* tp_str */
!     (getattrofunc) NULL, 		/* tp_getattro */
!     (setattrofunc) NULL, 		/* tp_setattro */
      &unicode_as_buffer,			/* tp_as_buffer */
      Py_TPFLAGS_DEFAULT,			/* tp_flags */
  };
  
--- 5239,5258 ----
      0, 					/* tp_call*/
      (reprfunc) unicode_str,	 	/* tp_str */
!     0,			 		/* tp_getattro */
!     0,			 		/* tp_setattro */
      &unicode_as_buffer,			/* 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 */
+     unicode_methods,			/* tp_methods */
+     0,					/* tp_members */
+     0,					/* tp_getset */
+     0,					/* tp_base */
+     0,					/* tp_dict */
  };