summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2011-11-01 08:58:05 -0400
committerAlexander Bokovoy <abokovoy@redhat.com>2012-01-02 11:51:26 +0300
commit9beb467d98cb16e09fcda5ebbeb27056dfff3a2d (patch)
treed374273454f5fa5627eb1fe83782c437cdbddde2 /ipalib
parent46d3abc450db20c3e4c0854dbf9e711f59db3bff (diff)
downloadfreeipa-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.py2
-rw-r--r--ipalib/errors.py6
-rw-r--r--ipalib/util.py34
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")