summaryrefslogtreecommitdiff
path: root/artima/python/webpy/resource.py
blob: 965b7203d3064edcb8ab8153af6977f37de4a6f7 (plain)
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import web

class inputmethod(object):
    """
    A descriptor passing web.input() as first argument to the
    inner function.
    """
    def __init__(self, func):
        self._func = func
    def __get__(self, obj, objcls):
        return self._func.__get__(web.input())

def identity(func):
    "A do nothing decorator"
    return func

class Register(object):
    """
    Each instance is a decorator associated to a web.py application.
    Each application adds a RESTful resource.
    """
    def __init__(self, dec=identity):
        self.dec = dec
        self.app = web.application([]) # self.app.mapping is the empty list
        self.mapping = {}
    
    def __call__(self, path):
        def dec(func):
            chunks = func.__name__.split('_')
            name = '_'.join(chunks[:-1])
            meth = chunks[-1]
            assert meth in ('GET', 'POST', 'PUT', 'DELETE'), meth
            func = self.dec(func) # decorate the original function
            self._addcls(path, name, meth, inputmethod(func))
            return func
        return dec

    def _addcls(self, path, name, method, meth):
        if path not in self.mapping:
            cls = type(name, (), dict(path=path))
            self.mapping[path] = cls
            self.app.mapping.extend([path, cls])
        else:
            cls = self.mapping[path]
        setattr(cls, method, meth)

if __name__ == '__main__':

    resource = Register()
    
    @resource('/b')
    def book_GET():
        pass

    @resource('/c')
    def book_POST():
        pass

    @resource('/d')
    def book_PUT():
        pass

    @resource('/e')
    def book_DELETE():
        pass

    print resource.app.mapping, resource.mapping