[pypy-svn] r17696 - in pypy/dist/pypy/interpreter: astcompiler test

ac at codespeak.net ac at codespeak.net
Tue Sep 20 17:11:19 CEST 2005


Author: ac
Date: Tue Sep 20 17:11:18 2005
New Revision: 17696

Modified:
   pypy/dist/pypy/interpreter/astcompiler/symbols.py
   pypy/dist/pypy/interpreter/test/test_compiler.py
Log:
Warn about improper use of globals.

Modified: pypy/dist/pypy/interpreter/astcompiler/symbols.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/symbols.py	(original)
+++ pypy/dist/pypy/interpreter/astcompiler/symbols.py	Tue Sep 20 17:11:18 2005
@@ -5,6 +5,7 @@
     SC_FREE, SC_CELL, SC_UNKNOWN, SC_DEFAULT
 from pypy.interpreter.astcompiler.misc import mangle, Counter
 from pypy.interpreter.pyparser.error import SyntaxError
+from pypy.interpreter import gateway
 import types
 
 
@@ -210,6 +211,21 @@
     def __init__(self, name, module):
         Scope.__init__(self, name, module, name)
 
+app = gateway.applevel(r'''
+def issue_warning(msg, filename, lineno):
+    import warnings
+    try:
+        warnings.warn_explicit(msg, SyntaxWarning, filename, lineno,
+                               None, None)
+    except SyntaxWarning:
+        raise SyntaxError(msg, filename, lineno)
+''')
+
+_issue_warning = app.interphook('issue_warning')
+def issue_warning(space, msg, filename, lineno):
+    _issue_warning(space, space.wrap(msg), space.wrap(filename),
+                   space.wrap(lineno))
+
 class SymbolVisitor(ast.ASTVisitor):
     def __init__(self, space):
         self.space = space
@@ -400,6 +416,15 @@
     def visitGlobal(self, node ):
         scope = self.cur_scope()
         for name in node.names:
+            namescope = scope.check_name(name)
+            if namescope == SC_LOCAL:
+                issue_warning(self.space, "name '%s' is assigned to before "
+                              "global declaration" %(name,),
+                              node.filename, node.lineno)
+            elif namescope != SC_GLOBAL and name in scope.uses:
+                issue_warning(self.space, "name '%s' is used prior "
+                              "to global declaration" %(name,),
+                              node.filename, node.lineno)
             scope.add_global(name)
 
     def visitAssign(self, node ):

Modified: pypy/dist/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_compiler.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_compiler.py	Tue Sep 20 17:11:18 2005
@@ -4,6 +4,7 @@
 from pypy.interpreter.pycompiler import CPythonCompiler, PythonCompiler, PythonAstCompiler
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.argument import Arguments
 
 class BaseTestCompiler:
     def setup_method(self, method):
@@ -271,11 +272,46 @@
             ex = e.value
             ex.normalize_exception(self.space)
             assert ex.match(self.space, self.space.w_SyntaxError)
-    
+
+    def test_globals_warnings(self):
+        space = self.space
+        w_mod = space.appexec((), '():\n import warnings\n return warnings\n') #sys.getmodule('warnings')
+        w_filterwarnings = space.getattr(w_mod, space.wrap('filterwarnings'))
+        filter_arg = Arguments(space, [ space.wrap('error') ],
+                       dict(module=space.wrap('<tmp>')))
+                        
+        for code in ('''
+def wrong1():
+    a = 1
+    b = 2
+    global a
+    global b
+''', '''
+def wrong2():
+    print x
+    global x
+''', '''
+def wrong3():
+    print x
+    x = 2
+    global x
+'''):
+
+            space.call_args(w_filterwarnings, filter_arg)
+            e = py.test.raises(OperationError, self.compiler.compile,
+                               code, '<tmp>', 'exec', 0)
+            space.call_method(w_mod, 'resetwarnings') 
+            ex = e.value
+            ex.normalize_exception(space)
+            assert ex.match(space, space.w_SyntaxError)
+                
 class TestECCompiler(BaseTestCompiler):
     def setup_method(self, method):
         self.compiler = self.space.getexecutioncontext().compiler
 
+    def test_globals_warnings(self):
+        py.test.skip('INPROGRES')
+
 class TestPyCCompiler(BaseTestCompiler):
     def setup_method(self, method):
         self.compiler = CPythonCompiler(self.space)
@@ -284,6 +320,9 @@
     def setup_method(self, method):
         self.compiler = PythonCompiler(self.space)
 
+    def test_globals_warnings(self):
+        py.test.skip('INPROGRES')
+        
 class TestPythonAstCompiler(BaseTestCompiler):
     def setup_method(self, method):
         self.compiler = PythonAstCompiler(self.space)



More information about the Pypy-commit mailing list