diff options
author | Guido van Rossum <guido@python.org> | 2001-08-29 15:47:46 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-08-29 15:47:46 (GMT) |
commit | bef1417f9f31fdf0f7b7bdb458c1c1f17c5cfada (patch) | |
tree | 23a3648e6c25e55c0d1b1df836f0a29623b94155 | |
parent | e705ef1bced126819d7568b1d4e0ac6944b987e0 (diff) | |
download | cpython-bef1417f9f31fdf0f7b7bdb458c1c1f17c5cfada.zip cpython-bef1417f9f31fdf0f7b7bdb458c1c1f17c5cfada.tar.gz cpython-bef1417f9f31fdf0f7b7bdb458c1c1f17c5cfada.tar.bz2 |
Make int, long and float subclassable.
This uses a slightly wimpy and wasteful approach, but it works. :-)
-rw-r--r-- | Objects/floatobject.c | 40 | ||||
-rw-r--r-- | Objects/intobject.c | 47 | ||||
-rw-r--r-- | Objects/longobject.c | 38 |
3 files changed, 111 insertions, 14 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 69aede4..295f47e 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -626,13 +626,17 @@ float_float(PyObject *v) } +staticforward PyObject * +float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + static PyObject * float_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *x = Py_False; /* Integer zero */ static char *kwlist[] = {"x", 0}; - assert(type == &PyFloat_Type); + if (type != &PyFloat_Type) + return float_subtype_new(type, args, kwds); /* Wimp out */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x)) return NULL; if (PyString_Check(x)) @@ -640,6 +644,29 @@ float_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return PyNumber_Float(x); } +/* 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\ \n\ @@ -708,7 +735,8 @@ PyTypeObject PyFloat_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_BASETYPE, /* tp_flags */ float_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -750,7 +778,7 @@ PyFloat_Fini(void) for (i = 0, p = &list->objects[0]; i < N_FLOATOBJECTS; i++, p++) { - if (PyFloat_Check(p) && p->ob_refcnt != 0) + if (p->ob_type == &PyFloat_Type && p->ob_refcnt != 0) frem++; } next = list->next; @@ -760,7 +788,8 @@ PyFloat_Fini(void) for (i = 0, p = &list->objects[0]; i < N_FLOATOBJECTS; i++, p++) { - if (!PyFloat_Check(p) || p->ob_refcnt == 0) { + if (p->ob_type != &PyFloat_Type || + p->ob_refcnt == 0) { p->ob_type = (struct _typeobject *) free_list; free_list = p; @@ -792,7 +821,8 @@ PyFloat_Fini(void) for (i = 0, p = &list->objects[0]; i < N_FLOATOBJECTS; i++, p++) { - if (PyFloat_Check(p) && p->ob_refcnt != 0) { + if (p->ob_type == &PyFloat_Type && + p->ob_refcnt != 0) { char buf[100]; PyFloat_AsString(buf, p); fprintf(stderr, diff --git a/Objects/intobject.c b/Objects/intobject.c index 77d7e38..80cdf4b 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -134,8 +134,12 @@ PyInt_FromLong(long ival) static void int_dealloc(PyIntObject *v) { - v->ob_type = (struct _typeobject *)free_list; - free_list = 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); } long @@ -783,6 +787,9 @@ int_hex(PyIntObject *v) return PyString_FromString(buf); } +staticforward PyObject * +int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + static PyObject * int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -790,7 +797,8 @@ int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) int base = -909; static char *kwlist[] = {"x", "base", 0}; - assert(type == &PyInt_Type); + if (type != &PyInt_Type) + return int_subtype_new(type, args, kwds); /* Wimp out */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base)) return NULL; @@ -811,6 +819,29 @@ int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } +/* 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\ \n\ @@ -882,7 +913,8 @@ PyTypeObject PyInt_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_BASETYPE, /* tp_flags */ int_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -934,7 +966,7 @@ PyInt_Fini(void) for (i = 0, p = &list->objects[0]; i < N_INTOBJECTS; i++, p++) { - if (PyInt_Check(p) && p->ob_refcnt != 0) + if (p->ob_type == &PyInt_Type && p->ob_refcnt != 0) irem++; } next = list->next; @@ -944,7 +976,8 @@ PyInt_Fini(void) for (i = 0, p = &list->objects[0]; i < N_INTOBJECTS; i++, p++) { - if (!PyInt_Check(p) || p->ob_refcnt == 0) { + if (p->ob_type != &PyInt_Type || + p->ob_refcnt == 0) { p->ob_type = (struct _typeobject *) free_list; free_list = p; @@ -986,7 +1019,7 @@ PyInt_Fini(void) for (i = 0, p = &list->objects[0]; i < N_INTOBJECTS; i++, p++) { - if (PyInt_Check(p) && p->ob_refcnt != 0) + if (p->ob_type == &PyInt_Type && p->ob_refcnt != 0) fprintf(stderr, "# <int at %p, refcnt=%d, val=%ld>\n", p, p->ob_refcnt, p->ob_ival); diff --git a/Objects/longobject.c b/Objects/longobject.c index 01a7276..ea0685e 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2038,6 +2038,8 @@ long_hex(PyObject *v) { return long_format(v, 16, 1); } +staticforward PyObject * +long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -2046,7 +2048,8 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) int base = -909; /* unlikely! */ static char *kwlist[] = {"x", "base", 0}; - assert(type == &PyLong_Type); + if (type != &PyLong_Type) + return long_subtype_new(type, args, kwds); /* Wimp out */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist, &x, &base)) return NULL; @@ -2069,6 +2072,36 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } +/* 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\ \n\ @@ -2140,7 +2173,8 @@ PyTypeObject PyLong_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_BASETYPE, /* tp_flags */ long_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ |