/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
1
# Copyright (C) 2005 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
2230.2.3 by John Arbash Meinel
Add the ability to have fast decorators as well as pretty ones, and have 'bzr' select the right one at startup.
18
_inspect = None
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
19
20
1185.65.27 by Robert Collins
Tweak storage towards mergability.
21
__all__ = ['needs_read_lock',
22
           'needs_write_lock',
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
23
           'use_fast_decorators',
24
           'use_pretty_decorators',
1185.65.27 by Robert Collins
Tweak storage towards mergability.
25
           ]
26
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
27
28
def _get_parameters(func):
29
    """Recreate the parameters for a function using introspection.
30
31
    :return: (function_params, passed_params)
32
        function_params is the list of parameters to the original function.
33
        This is something like "a, b, c=None, d=1"
34
        passed_params is how you would pass the parameters to a new function.
35
        This is something like "a=a, b=b, c=c, d=d"
36
    """
2230.2.3 by John Arbash Meinel
Add the ability to have fast decorators as well as pretty ones, and have 'bzr' select the right one at startup.
37
    global _inspect
38
    if _inspect is None:
39
        import inspect
40
        _inspect = inspect
41
    args, varargs, varkw, defaults = _inspect.getargspec(func)
42
    formatted = _inspect.formatargspec(args, varargs=varargs,
43
                                       varkw=varkw,
44
                                       defaults=defaults)
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
45
    if defaults is None:
46
        args_passed = args
47
    else:
48
        first_default = len(args) - len(defaults)
49
        args_passed = args[:first_default]
50
        for arg in args[first_default:]:
51
            args_passed.append("%s=%s" % (arg, arg))
52
    if varargs is not None:
53
        args_passed.append('*' + varargs)
54
    if varkw is not None:
55
        args_passed.append('**' + varkw)
56
    args_passed = ', '.join(args_passed)
57
58
    return formatted[1:-1], args_passed
59
60
2230.2.3 by John Arbash Meinel
Add the ability to have fast decorators as well as pretty ones, and have 'bzr' select the right one at startup.
61
def _pretty_needs_read_lock(unbound):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
62
    """Decorate unbound to take out and release a read lock.
63
64
    This decorator can be applied to methods of any class with lock_read() and
65
    unlock() methods.
66
    
67
    Typical usage:
68
        
69
    class Branch(...):
70
        @needs_read_lock
71
        def branch_method(self, ...):
72
            stuff
73
    """
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
74
    # This compiles a function with a similar name, but wrapped with
75
    # lock_read/unlock calls. We use dynamic creation, because we need the
76
    # internal name of the function to be modified so that --lsprof will see
77
    # the correct name.
78
    # TODO: jam 20070111 Modify this template so that the generated function
79
    #       has the same argument signature as the original function, which
80
    #       will help commands like epydoc.
81
    #       This seems possible by introspecting foo.func_defaults, and
82
    #       foo.func_code.co_argcount and foo.func_code.co_varnames
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
83
    template = """\
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
84
def %(name)s_read_locked(%(params)s):
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
85
    self.lock_read()
86
    try:
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
87
        return unbound(%(passed_params)s)
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
88
    finally:
89
        self.unlock()
90
read_locked = %(name)s_read_locked
91
"""
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
92
    params, passed_params = _get_parameters(unbound)
93
    variables = {'name':unbound.__name__,
94
                 'params':params,
95
                 'passed_params':passed_params,
96
                }
97
    func_def = template % variables
98
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
99
    exec func_def in locals()
100
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
101
    read_locked.__doc__ = unbound.__doc__
102
    read_locked.__name__ = unbound.__name__
103
    return read_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
104
105
2230.2.3 by John Arbash Meinel
Add the ability to have fast decorators as well as pretty ones, and have 'bzr' select the right one at startup.
106
def _fast_needs_read_lock(unbound):
107
    """Decorate unbound to take out and release a read lock.
108
109
    This decorator can be applied to methods of any class with lock_read() and
110
    unlock() methods.
111
    
112
    Typical usage:
113
        
114
    class Branch(...):
115
        @needs_read_lock
116
        def branch_method(self, ...):
117
            stuff
118
    """
119
    def read_locked(self, *args, **kwargs):
120
        self.lock_read()
121
        try:
122
            return unbound(self, *args, **kwargs)
123
        finally:
124
            self.unlock()
125
    read_locked.__doc__ = unbound.__doc__
126
    read_locked.__name__ = unbound.__name__
127
    return read_locked
128
129
130
def _pretty_needs_write_lock(unbound):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
131
    """Decorate unbound to take out and release a write lock."""
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
132
    template = """\
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
133
def %(name)s_write_locked(%(params)s):
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
134
    self.lock_write()
135
    try:
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
136
        return unbound(%(passed_params)s)
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
137
    finally:
138
        self.unlock()
139
write_locked = %(name)s_write_locked
140
"""
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
141
    params, passed_params = _get_parameters(unbound)
142
    variables = {'name':unbound.__name__,
143
                 'params':params,
144
                 'passed_params':passed_params,
145
                }
146
    func_def = template % variables
147
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
148
    exec func_def in locals()
149
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
150
    write_locked.__doc__ = unbound.__doc__
151
    write_locked.__name__ = unbound.__name__
152
    return write_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
153
2230.2.3 by John Arbash Meinel
Add the ability to have fast decorators as well as pretty ones, and have 'bzr' select the right one at startup.
154
155
def _fast_needs_write_lock(unbound):
156
    """Decorate unbound to take out and release a write lock."""
157
    def write_locked(self, *args, **kwargs):
158
        self.lock_write()
159
        try:
160
            return unbound(self, *args, **kwargs)
161
        finally:
162
            self.unlock()
163
    write_locked.__doc__ = unbound.__doc__
164
    write_locked.__name__ = unbound.__name__
165
    return write_locked
166
167
168
# Default is more functionality, 'bzr' the commandline will request fast
169
# versions.
170
needs_read_lock = _pretty_needs_read_lock
171
needs_write_lock = _pretty_needs_write_lock
172
173
174
def use_fast_decorators():
175
    """Change the default decorators to be fast loading ones.
176
177
    The alternative is to have decorators that do more work to produce
178
    nice-looking decorated functions, but this slows startup time.
179
    """
180
    global needs_read_lock, needs_write_lock
181
    needs_read_lock = _fast_needs_read_lock
182
    needs_write_lock = _fast_needs_write_lock
183
184
185
def use_pretty_decorators():
186
    """Change the default decorators to be pretty ones."""
187
    global needs_read_lock, needs_write_lock
188
    needs_read_lock = _pretty_needs_read_lock
189
    needs_write_lock = _pretty_needs_write_lock