Author: Philip Jenvey <pjen...@underboss.org>
Branch: 
Changeset: r69047:3c0908d6f8ad
Date: 2014-02-02 14:08 -0800
http://bitbucket.org/pypy/pypy/changeset/3c0908d6f8ad/

Log:    describe invalid source strings at the pypy level vs rpython.
        simplifies py3k and improves error messages

diff --git a/pypy/module/_csv/interp_reader.py 
b/pypy/module/_csv/interp_reader.py
--- a/pypy/module/_csv/interp_reader.py
+++ b/pypy/module/_csv/interp_reader.py
@@ -39,6 +39,7 @@
         field_builder.append(c)
 
     def save_field(self, field_builder):
+        space = self.space
         field = field_builder.build()
         if self.numeric_field:
             from rpython.rlib.rstring import ParseStringError
@@ -46,12 +47,12 @@
             self.numeric_field = False
             try:
                 ff = string_to_float(field)
-            except ParseStringError, e:
-                raise OperationError(self.space.w_ValueError,
-                                     self.space.wrap(e.msg))
-            w_obj = self.space.wrap(ff)
+            except ParseStringError as e:
+                from pypy.objspace.std.inttype import wrap_parsestringerror
+                raise wrap_parsestringerror(space, e, space.wrap(field))
+            w_obj = space.wrap(ff)
         else:
-            w_obj = self.space.wrap(field)
+            w_obj = space.wrap(field)
         self.fields_w.append(w_obj)
 
     def next_w(self):
diff --git a/pypy/objspace/std/floattype.py b/pypy/objspace/std/floattype.py
--- a/pypy/objspace/std/floattype.py
+++ b/pypy/objspace/std/floattype.py
@@ -34,20 +34,11 @@
         value = space.float_w(w_obj)
     elif (space.isinstance_w(w_value, space.w_str) or
           space.isinstance_w(w_value, space.w_bytearray)):
-        strvalue = space.bufferstr_w(w_value)
-        try:
-            value = rfloat.string_to_float(strvalue)
-        except ParseStringError, e:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap(e.msg))
+        value = _string_to_float(space, w_value, space.bufferstr_w(w_value))
     elif space.isinstance_w(w_value, space.w_unicode):
         from unicodeobject import unicode_to_decimal_w
-        strvalue = unicode_to_decimal_w(space, w_value)
-        try:
-            value = rfloat.string_to_float(strvalue)
-        except ParseStringError, e:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap(e.msg))
+        value = _string_to_float(space, w_value,
+                                 unicode_to_decimal_w(space, w_value))
     else:
         value = space.float_w(w_x)
     w_obj = space.allocate_instance(W_FloatObject, w_floattype)
@@ -55,6 +46,14 @@
     return w_obj
 
 
+def _string_to_float(space, w_source, string):
+    try:
+        return rfloat.string_to_float(string)
+    except ParseStringError as e:
+        from pypy.objspace.std.inttype import wrap_parsestringerror
+        raise wrap_parsestringerror(space, e, w_source)
+
+
 def detect_floatformat():
     from rpython.rtyper.lltypesystem import rffi, lltype
     buf = lltype.malloc(rffi.CCHARP.TO, 8, flavor='raw')
diff --git a/pypy/objspace/std/inttype.py b/pypy/objspace/std/inttype.py
--- a/pypy/objspace/std/inttype.py
+++ b/pypy/objspace/std/inttype.py
@@ -9,7 +9,8 @@
 from rpython.rlib.rarithmetic import r_uint, string_to_int
 from rpython.rlib.objectmodel import instantiate
 from rpython.rlib.rbigint import rbigint
-from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError
+from rpython.rlib.rstring import (
+    InvalidBaseError, ParseStringError, ParseStringOverflowError)
 from rpython.rlib import jit
 
 # ____________________________________________________________
@@ -63,27 +64,33 @@
 # ____________________________________________________________
 
 @jit.elidable
-def string_to_int_or_long(space, string, base=10):
+def string_to_int_or_long(space, w_source, string, base=10):
     w_longval = None
     value = 0
     try:
         value = string_to_int(string, base)
