]> granicus.if.org Git - python/commitdiff
Fix int() and long() to repr() their argument when formatting the exception,
authorThomas Wouters <thomas@python.org>
Tue, 11 Apr 2006 23:50:33 +0000 (23:50 +0000)
committerThomas Wouters <thomas@python.org>
Tue, 11 Apr 2006 23:50:33 +0000 (23:50 +0000)
to avoid confusing situations like:

>>> int("")
ValueError: invalid literal for int():
>>> int("2\n\n2")
ValueError: invalid literal for int(): 2

2

Also report the base used, to avoid:

ValueError: invalid literal for int(): 2

They now report:

>>> int("")
ValueError: invalid literal for int() with base 10: ''
>>> int("2\n\n2")
ValueError: invalid literal for int() with base 10: '2\n\n2'
>>> int("2", 2)
ValueError: invalid literal for int() with base 2: '2'

(Reporting the base could be avoided when base is 10, which is the default,
but hrm.) Another effect of these changes is that the errormessage can be
longer; before, it was cut off at about 250 characters. Now, it can be up to
four times as long, as the unrepr'ed string is cut off at 200 characters,
instead.

No tests were added or changed, since testing for exact errormsgs is (pardon
the pun) somewhat errorprone, and I consider not testing the exact text
preferable. The actually changed code is tested frequent enough in the
test_builtin test as it is (120 runs for each of ints and longs.)

Objects/intobject.c
Objects/longobject.c

index e3af06318415ee6d1e422e72b7b7c721937f80bf..63034bcac09c8ae4f34f9600105d93ffc3762bf4 100644 (file)
@@ -335,7 +335,8 @@ PyInt_FromString(char *s, char **pend, int base)
 {
        char *end;
        long x;
-       char buffer[256]; /* For errors */
+       Py_ssize_t slen;
+       PyObject *sobj, *srepr;
 
        if ((base != 0 && base < 2) || base > 36) {
                PyErr_SetString(PyExc_ValueError,
@@ -359,9 +360,18 @@ PyInt_FromString(char *s, char **pend, int base)
                end++;
        if (*end != '\0') {
   bad:
-               PyOS_snprintf(buffer, sizeof(buffer),
-                             "invalid literal for int(): %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
+               slen = strlen(s) < 200 ? strlen(s) : 200;
+               sobj = PyString_FromStringAndSize(s, slen);
+               if (sobj == NULL)
+                       return NULL;
+               srepr = PyObject_Repr(sobj);
+               Py_DECREF(sobj);
+               if (srepr == NULL)
+                       return NULL;
+               PyErr_Format(PyExc_ValueError,
+                            "invalid literal for int() with base %d: %s",
+                            base, PyString_AS_STRING(srepr));
+               Py_DECREF(srepr);
                return NULL;
        }
        else if (errno != 0)
index 2d3dce67e4e3d3b21e9bd7a3cdd3627455580dee..634252f0d716fe120723a4756f465d1883392f4d 100644 (file)
@@ -1400,6 +1400,8 @@ PyLong_FromString(char *str, char **pend, int base)
        int sign = 1;
        char *start, *orig_str = str;
        PyLongObject *z;
+       PyObject *strobj, *strrepr;
+       Py_ssize_t slen;
 
        if ((base != 0 && base < 2) || base > 36) {
                PyErr_SetString(PyExc_ValueError,
@@ -1465,9 +1467,19 @@ PyLong_FromString(char *str, char **pend, int base)
        return (PyObject *) z;
 
  onError:
-       PyErr_Format(PyExc_ValueError,
-                    "invalid literal for long(): %.200s", orig_str);
        Py_XDECREF(z);
+       slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200;
+       strobj = PyString_FromStringAndSize(orig_str, slen);
+       if (strobj == NULL)
+               return NULL;
+       strrepr = PyObject_Repr(strobj);
+       Py_DECREF(strobj);
+       if (strrepr == NULL)
+               return NULL;
+       PyErr_Format(PyExc_ValueError,
+                    "invalid literal for long() with base %d: %s",
+                    base, PyString_AS_STRING(strrepr));
+       Py_DECREF(strrepr);
        return NULL;
 }