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.