/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
16
6379.6.1 by Jelmer Vernooij
Import absolute_import in a few places.
17
from __future__ import absolute_import
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
18
1185.65.27 by Robert Collins
Tweak storage towards mergability.
19
__all__ = ['needs_read_lock',
20
           'needs_write_lock',
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
21
           'use_fast_decorators',
22
           'use_pretty_decorators',
1185.65.27 by Robert Collins
Tweak storage towards mergability.
23
           ]
24
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
25
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
26
from . import trace
4634.85.9 by Andrew Bennetts
Add some experimental decorators: @only_raises(..) and @cleanup_method.
27
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
28
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
29
def _get_parameters(func):
30
    """Recreate the parameters for a function using introspection.
31
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
32
    :return: (function_params, calling_params, default_values)
2230.2.6 by John Arbash Meinel
Clean up the documentation and imports for decorators (per Martin's suggestions)
33
        function_params: is a string representing the parameters of the
34
            function. (such as "a, b, c=None, d=1")
35
            This is used in the function declaration.
36
        calling_params: is another string representing how you would call the
37
            function with the correct parameters. (such as "a, b, c=c, d=d")
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
38
            Assuming you used function_params in the function declaration, this
2230.2.6 by John Arbash Meinel
Clean up the documentation and imports for decorators (per Martin's suggestions)
39
            is the parameters to put in the function call.
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
40
        default_values_block: a dict with the default values to be passed as
41
            the scope for the 'exec' statement.
2230.2.6 by John Arbash Meinel
Clean up the documentation and imports for decorators (per Martin's suggestions)
42
43
        For example:
44
45
        def wrapper(%(function_params)s):
46
            return original(%(calling_params)s)
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
47
    """
