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

arigo at codespeak.net arigo at codespeak.net
Mon Nov 29 18:56:12 CET 2004


Author: arigo
Date: Mon Nov 29 18:56:12 2004
New Revision: 7705

Added:
   pypy/trunk/src/pypy/objspace/std/test/test_strutil.py   (contents, props changed)
Modified:
   pypy/trunk/src/pypy/objspace/std/inttype.py
Log:
A pure Python reimplementation of int(str, base), with a test suite.



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	Mon Nov 29 18:56:12 2004
@@ -1,38 +1,47 @@
 from pypy.objspace.std.stdtypedef import *
+from pypy.objspace.std.strutil import string_to_int
 from pypy.interpreter.error import OperationError
 
 def descr__new__(space, w_inttype, w_value=None, w_base=None):
     from pypy.objspace.std.intobject import W_IntObject
     if w_base is None:
-        w_base = space.w_None
-    if w_value is None:
-        value = 0
-    elif w_base == space.w_None and not space.is_true(space.isinstance(w_value, space.w_str)):
-        w_obj = space.int(w_value)
-        if space.is_true(space.is_(w_inttype, space.w_int)):
-            return w_obj  # 'int(x)' should return whatever x.__int__() returned
-        value = space.unwrap(w_obj)
-        if not isinstance(value, int):   # XXX typechecking in unwrap!
-            raise OperationError(space.w_ValueError,
+        # check for easy cases
+        if w_value is None:
+            value = 0
+        elif isinstance(w_value, W_IntObject):
+            value = w_value.intval
+        elif space.is_true(space.isinstance(w_value, space.w_str)):
+            try:
+                value = string_to_int(space.unwrap(w_value))
+            except ValueError, e:
+                raise OperationError(space.w_ValueError,
+                                     space.wrap(e.args[0]))
+        else:
+            # otherwise, use the __int__() method
+            w_obj = space.int(w_value)
+            # 'int(x)' should return whatever x.__int__() returned
+            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!
+                raise OperationError(space.w_ValueError,
                                  space.wrap("value can't be converted to int"))
     else:
-        if w_base == space.w_None:
-            base = -909 # don't blame us!!
-        else:
-            base = space.unwrap(w_base)
-        # XXX write the logic for int("str", base)
+        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)
-        try:
-            value = int(s, base)
-        except TypeError, e:
+        if not isinstance(s, str):   # XXX typechecking in unwrap!
             raise OperationError(space.w_TypeError,
-                         space.wrap(str(e)))
+                                 space.wrap("int() can't convert non-string "
+                                            "with explicit base"))
+        try:
+            value = string_to_int(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]))
+
     if isinstance(value, long):
         # XXX is this right??
         from pypy.objspace.std.longobject import W_LongObject

Added: pypy/trunk/src/pypy/objspace/std/test/test_strutil.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/objspace/std/test/test_strutil.py	Mon Nov 29 18:56:12 2004
@@ -0,0 +1,106 @@
+import autopath
+from pypy.tool import testit
+from pypy.objspace.std.strutil import *
+
+class TestStrUtil(testit.TestCase):
+
+    def test_string_to_int(self):
+        cases = [('0', 0),
+                 ('1', 1),
+                 ('9', 9),
+                 ('10', 10),
+                 ('09', 9),
+                 ('0000101', 101),    # not octal unless base 0 or 8
+                 ('5123', 5123),
+                 ('1891234174197319', 1891234174197319),
+                 (' 0', 0),
+                 ('0  ', 0),
+                 (' \t \n   32313  \f  \v   \r  \n\r    ', 32313),
+                 ('+12', 12),
+                 ('-5', -5),
+                 ('  -123456789 ', -123456789),
+                 ]
+        for s, expected in cases:
+            self.assertEquals(string_to_int(s), expected)
+
+    def test_string_to_int_base(self):
+        cases = [('111', 2, 7),
+                 ('010', 2, 2),
+                 ('102', 3, 11),
+                 ('103', 4, 19),
+                 ('107', 8, 71),
+                 ('109', 10, 109),
+                 ('10A', 11, 131),
+                 ('10a', 11, 131),
+                 ('10f', 16, 271),
+                 ('10F', 16, 271),
+                 ('0x10f', 16, 271),
+                 ('0x10F', 16, 271),
+                 ('10z', 36, 1331),
+                 ('10Z', 36, 1331),
+                 ('12',   0, 12),
+                 ('015',  0, 13),
+                 ('0x10', 0, 16),
+                 ('0XE',  0, 14),
+                 ('0',    0, 0),
+                 ('0x',   0, 0),    # according to CPython so far
+                 ('0X',   0, 0),    #     "           "
+                 ('0x',  16, 0),    #     "           "
+                 ('0X',  16, 0),    #     "           "
+                 ]
+        for s, base, expected in cases:
+            self.assertEquals(string_to_int(s, base), expected)
+            self.assertEquals(string_to_int('+'+s, base), expected)
+            self.assertEquals(string_to_int('-'+s, base), -expected)
+            self.assertEquals(string_to_int(s+'\n', base), expected)
+            self.assertEquals(string_to_int('  +'+s, base), expected)
+            self.assertEquals(string_to_int('-'+s+'  ', base), -expected)
+
+    def test_string_to_int_error(self):
+        cases = ['0x123',    # must use base 0 or 16
+                 ' 0X12 ',
+                 '',
+                 '++12',
+                 '+-12',
+                 '-+12',
+                 '--12',
+                 '- 5',
+                 '+ 5',
+                 '12a6',
+                 '12A6',
+                 'f',
+                 'Z',
+                 '.',
+                 '@',
+                 ]
+        for s in cases:
+            self.assertRaises(ValueError, string_to_int, s)
+            self.assertRaises(ValueError, string_to_int, '  '+s)
+            self.assertRaises(ValueError, string_to_int, s+'  ')
+            self.assertRaises(ValueError, string_to_int, '+'+s)
+            self.assertRaises(ValueError, string_to_int, '-'+s)
+
+    def test_string_to_int_base_error(self):
+        cases = [('1', 1),
+                 ('1', 37),
+                 ('a', 0),
+                 ('9', 9),
+                 ('0x123', 7),
+                 ('145cdf', 15),
+                 ('12', 37),
+                 ('12', 98172),
+                 ('12', -1),
+                 ('12', -908),
+                 ('12.3', 10),
+                 ('12.3', 13),
+                 ('12.3', 16),
+                 ]
+        for s, base in cases:
+            self.assertRaises(ValueError, string_to_int, s, base)
+            self.assertRaises(ValueError, string_to_int, '  '+s, base)
+            self.assertRaises(ValueError, string_to_int, s+'  ', base)
+            self.assertRaises(ValueError, string_to_int, '+'+s, base)
+            self.assertRaises(ValueError, string_to_int, '-'+s, base)
+
+if __name__ == '__main__':
+    testit.main()



More information about the Pypy-commit mailing list