]> granicus.if.org Git - python/commitdiff
Correct the order of application for decorators. Meant to be bottom-up and not
authorBrett Cannon <bcannon@gmail.com>
Sun, 15 Aug 2004 07:21:25 +0000 (07:21 +0000)
committerBrett Cannon <bcannon@gmail.com>
Sun, 15 Aug 2004 07:21:25 +0000 (07:21 +0000)
top-down.  Now matches the PEP.

Lib/test/test_decorators.py
Misc/NEWS
Python/compile.c

index dbe45cf3fd3760f99e33792ca4f57485565b9dba..8010ea37f3d79437b5947bdff8ded897ce3f4f19 100644 (file)
@@ -129,7 +129,8 @@ class TestDecorators(unittest.TestCase):
         # XXX: This doesn't work unless memoize is the last decorator -
         #      see the comment in countcalls.
         counts = {}
-        @countcalls(counts) @memoize
+        @memoize
+        @countcalls(counts)
         def double(x):
             return x * 2
 
@@ -186,12 +187,20 @@ class TestDecorators(unittest.TestCase):
         self.assertEqual(C.foo.booh, 42)
 
     def test_order(self):
-        class C(object):
-            @funcattrs(abc=1) @staticmethod
-            def foo(): return 42
-        # This wouldn't work if staticmethod was called first
-        self.assertEqual(C.foo(), 42)
-        self.assertEqual(C().foo(), 42)
+        # Test that decorators are conceptually applied right-recursively;
+        # that means bottom-up
+        def ordercheck(num):
+            def deco(func):
+                return lambda: num
+            return deco
+
+        # Should go ordercheck(1)(ordercheck(2)(blah)) which should lead to
+        # blah() == 1
+        @ordercheck(1)
+        @ordercheck(2)
+        def blah(): pass
+        self.assertEqual(blah(), 1, "decorators are meant to be applied "
+                                    "bottom-up")
 
 def test_main():
     test_support.run_unittest(TestDecorators)
index 43e7553dcf72e53bd84d026eb74cbb75c066f08a..e564c2b69377a741689b29f517b4481a05a14ff4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.4 alpha 3?
 Core and builtins
 -----------------
 
+- Fix the order of application of decorators.  The proper order is bottom-up;
+  the first decorator listed is the last one called.
+
 - SF patch #1005778.  Fix a seg fault if the list size changed while
   calling list.index().  This could happen if a rich comparison function
   modified the list.
index de29536528457694345cb724baf6c2ae60866e4a..79620c209fe39908f9262a2a9d5fd070cd06432c 100644 (file)
@@ -4132,7 +4132,10 @@ com_decorators(struct compiling *c, node *n)
        REQ(CHILD(n, nch - 1), NEWLINE);
 
        ndecorators = 0;
-       for (i = NCH(n) - 1; i >= 0; --i) {
+       /* the application order for decorators is the reverse of how they are
+          listed; bottom-up */
+       nch -= 1;
+       for (i = 0; i < nch; i+=1) {
                node *ch = CHILD(n, i);
                if (TYPE(ch) != NEWLINE) {
                        com_decorator(c, ch);