diff options
author | Jan Cholasta <jcholast@redhat.com> | 2011-11-01 08:58:05 -0400 |
---|---|---|
committer | Alexander Bokovoy <abokovoy@redhat.com> | 2012-01-02 11:51:26 +0300 |
commit | 9beb467d98cb16e09fcda5ebbeb27056dfff3a2d (patch) | |
tree | d374273454f5fa5627eb1fe83782c437cdbddde2 /ipalib/util.py | |
parent | 46d3abc450db20c3e4c0854dbf9e711f59db3bff (diff) | |
download | freeipa-9beb467d98cb16e09fcda5ebbeb27056dfff3a2d.tar.gz freeipa-9beb467d98cb16e09fcda5ebbeb27056dfff3a2d.tar.xz freeipa-9beb467d98cb16e09fcda5ebbeb27056dfff3a2d.zip |
Fix attempted write to attribute of read-only object.
Add new class "cachedproperty" for creating property-like attributes
that cache the return value of a method call.
Also fix few issues in the unit tests to enable them to succeed.
ticket 1959
Diffstat (limited to 'ipalib/util.py')
-rw-r--r-- | ipalib/util.py | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/ipalib/util.py b/ipalib/util.py index ffa275942..d575329e7 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -27,6 +27,7 @@ import time import socket import re from types import NoneType +from weakref import WeakKeyDictionary from ipalib import errors from ipalib.text import _ @@ -272,3 +273,36 @@ def validate_hostname(hostname): if not all(regex_name.match(part) for part in hostname.split(".")): raise ValueError(_('hostname parts may only include letters, numbers, and - ' \ '(which is not allowed as the last character)')) + +class cachedproperty(object): + """ + A property-like attribute that caches the return value of a method call. + + When the attribute is first read, the method is called and its return + value is saved and returned. On subsequent reads, the saved value is + returned. + + Typical usage: + class C(object): + @cachedproperty + def attr(self): + return 'value' + """ + __slots__ = ('getter', 'store') + + def __init__(self, getter): + self.getter = getter + self.store = WeakKeyDictionary() + + def __get__(self, obj, cls): + if obj is None: + return None + if obj not in self.store: + self.store[obj] = self.getter(obj) + return self.store[obj] + + def __set__(self, obj, value): + raise AttributeError("can't set attribute") + + def __delete__(self, obj): + raise AttributeError("can't delete attribute") |