summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2011-11-01 08:58:05 -0400
committerSimo Sorce <ssorce@redhat.com>2012-01-11 12:04:22 -0500
commit40a8ecf28c6192e20c837f8ead836885b1b1147c (patch)
treedb174fdd5ef15f71b0f4aed5f374f17c30e3ec32 /ipalib
parent18fa8baded287fd7c811eb3e60e065e2d2d5f776 (diff)
downloadfreeipa.git-40a8ecf28c6192e20c837f8ead836885b1b1147c.tar.gz
freeipa.git-40a8ecf28c6192e20c837f8ead836885b1b1147c.tar.xz
freeipa.git-40a8ecf28c6192e20c837f8ead836885b1b1147c.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 dc3119d9..6f2f7deb 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 5b634880..f115f0c4 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 ffa27594..d575329e 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")