Welcome, guest | Sign In | My Account | Store | Cart

Use my modulehacker recipe (recipe 577740) to apply decorators to any number of modules, or even (nearly) all of them.

Python, 38 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""decorations module"""

import types
import modulehacker

_modules = {}
_decorators = []
def register(decorator, modules=None):
    """Register a decorator for a list of module names."""
    if not decorator:
        return
    if not modules and decorator in _decorators:
        return
    if not modules:
        _decorators.append(decorator)
        return

    if isinstance(modules, str):
        modules = (modules,)
    for module in modules:
        if module not in _modules:
            _modules[module] = []
        _modules[module].append(decorator)

class Hacker(modulehacker.Hacker):
    def hack(self, module):
        for decorator in _modules.get(module.__name__, ()):
            self.decorate(module, decorator)
        for decorator in _decorators:
            self.decorate(module, decorator)
        return module
    def decorate(self, module, decorator):
        for attr in module.__dict__:
            obj = getattr(module, attr)
            if isinstance(obj, types.FunctionType):
                setattr(module, attr, decorator(obj))

modulehacker.register(Hacker())

Example

<rpc.py>

class Response:
   
def __init__(self, request, code=0):
       
self.request = request
       
self.code = code
       
self.result = None

class Request:
   
def __init__(self, id, method, args, access):
       
self.id = id
       
self.method = method
       
self.args = args
       
self.access = access
   
def generate_response(self):
       
return Response(self)

<something.py>

def f(request):
    response
= request.generate_response()
    response
.result = "Didn't do anything"
   
return response

<__main__>

import rpc

def log(message):
   
print(message)

# the decorators

def logs_in(f):
   
def newfunc(request):
        log
("handling <{o.method}> {o.args}".format(o=request))
       
return f(request)
   
return newfunc

def logs_out(f):
   
def newfunc(request):
        response
= f(request)
        log
("response: ({o.code}) {o.result}".format(o=response))
       
return response
   
return newfunc

import decorations
decorations
.register(logs_in, "something")
decorations
.register(logs_out, "something")

# now go for it

import something
request
= rpc.Request(1, "help", {"module": "abc"}, None)
response
= something.f(request)
# handling <help> {'module': 'abc'}
# response: (0) Didn't do anything

One neat thing is that you could use the modulehacker to automate some of this. In __main__, register one hacker that looks for some trigger in the module (like __decorate__ = True) and quickly registers another hacker that applies the decorator subsequently.