/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):
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
102
    with self.lock_read():
103
        return unbound(%(passed_params)s)
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
104
read_locked = %(name)s_read_locked
105
"""
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
106
    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.
107
    variables = {'name':unbound.__name__,
108
                 'params':params,
109
                 'passed_params':passed_params,
110
                }
111
    func_def = template % variables
112
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
113
    scope = dict(defaults_dict)
114
    scope['unbound'] = unbound
6619.3.10 by Jelmer Vernooij
Run 2to3 exec fixer.
115
    exec(func_def, scope)
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
116
    read_locked = scope['read_locked']
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
117
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
118
    read_locked.__doc__ = unbound.__doc__
119
    read_locked.__name__ = unbound.__name__
120
    return read_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
121
122
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.
123
def _fast_needs_read_lock(unbound):
124
    """Decorate unbound to take out and release a read lock.
125
126
    This decorator can be applied to methods of any class with lock_read() and
127
    unlock() methods.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
128
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.
129
    Typical usage:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
130
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.
131
    class Branch(...):
132
        @needs_read_lock
133
        def branch_method(self, ...):
134
            stuff
135
    """
136
    def read_locked(self, *args, **kwargs):
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
137
        with self.lock_read():
138
            return unbound(self, *args, **kwargs)
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.
139
    read_locked.__doc__ = unbound.__doc__
140
    read_locked.__name__ = unbound.__name__
141
    return read_locked
142
143
144
def _pretty_needs_write_lock(unbound):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
145
    """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
146
    template = """\
2230.2.2 by John Arbash Meinel
Change decorators to define the same parameters as the wrapped func.
147
def %(name)s_write_locked(%(params)s):
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
148
    with self.lock_write():
149
        return unbound(%(passed_params)s)
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
150
write_locked = %(name)s_write_locked
151
"""
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
152
    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.
153
    variables = {'name':unbound.__name__,
154
                 'params':params,
155
                 'passed_params':passed_params,
156
                }
157
    func_def = template % variables
158
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
159
    scope = dict(defaults_dict)
160
    scope['unbound'] = unbound
6619.3.10 by Jelmer Vernooij
Run 2to3 exec fixer.
161
    exec(func_def, scope)
5662.1.1 by Andrew Bennetts
Preserve identity of default values in the pretty decorators.
162
    write_locked = scope['write_locked']
2230.2.1 by John Arbash Meinel
Change the read_lock and write_lock decorators to use custom names
163
1534.4.48 by Robert Collins
Make needs_read_lock and needs_write_lock more visible in tracebacks
164
    write_locked.__doc__ = unbound.__doc__
165
    write_locked.__name__ = unbound.__name__
166
    return write_locked
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
167
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.
168
169
def _fast_needs_write_lock(unbound):
170
    """Decorate unbound to take out and release a write lock."""
171
    def write_locked(self, *args, **kwargs):
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
172
        with self.lock_write():
173
            return unbound(self, *args, **kwargs)
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.
174
    write_locked.__doc__ = unbound.__doc__
175
    write_locked.__name__ = unbound.__name__
176
    return write_locked
177
178
4634.85.9 by Andrew Bennetts
Add some experimental decorators: @only_raises(..) and @cleanup_method.
179
def only_raises(*errors):
4634.62.2 by Andrew Bennetts
Update test_decorators, add docstring.
180
    """Make a decorator that will only allow the given error classes to be
181
    raised.  All other errors will be logged and then discarded.
182
183
    Typical use is something like::
184
185
        @only_raises(LockNotHeld, LockBroken)
186
        def unlock(self):
187
            # etc
188
    """
4634.85.9 by Andrew Bennetts
Add some experimental decorators: @only_raises(..) and @cleanup_method.
189
    def decorator(unbound):
190
        def wrapped(*args, **kwargs):
191
            try:
192
                return unbound(*args, **kwargs)
193
            except errors:
194
                raise
195
            except:
196
                trace.mutter('Error suppressed by only_raises:')
197
                trace.log_exception_quietly()
198
        wrapped.__doc__ = unbound.__doc__
199
        wrapped.__name__ = unbound.__name__
200
        return wrapped
201
    return decorator
202
203
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.
204
# Default is more functionality, 'bzr' the commandline will request fast
205
# versions.
206
needs_read_lock = _pretty_needs_read_lock
207
needs_write_lock = _pretty_needs_write_lock
208
209
210
def use_fast_decorators():
211
    """Change the default decorators to be fast loading ones.
212
213
    The alternative is to have decorators that do more work to produce
214
    nice-looking decorated functions, but this slows startup time.
215
    """
216
    global needs_read_lock, needs_write_lock
217
    needs_read_lock = _fast_needs_read_lock
218
    needs_write_lock = _fast_needs_write_lock
219
220
221
def use_pretty_decorators():
222
    """Change the default decorators to be pretty ones."""
223
    global needs_read_lock, needs_write_lock
224
    needs_read_lock = _pretty_needs_read_lock
225
    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.
226
227
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
228
# This implementation of cachedproperty is copied from Launchpad's
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
229
# canonical.launchpad.cachedproperty module (with permission from flacoste)
230
# -- spiv & vila 100120
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
231
def cachedproperty(attrname_or_fn):
232
    """A decorator for methods that makes them properties with their return
233
    value cached.
234
235
    The value is cached on the instance, using the attribute name provided.
236
237
    If you don't provide a name, the mangled name of the property is used.
238
239
    >>> class CachedPropertyTest(object):
240
    ...
241
    ...     @cachedproperty('_foo_cache')
242
    ...     def foo(self):
243
    ...         print 'foo computed'
244
    ...         return 23
245
    ...
246
    ...     @cachedproperty
247
    ...     def bar(self):
248
    ...         print 'bar computed'
249
    ...         return 69
250
251
    >>> cpt = CachedPropertyTest()
252
    >>> getattr(cpt, '_foo_cache', None) is None
253
    True
254
    >>> cpt.foo
255
    foo computed
256
    23
257
    >>> cpt.foo
258
    23
259
    >>> cpt._foo_cache
260
    23
261
    >>> cpt.bar
262
    bar computed
263
    69
264
    >>> cpt._bar_cached_value
265
    69
266
4869.3.13 by Andrew Bennetts
Add simple cachedproperty decorator, and add {this,other,base}_lines cachedproperties to MergeHookParams.
267
    """
6621.2.26 by Martin
Misc set of changes to get started with selftest on Python 3
268
    if isinstance(attrname_or_fn, str):
4869.3.32 by Andrew Bennetts
Use Launchpad's cachedproperty decorator instead of my stupidly broken one.
269
        attrname = attrname_or_fn
270
        return _CachedPropertyForAttr(attrname)
271
    else:
272
        fn = attrname_or_fn
273
        attrname = '_%s_cached_value' % fn.__name__
274
        return _CachedProperty(attrname, fn)
275
276
277
class _CachedPropertyForAttr(object):
278
279
    def __init__(self, attrname):
280
        self.attrname = attrname
281
282
    def __call__(self, fn):
283
        return _CachedProperty(self.attrname, fn)
284
285
286
class _CachedProperty(object):
287
288
    def __init__(self, attrname, fn):
289
        self.fn = fn
290
        self.attrname = attrname
291
        self.marker = object()
292
293
    def __get__(self, inst, cls=None):
294
        if inst is None:
295
            return self
296
        cachedresult = getattr(inst, self.attrname, self.marker)
297
        if cachedresult is self.marker:
298
            result = self.fn(inst)
299
            setattr(inst, self.attrname, result)
300
            return result
301
        else:
302
            return cachedresult