summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_decorators.py23
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/compile.c5
3 files changed, 23 insertions, 8 deletions
diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py
index dbe45cf..8010ea3 100644
--- a/Lib/test/test_decorators.py
+++ b/Lib/test/test_decorators.py
@@ -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)
diff --git a/Misc/NEWS b/Misc/NEWS
index 43e7553..e564c2b 100644
--- 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.
diff --git a/Python/compile.c b/Python/compile.c
index de29536..79620c2 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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);