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 | |
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')
-rw-r--r-- | ipalib/dn.py | 2 | ||||
-rw-r--r-- | ipalib/errors.py | 6 | ||||
-rw-r--r-- | ipalib/util.py | 34 |
3 files changed, 38 insertions, 4 deletions
diff --git a/ipalib/dn.py b/ipalib/dn.py index dc3119d9a..6f2f7deb5 100644 --- a/ipalib/dn.py +++ b/ipalib/dn.py @@ -1092,7 +1092,7 @@ class DN(object): return rdns elif isinstance(value, (tuple, list)): if len(value) != 2: - raise ValueError("tuple or list must be 2-valued, not \"%s\"" % (rdn)) + raise ValueError("tuple or list must be 2-valued, not \"%s\"" % (value)) rdn = RDN(value, first_key_match=self.first_key_match) return rdn else: diff --git a/ipalib/errors.py b/ipalib/errors.py index 5b634880d..f115f0c4e 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -448,10 +448,10 @@ class RefererError(PublicError): For example: - >>> raise RefererError() + >>> raise RefererError(referer='referer') Traceback (most recent call last): ... - RefererError: Missing or invalid HTTP Referer + RefererError: Missing or invalid HTTP Referer, referer """ errno = 911 @@ -1537,7 +1537,7 @@ class DependentEntry(ExecutionError): >>> raise DependentEntry(label=u'SELinux User Map', key=u'test', dependent=u'test1') Traceback (most recent call last): ... - DependentEntry: Not registered yet + DependentEntry: test cannot be deleted because SELinux User Map test1 requires it """ 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") |