Author: Philip Jenvey <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit