Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 64b5ce3

Browse files
committed
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.
1 parent 8b4e43e commit 64b5ce3

6 files changed

Lines changed: 55 additions & 3 deletions

File tree

Include/intobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ typedef struct {
2828
extern DL_IMPORT(PyTypeObject) PyInt_Type;
2929

3030
#define PyInt_Check(op) PyObject_TypeCheck(op, &PyInt_Type)
31+
#define PyInt_CheckExact(op) ((op)->ob_type == &PyInt_Type)
3132

3233
extern DL_IMPORT(PyObject *) PyInt_FromString(char*, char**, int);
3334
#ifdef Py_USING_UNICODE

Include/longintrepr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct _longobject {
4646

4747
DL_IMPORT(PyLongObject *) _PyLong_New(int);
4848

49+
/* Return a copy of src. */
50+
DL_IMPORT(PyObject *) _PyLong_Copy(PyLongObject *src);
51+
4952
#ifdef __cplusplus
5053
}
5154
#endif

Include/longobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */
1212
extern DL_IMPORT(PyTypeObject) PyLong_Type;
1313

1414
#define PyLong_Check(op) PyObject_TypeCheck(op, &PyLong_Type)
15+
#define PyLong_CheckExact(op) ((op)->ob_type == &PyLong_Type)
1516

1617
extern DL_IMPORT(PyObject *) PyLong_FromLong(long);
1718
extern DL_IMPORT(PyObject *) PyLong_FromUnsignedLong(unsigned long);

Lib/test/test_descr.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,9 @@ def __add__(self, other):
13401340
# because the int type gets first dibs.)
13411341
verify(repr(hexint(7) + 9) == "0x10")
13421342
verify(repr(hexint(1000) + 7) == "0x3ef")
1343+
a = hexint(12345)
1344+
#XXX verify(int(a) == 12345)
1345+
verify(int(a).__class__ is int)
13431346

13441347
class octlong(long):
13451348
__slots__ = []
@@ -1355,6 +1358,9 @@ def __add__(self, other):
13551358
# (Note that overriding __radd__ here only seems to work
13561359
# because the example uses a short int left argument.)
13571360
verify(str(5 + octlong(3000)) == "05675")
1361+
a = octlong(12345)
1362+
#XXX verify(long(a) == 12345L)
1363+
verify(long(a).__class__ is long)
13581364

13591365
class precfloat(float):
13601366
__slots__ = ['prec']
@@ -1364,6 +1370,9 @@ def __init__(self, value=0.0, prec=12):
13641370
def __repr__(self):
13651371
return "%.*g" % (self.prec, self)
13661372
verify(repr(precfloat(1.1)) == "1.1")
1373+
a = precfloat(12345)
1374+
#XXX verify(float(a) == 12345.0)
1375+
#XXX verify(float(a).__class__ is float)
13671376

13681377
class madtuple(tuple):
13691378
_rev = None
@@ -1382,6 +1391,12 @@ def rev(self):
13821391
u = t.rev()
13831392
v = u.rev()
13841393
verify(v == t)
1394+
a = madtuple((1,2,3,4,5))
1395+
verify(tuple(a) == (1,2,3,4,5))
1396+
#XXX verify(tuple(a).__class__ is tuple)
1397+
a = madtuple(())
1398+
verify(tuple(a) == ())
1399+
#XXX verify(tuple(a).__class__ is tuple)
13851400

13861401
class madstring(str):
13871402
_rev = None
@@ -1400,6 +1415,9 @@ def rev(self):
14001415
t = s.rev()
14011416
u = t.rev()
14021417
verify(u == s)
1418+
s = madstring("12345")
1419+
#XXX verify(str(s) == "12345")
1420+
#XXX verify(str(s).__class__ is str)
14031421

14041422
class madunicode(unicode):
14051423
_rev = None
@@ -1413,6 +1431,9 @@ def rev(self):
14131431
u = madunicode("ABCDEF")
14141432
verify(u.rev() == madunicode(u"FEDCBA"))
14151433
verify(u.rev().rev() == madunicode(u"ABCDEF"))
1434+
u = madunicode(u"12345")
1435+
verify(unicode(u) == u"12345")
1436+
#XXX verify(unicode(u).__class__ is unicode)
14161437

14171438
def all():
14181439
lists()

Objects/abstract.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Python.h"
55
#include <ctype.h>
66
#include "structmember.h" /* we need the offsetof() macro from there */
7+
#include "longintrepr.h"
78

89
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
910
Py_TPFLAGS_CHECKTYPES)
@@ -818,10 +819,14 @@ PyNumber_Int(PyObject *o)
818819

819820
if (o == NULL)
820821
return null_error();
821-
if (PyInt_Check(o)) {
822+
if (PyInt_CheckExact(o)) {
822823
Py_INCREF(o);
823824
return o;
824825
}
826+
if (PyInt_Check(o)) {
827+
PyIntObject *io = (PyIntObject*)o;
828+
return PyInt_FromLong(io->ob_ival);
829+
}
825830
if (PyString_Check(o))
826831
return int_from_string(PyString_AS_STRING(o),
827832
PyString_GET_SIZE(o));
@@ -868,10 +873,12 @@ PyNumber_Long(PyObject *o)
868873

869874
if (o == NULL)
870875
return null_error();
871-
if (PyLong_Check(o)) {
876+
if (PyLong_CheckExact(o)) {
872877
Py_INCREF(o);
873878
return o;
874879
}
880+
if (PyLong_Check(o))
881+
return _PyLong_Copy((PyLongObject *)o);
875882
if (PyString_Check(o))
876883
/* need to do extra error checking that PyLong_FromString()
877884
* doesn't do. In particular long('9.5') must raise an

Objects/longobject.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ _PyLong_New(int size)
5151
return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
5252
}
5353

54+
PyObject *
55+
_PyLong_Copy(PyLongObject *src)
56+
{
57+
PyLongObject *result;
58+
int i;
59+
60+
assert(src != NULL);
61+
i = src->ob_size;
62+
if (i < 0)
63+
i = -(i);
64+
result = _PyLong_New(i);
65+
if (result != NULL) {
66+
result->ob_size = i;
67+
while (--i >= 0)
68+
result->ob_digit[i] = src->ob_digit[i];
69+
}
70+
return (PyObject *)result;
71+
}
72+
5473
/* Create a new long int object from a C long int */
5574

5675
PyObject *
@@ -2205,7 +2224,7 @@ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
22052224
tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds);
22062225
if (tmp == NULL)
22072226
return NULL;
2208-
assert(PyLong_Check(tmp));
2227+
assert(PyLong_CheckExact(tmp));
22092228
n = tmp->ob_size;
22102229
if (n < 0)
22112230
n = -n;

0 commit comments

Comments
 (0)