[pypy-svn] r44999 - in pypy/dist/pypy/interpreter: pyparser/data pyparser/test test

jacob at codespeak.net jacob at codespeak.net
Fri Jul 13 09:50:20 CEST 2007


Author: jacob
Date: Fri Jul 13 09:50:19 2007
New Revision: 44999

Modified:
   pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a
   pypy/dist/pypy/interpreter/pyparser/test/test_parser.py
   pypy/dist/pypy/interpreter/test/test_syntax.py
Log:
Modified grammar towards supporting future imports.

Modified: pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a	(original)
+++ pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a	Fri Jul 13 09:50:19 2007
@@ -24,10 +24,15 @@
 #	file_input is a module or sequence of commands read from an input file;
 #	eval_input is the input for the eval() and input() functions.
 # NB: compound_stmt in single_input is followed by extra NEWLINE!
-single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
-file_input: (NEWLINE | stmt)* ENDMARKER
+single_input:  NEWLINE | future_import_list [';'] | future_import_list ';' simple_stmt | compound_stmt NEWLINE
+file_input: (future_import_list [';'])* (NEWLINE | stmt)* ENDMARKER
 eval_input: testlist NEWLINE* ENDMARKER
 
+future_import_list: import_from_future (';' import_from_future)*
+import_from_future: 'from' '__future__' 'import' ('(' future_import_as_names [','] ')' | future_import_as_names)
+future_import_feature: NAME [('as'|NAME) NAME]
+future_import_as_names: future_import_feature (',' future_import_feature)*
+
 decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
 decorators: decorator+
 funcdef: [decorators] 'def' NAME parameters ':' suite
@@ -63,7 +68,8 @@
 exec_stmt: 'exec' expr ['in' test [',' test]]
 assert_stmt: 'assert' test [',' test]
 
-compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef
+# with_stmt is added dynamically to compund_stmt if imported from __future__
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
 if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
 while_stmt: 'while' test ':' suite ['else' ':' suite]
 for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]

Modified: pypy/dist/pypy/interpreter/pyparser/test/test_parser.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_parser.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_parser.py	Fri Jul 13 09:50:19 2007
@@ -2,7 +2,6 @@
 from pypy.interpreter.pyparser.grammar import Parser
 
 
-
 def test_symbols():
     p = Parser()
     x1 = p.add_symbol('sym')
@@ -43,3 +42,90 @@
     assert v == 6
     v = p.add_symbol( 'sym3' )
     assert v == 9
+
+class FakeSpace:
+    w_None = None
+    w_str = str
+    w_basestring = basestring
+    w_int = int
+    
+    def wrap(self,obj):
+        return obj
+
+    def isinstance(self, obj, wtype ):
+        return isinstance(obj,wtype)
+
+    def is_true(self, obj):
+        return obj
+
+    def eq_w(self, obj1, obj2):
+        return obj1 == obj2
+
+    def is_w(self, obj1, obj2):
+        return obj1 is obj2
+
+    def type(self, obj):
+        return type(obj)
+
+    def newlist(self, lst):
+        return list(lst)
+
+    def newtuple(self, lst):
+        return tuple(lst)
+    
+    def call_method(self, obj, meth, *args):
+        return getattr(obj, meth)(*args)
+
+    def call_function(self, func, *args):
+        return func(*args)
+
+    builtin = dict(int=int, long=long, float=float, complex=complex)
+
+from pypy.interpreter.pyparser.asthelper import get_atoms
+class RuleTracer(dict):
+    
+    def __init__(self, *args, **kw):
+        self.trace = []
+
+    def __getitem__(self, attr):
+        if attr in ['file_input', 'future_import_list', 'import_from_future',
+                    'future_import_as_names']:
+            return lambda *args: None
+        
+        def record_trace(builder, number):
+            result = [t.value for t in get_atoms(builder, number)]
+            self.trace.append((attr, result))
+        return record_trace
+
+    def get(self, attr, default):
+        return self.__getitem__(attr)
+    
+from pypy.interpreter.pyparser.astbuilder import AstBuilder
+class MockBuilder(AstBuilder):
+
+    def __init__(self, *args, **kw):
+        AstBuilder.__init__(self, *args, **kw)
+        self.build_rules = RuleTracer()
+
+class TestFuture(object):
+
+    def setup_class(self):
+        from pypy.interpreter.pyparser.pythonparse import make_pyparser
+        self.parser = make_pyparser('2.5a')
+
+    def setup_method(self, method):
+        self.builder = MockBuilder(self.parser, space=FakeSpace())
+    def check_parse(self, tst, expected):
+        self.parser.parse_source(tst, 'exec' , self.builder)
+        assert self.builder.build_rules.trace == expected
+        
+    def test_single_future_import(self):
+        tst = 'from __future__ import na\n'
+        expected = [('future_import_feature', ['na'])]
+        self.check_parse(tst, expected)
+        
+    def test_double_future_import(self):
+        tst = 'from __future__ import na, xx\n'
+        expected = [('future_import_feature', ['na']),
+                    ('future_import_feature', ['xx'])]
+        self.check_parse(tst, expected)

Modified: pypy/dist/pypy/interpreter/test/test_syntax.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_syntax.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_syntax.py	Fri Jul 13 09:50:19 2007
@@ -491,6 +491,30 @@
         else:
             assert False, 'Assignment to with did not raise SyntaxError'
         
+    def test_with_as_keyword_and_docstring(self):
+        try:
+            exec "'Docstring'\nfrom __future__ import with_statement\nwith = 9"
+        except SyntaxError:
+            pass
+        else:
+            assert False, 'Assignment to with did not raise SyntaxError'
+        
+    def test_with_as_keyword_compound(self):
+        try:
+            exec "from __future__ import generators, with_statement\nwith = 9"
+        except SyntaxError:
+            pass
+        else:
+            assert False, 'Assignment to with did not raise SyntaxError'
+        
+    def test_with_as_keyword_multiple(self):
+        try:
+            exec "from __future__ import generators\nfrom __future__ import with_statement\nwith = 9"
+        except SyntaxError:
+            pass
+        else:
+            assert False, 'Assignment to with did not raise SyntaxError'
+        
     def test_as_as_identifier(self):
         exec "as = 9"
         exec "import sys as foo"



More information about the Pypy-commit mailing list