-    except ParseStringError, e:
-        raise OperationError(space.w_ValueError,
-                             space.wrap(e.msg))
+    except ParseStringError as e:
+        raise wrap_parsestringerror(space, e, w_source)
     except ParseStringOverflowError, e:
-        w_longval = retry_to_w_long(space, e.parser)
+        w_longval = retry_to_w_long(space, e.parser, w_source)
     return value, w_longval
 
-def retry_to_w_long(space, parser):
+def retry_to_w_long(space, parser, w_source):
     parser.rewind()
     try:
         bigint = rbigint._from_numberstring_parser(parser)
-    except ParseStringError, e:
-        raise OperationError(space.w_ValueError,
-                             space.wrap(e.msg))
+    except ParseStringError as e:
+        raise wrap_parsestringerror(space, e, w_source)
     return space.newlong_from_rbigint(bigint)
 
+def wrap_parsestringerror(space, e, w_source):
+    if isinstance(e, InvalidBaseError):
+        w_msg = space.wrap(e.msg)
+    else:
+        w_msg = space.wrap('%s: %s' % (e.msg,
+                                       space.str_w(space.repr(w_source))))
+    return OperationError(space.w_ValueError, w_msg)
+
 @unwrap_spec(w_x = WrappedDefault(0))
 def descr__new__(space, w_inttype, w_x, w_base=None):
     from pypy.objspace.std.intobject import W_IntObject
@@ -110,11 +117,12 @@
             # an overflowing long
             value = space.int_w(w_obj)
         elif space.isinstance_w(w_value, space.w_str):
-            value, w_longval = string_to_int_or_long(space, 
space.str_w(w_value))
+            value, w_longval = string_to_int_or_long(space, w_value,
+                                                     space.str_w(w_value))
         elif space.isinstance_w(w_value, space.w_unicode):
             from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
             string = unicode_to_decimal_w(space, w_value)
-            value, w_longval = string_to_int_or_long(space, string)
+            value, w_longval = string_to_int_or_long(space, w_value, string)
         else:
             # If object supports the buffer interface
             try:
@@ -127,7 +135,8 @@
                     w_value)
             else:
                 buf = space.interp_w(Buffer, w_buffer)
-                value, w_longval = string_to_int_or_long(space, buf.as_str())
+                value, w_longval = string_to_int_or_long(space, w_value,
+                                                         buf.as_str())
     else:
         base = space.int_w(w_base)
 
@@ -142,7 +151,7 @@
                                      space.wrap("int() can't convert 
non-string "
                                                 "with explicit base"))
 
-        value, w_longval = string_to_int_or_long(space, s, base)
+        value, w_longval = string_to_int_or_long(space, w_value, s, base)
 
     if w_longval is not None:
         if not space.is_w(w_inttype, space.w_int):
diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py
--- a/pypy/objspace/std/longtype.py
+++ b/pypy/objspace/std/longtype.py
@@ -41,10 +41,11 @@
                 w_obj = space.int(w_obj)
             return newbigint(space, w_longtype, space.bigint_w(w_obj))
         elif space.isinstance_w(w_value, space.w_str):
-            return string_to_w_long(space, w_longtype, space.str_w(w_value))
+            return string_to_w_long(space, w_longtype, w_value,
+                                    space.str_w(w_value))
         elif space.isinstance_w(w_value, space.w_unicode):
             from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
-            return string_to_w_long(space, w_longtype,
+            return string_to_w_long(space, w_longtype, w_value,
                                     unicode_to_decimal_w(space, w_value))
         else:
             try:
@@ -57,7 +58,8 @@
                     w_value)
             else:
                 buf = space.interp_w(Buffer, w_buffer)
-                return string_to_w_long(space, w_longtype, buf.as_str())
+                return string_to_w_long(space, w_longtype, w_value,
+                                        buf.as_str())
     else:
         base = space.int_w(w_base)
 
