support xrange() in Py3 by mapping it to range()
authorStefan Behnel <scoder@users.berlios.de>
Wed, 13 Jan 2010 20:19:14 +0000 (21:19 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Wed, 13 Jan 2010 20:19:14 +0000 (21:19 +0100)
Cython/Compiler/Code.py
Cython/Compiler/Symtab.py
tests/run/builtin_py3.pyx [new file with mode: 0644]

index bdc697e033333b36588fee1a003f56d3e441ff02..5d198835151948190edc5394fe244d26b5972d2f 100644 (file)
@@ -619,15 +619,30 @@ class GlobalState(object):
     def add_cached_builtin_decl(self, entry):
         if Options.cache_builtins:
             if self.should_declare(entry.cname, entry):
-                interned_cname = self.get_interned_identifier(entry.name).cname
                 self.put_pyobject_decl(entry)
                 w = self.parts['cached_builtins']
-                w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
-                    entry.cname,
-                    Naming.builtins_cname,
-                    interned_cname,
-                    entry.cname,
-                    w.error_goto(entry.pos)))
+                if entry.name == 'xrange':
+                    # replaced by range() in Py3
+                    w.putln('#if PY_MAJOR_VERSION >= 3')
+                    self.put_cached_builtin_init(
+                        entry.pos, StringEncoding.EncodedString('range'),
+                        entry.cname)
+                    w.putln('#else')
+                self.put_cached_builtin_init(
+                    entry.pos, StringEncoding.EncodedString(entry.name),
+                    entry.cname)
+                if entry.name == 'xrange':
+                    w.putln('#endif')
+
+    def put_cached_builtin_init(self, pos, name, cname):
+        w = self.parts['cached_builtins']
+        interned_cname = self.get_interned_identifier(name).cname
+        w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
+            cname,
+            Naming.builtins_cname,
+            interned_cname,
+            cname,
+            w.error_goto(pos)))
 
     def generate_const_declarations(self):
         self.generate_string_constants()
index c8fb01c7f1c2d5695a7de3234668894afab10d89..1baf3ede0c48a739b4f4e361d20ce6408aeaa54d 100644 (file)
@@ -727,7 +727,8 @@ class ModuleScope(Scope):
         return self
     
     def declare_builtin(self, name, pos):
-        if not hasattr(builtins, name):
+        if not hasattr(builtins, name) and name != 'xrange':
+            # 'xrange' is special cased in Code.py
             if self.has_import_star:
                 entry = self.declare_var(name, py_object_type, pos)
                 return entry
diff --git a/tests/run/builtin_py3.pyx b/tests/run/builtin_py3.pyx
new file mode 100644 (file)
index 0000000..55aa0e0
--- /dev/null
@@ -0,0 +1,44 @@
+__doc__ = u"""
+>>> test_xrange()
+0
+1
+2
+>>> test_range()
+0
+1
+2
+
+>>> test_long() == 12
+True
+>>> test_int() == 12
+True
+"""
+
+# the builtins 'xrange' and 'long' are not available in Py3, but they
+# can safely be replaced by 'range' and 'int' on that platform
+
+import sys
+
+IS_PY3 = sys.version_info[0] >= 3
+
+def test_xrange():
+    r = xrange(3)
+    assert type(r) is xrange
+    for i in r:
+        print i
+
+def test_range():
+    r = range(3)
+    assert (type(r) is range) if IS_PY3 else (type(r) is list)
+    for i in r:
+        print i
+
+def test_long():
+    long_val = long(12)
+    assert type(long_val) is long
+    return long_val
+
+def test_int():
+    int_val = int(12)
+    assert type(int_val) is int
+    return int_val