1   
  2  """XRI resolution. 
  3  """ 
  4   
  5  from urllib import urlencode 
  6  from openid import fetchers 
  7  from openid.yadis import etxrd 
  8  from openid.yadis.xri import toURINormal 
  9  from openid.yadis.services import iterServices 
 10   
 11  DEFAULT_PROXY = 'http://proxy.xri.net/' 
 12   
 14      """Python interface to a remote XRI proxy resolver. 
 15      """ 
 17          self.proxy_url = proxy_url 
  18   
 19   
 20 -    def queryURL(self, xri, service_type=None): 
  21          """Build a URL to query the proxy resolver. 
 22   
 23          @param xri: An XRI to resolve. 
 24          @type xri: unicode 
 25   
 26          @param service_type: The service type to resolve, if you desire 
 27              service endpoint selection.  A service type is a URI. 
 28          @type service_type: str 
 29   
 30          @returns: a URL 
 31          @returntype: str 
 32          """ 
 33           
 34           
 35           
 36          qxri = toURINormal(xri)[6:] 
 37          hxri = self.proxy_url + qxri 
 38          args = { 
 39               
 40               
 41               
 42               
 43              '_xrd_r': 'application/xrds+xml', 
 44              } 
 45          if service_type: 
 46              args['_xrd_t'] = service_type 
 47          else: 
 48               
 49              args['_xrd_r'] += ';sep=false' 
 50          query = _appendArgs(hxri, args) 
 51          return query 
  52   
 53   
 54 -    def query(self, xri, service_types): 
  55          """Resolve some services for an XRI. 
 56   
 57          Note: I don't implement any service endpoint selection beyond what 
 58          the resolver I'm querying does, so the Services I return may well 
 59          include Services that were not of the types you asked for. 
 60   
 61          May raise fetchers.HTTPFetchingError or L{etxrd.XRDSError} if 
 62          the fetching or parsing don't go so well. 
 63   
 64          @param xri: An XRI to resolve. 
 65          @type xri: unicode 
 66   
 67          @param service_types: A list of services types to query for.  Service 
 68              types are URIs. 
 69          @type service_types: list of str 
 70   
 71          @returns: tuple of (CanonicalID, Service elements) 
 72          @returntype: (unicode, list of C{ElementTree.Element}s) 
 73          """ 
 74           
 75          services = [] 
 76           
 77           
 78           
 79   
 80          canonicalID = None 
 81   
 82          for service_type in service_types: 
 83              url = self.queryURL(xri, service_type) 
 84              response = fetchers.fetch(url) 
 85              if response.status not in (200, 206): 
 86                   
 87                   
 88                  continue 
 89              et = etxrd.parseXRDS(response.body) 
 90              canonicalID = etxrd.getCanonicalID(xri, et) 
 91              some_services = list(iterServices(et)) 
 92              services.extend(some_services) 
 93           
 94           
 95           
 96           
 97          return canonicalID, services 
   98   
 99   
101      """Append some arguments to an HTTP query. 
102      """ 
103       
104      if hasattr(args, 'items'): 
105          args = args.items() 
106          args.sort() 
107   
108      if len(args) == 0: 
109          return url 
110   
111       
112       
113       
114       
115       
116       
117   
118      if '?' in url.rstrip('?'): 
119          sep = '&' 
120      else: 
121          sep = '?' 
122   
123      return '%s%s%s' % (url, sep, urlencode(args)) 
 124