2230.2.6 by John Arbash Meinel
Clean up the documentation and imports for decorators (per Martin's suggestions)
48
    # "import inspect" should stay in local scope. 'inspect' takes a long time
49
    # to import the first time. And since we don't always need it, don't import
50
    # it globally.
51
    import inspect
52
    args, varargs, varkw, defaults = inspect.getargspec(func)
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
53
    defaults_dict = {}
54
    def formatvalue(value):
55
        default_name = '__default_%d' % len(defaults_dict)
56
        defaults_dict[default_name] = value
57
        return '=' + default_name
2230.2.6 by John Arbash Meinel
Clean up the documentation and imports for decorators (per Martin's suggestions)
58
    formatted = inspect.formatargspec(args, varargs=varargs,
59
                                      varkw=varkw,
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
60
                                      defaults=defaults,
61
                                      formatvalue=formatvalue)
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
62
    if defaults is None:
63
        args_passed = args
64
    else:
65
        first_default = len(args) - len(defaults)
66
        args_passed = args[:first_default]
67
        for arg in args[first_default:]:
68
            args_passed.append("%s=%s" % (arg, arg))
69
    if varargs is not None:
70
        args_passed.append('*' + varargs)
71
    if varkw is not None:
72
        args_passed.append('**' + varkw)
73
    args_passed = ', '.join(args_passed)
74
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
75
    return formatted[1:-1], args_passed, defaults_dict
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
76
77
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.
78
def _pretty_needs_read_lock(unbound):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
79
    """Decorate unbound to take out and release a read lock.
80
81
    This decorator can be applied to methods of any class with lock_read() and
82
    unlock() methods.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
83
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
84
    Typical usage:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
85
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
86
    class Branch(...):
87
        @needs_read_lock
88
        def branch_method(self, ...):
89
            stuff
90
    """
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
91
    # This compiles a function with a similar name, but wrapped with
92
    # lock_read/unlock calls. We use dynamic creation, because we need the
93
    # internal name of the function to be modified so that --lsprof will see
94
    # the correct name.
95
    # TODO: jam 20070111 Modify this template so that the generated function
96
    #       has the same argument signature as the original function, which
97
    #       will help commands like epydoc.
98
    #       This seems possible by introspecting foo.func_defaults, and
99
    #       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
100
    template = """\
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
101
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
102
    self.lock_read()
103
    try:
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
104
        result = unbound(%(passed_params)s)
105
    except:
106
        try:
107
            self.unlock()
108
        finally:
6621.8.1 by Martin
Simplify exception handling in locking decorators
109
            raise
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
110
    else:
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
111
        self.unlock()
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
112
        return result
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
113
read_locked = %(name)s_read_locked
114
"""
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
115
    params, passed_params, defaults_dict = _get_parameters(unbound)
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
116
    variables = {'name':unbound.__name__,
117
                 'params':params,
118
                 'passed_params':passed_params,
119
                }
120
    func_def = template % variables
121
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
122
    scope = dict(defaults_dict)
123
    scope['unbound'] = unbound
6619.3.10 by Jelmer Vernooij
Run 2to3 exec fixer.
124
    exec(func_def, scope)
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
125
    read_locked = scope['read_locked']
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
126
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
127
    read_locked.__doc__ = unbound.__doc__
128
    read_locked.__name__ = unbound.__name__
129
    return read_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
130
131
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.
132
def _fast_needs_read_lock(unbound):
133
    """Decorate unbound to take out and release a read lock.
134
135
    This decorator can be applied to methods of any class with lock_read() and
136
    unlock() methods.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
137
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.
138
    Typical usage:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
139
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.
140
    class Branch(...):
141
        @needs_read_lock
142
        def branch_method(self, ...):
143
            stuff
144
    """
145
    def read_locked(self, *args, **kwargs):
146
        self.lock_read()
147
        try:
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
148
            result = unbound(self, *args, **kwargs)
149
        except:
150
            try:
151
                self.unlock()
152
            finally:
6621.8.1 by Martin
Simplify exception handling in locking decorators
153
                raise
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
154
        else:
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.
155
            self.unlock()
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
156
            return result
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.
157
    read_locked.__doc__ = unbound.__doc__
158
    read_locked.__name__ = unbound.__name__
159
    return read_locked
160
161
162
def _pretty_needs_write_lock(unbound):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
163
    """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
164
    template = """\
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
165
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
166
    self.lock_write()
167
    try:
3316.3.2 by John Arbash Meinel
Finish fix for bug #125784. need_read/write_lock decorators should attempt to raise an original exception.
168
        result = unbound(%(passed_params)s)
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
169
    except:
170
        try:
171
            self.unlock()
172
        finally:
6621.8.1 by Martin
Simplify exception handling in locking decorators
173
            raise
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
174
    else:
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
175
        self.unlock()
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
176
        return result
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
177
write_locked = %(name)s_write_locked
178
"""
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
179
    params, passed_params, defaults_dict = _get_parameters(unbound)
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
180
    variables = {'name':unbound.__name__,
181
                 'params':params,
182
                 'passed_params':passed_params,
183
                }
184
    func_def = template % variables
185
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
186
    scope = dict(defaults_dict)
187
    scope['unbound'] = unbound
6619.3.10 by Jelmer Vernooij
Run 2to3 exec fixer.
188
    exec(func_def, scope)
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
189
    write_locked = scope['write_locked']
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
190
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
191
    write_locked.__doc__ = unbound.__doc__
192
    write_locked.__name__ = unbound.__name__
193
    return write_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
194
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.
195
196
def _fast_needs_write_lock(unbound):
197
    """Decorate unbound to take out and release a write lock."""
198
    def write_locked(self, *args, **kwargs):
199
        self.lock_write()
200
        try:
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
201
            result = unbound(self, *args, **kwargs)
202
        except:
203
            try:
204
                self.unlock()
205
            finally:
6621.8.1 by Martin
Simplify exception handling in locking decorators
206
                raise
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
207
        else:
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.
208
            self.unlock()
3316.3.1 by Andrew Bennetts
Try not to lose the original exception in needs_write_lock decorator if the unlock raises a secondary exception.
209
            return result
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.
210
    write_locked.__doc__ = unbound.__doc__
211
    write_locked.__name__ = unbound.__name__
212
    return write_locked
213
214
4634.85.9 by Andrew Bennetts
Add some experimental decorators: @only_raises(..) and @cleanup_method.
215
def only_raises(*errors):
4634.62.2 by Andrew Bennetts
Update test_decorators, add docstring.
216
    """Make a decorator that will only allow the given error classes to be
217
    raised.  All other errors will be logged and then discarded.
218
219
    Typical use is something like::
220
221
        @only_raises(LockNotHeld, LockBroken)
222
        def unlock(self):
223
            # etc
224
    """
4634.85.9 by Andrew Bennetts
Add some experimental decorators: @only_raises(..) and @cleanup_method.
225
    def decorator(unbound):
226
        def wrapped(*args, **kwargs):
227
            try:
228
                return unbound(*args, **kwargs)
229
            except errors:
230
                raise
231
            except:
232
                trace.mutter('Error suppressed by only_raises:')
233
                trace.log_exception_quietly()
234
        wrapped.__doc__ = unbound.__doc__
235
        wrapped.__name__ = unbound.__name__
236
        return wrapped
237
    return decorator
238
239
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.
240
# Default is more functionality, 'bzr' the commandline will request fast
241
# versions.
242
needs_read_lock = _pretty_needs_read_lock
243
needs_write_lock = _pretty_needs_write_lock
244
245
246
def use_fast_decorators():
247
    """Change the default decorators to be fast loading ones.
248
249
    The alternative is to have decorators that do more work to produce
250
    nice-looking decorated functions, but this slows startup time.
251
    """
252
    global needs_read_lock, needs_write_lock
253
    needs_read_lock = _fast_needs_read_lock
254
    needs_write_lock = _fast_needs_write_lock
255
256
257
def use_pretty_decorators():
258
    """Change the default decorators to be pretty ones."""
259
    global needs_read_lock, needs_write_lock
260
    needs_read_lock = _pretty_needs_read_lock
261
    needs_write_lock = _pretty_needs_write_lock
4869.3.13 by Andrew Bennetts
Add simple cachedproperty decorator, and add {this,other,base}_lines cachedproperties to MergeHookParams.
262
263
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
264
# This implementation of cachedproperty is copied from Launchpad's
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
265
# canonical.launchpad.cachedproperty module (with permission from flacoste)
266
# -- spiv & vila 100120
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
267
def cachedproperty(attrname_or_fn):
268
    """A decorator for methods that makes them properties with their return
269
    value cached.
270
271
    The value is cached on the instance, using the attribute name provided.
272
273
    If you don't provide a name, the mangled name of the property is used.
274
275
    >>> class CachedPropertyTest(object):
276
    ...
277
    ...     @cachedproperty('_foo_cache')
278
    ...     def foo(self):
279
    ...         print 'foo computed'
280
    ...         return 23
281
    ...
282
    ...     @cachedproperty
283
    ...     def bar(self):
284
    ...         print 'bar computed'
285
    ...         return 69
286
287
    >>> cpt = CachedPropertyTest()
288
    >>> getattr(cpt, '_foo_cache', None) is None
289
    True
290
    >>> cpt.foo
291
    foo computed
292
    23
293
    >>> cpt.foo
294
    23
295
    >>> cpt._foo_cache
296
    23
297
    >>> cpt.bar
298
    bar computed
299
    69
300
    >>> cpt._bar_cached_value
301
    69
302
4869.3.13 by Andrew Bennetts
Add simple cachedproperty decorator, and add {this,other,base}_lines cachedproperties to MergeHookParams.
303
    """
6621.2.26 by Martin
Misc set of changes to get started with selftest on Python 3
304
    if isinstance(attrname_or_fn, str):
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
305
        attrname = attrname_or_fn
306
        return _CachedPropertyForAttr(attrname)
307
    else:
308
        fn = attrname_or_fn
309
        attrname = '_%s_cached_value' % fn.__name__
310
        return _CachedProperty(attrname, fn)
311
312
313
class _CachedPropertyForAttr(object):
314
315
    def __init__(self, attrname):
316
        self.attrname = attrname
317
318
    def __call__(self, fn):
319
        return _CachedProperty(self.attrname, fn)
320
321
322
class _CachedProperty(object):
323
324
    def __init__(self, attrname, fn):
325
        self.fn = fn
326
        self.attrname = attrname
327
        self.marker = object()
328
329
    def __get__(self, inst, cls=None):
330
        if inst is None:
331
            return self
332
        cachedresult = getattr(inst, self.attrname, self.marker)
333
        if cachedresult is self.marker:
334
            result = self.fn(inst)
335
            setattr(inst, self.attrname, result)
336
            return result
337
        else:
338
            return cachedresult