[pypy-svn] r7711 - in pypy/trunk/src/pypy/objspace/std: . test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 30 14:53:44 CET 2004


Author: arigo
Date: Tue Nov 30 14:53:43 2004
New Revision: 7711

Modified:
   pypy/trunk/src/pypy/objspace/std/inttype.py
   pypy/trunk/src/pypy/objspace/std/longtype.py
   pypy/trunk/src/pypy/objspace/std/strutil.py
   pypy/trunk/src/pypy/objspace/std/test/test_strutil.py
Log:
long() parsing code, reusing the int() parsing code.


Modified: pypy/trunk/src/pypy/objspace/std/inttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/inttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/inttype.py	Tue Nov 30 14:53:43 2004
@@ -23,7 +23,7 @@
             if space.is_true(space.is_(w_inttype, space.w_int)):
                 return w_obj
             value = space.unwrap(w_obj)
-            if not isinstance(value, int):   # XXX typechecking in unwrap!
+            if not isinstance(value, (int, long)): # XXX typechecking in unwrap!
                 raise OperationError(space.w_ValueError,
                                  space.wrap("value can't be converted to int"))
     else:

Modified: pypy/trunk/src/pypy/objspace/std/longtype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/longtype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/longtype.py	Tue Nov 30 14:53:43 2004
@@ -1,42 +1,50 @@
 from pypy.objspace.std.stdtypedef import *
+from pypy.objspace.std.strutil import string_to_long
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.inttype import int_typedef
 
 def descr__new__(space, w_longtype, w_value=None, w_base=None):
     from pypy.objspace.std.longobject import W_LongObject
     if w_base is None:
-        w_base = space.w_None
-    if w_value is None:
-        value = 0L
-    elif w_base == space.w_None and not space.is_true(space.isinstance(w_value, space.w_str)):
-        w_obj = space.long(w_value)
-        if space.is_true(space.is_(w_longtype, space.w_long)):
-            return w_obj  # 'long(x)' should return
-                          # whatever x.__long__() returned
-        value = space.unwrap(w_obj)
-        if isinstance(value, int):     # XXX typechecking in unwrap!
-            value = long(value)
-        if not isinstance(value, long):   # XXX typechecking in unwrap!
-            raise OperationError(space.w_ValueError,
-                             space.wrap("value can't be converted to long"))
-
-    else:
-        if w_base == space.w_None:
-            base = -909 # don't blame us!!
+        # check for easy cases
+        if w_value is None:
+            value = 0L
+        elif isinstance(w_value, W_LongObject):
+            value = w_value.longval
+        elif space.is_true(space.isinstance(w_value, space.w_str)):
+            try:
+                value = string_to_long(space.unwrap(w_value))
+            except ValueError, e:
+                raise OperationError(space.w_ValueError,
+                                     space.wrap(e.args[0]))
         else:
-            base = space.unwrap(w_base)
-        s = space.unwrap(w_value)            
-        try:
-            value = long(s, base)
-        except TypeError, e:
+            # otherwise, use the __long__() method
+            w_obj = space.long(w_value)
+            # 'long(x)' should return whatever x.__long__() returned
+            if space.is_true(space.is_(w_longtype, space.w_long)):
+                return w_obj
+            value = space.unwrap(w_obj)
+            if isinstance(value, int):    # XXX typechecking in unwrap!
+                value = long(value)
+            if not isinstance(value, long):
+                raise OperationError(space.w_ValueError,
+                                 space.wrap("value can't be converted to long"))
+    else:
+        base = space.unwrap(w_base)
+        if not isinstance(base, int):   # XXX typechecking in unwrap!
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("an integer is required"))
+        s = space.unwrap(w_value)
+        if not isinstance(s, str):   # XXX typechecking in unwrap!
             raise OperationError(space.w_TypeError,
-                         space.wrap(str(e)))
+                                 space.wrap("long() can't convert non-string "
+                                            "with explicit base"))
+        try:
+            value = string_to_long(s, base)
         except ValueError, e:
             raise OperationError(space.w_ValueError,
-                         space.wrap(str(e)))
-        except OverflowError, e:
-            raise OperationError(space.w_OverflowError,
-                         space.wrap(str(e)))
+                                 space.wrap(e.args[0]))
+
     w_obj = space.allocate_instance(W_LongObject, w_longtype)
     w_obj.__init__(space, value)
     return w_obj

Modified: pypy/trunk/src/pypy/objspace/std/strutil.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/strutil.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/strutil.py	Tue Nov 30 14:53:43 2004
@@ -15,12 +15,11 @@
         q -= 1
     return s[p:q]
 
