Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #728 (closed enhancement: fixed)

Opened 13 years ago

Last modified 12 years ago

Investigate PEAK's [] syntax for decorators under 2.3

Reported by: kevin Owned by: simon
Priority: normal Milestone: 0.9
Component: TurboGears Version: 0.9a4
Severity: normal Keywords:


TurboGears uses decorators. A lot. The 2.3 syntax for decorating methods is really ugly. Phillip Eby has a syntax for doing decorators that is only slightly worse than the Python 2.4 syntax. If we can use that syntax with TurboGears under Python 2.3, that would be a win. We already include RuleDispatch? and PyProtocols?, so we might have the necessary tools available.

Change History

comment:1 Changed 13 years ago by simon

  • Status changed from new to assigned
  • Owner changed from anonymous to simon

What needs to be done is to incorporate dispatch.as().

I'll give it a whirl.

comment:2 Changed 13 years ago by simon

Some good news and some bad news. The good news is, it can be done pretty trivially, the bad news is, trivial is cumbersome as it involves passing return value from the decorator through yet another function:

def foo(baz, bar):
  def entangle(func):
    def foo(func, *arg, **kw):
      return func(*arg, **kw)
    return decorator(foo)(func)
  return legacy_decorator(entangle)

Ideally this functionality should be seamlessly bundled with decorator(). I see two obvious ways of doing so:

1) dirty hack/magic -- we constrain inner and outer decorator functions to have the same name.

2) change the logic behind decorator() -- breaks backward compatibility.

My vote goes to 2).

comment:3 Changed 13 years ago by kevin

I hadn't expected anyone to actually look at this ticket :)

Here's what Phillip had to say on the subject:

The machinery you want is
protocols.advice.add_assignment_advisor.  Keep in mind that it uses
debugger tracing, so it's *possible* that it could interfere with an
active debugger, but only during the module *import*, not during
actual program execution.  The machinery is compatible with both
Python 2.3 and 2.4.

One additional limitation of the syntax is if you use "doctest" or
write code in the interactive interpreter, it doesn't know that the
decorator is part of the function definition, so you have to do something like:

   if 1:
       def whatever(...):

in order to get the *interactive* interpreter to treat the whole
thing as a single statement.  You don't need this in a file, just at
the Python prompt or in a doctest.

I'm not concerned about decorator() backwards compatibility as long as *our* decorators are all brought up to date.

This change should only be turned on for Python 2.3.

comment:4 Changed 13 years ago by pje

You don't really want to enable it for *only* Python 2.3, because otherwise you're going to create one heck of a problem for people when they upgrade from 2.3 to 2.4. They'll have to search-and-replace all their code, all at once. Also, people offering TurboGears add-ons or libraries will have to distribute two versions to support both 2.3 and 2.4.

So if you do this, be aware that you'll effectively be making everybody use the 2.3 syntax until 2.3 is dead and buried.

comment:5 Changed 13 years ago by simon

I have a working version. Only problem is, it's impossible to use "simple" decorators (single level of nesting) with this alternative syntax[1].

Do we go for it and upgrade all our decorators?

[1]  http://www.eby-sarna.com/pipermail/peak/2006-April/002519.html

comment:6 Changed 13 years ago by pje

FYI, the 'dispatch.as()' decorator in RuleDispatch? will apply no-argument decorators, e.g.:


So, it's certainly possible for you to make a decorator that takes uncalled decorators, if you don't want to have to change them.

Indeed, you could create just one decorator called "decorate(*decorators)", and you wouldn't have to change any of your existing decorators' code at all.

comment:7 Changed 13 years ago by simon

I was thinking about just rebinding as() into our namespace as an utility.

I am not very fond of offering two ways of doing things, especially since (currently) all our decorators take arguments, making the simper invocation an obvious choice. As wired as it may sound, legacy code will also follow the composition/look of tutorials and docs more closely that way.

comment:8 Changed 13 years ago by simon

  • Status changed from assigned to closed
  • Resolution set to fixed

Done in r1279.

Note: See TracTickets for help on using tickets.