[Python-checkins] CVS: python/dist/src/Objects floatobject.c,2.87,2.88 intobject.c,2.65,2.66 longobject.c,1.92,1.93

Guido van Rossum gvanrossum@users.sourceforge.net
Wed, 29 Aug 2001 08:47:49 -0700


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

Modified Files:
	floatobject.c intobject.c longobject.c 
Log Message:
Make int, long and float subclassable.
This uses a slightly wimpy and wasteful approach, but it works. :-)


Index: floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.87
retrieving revision 2.88
diff -C2 -d -r2.87 -r2.88
*** floatobject.c	2001/08/23 22:31:37	2.87
--- floatobject.c	2001/08/29 15:47:46	2.88
***************
*** 627,630 ****
--- 627,633 ----
  
  
+ staticforward PyObject *
+ float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+ 
  static PyObject *
  float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
***************
*** 633,637 ****
  	static char *kwlist[] = {"x", 0};
  
! 	assert(type == &PyFloat_Type);
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
  		return NULL;
--- 636,641 ----
  	static char *kwlist[] = {"x", 0};
  
! 	if (type != &PyFloat_Type)
! 		return float_subtype_new(type, args, kwds); /* Wimp out */
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
  		return NULL;
***************
*** 641,644 ****
--- 645,671 ----
  }
  
+ /* Wimpy, slow approach to tp_new calls for subtypes of float:
+    first create a regular float from whatever arguments we got,
+    then allocate a subtype instance and initialize its ob_fval
+    from the regular float.  The regular float is then thrown away.
+ */
+ static PyObject *
+ float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyObject *tmp, *new;
+ 
+ 	assert(PyType_IsSubtype(type, &PyFloat_Type));
+ 	tmp = float_new(&PyFloat_Type, args, kwds);
+ 	if (tmp == NULL)
+ 		return NULL;
+ 	assert(PyFloat_Check(tmp));
+ 	new = type->tp_alloc(type, 0);;
+ 	if (new == NULL)
+ 		return NULL;
+ 	((PyFloatObject *)new)->ob_fval = ((PyFloatObject *)tmp)->ob_fval;
+ 	Py_DECREF(tmp);
+ 	return new;
+ }
+ 
  static char float_doc[] =
  "float(x) -> floating point number\n\
***************
*** 709,713 ****
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
  	float_doc,				/* tp_doc */
   	0,					/* tp_traverse */
--- 736,741 ----
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
! 		Py_TPFLAGS_BASETYPE,		/* tp_flags */
  	float_doc,				/* tp_doc */
   	0,					/* tp_traverse */
***************
*** 751,755 ****
  		     i < N_FLOATOBJECTS;
  		     i++, p++) {
! 			if (PyFloat_Check(p) && p->ob_refcnt != 0)
  				frem++;
  		}
--- 779,783 ----
  		     i < N_FLOATOBJECTS;
  		     i++, p++) {
! 			if (p->ob_type == &PyFloat_Type && p->ob_refcnt != 0)
  				frem++;
  		}
***************
*** 761,765 ****
  			     i < N_FLOATOBJECTS;
  			     i++, p++) {
! 				if (!PyFloat_Check(p) || p->ob_refcnt == 0) {
  					p->ob_type = (struct _typeobject *)
  						free_list;
--- 789,794 ----
  			     i < N_FLOATOBJECTS;
  			     i++, p++) {
! 				if (p->ob_type != &PyFloat_Type ||
! 				    p->ob_refcnt == 0) {
  					p->ob_type = (struct _typeobject *)
  						free_list;
***************
*** 793,797 ****
  			     i < N_FLOATOBJECTS;
  			     i++, p++) {
! 				if (PyFloat_Check(p) && p->ob_refcnt != 0) {
  					char buf[100];
  					PyFloat_AsString(buf, p);
--- 822,827 ----
  			     i < N_FLOATOBJECTS;
  			     i++, p++) {
! 				if (p->ob_type == &PyFloat_Type &&
! 				    p->ob_refcnt != 0) {
  					char buf[100];
  					PyFloat_AsString(buf, p);

Index: intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.65
retrieving revision 2.66
diff -C2 -d -r2.65 -r2.66
*** intobject.c	2001/08/23 21:32:40	2.65
--- intobject.c	2001/08/29 15:47:46	2.66
***************
*** 135,140 ****
  int_dealloc(PyIntObject *v)
  {
! 	v->ob_type = (struct _typeobject *)free_list;
! 	free_list = v;
  }
  
--- 135,144 ----
  int_dealloc(PyIntObject *v)
  {
! 	if (v->ob_type == &PyInt_Type) {
! 		v->ob_type = (struct _typeobject *)free_list;
! 		free_list = v;
! 	}
! 	else
! 		v->ob_type->tp_free((PyObject *)v);
  }
  
***************
*** 784,787 ****
--- 788,794 ----
  }
  
+ staticforward PyObject *
+ int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+ 
  static PyObject *
  int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
***************
*** 791,795 ****
  	static char *kwlist[] = {"x", "base", 0};
  
! 	assert(type == &PyInt_Type);
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
  					 &x, &base))
--- 798,803 ----
  	static char *kwlist[] = {"x", "base", 0};
  
! 	if (type != &PyInt_Type)
! 		return int_subtype_new(type, args, kwds); /* Wimp out */
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
  					 &x, &base))
