summaryrefslogtreecommitdiffstats
path: root/ipalib/plugable.py
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-08-09 04:35:06 +0000
committerJason Gerard DeRose <jderose@redhat.com>2008-08-09 04:35:06 +0000
commit72f3132d2b98a44881ae7001d0001602a66bf8b5 (patch)
treed75ce61572ba4d18fcc746583f911f150e1c968a /ipalib/plugable.py
parent3495c67d57868a02bafe6f1935d4846cd5615bf5 (diff)
downloadfreeipa.git-72f3132d2b98a44881ae7001d0001602a66bf8b5.tar.gz
freeipa.git-72f3132d2b98a44881ae7001d0001602a66bf8b5.tar.xz
freeipa.git-72f3132d2b98a44881ae7001d0001602a66bf8b5.zip
95: Improved docstrings for ReadOnly class; added ReadOnly.__islocked__() method; added corresponding unit tests
Diffstat (limited to 'ipalib/plugable.py')
-rw-r--r--ipalib/plugable.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index c5ec08ec..4ce4a9ba 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -39,6 +39,39 @@ def check_identifier(name):
class ReadOnly(object):
"""
Base class for classes with read-only attributes.
+
+ Be forewarned that Python does not offer true read-only user defined
+ classes. In particular, do not rely upon the read-only-ness of this
+ class for security purposes.
+
+ The point of this class is not to make it impossible to set or delete
+ attributes, but do make it impossible to accidentally do so. The plugins
+ are not thread-safe: in the server, they are loaded once and the same
+ instances will be used to process many requests. Therefore, it is
+ imperative that they not set any instance attributes after they have
+ been initialized. This base class enforces that policy.
+
+ For example:
+
+ >>> class givenName(ReadOnly):
+ >>> def __init__(self):
+ >>> self.whatever = 'some value' # Hasn't been locked yet
+ >>> self.__lock__()
+ >>>
+ >>> def finalize(self, api):
+ >>> # After the instance has been locked, attributes can still be
+ >>> # set, but only in a round-about, unconventional way:
+ >>> object.__setattr__(self, 'api', api)
+ >>>
+ >>> def normalize(self, value):
+ >>> # After the instance has been locked, trying to set an
+ >>> # attribute in the normal way will raise AttributeError.
+ >>> self.value = value # Not thread safe!
+ >>> return self.actually_normalize()
+ >>>
+ >>> def actually_normalize(self):
+ >>> # Again, this is not thread safe:
+ >>> return unicode(self.value).strip()
"""
__locked = False
@@ -50,6 +83,12 @@ class ReadOnly(object):
assert self.__locked is False, '__lock__() can only be called once'
self.__locked = True
+ def __islocked__(self):
+ """
+ Returns True if this instance is locked, False otherwise.
+ """
+ return self.__locked
+
def __setattr__(self, name, value):
"""
Raises an AttributeError if ReadOnly.__lock__() has already been called;