diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-09-10 20:52:51 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-09-10 20:52:51 (GMT) |
commit | 64b5ce3a69569b203a39f74c5c03348ba0a67583 (patch) | |
tree | 87f71bc6ef25a7b7e11087afb1d7827bbcc4d474 | |
parent | 8b4e43e768f3f49513f6f32f20ecb6478c1ad840 (diff) | |
download | cpython-64b5ce3a69569b203a39f74c5c03348ba0a67583.zip cpython-64b5ce3a69569b203a39f74c5c03348ba0a67583.tar.gz cpython-64b5ce3a69569b203a39f74c5c03348ba0a67583.tar.bz2 |
SF bug #460020: bug or feature: unicode() and subclasses.
Given an immutable type M, and an instance I of a subclass of M, the
constructor call M(I) was just returning I as-is; but it should return a
new instance of M. This fixes it for M in {int, long}. Strings, floats
and tuples remain to be done.
Added new macros PyInt_CheckExact and PyLong_CheckExact, to more easily
distinguish between "is" and "is a" (i.e., only an int passes
PyInt_CheckExact, while any sublass of int passes PyInt_Check).
Added private API function _PyLong_Copy.
-rw-r--r-- | Include/intobject.h | 1 | ||||
-rw-r--r-- | Include/longintrepr.h | 3 | ||||
-rw-r--r-- | Include/longobject.h | 1 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 21 | ||||
-rw-r--r-- | Objects/abstract.c | 11 | ||||
-rw-r--r-- | Objects/longobject.c | 21 |
6 files changed, 55 insertions, 3 deletions
diff --git a/Include/intobject.h b/Include/intobject.h index 29448e3..2d244ec 100644 --- a/Include/intobject.h +++ b/Include/intobject.h @@ -28,6 +28,7 @@ typedef struct { extern DL_IMPORT(PyTypeObject) PyInt_Type; #define PyInt_Check(op) PyObject_TypeCheck(op, &PyInt_Type) +#define PyInt_CheckExact(op) ((op)->ob_type == &PyInt_Type) extern DL_IMPORT(PyObject *) PyInt_FromString(char*, char**, int); #ifdef Py_USING_UNICODE diff --git a/Include/longintrepr.h b/Include/longintrepr.h index 1154e0b..89ba586 100644 --- a/Include/longintrepr.h +++ b/Include/longintrepr.h @@ -46,6 +46,9 @@ struct _longobject { DL_IMPORT(PyLongObject *) _PyLong_New(int); +/* Return a copy of src. */ +DL_IMPORT(PyObject *) _PyLong_Copy(PyLongObject *src); + #ifdef __cplusplus } #endif diff --git a/Include/longobject.h b/Include/longobject.h index e592891..6b10625 100644 --- a/Include/longobject.h +++ b/Include/longobject.h @@ -12,6 +12,7 @@ typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */ extern DL_IMPORT(PyTypeObject) PyLong_Type; #define PyLong_Check(op) PyObject_TypeCheck(op, &PyLong_Type) +#define PyLong_CheckExact(op) ((op)->ob_type == &PyLong_Type) extern DL_IMPORT(PyObject *) PyLong_FromLong(long); extern DL_IMPORT(PyObject *) PyLong_FromUnsignedLong(unsigned long); diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index f0f121b..35544c6 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1340,6 +1340,9 @@ def inherits(): # because the int type gets first dibs.) verify(repr(hexint(7) + 9) == "0x10") verify(repr(hexint(1000) + 7) == "0x3ef") + a = hexint(12345) + #XXX verify(int(a) == 12345) + verify(int(a).__class__ is int) class octlong(long): __slots__ = [] @@ -1355,6 +1358,9 @@ def inherits(): # (Note that overriding __radd__ here only seems to work # because the example uses a short int left argument.) verify(str(5 + octlong(3000)) == "05675") + a = octlong(12345) + #XXX verify(long(a) == 12345L) + verify(long(a).__class__ is long) class precfloat(float): __slots__ = ['prec'] @@ -1364,6 +1370,9 @@ def inherits(): def __repr__(self): return "%.*g" % (self.prec, self) verify(repr(precfloat(1.1)) == "1.1") + a = precfloat(12345) + #XXX verify(float(a) == 12345.0) + #XXX verify(float(a).__class__ is float) class madtuple(tuple): _rev = None @@ -1382,6 +1391,12 @@ def inherits(): u = t.rev() v = u.rev() verify(v == t) + a = madtuple((1,2,3,4,5)) + verify(tuple(a) == (1,2,3,4,5)) + #XXX verify(tuple(a).__class__ is tuple) + a = madtuple(()) + verify(tuple(a) == ()) + #XXX verify(tuple(a).__class__ is tuple) class madstring(str): _rev = None @@ -1400,6 +1415,9 @@ def inherits(): t = s.rev() u = t.rev() verify(u == s) + s = madstring("12345") + #XXX verify(str(s) == "12345") + #XXX verify(str(s).__class__ is str) class madunicode(unicode): _rev = None @@ -1413,6 +1431,9 @@ def inherits(): u = madunicode("ABCDEF") verify(u.rev() == madunicode(u"FEDCBA")) verify(u.rev().rev() == madunicode(u"ABCDEF")) + u = madunicode(u"12345") + verify(unicode(u) == u"12345") + #XXX verify(unicode(u).__class__ is unicode) def all(): lists() diff --git a/Objects/abstract.c b/Objects/abstract.c index 5361b1d..2bd0fcc 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -4,6 +4,7 @@ #include "Python.h" #include <ctype.h> #include "structmember.h" /* we need the offsetof() macro from there */ +#include "longintrepr.h" #define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \ Py_TPFLAGS_CHECKTYPES) @@ -818,10 +819,14 @@ PyNumber_Int(PyObject *o) if (o == NULL) return null_error(); - if (PyInt_Check(o)) { + if (PyInt_CheckExact(o)) { Py_INCREF(o); return o; } + if (PyInt_Check(o)) { + PyIntObject *io = (PyIntObject*)o; + return PyInt_FromLong(io->ob_ival); + } if (PyString_Check(o)) return int_from_string(PyString_AS_STRING(o), PyString_GET_SIZE(o)); @@ -868,10 +873,12 @@ PyNumber_Long(PyObject *o) if (o == NULL) return null_error(); - if (PyLong_Check(o)) { + if (PyLong_CheckExact(o)) { Py_INCREF(o); return o; } + if (PyLong_Check(o)) + return _PyLong_Copy((PyLongObject *)o); if (PyString_Check(o)) /* need to do extra error checking that PyLong_FromString() * doesn't do. In particular long('9.5') must raise an diff --git a/Objects/longobject.c b/Objects/longobject.c index c7608aa..b9271e6 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -51,6 +51,25 @@ _PyLong_New(int size) return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size); } +PyObject * +_PyLong_Copy(PyLongObject *src) +{ + PyLongObject *result; + int i; + + assert(src != NULL); + i = src->ob_size; + if (i < 0) + i = -(i); + result = _PyLong_New(i); + if (result != NULL) { + result->ob_size = i; + while (--i >= 0) + result->ob_digit[i] = src->ob_digit[i]; + } + return (PyObject *)result; +} + /* Create a new long int object from a C long int */ PyObject * @@ -2205,7 +2224,7 @@ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds); if (tmp == NULL) return NULL; - assert(PyLong_Check(tmp)); + assert(PyLong_CheckExact(tmp)); n = tmp->ob_size; if (n < 0) n = -n; |