[pypy-svn] r57656 - in pypy/dist/pypy/interpreter/pyparser: . test test/samples

arigo at codespeak.net arigo at codespeak.net
Wed Aug 27 19:15:32 CEST 2008


Author: arigo
Date: Wed Aug 27 19:15:29 2008
New Revision: 57656

Added:
   pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_decorators_2.py
Modified:
   pypy/dist/pypy/interpreter/pyparser/astbuilder.py
   pypy/dist/pypy/interpreter/pyparser/asthelper.py
   pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
   pypy/dist/pypy/interpreter/pyparser/test/test_samples.py
Log:
Fix for decorators of the form  @f()  with an empty argument list.


Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py	Wed Aug 27 19:15:29 2008
@@ -580,18 +580,23 @@
 def build_decorator(builder, nb):
     """decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE"""
     atoms = get_atoms(builder, nb)
-    nodes = []
-    # remove '@', '(' and ')' from atoms and use parse_attraccess
-    for token in atoms[1:]:
-        if isinstance(token, TokenObject) and (
-               token.name == builder.parser.tokens['LPAR']
-               or token.name == builder.parser.tokens['RPAR']
-               or token.name == builder.parser.tokens['NEWLINE']):
-            # skip those ones
-            continue
-        else:
-            nodes.append(token)
-    obj = parse_attraccess(nodes, builder)
+    # collect all nodes up to '(' or NEWLINE
+    end = 1
+    while True:
+        token = atoms[end]
+        if isinstance(token, TokenObject):
+            if token.name == builder.parser.tokens['NEWLINE']:
+                arglist = None
+                break
+            if token.name == builder.parser.tokens['LPAR']:
+                arglist = atoms[end+1]
+                if not isinstance(arglist, ArglistObject):  # because it's RPAR
+                    arglist = ArglistObject([], None, None, token.lineno)
+                break
+        end += 1
+    obj = parse_attraccess(atoms[1:end], builder)
+    if arglist is not None:
+        obj = reduce_callfunc(obj, arglist)
     builder.push(obj)
 
 def build_funcdef(builder, nb):

Modified: pypy/dist/pypy/interpreter/pyparser/asthelper.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/asthelper.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/asthelper.py	Wed Aug 27 19:15:29 2008
@@ -494,6 +494,9 @@
     """parses token list like ['a', '.', 'b', '.', 'c', ...]
 
     and returns an ast node : ast.Getattr(Getattr(Name('a'), 'b'), 'c' ...)
+
+    Well, no, that's lying.  In reality this is also parsing everything
+    that goes in the grammar 'trailer' rule.
     """
     token = tokens[0]
     # XXX HACK for when parse_attraccess is called from build_decorator
@@ -614,10 +617,12 @@
         self.lineno = lineno
 
     def __str__(self):
-        return "<ArgList: (%s, %s, %s)>" % self.value
+        return repr(self)
 
     def __repr__(self):
-        return "<ArgList: (%s, %s, %s)>" % self.value
+        return "<ArgList: (%s, %s, %s)>" % (self.arguments,
+                                            self.stararg,
+                                            self.dstararg)
 
 class SubscriptObject(ObjectAccessor):
     """helper class to build subscript list

Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_decorators_2.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_decorators_2.py	Wed Aug 27 19:15:29 2008
@@ -0,0 +1,7 @@
+
+
+# this one makes the "stablecompiler" explode.  Ha ha.
+
+ at spam.egg()
+def f():
+    pass

Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py	Wed Aug 27 19:15:29 2008
@@ -257,6 +257,7 @@
     'snippet_whitespaces.py',
     'snippet_samples.py',
     'snippet_decorators.py',
+    'snippet_decorators_2.py',
     'snippet_listlinenos.py',
     'snippet_whilelineno.py',
     ]

Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py	Wed Aug 27 19:15:29 2008
@@ -23,6 +23,7 @@
 SKIP_ALWAYS = [
     "snippet_with_1.py",
     "snippet_with_2.py",
+    "snippet_decorators_2.py",
 ]
 REAL_EXPECTED_OUTPUT = {
     # for snippets that show bugs of Python's compiler package
@@ -79,11 +80,11 @@
         for path in sample_paths:
             fname = path.basename 
             if fname in SKIP_ALWAYS:
-                yield lambda: py.test.skip(
+                yield lambda fname=fname: py.test.skip(
                     "%r is set to always skip." % (fname,))
                 continue
             if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE:
-                yield lambda: py.test.skip(
+                yield lambda fname=fname: py.test.skip(
                     "Grammar mismatch and %s is not native" % (fname,))
                 continue
             yield check_parse, str(path)



More information about the Pypy-commit mailing list