-def string_to_int(s, base=10):
-    """Utility to converts a string to an integer (or possibly a long).
-    If base is 0, the proper base is guessed based on the leading
-    characters of 's'.  Raises ValueError in case of error.
-    """
-    s = literal = strip_spaces(s)
+class InvalidLiteral(Exception):
+    pass
+
+def _parse_string(s, literal, base, fname):
+    # internal utility for string_to_int() and string_to_long().
     sign = 1
     if s.startswith('-'):
         sign = -1
@@ -35,27 +34,46 @@
         else:
             base = 10
     elif base < 2 or base > 36:
-        raise ValueError, "int() base must be >= 2 and <= 36"
-    if not s:
-        if not literal:
-            raise ValueError, 'empty literal for int()'
+        raise ValueError, "%s() base must be >= 2 and <= 36" % (fname,)
+    try:
+        if not s:
+            raise InvalidLiteral
+        if base == 16 and (s.startswith('0x') or s.startswith('0X')):
+            s = s[2:]
+        # XXX uses int-to-long overflow so far
+        result = 0
+        for c in s:
+            digit = ord(c)
+            if '0' <= c <= '9':
+                digit -= ord('0')
+            elif 'A' <= c <= 'Z':
+                digit = (digit - ord('A')) + 10
+            elif 'a' <= c <= 'z':
+                digit = (digit - ord('a')) + 10
+            else:
+                raise InvalidLiteral
+            if digit >= base:
+                raise InvalidLiteral
+            result = result*base + digit
+        return result * sign
+    except InvalidLiteral:
+        if literal:
+            raise ValueError, 'invalid literal for %s(): %s' % (fname, literal)
         else:
-            raise ValueError, 'invalid literal for int(): ' + literal
-    if base == 16 and (s.startswith('0x') or s.startswith('0X')):
-        s = s[2:]
-    # XXX uses int-to-long overflow so far
-    result = 0
-    for c in s:
-        digit = ord(c)
-        if '0' <= c <= '9':
-            digit -= ord('0')
-        elif 'A' <= c <= 'Z':
-            digit = (digit - ord('A')) + 10
-        elif 'a' <= c <= 'z':
-            digit = (digit - ord('a')) + 10
-        else:
-            raise ValueError, 'invalid literal for int(): ' + literal
-        if digit >= base:
-            raise ValueError, 'invalid literal for int(): ' + literal
-        result = result*base + digit
-    return result * sign
+            raise ValueError, 'empty literal for %s()' % (fname,)
+
+def string_to_int(s, base=10):
+    """Utility to converts a string to an integer (or possibly a long).
+    If base is 0, the proper base is guessed based on the leading
+    characters of 's'.  Raises ValueError in case of error.
+    """
+    s = literal = strip_spaces(s)
+    return _parse_string(s, literal, base, 'int')
+
+def string_to_long(s, base=10):
+    """As string_to_int(), but ignores an optional 'l' or 'L' suffix."""
+    s = literal = strip_spaces(s)
+    if (s.endswith('l') or s.endswith('L')) and base < 22:
+        # in base 22 and above, 'L' is a valid digit!  try: long('L',22)
+        s = s[:-1]
+    return long(_parse_string(s, literal, base, 'long'))

Modified: pypy/trunk/src/pypy/objspace/std/test/test_strutil.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/test/test_strutil.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/test/test_strutil.py	Tue Nov 30 14:53:43 2004
@@ -22,6 +22,7 @@
                  ]
         for s, expected in cases:
             self.assertEquals(string_to_int(s), expected)
+            self.assertEquals(string_to_long(s), expected)
 
     def test_string_to_int_base(self):
         cases = [('111', 2, 7),
@@ -102,5 +103,15 @@
             self.assertRaises(ValueError, string_to_int, '+'+s, base)
             self.assertRaises(ValueError, string_to_int, '-'+s, base)
 
+    def test_string_to_long(self):
+        self.assertEquals(string_to_long('123L'), 123)
+        self.assertEquals(string_to_long('123L  '), 123)
+        self.assertRaises(ValueError, string_to_long, 'L')
+        self.assertRaises(ValueError, string_to_long, 'L  ')
+        self.assertEquals(string_to_long('123L', 4), 27)
+        self.assertEquals(string_to_long('123L', 30), 27000 + 1800 + 90 + 21)
+        self.assertEquals(string_to_long('123L', 22), 10648 + 968 + 66 + 21)
+        self.assertEquals(string_to_long('123L', 21), 441 + 42 + 3)
+
 if __name__ == '__main__':
     testit.main()



More information about the Pypy-commit mailing list