~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/decorators.py

  • Committer: Danny van Heumen
  • Date: 2010-03-09 21:42:11 UTC
  • mto: (4634.139.5 2.0)
  • mto: This revision was merged to the branch mainline in revision 5160.
  • Revision ID: danny@dannyvanheumen.nl-20100309214211-iqh42x6qcikgd9p3
Reverted now-useless TODO list.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
24
24
 
25
25
import sys
26
26
 
27
 
from bzrlib import trace
28
 
 
29
27
 
30
28
def _get_parameters(func):
31
29
    """Recreate the parameters for a function using introspection.
206
204
    return write_locked
207
205
 
208
206
 
209
 
def only_raises(*errors):
210
 
    """Make a decorator that will only allow the given error classes to be
211
 
    raised.  All other errors will be logged and then discarded.
212
 
 
213
 
    Typical use is something like::
214
 
 
215
 
        @only_raises(LockNotHeld, LockBroken)
216
 
        def unlock(self):
217
 
            # etc
218
 
    """
219
 
    def decorator(unbound):
220
 
        def wrapped(*args, **kwargs):
221
 
            try:
222
 
                return unbound(*args, **kwargs)
223
 
            except errors:
224
 
                raise
225
 
            except:
226
 
                trace.mutter('Error suppressed by only_raises:')
227
 
                trace.log_exception_quietly()
228
 
        wrapped.__doc__ = unbound.__doc__
229
 
        wrapped.__name__ = unbound.__name__
230
 
        return wrapped
231
 
    return decorator
232
 
 
233
 
 
234
207
# Default is more functionality, 'bzr' the commandline will request fast
235
208
# versions.
236
209
needs_read_lock = _pretty_needs_read_lock
253
226
    global needs_read_lock, needs_write_lock
254
227
    needs_read_lock = _pretty_needs_read_lock
255
228
    needs_write_lock = _pretty_needs_write_lock
256
 
 
257
 
 
258
 
# This implementation of cachedproperty is copied from Launchpad's
259
 
# canonical.launchpad.cachedproperty module (with permission from flacoste)
260
 
# -- spiv & vila 100120
261
 
def cachedproperty(attrname_or_fn):
262
 
    """A decorator for methods that makes them properties with their return
263
 
    value cached.
264
 
 
265
 
    The value is cached on the instance, using the attribute name provided.
266
 
 
267
 
    If you don't provide a name, the mangled name of the property is used.
268
 
 
269
 
    >>> class CachedPropertyTest(object):
270
 
    ...
271
 
    ...     @cachedproperty('_foo_cache')
272
 
    ...     def foo(self):
273
 
    ...         print 'foo computed'
274
 
    ...         return 23
275
 
    ...
276
 
    ...     @cachedproperty
277
 
    ...     def bar(self):
278
 
    ...         print 'bar computed'
279
 
    ...         return 69
280
 
 
281
 
    >>> cpt = CachedPropertyTest()
282
 
    >>> getattr(cpt, '_foo_cache', None) is None
283
 
    True
284
 
    >>> cpt.foo
285
 
    foo computed
286
 
    23
287
 
    >>> cpt.foo
288
 
    23
289
 
    >>> cpt._foo_cache
290
 
    23
291
 
    >>> cpt.bar
292
 
    bar computed
293
 
    69
294
 
    >>> cpt._bar_cached_value
295
 
    69
296
 
 
297
 
    """
298
 
    if isinstance(attrname_or_fn, basestring):
299
 
        attrname = attrname_or_fn
300
 
        return _CachedPropertyForAttr(attrname)
301
 
    else:
302
 
        fn = attrname_or_fn
303
 
        attrname = '_%s_cached_value' % fn.__name__
304
 
        return _CachedProperty(attrname, fn)
305
 
 
306
 
 
307
 
class _CachedPropertyForAttr(object):
308
 
 
309
 
    def __init__(self, attrname):
310
 
        self.attrname = attrname
311
 
 
312
 
    def __call__(self, fn):
313
 
        return _CachedProperty(self.attrname, fn)
314
 
 
315
 
 
316
 
class _CachedProperty(object):
317
 
 
318
 
    def __init__(self, attrname, fn):
319
 
        self.fn = fn
320
 
        self.attrname = attrname
321
 
        self.marker = object()
322
 
 
323
 
    def __get__(self, inst, cls=None):
324
 
        if inst is None:
325
 
            return self
326
 
        cachedresult = getattr(inst, self.attrname, self.marker)
327
 
        if cachedresult is self.marker:
328
 
            result = self.fn(inst)
329
 
            setattr(inst, self.attrname, result)
330
 
            return result
331
 
        else:
332
 
            return cachedresult