[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Security - Settings.py:1.1.2.6
Steve Alexander
steve@cat-box.net
Wed, 20 Mar 2002 17:50:57 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/Security
In directory cvs.zope.org:/tmp/cvs-serv7531
Modified Files:
Tag: Zope-3x-branch
Settings.py
Log Message:
Reimplemented symbolic constants class for security settings.
Added test to check that a setting retains its identity on pickling
and unpickling.
=== Zope3/lib/python/Zope/App/Security/Settings.py 1.1.2.5 => 1.1.2.6 ===
""" Security setting constants """
-# PermissionSettingMetaClass and PermissionSetting function together to produce
-# typed constants. These constants (such as Allow, Deny, etc. below) can be
-# compared by identity, even when pickled and unpickled. This is because they
-# are stored in pickles just as the fully-qualified names of the classes
-# we're using for the constants.
-#
-# Methods and properties for PermissionSetting classes are set in the
-# PermissionSettingMetaClass. See _setDescription and getDescription
-# for an example.
-#
-# Except in the case of __str__ and __repr__, adding a method to the
-# metaclass is equivalent to adding a classmethod to the class.
-# So, _setDescription and getDescription could have been added
-# to PermissionSetting as classmethods.
-
-class PermissionSettingMetaClass(type):
- def __init__(self, name, bases, namespace):
- type.__init__(self, name, bases, namespace)
- self._name=name
-
- def __str__(self):
- return "PermissionSetting: %s" % self._name
-
- def _setDescription(self, description):
- self._description=description
+
+class PermissionSetting(object):
+ """PermissionSettings should be considered as immutable.
+ They can be compared by identity. They are identified by
+ their name.
+ """
+
+ def __new__(cls, name, description=None):
+ """Keep a dict of PermissionSetting instances, indexed by
+ name. If the name already exists in the dict, return that
+ instance rather than creating a new one.
+ """
+ instances = cls.__dict__.get('__instances__')
+ if instances is None:
+ cls.__instances__ = instances = {}
+ it = instances.get(name)
+ if it is None:
+ instances[name] = it = object.__new__(cls)
+ it._init(name, description)
+ return it
+
+ def _init(self, name, description):
+ self.__name = name
+ self.__description = description
def getDescription(self):
- return self._description
-
-class PermissionSetting(object):
- __metaclass__=PermissionSettingMetaClass
- def __init__(self):
- raise TypeError, "Cannot instantiate PermissionSetting objects"
+ return self.__description
+
+ def getName(self):
+ return self.__name
+
+ def __str__(self):
+ return "PermissionSetting: %s" % self.__name
+# register PermissionSettings to be symbolic constants by identity,
+# even when pickled and unpickled.
+import copy_reg
+copy_reg.constructor(PermissionSetting)
+copy_reg.pickle(PermissionSetting,
+ PermissionSetting.getName,
+ PermissionSetting)
-class Allow(PermissionSetting): pass
-Allow._setDescription('Explicit allow setting for permissions')
+
+Allow = PermissionSetting('Allow',
+ 'Explicit allow setting for permissions')
-class Deny(PermissionSetting): pass
-Deny._setDescription('Explicit deny setting for permissions')
+Deny = PermissionSetting('Deny',
+ 'Explicit deny setting for permissions')
-class Unset(PermissionSetting): pass
-Unset._setDescription(
- 'Unset constant that denotes no setting for permission and role')
+Unset = PermissionSetting('Unset',
+ 'Unset constant that denotes no setting for permission and role')
-class Assign(PermissionSetting): pass
-Assign._setDescription('Explicit assign setting for roles')
+Assign = PermissionSetting('Assign',
+ 'Explicit assign setting for roles')
-class Remove(PermissionSetting): pass
-Remove._setDescription('Explicit remove setting for roles')
+Remove = PermissionSetting('Remove',
+ 'Explicit remove setting for roles')