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٢٣٤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