def __call__(self, *credential, **payload): """Perform the RPC call while following CCP's caching guidelines.""" if len(credential) > 1: raise Exception("The only positional parameter allowed is the credentials object.") now = datetime.utcnow() uri = self.uri(self.name) # Define the keyID/vCode API key arguments, if we have credentials. if credential: payload['keyID'] = credential[0].key payload['vCode'] = credential[0].code # Hash the arguments in a reliable way by converting to text in a way which sorts the keys. payload_hash = sha256(EnhancedBencode().encode(payload)).hexdigest() # Examine the cache. cv = CachedAPIValue.objects( key = payload.get('keyID', None), name = self.name, arguments = payload_hash, expires__gte = now ).first() if cv and cv.current: log.info("Returning cached result of %s for key ID %d.", self.name, payload.get('keyID', -1)) return bunchify_lite(cv.result) log.info("Making query to %s for key ID %d.", self.name, payload.get('keyID', -1)) # Actually perform the query if a cached version could not be found. response = requests.post(uri, data=payload or None) response.raise_for_status() # We don't want the initial XML prefix. We should still check it, though. prefix, _, data = response.text.partition('\n') if prefix.strip() != "<?xml version='1.0' encoding='UTF-8'?>": raise Exception("Data returned doesn't seem to be XML!") data = xml(data)['eveapi'] result = bunchify(data['result'], 'result') data = Bunch(data) if len(result) == 1: result = getattr(result, result.keys()[0]) # Upsert (update if exists, create if it doesn't) the cache value. CachedAPIValue.objects( key = payload.get('keyID', None), name = self.name, arguments = payload_hash ).update_one( upsert = True, set__expires = datetime.strptime(data.cachedUntil, "%Y-%m-%d %H:%M:%S"), set__result = result ) return result
def convert(self, content, conversion): """Convert content to Python data structures.""" if not conversion: data = content elif self.format == 'json': data = json.loads(content) elif self.format == 'xml': content = xml(content) first = content.keys()[0] data = content[first] else: data = content return data
def get(self, call, **kwargs): from newauth.models import APIKey, db cache_key = hash((self.base, call, frozenset(kwargs))) cached_data = redis.get(cache_key) if cached_data: cached_data = cPickle.loads(cached_data) if arrow.utcnow() < cached_data[0]: return cached_data[1] try: req = self.session.get(self.base + call + '.xml.aspx', params=kwargs) req.raise_for_status() except requests.exceptions.RequestException as e: raise e if req.status_code != 200: if req.status_code == requests.codes['not_found']: raise Exception( "{} is not available on the API server (404)".format( call.value)) elif req.status_code == requests.codes['forbidden']: if self.api_key and self.api_key.id: self.api_key.disabled = True db.session.add(self.api_key) db.session.commit() raise AuthenticationException(self.key_id) else: raise Exception("Eve API server exception.") request_data = req.text prefix, _, data = req.text.partition('\n') if prefix.strip() != "<?xml version='1.0' encoding='UTF-8'?>": raise Exception("Data returned doesn't seem to be XML!") if isinstance(data, unicode): data = data.encode('UTF-8') data = xml(data)['eveapi'] result = bunchify(data['result'], 'result') data = Bunch(data) if len(result) == 1: result = getattr(result, result.keys())[0] redis.set(cache_key, cPickle.dumps((arrow.get(data.cachedUntil), result), -1)) return result
def home(): """Render website's home page.""" if request.method == 'POST': files = request.form.items() try: # Not sure why Flask is splitting them apart? data = '='.join(files[0]) except: return 'No file received.' try: content = xml(data) except Exception as error: content = {"error": str(error)} json = dumps(content) if 'X-callback' in request.headers: callback = request.headers['X-callback'] req.post(callback, data=json) return json return render_template('home.html')
def get(self, call, **kwargs): from newauth.models import APIKey, db cache_key = hash((self.base, call, frozenset(kwargs))) cached_data = redis.get(cache_key) if cached_data: cached_data = cPickle.loads(cached_data) if arrow.utcnow() < cached_data[0]: return cached_data[1] try: req = self.session.get(self.base + call + '.xml.aspx', params=kwargs) req.raise_for_status() except requests.exceptions.RequestException as e: raise e if req.status_code != 200: if req.status_code == requests.codes['not_found']: raise Exception("{} is not available on the API server (404)".format(call.value)) elif req.status_code == requests.codes['forbidden']: if self.api_key and self.api_key.id: self.api_key.disabled = True db.session.add(self.api_key) db.session.commit() raise AuthenticationException(self.key_id) else: raise Exception("Eve API server exception.") request_data = req.text prefix, _, data = req.text.partition('\n') if prefix.strip() != "<?xml version='1.0' encoding='UTF-8'?>": raise Exception("Data returned doesn't seem to be XML!") if isinstance(data, unicode): data = data.encode('UTF-8') data = xml(data)['eveapi'] result = bunchify(data['result'], 'result') data = Bunch(data) if len(result) == 1: result = getattr(result, result.keys())[0] redis.set(cache_key, cPickle.dumps((arrow.get(data.cachedUntil), result), -1)) return result
def discovery(self, url=None): """ Retrieve the standard discovery file that provides routing information. >>> Three().discovery() {'discovery': 'data'} """ if url: data = self.session.get(url).content elif self.discovery_url: response = self.session.get(self.discovery_url) if self.format == 'xml': # Because, SF doesn't follow the spec. data = xml(response.text) else: # Spec calls for discovery always allowing JSON. data = response.json() else: data = self.get('discovery') return data
def discovery(self, url=None): """ Retrieve the standard discovery file that provides routing information. >>> Three().discovery() {'discovery': 'data'} """ if url: data = requests.get(url).content elif self.discovery_url: response = requests.get(self.discovery_url) if self.format == 'xml': # Because, SF doesn't follow the spec. data = xml(response.text) else: # Spec calls for discovery always allowing JSON. data = response.json() else: data = self.get('discovery') return data
from relaxml import xml import requests as req url='http:export.yandex.ru/weather-ng/forecasts/26686.xml' content = req.get(url).text print content print xml(content)
def _output(self, content): """Return the output from a given GET request.""" if self.xml: return content return xml(content)