@@ -71,15 +73,15 @@
                 raise OperationError(space.w_TypeError,
                                      space.wrap("long() can't convert 
non-string "
                                                 "with explicit base"))
-        return string_to_w_long(space, w_longtype, s, base)
+        return string_to_w_long(space, w_longtype, w_value, s, base)
 
 
-def string_to_w_long(space, w_longtype, s, base=10):
+def string_to_w_long(space, w_longtype, w_source, string, base=10):
     try:
-        bigint = rbigint.fromstr(s, base)
-    except ParseStringError, e:
-        raise OperationError(space.w_ValueError,
-                             space.wrap(e.msg))
+        bigint = rbigint.fromstr(string, base)
+    except ParseStringError as e:
+        from pypy.objspace.std.inttype import wrap_parsestringerror
+        raise wrap_parsestringerror(space, e, w_source)
     return newbigint(space, w_longtype, bigint)
 string_to_w_long._dont_inline_ = True
 
diff --git a/pypy/objspace/std/test/test_intobject.py 
b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -1,3 +1,4 @@
+# encoding: utf-8
 import py
 import sys
 from pypy.objspace.std import intobject as iobj
@@ -517,6 +518,18 @@
         assert str(e.value) == (
             "int() argument must be a string or a number, not 'list'")
 
+    def test_invalid_literal_message(self):
+        import sys
+        if '__pypy__' not in sys.builtin_module_names:
+            skip('PyPy 2.x/CPython 3.4 only')
+        for value in b'  1j ', u'  1&#1634;&#1635;&#1636;j ':
+            try:
+                int(value)
+            except ValueError as e:
+                assert repr(value) in str(e)
+            else:
+                assert False, value
+
 
 class AppTestIntOptimizedAdd(AppTestInt):
     spaceconfig = {"objspace.std.optimized_int_add": True}
diff --git a/rpython/rlib/rfloat.py b/rpython/rlib/rfloat.py
--- a/rpython/rlib/rfloat.py
+++ b/rpython/rlib/rfloat.py
@@ -25,6 +25,8 @@
 
 globals().update(rffi_platform.configure(CConfig))
 
+INVALID_MSG = "invalid literal for float()"
+
 def string_to_float(s):
     """
     Conversion of string to float.
@@ -36,10 +38,8 @@
     from rpython.rlib.rstring import strip_spaces, ParseStringError
 
     s = strip_spaces(s)
-
     if not s:
-        raise ParseStringError("empty string for float()")
-
+        raise ParseStringError(INVALID_MSG)
 
     low = s.lower()
     if low == "-inf" or low == "-infinity":
@@ -56,7 +56,7 @@
     try:
         return rstring_to_float(s)
     except ValueError:
-        raise ParseStringError("invalid literal for float(): '%s'" % s)
+        raise ParseStringError(INVALID_MSG)
 
 def rstring_to_float(s):
     from rpython.rlib.rdtoa import strtod
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -278,6 +278,9 @@
     def __init__(self, msg):
         self.msg = msg
 
+class InvalidBaseError(ParseStringError):
+    """Signals an invalid base argument"""
+
 class ParseStringOverflowError(Exception):
     def __init__(self, parser):
         self.parser = parser
@@ -286,11 +289,10 @@
 class NumberStringParser:
 
     def error(self):
-        raise ParseStringError("invalid literal for %s() with base %d: '%s'" %
-                               (self.fname, self.original_base, self.literal))
+        raise ParseStringError("invalid literal for %s() with base %d" %
+                               (self.fname, self.original_base))
 
     def __init__(self, s, literal, base, fname):
-        self.literal = literal
         self.fname = fname
         sign = 1
         if s.startswith('-'):
@@ -311,7 +313,7 @@
             else:
                 base = 10
         elif base < 2 or base > 36:
-            raise ParseStringError, "%s() base must be >= 2 and <= 36" % 
(fname,)
+            raise InvalidBaseError("%s() base must be >= 2 and <= 36" % fname)
         self.base = base
 
         if base == 16 and (s.startswith('0x') or s.startswith('0X')):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to