source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/utils/__init__.py @ 7314

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/utils/__init__.py@7314
Revision 7314, 6.6 KB checked in by pjkersha, 10 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • significant progress on PIP - can init from config file and added unit tests
  • Property svn:keywords set to Id
Line 
1"""Utilities package for NDG Security
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "02/04/09"
7__copyright__ = ""
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = '$Id$'
11import UserDict
12
13# Interpret a string as a boolean
14str2Bool = lambda str: str.lower() in ("yes", "true", "t", "1")
15
16
17class UniqList(list):
18    """Extended version of list type to enable a list with unique items.
19    If an item is added that is already present then it is silently omitted
20    from the list
21    """
22    def extend(self, iter):
23        return super(UniqList, self).extend([i for i in iter if i not in self])
24       
25    def __iadd__(self, iter):
26        return super(UniqList, self).__iadd__([i for i in iter 
27                                               if i not in self])
28         
29    def append(self, item):
30        for i in self:
31            if i == item:
32                return None
33           
34        return super(UniqList, self).append(item)
35
36
37class TypedList(list):
38    """Extend list type to enabled only items of a given type.  Supports
39    any type where the array type in the Standard Library is restricted to
40    only limited set of primitive types
41    """
42   
43    def __init__(self, elementType, *arg, **kw):
44        """
45        @type elementType: type/tuple
46        @param elementType: object type or types which the list is allowed to
47        contain.  If more than one type, pass as a tuple
48        """
49        self.__elementType = elementType
50        super(TypedList, self).__init__(*arg, **kw)
51   
52    def _getElementType(self):
53        return self.__elementType
54   
55    elementType = property(fget=_getElementType, 
56                           doc="The allowed type or types for list elements")
57     
58    def extend(self, iter):
59        for i in iter:
60            if not isinstance(i, self.__elementType):
61                raise TypeError("List items must be of type %s" % 
62                                (self.__elementType,))
63               
64        return super(TypedList, self).extend(iter)
65       
66    def __iadd__(self, iter):
67        for i in iter:
68            if not isinstance(i, self.__elementType):
69                raise TypeError("List items must be of type %s" % 
70                                (self.__elementType,))
71                   
72        return super(TypedList, self).__iadd__(iter)
73         
74    def append(self, item):
75        if not isinstance(item, self.__elementType):
76                raise TypeError("List items must be of type %s" % 
77                                (self.__elementType,))
78   
79        return super(TypedList, self).append(item)
80
81class RestrictedKeyNamesDict(dict):
82    """Utility class for holding a constrained list of key names
83    """
84   
85    def __init__(self, *arg, **kw):
86        """Alter standard dict() initialisation to fix key names set at
87        initialisation
88        """
89        super(RestrictedKeyNamesDict, self).__init__(*arg, **kw)
90        self.__keyNames = self.keys() 
91         
92    def __setitem__(self, key, val):
93        if key not in self.__keyNames:
94            raise KeyError('Key name %r not recognised.  Valid key names '
95                           'are: %r' % (key, self.__keyNames))
96           
97        dict.__setitem__(self, key, val)
98
99    def update(self, d, **kw):       
100        for dictArg in (d, kw):
101            for k in dictArg:
102                if k not in self.__keyNames:
103                    raise KeyError('Key name "%s" not recognised.  Valid '
104                                   'key names are: %s' % 
105                                   self.__keyNames)
106       
107        dict.update(self, d, **kw)
108       
109 
110class VettedDict(UserDict.DictMixin):
111    """Enforce custom checking on keys and items before addition to a
112    dictionary
113    """
114   
115    def __init__(self, *args):
116        """Initialise setting the allowed type or types for keys and items
117       
118        @param args: two arguments: the first is a callable which filters for
119        permissable keys in this dict, the second sets the type or list of
120        types permissable for items in this dict
121        @type args: tuple
122        """
123        if len(args) != 2:
124            raise TypeError('__init__() takes 2 arguments, KeyFilter and '
125                            'valueFilter (%d given)' % len(args))
126       
127        # Validation of inputs
128        for arg, argName in zip(args, ('KeyFilter', 'valueFilter')):
129            if not callable(arg):
130                raise TypeError('Expecting callable for %r input; got %r' % 
131                                (argName, type(arg)))
132
133        self.__KeyFilter, self.__valueFilter = args
134       
135        self.__map = {}
136       
137    def _verifyKeyValPair(self, key, val):
138        """Check given key value pair and return False if they should be
139        filtered out.  Filter functions may also raise an exception if they
140        wish to abort completely
141       
142        @param key: dict key to check
143        @type key: basestring
144        @param val: value to check
145        @type val: any
146        """
147        if not self.__KeyFilter(key):
148            return False
149       
150        elif not self.__valueFilter(val):
151            return False
152       
153        else:
154            return True
155                 
156    def __setitem__(self, key, val):
157        """Enforce type checking when setting new items
158       
159        @param key: key for item to set
160        @type key: any
161        @param val: value to set for this key
162        @type val: any
163        """       
164        if self._verifyKeyValPair(key, val):
165            self.__map[key] = val
166
167    def __getitem__(self, key):
168        """Provide implementation for getting items
169        @param key: key for item to retrieve
170        @type key: any
171        @return: value for input key
172        @rtype: any
173        """
174        if key not in self.__map:
175            raise KeyError('%r key not found in dict' % key)
176       
177        return self.__map[key]
178   
179    def get(self, key, *arg):
180        """Provide implementation of get item with default
181       
182        @param key: key for item to retrieve
183        @type key: any
184        @param arg: use to set a default argument
185        @type arg: tuple
186        """
187        if key in self.__map:
188            return self.__map[key]
189       
190        elif len(arg) > 1:
191            # Default value set
192            return arg[1]
193        else:
194            return None
195
196    def __repr__(self):
197        return repr(self.__map)
198   
199    def keys(self):
200        return self.__map.keys()
201   
202    def items(self):
203        return self.__map.items()
204   
205    def values(self):
206        return self.__map.values()
207   
208    def __contains__(self, val):
209        return self.__map.__contains__(val)
Note: See TracBrowser for help on using the repository browser.