95: Improved docstrings for ReadOnly class; added ReadOnly.__islocked__() method; added corresponding unit tests

This commit is contained in:
Jason Gerard DeRose
2008-08-09 04:35:06 +00:00
parent 3495c67d57
commit 72f3132d2b
2 changed files with 51 additions and 0 deletions

View File

@@ -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;

View File

@@ -62,6 +62,18 @@ class test_ReadOnly(ClassChecker):
def test_class(self):
assert self.cls.__bases__ == (object,)
assert callable(self.cls.__lock__)
assert callable(self.cls.__islocked__)
def test_lock(self):
"""
Tests the `__lock__` and `__islocked__` methods.
"""
o = self.cls()
assert o.__islocked__() is False
o.__lock__()
assert o.__islocked__() is True
raises(AssertionError, o.__lock__) # Can only be locked once
assert o.__islocked__() is True # This should still be True
def test_when_unlocked(self):
"""