***************
*** 812,815 ****
--- 820,846 ----
  }
  
+ /* Wimpy, slow approach to tp_new calls for subtypes of int:
+    first create a regular int from whatever arguments we got,
+    then allocate a subtype instance and initialize its ob_ival
+    from the regular int.  The regular int is then thrown away.
+ */
+ static PyObject *
+ int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyObject *tmp, *new;
+ 
+ 	assert(PyType_IsSubtype(type, &PyInt_Type));
+ 	tmp = int_new(&PyInt_Type, args, kwds);
+ 	if (tmp == NULL)
+ 		return NULL;
+ 	assert(PyInt_Check(tmp));
+ 	new = type->tp_alloc(type, 0);;
+ 	if (new == NULL)
+ 		return NULL;
+ 	((PyIntObject *)new)->ob_ival = ((PyIntObject *)tmp)->ob_ival;
+ 	Py_DECREF(tmp);
+ 	return new;
+ }
+ 
  static char int_doc[] =
  "int(x[, base]) -> integer\n\
***************
*** 883,887 ****
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
  	int_doc,				/* tp_doc */
  	0,					/* tp_traverse */
--- 914,919 ----
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
! 		Py_TPFLAGS_BASETYPE,		/* tp_flags */
  	int_doc,				/* tp_doc */
  	0,					/* tp_traverse */
***************
*** 935,939 ****
  		     i < N_INTOBJECTS;
  		     i++, p++) {
! 			if (PyInt_Check(p) && p->ob_refcnt != 0)
  				irem++;
  		}
--- 967,971 ----
  		     i < N_INTOBJECTS;
  		     i++, p++) {
! 			if (p->ob_type == &PyInt_Type && p->ob_refcnt != 0)
  				irem++;
  		}
***************
*** 945,949 ****
  			     i < N_INTOBJECTS;
  			     i++, p++) {
! 				if (!PyInt_Check(p) || p->ob_refcnt == 0) {
  					p->ob_type = (struct _typeobject *)
  						free_list;
--- 977,982 ----
  			     i < N_INTOBJECTS;
  			     i++, p++) {
! 				if (p->ob_type != &PyInt_Type ||
! 				    p->ob_refcnt == 0) {
  					p->ob_type = (struct _typeobject *)
  						free_list;
***************
*** 987,991 ****
  			     i < N_INTOBJECTS;
  			     i++, p++) {
! 				if (PyInt_Check(p) && p->ob_refcnt != 0)
  					fprintf(stderr,
  				"#   <int at %p, refcnt=%d, val=%ld>\n",
--- 1020,1024 ----
  			     i < N_INTOBJECTS;
  			     i++, p++) {
! 				if (p->ob_type == &PyInt_Type && p->ob_refcnt != 0)
  					fprintf(stderr,
  				"#   <int at %p, refcnt=%d, val=%ld>\n",

Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.92
retrieving revision 1.93
diff -C2 -d -r1.92 -r1.93
*** longobject.c	2001/08/17 18:39:25	1.92
--- longobject.c	2001/08/29 15:47:46	1.93
***************
*** 2039,2042 ****
--- 2039,2044 ----
  	return long_format(v, 16, 1);
  }
+ staticforward PyObject *
+ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
  
  static PyObject *
***************
*** 2047,2051 ****
  	static char *kwlist[] = {"x", "base", 0};
  
! 	assert(type == &PyLong_Type);
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
  					 &x, &base))
--- 2049,2054 ----
  	static char *kwlist[] = {"x", "base", 0};
  
! 	if (type != &PyLong_Type)
! 		return long_subtype_new(type, args, kwds); /* Wimp out */
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
  					 &x, &base))
***************
*** 2070,2073 ****
--- 2073,2106 ----
  }
  
+ /* Wimpy, slow approach to tp_new calls for subtypes of long:
+    first create a regular long from whatever arguments we got,
+    then allocate a subtype instance and initialize it from
+    the regular long.  The regular long is then thrown away.
+ */
+ static PyObject *
+ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyLongObject *tmp, *new;
+ 	int i, n;
+ 
+ 	assert(PyType_IsSubtype(type, &PyLong_Type));
+ 	tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds);
+ 	if (tmp == NULL)
+ 		return NULL;
+ 	assert(PyLong_Check(tmp));
+ 	n = tmp->ob_size;
+ 	if (n < 0)
+ 		n = -n;
+ 	new = (PyLongObject *)type->tp_alloc(type, n);
+ 	if (new == NULL)
+ 		return NULL;
+ 	assert(PyLong_Check(new));
+ 	new->ob_size = type->ob_size;
+ 	for (i = 0; i < n; i++)
+ 		new->ob_digit[i] = tmp->ob_digit[i];
+ 	Py_DECREF(tmp);
+ 	return (PyObject *)new;
+ }
+ 
  static char long_doc[] =
  "long(x[, base]) -> integer\n\
***************
*** 2141,2145 ****
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
  	long_doc,				/* tp_doc */
  	0,					/* tp_traverse */
--- 2174,2179 ----
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
! 		Py_TPFLAGS_BASETYPE,		/* tp_flags */
  	long_doc,				/* tp_doc */
  	0,					/* tp_traverse */