Applying a decorator to a module

L

lkcl

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.
 
S

skip

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.
 
L

lkcl

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.
 
G

George Sakkis

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?

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
 
A

Arnaud Delobelle

lkcl said:
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.

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 decorated(*args, **kwargs):
.... print 'calling', f.__name__
.... return f(*args, **kwargs)
.... return decorated
.... calling tan
calling log
-1.1102230246251565e-16
 
D

Diez B. Roggisch

lkcl said:
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?


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
 
T

Terry Reedy

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.
 
S

Steven D'Aprano

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?

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top