def request(self, method, url, headers, post_data=None): if six.PY3 and isinstance(post_data, six.string_types): post_data = post_data.encode('utf-8') req = urllib.request.Request(url, post_data, headers) if method not in ('get', 'post'): req.get_method = lambda: method.upper() try: # use the custom proxy tied opener, if any. # otherwise, fall to the default urllib opener. response = self._opener.open(req) \ if self._opener \ else urllib.request.urlopen(req) rbody = response.read() rcode = response.code headers = dict(response.info()) except urllib.error.HTTPError as e: rcode = e.code rbody = e.read() headers = dict(e.info()) except (urllib.error.URLError, ValueError) as e: self._handle_request_error(e) lh = dict((k.lower(), v) for k, v in six.iteritems(dict(headers))) return rbody, rcode, lh
def refresh_from(self, values, api_key=None, partial=False, last_response=None): self.api_key = api_key or getattr(values, 'api_key', None) self._last_response = last_response # Wipe old state before setting new. This is useful for e.g. # updating a customer, where there is no persistent card # parameter. Mark those values which don't persist as transient if partial: self._unsaved_values = (self._unsaved_values - set(values)) else: removed = set(self.keys()) - set(values) self._transient_values = self._transient_values | removed self._unsaved_values = set() self.clear() self._transient_values = self._transient_values - set(values) for k, v in six.iteritems(values): super(PingppObject, self).__setitem__(k, util.convert_to_pingpp_object(v, api_key)) self._previous = values
def __deepcopy__(self, memo): copied = self.__copy__() memo[id(self)] = copied for k, v in six.iteritems(self): super(PingppObject, copied).__setitem__(k, deepcopy(v, memo)) return copied
def __copy__(self): copied = PingppObject(self.get('id'), self.api_key) copied._retrieve_params = self._retrieve_params for k, v in six.iteritems(self): super(PingppObject, copied).__setitem__(k, v) return copied
def request_raw(self, method, url, params=None, supplied_headers=None): """ Mechanism for issuing an API call """ if self.api_key: my_api_key = self.api_key else: from pingpp import api_key my_api_key = api_key if my_api_key is None: raise error.AuthenticationError( 'No API key provided. (HINT: set your API key using ' '"pingpp.api_key = <API-KEY>"). You can generate API keys ' 'from the Ping++ web interface. ' 'See https://www.pingxx.com/api for details.') abs_url = '%s%s' % (self.api_base, url) request_uri = url if method == 'get' or method == 'delete': if params: encoded_params = urlencode(list(_api_encode(params or {}))) abs_url = _build_api_url(abs_url, encoded_params) request_uri = _build_api_url(url, encoded_params) post_data = None elif method == 'post' or method == 'put': post_data = util.json.dumps(params).encode("utf-8") else: raise error.APIConnectionError( 'Unrecognized HTTP method %r. This may indicate a bug in the ' 'Ping++ bindings. ' % (method, )) headers = self.request_headers(my_api_key, method) if supplied_headers is not None: for key, value in six.iteritems(supplied_headers): headers[key] = value request_utc_timestamp = _get_utc_timestamp() headers['Pingplusplus-Request-Timestamp'] = request_utc_timestamp rsa_data = self.get_rsa_verify_data(post_data, request_uri, int(request_utc_timestamp)) util.log_debug('Signing data', data=rsa_data) privkey = self.get_private_key() if privkey is not None: headers['Pingplusplus-Signature'] = self.rsa_sign( privkey, rsa_data) rbody, rcode, rheaders = self.execute_request_with_retry( method, abs_url, headers, post_data) return rbody, rcode, rheaders, my_api_key
def request(self, method, url, headers, post_data=None): b = util.io.BytesIO() rheaders = util.io.BytesIO() self._curl.reset() proxy = self._get_proxy(url) if proxy: if proxy.hostname: self._curl.setopt(pycurl.PROXY, proxy.hostname) if proxy.port: self._curl.setopt(pycurl.PROXYPORT, proxy.port) if proxy.username or proxy.password: self._curl.setopt(pycurl.PROXYUSERPWD, "%s:%s" % (proxy.username, proxy.password)) if method == 'get': self._curl.setopt(pycurl.HTTPGET, 1) elif method == 'post': self._curl.setopt(pycurl.POST, 1) self._curl.setopt(pycurl.POSTFIELDS, post_data) else: self._curl.setopt(pycurl.CUSTOMREQUEST, method.upper()) # pycurl doesn't like unicode URLs self._curl.setopt(pycurl.URL, util.utf8(url)) self._curl.setopt(pycurl.WRITEFUNCTION, b.write) self._curl.setopt(pycurl.NOSIGNAL, 1) self._curl.setopt(pycurl.CONNECTTIMEOUT, pingpp.connect_timeout) self._curl.setopt(pycurl.TIMEOUT, pingpp.timeout) self._curl.setopt( pycurl.HTTPHEADER, ['%s: %s' % (k, v) for k, v in six.iteritems(dict(headers))]) if self._verify_ssl_certs: self._curl.setopt(pycurl.CAINFO, util.ca_bundle_path(self._ca_bundle)) else: self._curl.setopt(pycurl.SSL_VERIFYHOST, False) try: self._curl.perform() except pycurl.error as e: self._handle_request_error(e) rbody = b.getvalue().decode('utf-8') rcode = self._curl.getinfo(pycurl.RESPONSE_CODE) headers = self.parse_headers(rheaders.getvalue().decode('utf-8')) return rbody, rcode, headers
def serialize(self, previous): params = {} unsaved_keys = self._unsaved_values or set() previous = previous or self._previous or {} for k, v in six.iteritems(self): if k == 'id' or (isinstance(k, str) and k.startswith('_')): continue elif isinstance(v, pingpp.api_resources.abstract.APIResource): continue elif hasattr(v, 'serialize'): child = v.serialize(previous.get(k, None)) if child != {}: params[k] = child elif k in unsaved_keys: params[k] = _compute_diff(v, previous.get(k, None)) elif k == 'additional_owners' and v is not None: params[k] = _serialize_list(v, previous.get(k, None)) return params
def _api_encode(data): for key, value in six.iteritems(data): key = util.utf8(key) if value is None: continue elif hasattr(value, 'pingpp_id'): yield (key, value.pingpp_id) elif isinstance(value, list) or isinstance(value, tuple): for sv in value: if isinstance(sv, dict): subdict = _encode_nested_dict(key, sv, fmt='%s[][%s]') for k, v in _api_encode(subdict): yield (k, v) else: yield ("%s[]" % (key, ), util.utf8(sv)) elif isinstance(value, dict): subdict = _encode_nested_dict(key, value) for subkey, subvalue in _api_encode(subdict): yield (subkey, subvalue) elif isinstance(value, datetime.datetime): yield (key, _encode_datetime(value)) else: yield (key, util.utf8(value))
def parse_headers(self, data): if '\r\n' not in data: return {} raw_headers = data.split('\r\n', 1)[1] headers = email.message_from_string(raw_headers) return dict((k.lower(), v) for k, v in six.iteritems(dict(headers)))
def _encode_nested_dict(key, data, fmt='%s[%s]'): d = {} for subkey, subvalue in six.iteritems(data): d[fmt % (key, subkey)] = subvalue return d