~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/decorators.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-17 17:11:16 UTC
  • mfrom: (4797.2.17 2.1)
  • mto: (4797.2.18 2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: john@arbash-meinel.com-20100217171116-h7t9223ystbnx5h8
merge bzr.2.1 in preparation for NEWS entry.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
253
253
    global needs_read_lock, needs_write_lock
254
254
    needs_read_lock = _pretty_needs_read_lock
255
255
    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