source: TI12-security/trunk/NDG_XACML/ndg/xacml/utils/__init__.py @ 7072

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDG_XACML/ndg/xacml/utils/__init__.py@7072
Revision 7072, 6.0 KB checked in by pjkersha, 9 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • Major cleanup of function factories for efficiency. Only the required factories and function classes are loaded and any loaded classes are cached for future calls. All unit tests pass.
  • Property svn:keywords set to Id
Line 
1"""Utilities package for NDG XACML
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
16class UniqList(list):
17    """Extended version of list type to enable a list with unique items.
18    If an item is added that is already present then it is silently omitted
19    from the list
20    """
21    def extend(self, iter):
22        return super(UniqList, self).extend([i for i in iter if i not in self])
23       
24    def __iadd__(self, iter):
25        return super(UniqList, self).__iadd__([i for i in iter 
26                                               if i not in self])
27         
28    def append(self, item):
29        for i in self:
30            if i == item:
31                return None
32           
33        return super(UniqList, self).append(item)
34
35
36class TypedList(list):
37    """Extend list type to enabled only items of a given type.  Supports
38    any type where the array type in the Standard Library is restricted to
39    only limited set of primitive types
40    """
41   
42    def __init__(self, elementType, *arg, **kw):
43        """
44        @type elementType: type/tuple
45        @param elementType: object type or types which the list is allowed to
46        contain.  If more than one type, pass as a tuple
47        """
48        self.__elementType = elementType
49        super(TypedList, self).__init__(*arg, **kw)
50
51    def __repr__(self):
52        return "%r type: %s" % (self.__elementType, 
53                                super(TypedList, self).__repr__())
54       
55    def _getElementType(self):
56        return self.__elementType
57   
58    elementType = property(fget=_getElementType, 
59                           doc="The allowed type or types for list elements")
60     
61    def extend(self, iter):
62        for i in iter:
63            if not isinstance(i, self.__elementType):
64                raise TypeError("List items must be of type %s" % 
65                                (self.__elementType,))
66               
67        return super(TypedList, self).extend(iter)
68       
69    def __iadd__(self, iter):
70        for i in iter:
71            if not isinstance(i, self.__elementType):
72                raise TypeError("List items must be of type %s" % 
73                                (self.__elementType,))
74                   
75        return super(TypedList, self).__iadd__(iter)
76         
77    def append(self, item):
78        if not isinstance(item, self.__elementType):
79                raise TypeError("List items must be of type %s" % 
80                                (self.__elementType,))
81   
82        return super(TypedList, self).append(item)
83
84
85class RestrictedKeyNamesDict(dict):
86    """Utility class for holding a constrained list of key names
87    """
88   
89    def __init__(self, *arg, **kw):
90        """Alter standard dict() initialisation to fix key names set at
91        initialisation
92        """
93        super(RestrictedKeyNamesDict, self).__init__(*arg, **kw)
94        self.__keyNames = self.keys() 
95         
96    def __setitem__(self, key, val):
97        if key not in self.__keyNames:
98            raise KeyError('Key name %r not recognised.  Valid key names '
99                           'are: %r' % (key, self.__keyNames))
100           
101        dict.__setitem__(self, key, val)
102
103    def update(self, d, **kw):       
104        for dictArg in (d, kw):
105            for k in dictArg:
106                if k not in self.__keyNames:
107                    raise KeyError('Key name "%s" not recognised.  Valid '
108                                   'key names are: %s' % 
109                                   self.__keyNames)
110       
111        dict.update(self, d, **kw)
112       
113
114_isIterable = lambda obj: getattr(obj, '__iter__', False)
115
116 
117class VettedDict(UserDict.DictMixin):
118    """Enforce custom checking on keys and items before addition to a
119    dictionary"""
120   
121    def __init__(self, *args):
122        """Initialise setting the allowed type or types for keys and items
123       
124        @param args: two arguments: the first is a callable which filters for
125        permissable keys in this dict, the second sets the type or list of
126        types permissable for items in this dict
127        @type args: tuple
128        """
129        if len(args) != 2:
130            raise TypeError('__init__() takes 2 arguments, KeyFilter and '
131                            'valueFilter (%d given)' % len(args))
132       
133        # Validation of inputs
134        for arg, argName in zip(args, ('KeyFilter', 'valueFilter')):
135            if not callable(arg):
136                raise TypeError('Expecting callable for %r input; got %r' % 
137                                (argName, type(arg)))
138
139        self.__KeyFilter, self.__valueFilter = args
140       
141        self.__map = {}
142       
143    def _verifyKeyValPair(self, key, val):
144        """Check given key value pair and return False if they should be
145        filtered out.  Filter functions may also raise an exception if they
146        wish to abort completely
147        """
148        if not self.__KeyFilter(key):
149            return False
150       
151        elif not self.__valueFilter(val):
152            return False
153       
154        else:
155            return True
156                 
157    def __setitem__(self, key, val):
158        """Enforce type checking when setting new items"""       
159        if self._verifyKeyValPair(key, val):
160            self.__map[key] = val
161
162    def __getitem__(self, key):
163        """Provde implementation for getting items"""
164        if key not in self.__map:
165            raise KeyError('%r key not found in dict' % key)
166       
167        return self.__map[key]
168   
169    def get(self, key, *arg):
170        """Provide implementation of get item with default"""
171        if key in self.__map:
172            return self.__map[key]
173       
174        elif len(arg) > 1:
175            # Default value set
176            return arg[1]
177        else:
178            return None
179           
180
181   
Note: See TracBrowser for help on using the repository browser.