Package openid :: Package yadis :: Module filters
[frames] | no frames]

Source Code for Module openid.yadis.filters

  1  """This module contains functions and classes used for extracting 
  2  endpoint information out of a Yadis XRD file using the ElementTree XML 
  3  parser. 
  4  """ 
  5   
  6  __all__ = [ 
  7      'BasicServiceEndpoint', 
  8      'mkFilter', 
  9      'IFilter', 
 10      'TransformFilterMaker', 
 11      'CompoundFilter', 
 12      ] 
 13   
 14  from openid.yadis.etxrd import expandService 
 15   
16 -class BasicServiceEndpoint(object):
17 """Generic endpoint object that contains parsed service 18 information, as well as a reference to the service element from 19 which it was generated. If there is more than one xrd:Type or 20 xrd:URI in the xrd:Service, this object represents just one of 21 those pairs. 22 23 This object can be used as a filter, because it implements 24 fromBasicServiceEndpoint. 25 26 The simplest kind of filter you can write implements 27 fromBasicServiceEndpoint, which takes one of these objects. 28 """
29 - def __init__(self, yadis_url, type_uris, uri, service_element):
30 self.type_uris = type_uris 31 self.yadis_url = yadis_url 32 self.uri = uri 33 self.service_element = service_element
34
35 - def matchTypes(self, type_uris):
36 """Query this endpoint to see if it has any of the given type 37 URIs. This is useful for implementing other endpoint classes 38 that e.g. need to check for the presence of multiple versions 39 of a single protocol. 40 41 @param type_uris: The URIs that you wish to check 42 @type type_uris: iterable of str 43 44 @return: all types that are in both in type_uris and 45 self.type_uris 46 """ 47 return [uri for uri in type_uris if uri in self.type_uris]
48
49 - def fromBasicServiceEndpoint(endpoint):
50 """Trivial transform from a basic endpoint to itself. This 51 method exists to allow BasicServiceEndpoint to be used as a 52 filter. 53 54 If you are subclassing this object, re-implement this function. 55 56 @param endpoint: An instance of BasicServiceEndpoint 57 @return: The object that was passed in, with no processing. 58 """ 59 return endpoint
60 61 fromBasicServiceEndpoint = staticmethod(fromBasicServiceEndpoint)
62
63 -class IFilter(object):
64 """Interface for Yadis filter objects. Other filter-like things 65 are convertable to this class.""" 66
67 - def getServiceEndpoints(self, yadis_url, service_element):
68 """Returns an iterator of endpoint objects""" 69 raise NotImplementedError
70
71 -class TransformFilterMaker(object):
72 """Take a list of basic filters and makes a filter that transforms 73 the basic filter into a top-level filter. This is mostly useful 74 for the implementation of mkFilter, which should only be needed 75 for special cases or internal use by this library. 76 77 This object is useful for creating simple filters for services 78 that use one URI and are specified by one Type (we expect most 79 Types will fit this paradigm). 80 81 Creates a BasicServiceEndpoint object and apply the filter 82 functions to it until one of them returns a value. 83 """ 84
85 - def __init__(self, filter_functions):
86 """Initialize the filter maker's state 87 88 @param filter_functions: The endpoint transformer functions to 89 apply to the basic endpoint. These are called in turn 90 until one of them does not return None, and the result of 91 that transformer is returned. 92 """ 93 self.filter_functions = filter_functions
94
95 - def getServiceEndpoints(self, yadis_url, service_element):
96 """Returns an iterator of endpoint objects produced by the 97 filter functions.""" 98 endpoints = [] 99 100 # Do an expansion of the service element by xrd:Type and xrd:URI 101 for type_uris, uri, _ in expandService(service_element): 102 103 # Create a basic endpoint object to represent this 104 # yadis_url, Service, Type, URI combination 105 endpoint = BasicServiceEndpoint( 106 yadis_url, type_uris, uri, service_element) 107 108 e = self.applyFilters(endpoint) 109 if e is not None: 110 endpoints.append(e) 111 112 return endpoints
113
114 - def applyFilters(self, endpoint):
115 """Apply filter functions to an endpoint until one of them 116 returns non-None.""" 117 for filter_function in self.filter_functions: 118 e = filter_function(endpoint) 119 if e is not None: 120 # Once one of the filters has returned an 121 # endpoint, do not apply any more. 122 return e 123 124 return None
125
126 -class CompoundFilter(object):
127 """Create a new filter that applies a set of filters to an endpoint 128 and collects their results. 129 """
130 - def __init__(self, subfilters):
131 self.subfilters = subfilters
132
133 - def getServiceEndpoints(self, yadis_url, service_element):
134 """Generate all endpoint objects for all of the subfilters of 135 this filter and return their concatenation.""" 136 endpoints = [] 137 for subfilter in self.subfilters: 138 endpoints.extend( 139 subfilter.getServiceEndpoints(yadis_url, service_element)) 140 return endpoints
141 142 # Exception raised when something is not able to be turned into a filter 143 filter_type_error = TypeError( 144 'Expected a filter, an endpoint, a callable or a list of any of these.') 145
146 -def mkFilter(parts):
147 """Convert a filter-convertable thing into a filter 148 149 @param parts: a filter, an endpoint, a callable, or a list of any of these. 150 """ 151 # Convert the parts into a list, and pass to mkCompoundFilter 152 if parts is None: 153 parts = [BasicServiceEndpoint] 154 155 try: 156 parts = list(parts) 157 except TypeError: 158 return mkCompoundFilter([parts]) 159 else: 160 return mkCompoundFilter(parts)
161
162 -def mkCompoundFilter(parts):
163 """Create a filter out of a list of filter-like things 164 165 Used by mkFilter 166 167 @param parts: list of filter, endpoint, callable or list of any of these 168 """ 169 # Separate into a list of callables and a list of filter objects 170 transformers = [] 171 filters = [] 172 for subfilter in parts: 173 try: 174 subfilter = list(subfilter) 175 except TypeError: 176 # If it's not an iterable 177 if hasattr(subfilter, 'getServiceEndpoints'): 178 # It's a full filter 179 filters.append(subfilter) 180 elif hasattr(subfilter, 'fromBasicServiceEndpoint'): 181 # It's an endpoint object, so put its endpoint 182 # conversion attribute into the list of endpoint 183 # transformers 184 transformers.append(subfilter.fromBasicServiceEndpoint) 185 elif callable(subfilter): 186 # It's a simple callable, so add it to the list of 187 # endpoint transformers 188 transformers.append(subfilter) 189 else: 190 raise filter_type_error 191 else: 192 filters.append(mkCompoundFilter(subfilter)) 193 194 if transformers: 195 filters.append(TransformFilterMaker(transformers)) 196 197 if len(filters) == 1: 198 return filters[0] 199 else: 200 return CompoundFilter(filters)
201