mirror of
https://github.com/python/cpython.git
synced 2025-08-01 15:43:13 +00:00
Issue 1742669. Now %d accepts very big float numbers.
Thanks Gabriel Genellina.
This commit is contained in:
parent
b93e7d16d5
commit
c11cecf3d0
4 changed files with 118 additions and 32 deletions
|
@ -1033,7 +1033,14 @@ class MixinStrUnicodeUserStringTest:
|
||||||
# unicode raises ValueError, str raises OverflowError
|
# unicode raises ValueError, str raises OverflowError
|
||||||
self.checkraises((ValueError, OverflowError), '%c', '__mod__', ordinal)
|
self.checkraises((ValueError, OverflowError), '%c', '__mod__', ordinal)
|
||||||
|
|
||||||
|
longvalue = sys.maxint + 10L
|
||||||
|
slongvalue = str(longvalue)
|
||||||
|
if slongvalue[-1] in ("L","l"): slongvalue = slongvalue[:-1]
|
||||||
self.checkequal(' 42', '%3ld', '__mod__', 42)
|
self.checkequal(' 42', '%3ld', '__mod__', 42)
|
||||||
|
self.checkequal('42', '%d', '__mod__', 42L)
|
||||||
|
self.checkequal('42', '%d', '__mod__', 42.0)
|
||||||
|
self.checkequal(slongvalue, '%d', '__mod__', longvalue)
|
||||||
|
self.checkcall('%d', '__mod__', float(longvalue))
|
||||||
self.checkequal('0042.00', '%07.2f', '__mod__', 42)
|
self.checkequal('0042.00', '%07.2f', '__mod__', 42)
|
||||||
self.checkequal('0042.00', '%07.2F', '__mod__', 42)
|
self.checkequal('0042.00', '%07.2F', '__mod__', 42)
|
||||||
|
|
||||||
|
@ -1043,6 +1050,8 @@ class MixinStrUnicodeUserStringTest:
|
||||||
self.checkraises(TypeError, '%c', '__mod__', (None,))
|
self.checkraises(TypeError, '%c', '__mod__', (None,))
|
||||||
self.checkraises(ValueError, '%(foo', '__mod__', {})
|
self.checkraises(ValueError, '%(foo', '__mod__', {})
|
||||||
self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42))
|
self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42))
|
||||||
|
self.checkraises(TypeError, '%d', '__mod__', "42") # not numeric
|
||||||
|
self.checkraises(TypeError, '%d', '__mod__', (42+0j)) # no int/long conversion provided
|
||||||
|
|
||||||
# argument names with properly nested brackets are supported
|
# argument names with properly nested brackets are supported
|
||||||
self.checkequal('bar', '%((foo))s', '__mod__', {'(foo)': 'bar'})
|
self.checkequal('bar', '%((foo))s', '__mod__', {'(foo)': 'bar'})
|
||||||
|
|
|
@ -11,7 +11,7 @@ maxsize = MAX_Py_ssize_t
|
||||||
overflowok = 1
|
overflowok = 1
|
||||||
overflowrequired = 0
|
overflowrequired = 0
|
||||||
|
|
||||||
def testformat(formatstr, args, output=None):
|
def testformat(formatstr, args, output=None, limit=None):
|
||||||
if verbose:
|
if verbose:
|
||||||
if output:
|
if output:
|
||||||
print "%s %% %s =? %s ..." %\
|
print "%s %% %s =? %s ..." %\
|
||||||
|
@ -31,7 +31,18 @@ def testformat(formatstr, args, output=None):
|
||||||
print 'no'
|
print 'no'
|
||||||
print "overflow expected on %s %% %s" % \
|
print "overflow expected on %s %% %s" % \
|
||||||
(repr(formatstr), repr(args))
|
(repr(formatstr), repr(args))
|
||||||
elif output and result != output:
|
elif output and limit is None and result != output:
|
||||||
|
if verbose:
|
||||||
|
print 'no'
|
||||||
|
print "%s %% %s == %s != %s" % \
|
||||||
|
(repr(formatstr), repr(args), repr(result), repr(output))
|
||||||
|
# when 'limit' is specified, it determines how many characters
|
||||||
|
# must match exactly; lengths must always match.
|
||||||
|
# ex: limit=5, '12345678' matches '12345___'
|
||||||
|
# (mainly for floating point format tests for which an exact match
|
||||||
|
# can't be guaranteed due to rounding and representation errors)
|
||||||
|
elif output and limit is not None and (
|
||||||
|
len(result)!=len(output) or result[:limit]!=output[:limit]):
|
||||||
if verbose:
|
if verbose:
|
||||||
print 'no'
|
print 'no'
|
||||||
print "%s %% %s == %s != %s" % \
|
print "%s %% %s == %s != %s" % \
|
||||||
|
@ -98,6 +109,7 @@ testboth("%.2d", big, "123456789012345678901234567890")
|
||||||
testboth("%.30d", big, "123456789012345678901234567890")
|
testboth("%.30d", big, "123456789012345678901234567890")
|
||||||
testboth("%.31d", big, "0123456789012345678901234567890")
|
testboth("%.31d", big, "0123456789012345678901234567890")
|
||||||
testboth("%32.31d", big, " 0123456789012345678901234567890")
|
testboth("%32.31d", big, " 0123456789012345678901234567890")
|
||||||
|
testboth("%d", float(big), "123456________________________", 6)
|
||||||
|
|
||||||
big = 0x1234567890abcdef12345L # 21 hex digits
|
big = 0x1234567890abcdef12345L # 21 hex digits
|
||||||
testboth("%x", big, "1234567890abcdef12345")
|
testboth("%x", big, "1234567890abcdef12345")
|
||||||
|
@ -135,6 +147,7 @@ testboth("%#+27.23X", big, " +0X001234567890ABCDEF12345")
|
||||||
testboth("%#+027.23X", big, "+0X0001234567890ABCDEF12345")
|
testboth("%#+027.23X", big, "+0X0001234567890ABCDEF12345")
|
||||||
# same, except no 0 flag
|
# same, except no 0 flag
|
||||||
testboth("%#+27.23X", big, " +0X001234567890ABCDEF12345")
|
testboth("%#+27.23X", big, " +0X001234567890ABCDEF12345")
|
||||||
|
testboth("%x", float(big), "123456_______________", 6)
|
||||||
|
|
||||||
big = 012345670123456701234567012345670L # 32 octal digits
|
big = 012345670123456701234567012345670L # 32 octal digits
|
||||||
testboth("%o", big, "12345670123456701234567012345670")
|
testboth("%o", big, "12345670123456701234567012345670")
|
||||||
|
@ -175,16 +188,19 @@ testboth("%#.32o", big, "012345670123456701234567012345670")
|
||||||
testboth("%034.33o", big, "0012345670123456701234567012345670")
|
testboth("%034.33o", big, "0012345670123456701234567012345670")
|
||||||
# base marker shouldn't change that
|
# base marker shouldn't change that
|
||||||
testboth("%0#34.33o", big, "0012345670123456701234567012345670")
|
testboth("%0#34.33o", big, "0012345670123456701234567012345670")
|
||||||
|
testboth("%o", float(big), "123456__________________________", 6)
|
||||||
|
|
||||||
# Some small ints, in both Python int and long flavors).
|
# Some small ints, in both Python int and long flavors).
|
||||||
testboth("%d", 42, "42")
|
testboth("%d", 42, "42")
|
||||||
testboth("%d", -42, "-42")
|
testboth("%d", -42, "-42")
|
||||||
testboth("%d", 42L, "42")
|
testboth("%d", 42L, "42")
|
||||||
testboth("%d", -42L, "-42")
|
testboth("%d", -42L, "-42")
|
||||||
|
testboth("%d", 42.0, "42")
|
||||||
testboth("%#x", 1, "0x1")
|
testboth("%#x", 1, "0x1")
|
||||||
testboth("%#x", 1L, "0x1")
|
testboth("%#x", 1L, "0x1")
|
||||||
testboth("%#X", 1, "0X1")
|
testboth("%#X", 1, "0X1")
|
||||||
testboth("%#X", 1L, "0X1")
|
testboth("%#X", 1L, "0X1")
|
||||||
|
testboth("%#x", 1.0, "0x1")
|
||||||
testboth("%#o", 1, "01")
|
testboth("%#o", 1, "01")
|
||||||
testboth("%#o", 1L, "01")
|
testboth("%#o", 1L, "01")
|
||||||
testboth("%#o", 0, "0")
|
testboth("%#o", 0, "0")
|
||||||
|
@ -202,11 +218,13 @@ testboth("%x", 0x42, "42")
|
||||||
testboth("%x", -0x42, "-42")
|
testboth("%x", -0x42, "-42")
|
||||||
testboth("%x", 0x42L, "42")
|
testboth("%x", 0x42L, "42")
|
||||||
testboth("%x", -0x42L, "-42")
|
testboth("%x", -0x42L, "-42")
|
||||||
|
testboth("%x", float(0x42), "42")
|
||||||
|
|
||||||
testboth("%o", 042, "42")
|
testboth("%o", 042, "42")
|
||||||
testboth("%o", -042, "-42")
|
testboth("%o", -042, "-42")
|
||||||
testboth("%o", 042L, "42")
|
testboth("%o", 042L, "42")
|
||||||
testboth("%o", -042L, "-42")
|
testboth("%o", -042L, "-42")
|
||||||
|
testboth("%o", float(042), "42")
|
||||||
|
|
||||||
# Test exception for unknown format characters
|
# Test exception for unknown format characters
|
||||||
if verbose:
|
if verbose:
|
||||||
|
@ -235,7 +253,7 @@ if have_unicode:
|
||||||
test_exc(unicode('abc %\u3000','raw-unicode-escape'), 1, ValueError,
|
test_exc(unicode('abc %\u3000','raw-unicode-escape'), 1, ValueError,
|
||||||
"unsupported format character '?' (0x3000) at index 5")
|
"unsupported format character '?' (0x3000) at index 5")
|
||||||
|
|
||||||
test_exc('%d', '1', TypeError, "int argument required, not str")
|
test_exc('%d', '1', TypeError, "%d format: a number is required, not str")
|
||||||
test_exc('%g', '1', TypeError, "float argument required, not str")
|
test_exc('%g', '1', TypeError, "float argument required, not str")
|
||||||
test_exc('no format', '1', TypeError,
|
test_exc('no format', '1', TypeError,
|
||||||
"not all arguments converted during string formatting")
|
"not all arguments converted during string formatting")
|
||||||
|
|
|
@ -4585,6 +4585,7 @@ PyString_Format(PyObject *format, PyObject *args)
|
||||||
int prec = -1;
|
int prec = -1;
|
||||||
int c = '\0';
|
int c = '\0';
|
||||||
int fill;
|
int fill;
|
||||||
|
int isnumok;
|
||||||
PyObject *v = NULL;
|
PyObject *v = NULL;
|
||||||
PyObject *temp = NULL;
|
PyObject *temp = NULL;
|
||||||
char *pbuf;
|
char *pbuf;
|
||||||
|
@ -4786,23 +4787,52 @@ PyString_Format(PyObject *format, PyObject *args)
|
||||||
case 'X':
|
case 'X':
|
||||||
if (c == 'i')
|
if (c == 'i')
|
||||||
c = 'd';
|
c = 'd';
|
||||||
if (PyLong_Check(v)) {
|
isnumok = 0;
|
||||||
int ilen;
|
if (PyNumber_Check(v)) {
|
||||||
temp = _PyString_FormatLong(v, flags,
|
PyObject *iobj=NULL;
|
||||||
prec, c, &pbuf, &ilen);
|
|
||||||
len = ilen;
|
if (PyInt_Check(v) || (PyLong_Check(v))) {
|
||||||
if (!temp)
|
iobj = v;
|
||||||
goto error;
|
Py_INCREF(iobj);
|
||||||
sign = 1;
|
}
|
||||||
|
else {
|
||||||
|
iobj = PyNumber_Int(v);
|
||||||
|
if (iobj==NULL) iobj = PyNumber_Long(v);
|
||||||
|
}
|
||||||
|
if (iobj!=NULL) {
|
||||||
|
if (PyInt_Check(iobj)) {
|
||||||
|
isnumok = 1;
|
||||||
|
pbuf = formatbuf;
|
||||||
|
len = formatint(pbuf,
|
||||||
|
sizeof(formatbuf),
|
||||||
|
flags, prec, c, iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
if (len < 0)
|
||||||
|
goto error;
|
||||||
|
sign = 1;
|
||||||
|
}
|
||||||
|
else if (PyLong_Check(iobj)) {
|
||||||
|
int ilen;
|
||||||
|
|
||||||
|
isnumok = 1;
|
||||||
|
temp = _PyString_FormatLong(iobj, flags,
|
||||||
|
prec, c, &pbuf, &ilen);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
len = ilen;
|
||||||
|
if (!temp)
|
||||||
|
goto error;
|
||||||
|
sign = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
if (!isnumok) {
|
||||||
pbuf = formatbuf;
|
PyErr_Format(PyExc_TypeError,
|
||||||
len = formatint(pbuf,
|
"%%%c format: a number is required, "
|
||||||
sizeof(formatbuf),
|
"not %.200s", c, Py_TYPE(v)->tp_name);
|
||||||
flags, prec, c, v);
|
goto error;
|
||||||
if (len < 0)
|
|
||||||
goto error;
|
|
||||||
sign = 1;
|
|
||||||
}
|
}
|
||||||
if (flags & F_ZERO)
|
if (flags & F_ZERO)
|
||||||
fill = '0';
|
fill = '0';
|
||||||
|
|
|
@ -8334,6 +8334,7 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
int prec = -1;
|
int prec = -1;
|
||||||
Py_UNICODE c = '\0';
|
Py_UNICODE c = '\0';
|
||||||
Py_UNICODE fill;
|
Py_UNICODE fill;
|
||||||
|
int isnumok;
|
||||||
PyObject *v = NULL;
|
PyObject *v = NULL;
|
||||||
PyObject *temp = NULL;
|
PyObject *temp = NULL;
|
||||||
Py_UNICODE *pbuf;
|
Py_UNICODE *pbuf;
|
||||||
|
@ -8546,21 +8547,49 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
case 'X':
|
case 'X':
|
||||||
if (c == 'i')
|
if (c == 'i')
|
||||||
c = 'd';
|
c = 'd';
|
||||||
if (PyLong_Check(v)) {
|
isnumok = 0;
|
||||||
temp = formatlong(v, flags, prec, c);
|
if (PyNumber_Check(v)) {
|
||||||
if (!temp)
|
PyObject *iobj=NULL;
|
||||||
goto onError;
|
|
||||||
pbuf = PyUnicode_AS_UNICODE(temp);
|
if (PyInt_Check(v) || (PyLong_Check(v))) {
|
||||||
len = PyUnicode_GET_SIZE(temp);
|
iobj = v;
|
||||||
sign = 1;
|
Py_INCREF(iobj);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iobj = PyNumber_Int(v);
|
||||||
|
if (iobj==NULL) iobj = PyNumber_Long(v);
|
||||||
|
}
|
||||||
|
if (iobj!=NULL) {
|
||||||
|
if (PyInt_Check(iobj)) {
|
||||||
|
isnumok = 1;
|
||||||
|
pbuf = formatbuf;
|
||||||
|
len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
|
||||||
|
flags, prec, c, iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
if (len < 0)
|
||||||
|
goto onError;
|
||||||
|
sign = 1;
|
||||||
|
}
|
||||||
|
else if (PyLong_Check(iobj)) {
|
||||||
|
isnumok = 1;
|
||||||
|
temp = formatlong(iobj, flags, prec, c);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
if (!temp)
|
||||||
|
goto onError;
|
||||||
|
pbuf = PyUnicode_AS_UNICODE(temp);
|
||||||
|
len = PyUnicode_GET_SIZE(temp);
|
||||||
|
sign = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
if (!isnumok) {
|
||||||
pbuf = formatbuf;
|
PyErr_Format(PyExc_TypeError,
|
||||||
len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
|
"%%%c format: a number is required, "
|
||||||
flags, prec, c, v);
|
"not %.200s", c, Py_TYPE(v)->tp_name);
|
||||||
if (len < 0)
|
|
||||||
goto onError;
|
goto onError;
|
||||||
sign = 1;
|
|
||||||
}
|
}
|
||||||
if (flags & F_ZERO)
|
if (flags & F_ZERO)
|
||||||
fill = '0';
|
fill = '0';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue