Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Applying a decorator to a module

8 views
Skip to first unread message

lkcl

unread,
Nov 28, 2008, 1:03:17 AM11/28/08
to
Very simple question: how do you apply a decorator to an entire
module? an idea whose time has properly arrived is to merge pyjamas
(http://pyjs.org) into web2py (http://web2py.com), and to do that,
it's necessary to "identify" functions, classes, global variables and
modules that should be compiled into javascript, rather than executed
server-side.

i figured that the best pythonic way would be to put a decorator on an
entire module, if the entire module was to be compiled to javascript.

... however, i don't know how to do that!

@decorate(module) ?

@decorator()
import modulename

?

should this work?

many thanks,

l.

sk...@pobox.com

unread,
Nov 28, 2008, 1:13:41 AM11/28/08
to lkcl, pytho...@python.org

lkcl> Very simple question: how do you apply a decorator to an entire
lkcl> module?

Function-by-function or class-by-class. There is no decorator support for
modules.

--
Skip Montanaro - sk...@pobox.com - http://smontanaro.dyndns.org/

lkcl

unread,
Nov 28, 2008, 1:24:54 AM11/28/08
to
On Nov 27, 7:43 pm, s...@pobox.com wrote:
> lkcl> Very simple question: how do you apply a decorator to an entire
> lkcl> module?
>
> Function-by-function or class-by-class. There is no decorator support for
> modules.

awWww! i'm going to quietly throw my toys out of my pram.

... but seriously - doesn't that strike people as... a slightly odd
omission?

l.

George Sakkis

unread,
Nov 28, 2008, 1:38:29 AM11/28/08
to

Not really; functions and classes are explicitly defined by "def .."
and "class ...", modules are not.

You can always pass the module to the decorator explicitly:

import mymod
mymod = decorator(mymod)

George

sk...@pobox.com

unread,
Nov 28, 2008, 1:44:02 AM11/28/08
to lkcl, pytho...@python.org
>> Function-by-function or class-by-class. There is no decorator
>> support for modules.

lkcl> ... but seriously - doesn't that strike people as... a slightly
lkcl> odd omission?

Decorators are still a new feature in the language and were purposely added
in an incremental fashion. In 2.5 they were added for functions. Suitable
use cases were found to apply them to classes in 2.6. You could post your
needs to the python...@python.org list and see if they gain any traction
there. If so, perhaps decorators for modules can be added for 2.7.

One obvious question about module decorators would be where to apply them.
In your original post you suggested perhaps applying it at import time:

@compiletojs
import mypyjamasmodule

What if somewhere else in your application you had a naked import:

import mypyjamasmodule

Should that be compiled into normal Python bytecode?

I suspect in most instances you'd want a module compiled one way or the
other. To avoid errors you probably want the decorator inside the module
(somewhere - at the top?). Unfortunately, there is no keyword upon which
you can hang a decorator as you can with functions (def) and classes
(class). import is not the same as a definition.

It's not obvious to me that module decorators would use precisely the same
sort of syntax as function and class decorators.

Skip

Arnaud Delobelle

unread,
Nov 28, 2008, 1:58:43 AM11/28/08
to
lkcl <luke.l...@googlemail.com> writes:

You can do something like this:

def decorate_functions(decorator, module):
Function = type(lambda:0), type(len)
for name, obj in module.__dict__.iteritems():
if isinstance(obj, Function):
setattr(module, name, decorator(obj))

Example:

>>> def trace(f):
... def decorated(*args, **kwargs):
... print 'calling', f.__name__
... return f(*args, **kwargs)
... return decorated
...
>>> import math
>>> decorate_functions(trace, math)
>>> math.log(math.tan(math.pi/4))
calling tan
calling log
-1.1102230246251565e-16

--
Arnaud

Diez B. Roggisch

unread,
Nov 28, 2008, 2:58:54 AM11/28/08
to
lkcl schrieb:


Decorators are applied when the function or class is *defined*. Modules
OTOH are imported from quite a few places. So what would

@foo
import bar

@baz
import bar

mean - what's the semantics of that? If *anything*, you could declare a
decorator per module.


Anyway, for your original problem, you can always just iterate over the
module objects & decorate them. Like this:


for name in dir(module):
thing = getattr(module, name)
if callable(thing):
wrapped_thing = wrap(thing)
setattr(module, name, wrappend_thing)

Diez

Terry Reedy

unread,
Nov 28, 2008, 5:32:48 AM11/28/08
to pytho...@python.org
Decorators are syntactic sugar. They add no functionality.

@decorator
def/class possibly_long_name ...

abbreviates

def/class possibly_long_name ...
<possibly many lines running off screen or page>
possibly_long_name = decorator(possibly_long_name)

thereby warning the reader at the beginning that possibly_long_name will
be rebound and avoiding typing possibly_long_name thrice.

Neither consideration applies to module imports.
Wrapping the functions and classed inside the module does not wrap the
module, it mutates it. Module names tend to be short and would only
need to be written twice, not thrice. And the mutation call would
immediately follow the import line, so readers can easily see what happens.

Steven D'Aprano

unread,
Nov 28, 2008, 5:53:55 AM11/28/08
to

No.

Strictly speaking, to talk about applying a decorator to a module means
syntactic sugar for the following:

import mymodule
mymodule = decorator(mymodule)

Since it's only two lines, it's not a great hardship to expect people to
call the decorator directly, instead of having syntactic sugar for it.
The only hard part is to write the function decorator() itself -- and it
isn't clear what that should possibly do. Function and class decorators
wrap functions and classes, so presumably module decorators should wrap
the module object itself.

But that doesn't seem to be what you want: you want it to look inside the
module and wrap the individual functions and classes inside it. All of
them? Wrap them with what? What about other objects? Should it wrap
callable class instances ("functors") as well as the classes themselves?
Metaclasses? Functions imported from other modules?

There's too many possible answers to these questions to expect this to be
standard part of Python. In other words, this is an application-level
task, not a language task, which means it's your job, not the standard
library's.


--
Steven

0 new messages