]> granicus.if.org Git - python/commitdiff
SF bug #460020: bug or feature: unicode() and subclasses.
authorTim Peters <tim.peters@gmail.com>
Mon, 10 Sep 2001 20:52:51 +0000 (20:52 +0000)
committerTim Peters <tim.peters@gmail.com>
Mon, 10 Sep 2001 20:52:51 +0000 (20:52 +0000)
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.

Include/intobject.h
Include/longintrepr.h
Include/longobject.h
Lib/test/test_descr.py
Objects/abstract.c
Objects/longobject.c

index 29448e3cc17da027c895212cc93df318c151a024..2d244ecedd037a155b3a66c2fac3260cdb277d4e 100644 (file)
@@ -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
index 1154e0b02bd537d4dc6e74779a863736423ba72c..89ba5867e06f4a4ec3c6f2f0413ac30cd61eff19 100644 (file)
@@ -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
index e592891687a6ff649f9fdc3d50781b2444583de6..6b1062576e6e2321868de055f55cdbba2f6aee56 100644 (file)
@@ -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);
index f0f121b008e44620ef8c9c84b14491bfff516ca3..35544c6762270e4ef16bebc49fad2f347bce72ca 100644 (file)
@@ -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()
index 5361b1d5c1b4551f8d1da204876db899bd94999b..2bd0fcceba1618a5cf8ae0a97afdcba163181998 100644 (file)
@@ -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
index c7608aa48af255227e4e0b6532bf311b258b3527..b9271e66170da490ebaf704b3d28ce130c8e9c61 100644 (file)
@@ -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;