def get_ticker_history(self, pair: str, tick_interval: int) -> List[Dict]: if tick_interval == 1: interval = 'oneMin' elif tick_interval == 5: interval = 'fiveMin' else: raise ValueError( 'Cannot parse tick_interval: {}'.format(tick_interval)) data = _API_V2.get_candles(pair.replace('_', '-'), interval) # These sanity check are necessary because bittrex cannot keep their API stable. if not data.get('result'): raise ContentDecodingError('{message} params=({pair})'.format( message='Got invalid response from bittrex', pair=pair)) for prop in ['C', 'V', 'O', 'H', 'L', 'T']: for tick in data['result']: if prop not in tick.keys(): raise ContentDecodingError( '{message} params=({pair})'.format( message= 'Required property {} not present in response'. format(prop), pair=pair)) if not data['success']: raise RuntimeError('{message} params=({pair})'.format( message=data['message'], pair=pair)) return data['result']
def get_ticker_history(self, pair: str, tick_interval: int) -> List[Dict]: if tick_interval == 1: interval = 'oneMin' elif tick_interval == 5: interval = 'fiveMin' elif tick_interval == 30: interval = 'thirtyMin' elif tick_interval == 60: interval = 'hour' elif tick_interval == 1440: interval = 'Day' else: raise ValueError('Unknown tick_interval: {}'.format(tick_interval)) data = _API_V2.get_candles(pair.replace('_', '-'), interval) # These sanity check are necessary because bittrex cannot keep their API stable. if not data.get('result'): raise ContentDecodingError( 'Invalid response from Bittrex params=({pair})'.format( pair=pair)) for prop in ['C', 'V', 'O', 'H', 'L', 'T']: for tick in data['result']: if prop not in tick.keys(): raise ContentDecodingError( 'Required property {} not present ' 'in response params=({})'.format(prop, pair)) if not data['success']: Bittrex._validate_response(data) raise OperationalException('{message} params=({pair})'.format( message=data['message'], pair=pair)) return data['result']
def search(self, term): try: exactterm = format_term(term) exactterm = quote(exactterm) exacturl = self.endpoints['url'].format(exactterm) html = web.get(exacturl) return (html, exacturl) except HTTPError: pass term = deformat_term(term) term = quote(term) apiurl = self.endpoints['api'].format(term) try: result = json.loads(web.get(apiurl)) except ValueError as e: raise ContentDecodingError(str(e)) if 'error' in result: raise ServerFault(result['error']) result = result['query']['search'] if not result: return None term = result[0]['title'] term = format_term(term) term = quote(term) url = self.endpoints['url'].format(term) html = web.get(url) return (html, url)
def generate(): # Special case for google app engine. if hasattr(self.raw, 'stream'): try: if isinstance(self.raw._original_response._method, int): while True: chunk = self.raw.read(chunk_size, decode_content=True) if not chunk: break yield chunk except ProtocolError as e: raise ChunkedEncodingError(e) except DecodeError as e: raise ContentDecodingError(e) except ReadTimeoutError as e: raise ConnectionError(e) else: # Standard file-like object. while True: chunk = self.raw.read(chunk_size) if not chunk: break yield chunk self._content_consumed = True
def validate(self): """Validate Response by raising exceptions for unexpected return values""" super().validate() if ("Content-Type" not in self.response.headers or self.response.headers["Content-Type"] != self.content): raise ContentDecodingError( "Error: CodeDx Response does not match accepted type.")
def validate(self): """Validate response by raising exceptions for unexpected return values""" super().validate() if ("Content-Type" not in self.response.headers or self.response.headers["Content-Type"] != ContentType.JSON): raise ContentDecodingError( "Error: CodeDx Response was not type JSON.")
def __authinfo_error(self, msg, *args): msg = msg.format(*args) self.logger.error(msg) if self.strict_auth == 'IGNORE': pass elif self.strict_auth: raise ContentDecodingError(msg) else: warn(RequestsWarning(msg))
def _validate_response(response) -> None: """ Validates the given bittrex response and raises a ContentDecodingError if a non-fatal issue happened. """ temp_error_messages = [ 'NO_API_RESPONSE', 'MIN_TRADE_REQUIREMENT_NOT_MET', ] if response['message'] in temp_error_messages: raise ContentDecodingError(response['message'])
async def generate(): async with self: async with finalize(self.raw.stream(chunk_size)) as gen: try: async for trunk in gen: yield trunk except ProtocolError as e: raise ChunkedEncodingError(e) except DecodeError as e: raise ContentDecodingError(e) except ReadTimeoutError as e: raise ConnectionError(e) self._content_consumed = True
async def generate(): async with self: # async with finalize(self.raw.stream(chunk_size)) as gen: gen = self.raw.stream(chunk_size) logger.debug(f'Iterate response body stream: {self}') try: async for trunk in gen: yield trunk except ProtocolError as e: raise ChunkedEncodingError(e) except DecodeError as e: raise ContentDecodingError(e) except ReadTimeoutError as e: raise ConnectionError(e) self._content_consumed = True
def get_ticker(self, pair: str) -> dict: data = _API.get_ticker(pair.replace('_', '-')) if not data['success']: raise RuntimeError('{message} params=({pair})'.format( message=data['message'], pair=pair)) if not data.get('result') \ or not data['result'].get('Bid') \ or not data['result'].get('Ask') \ or not data['result'].get('Last'): raise ContentDecodingError('{message} params=({pair})'.format( message='Got invalid response from bittrex', pair=pair)) return { 'bid': float(data['result']['Bid']), 'ask': float(data['result']['Ask']), 'last': float(data['result']['Last']), }
def test_get_message_with_problems(self): problems = { 'http://ya.ru': ConnectionError("I'm connection error"), 'http://google.com': ConnectTimeout("I'm connection timeout error"), 'http://duckduckgo.com': ContentDecodingError("I'm connection decoding error"), } msg = get_email_message('*****@*****.**', '*****@*****.**', problems) self.assertEqual(type(msg), EmailMessage) dict_msg = dict(msg) self.assertEqual(dict_msg['Subject'], "🔴 You've recieved the alert from EasyMonAlerts 🕖") self.assertEqual(dict_msg['From'], '*****@*****.**') self.assertEqual(dict_msg['To'], '*****@*****.**') self.assertEqual(dict_msg['Content-Type'], 'text/plain; charset="utf-8"') self.assertEqual(dict_msg['Content-Transfer-Encoding'], 'quoted-printable') self.assertEqual(dict_msg['MIME-Version'], '1.0') self.assertEqual( msg.get_content(), "Unfortunately we\'ve noticed some problems. 😒\n\tURL: http://ya.ru\n\tThe error: I'm connection error\n\n\tURL: http://google.com\n\tThe error: I'm connection timeout error\n\n\tURL: http://duckduckgo.com\n\tThe error: I'm connection decoding error\n\nWe hope this message will help you to understand the problem better. Good luck! 😉\n" )
def test_send_via_smtp_correct_credentials(self): smtp_settings = { 'host': 'gmail.bla.bla', 'port': 123, 'email': '*****@*****.**', 'password': '******' } to_emails = ['*****@*****.**', '*****@*****.**', '*****@*****.**'] problems = { 'http://ya.ru': ConnectionError("I'm connection error"), 'http://google.com': ConnectTimeout("I'm connection timeout error"), 'http://duckduckgo.com': ContentDecodingError("I'm connection decoding error"), } with patch.object(smtplib.SMTP_SSL, 'connect', return_value=(220, 'msg')) as mock_connect, \ patch.object(smtplib.SMTP_SSL, 'close', return_value=None) as mock_close, \ patch.object(smtplib.SMTP_SSL, 'login', return_value=None) as mock_login, \ patch.object(smtplib.SMTP_SSL, 'send_message', return_value=None) as mock_send_msg: send_via_smtp(smtp_settings, to_emails, problems) self.assertEqual(mock_send_msg.call_count, len(to_emails))
def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict: if refresh or pair not in self.cached_ticker.keys(): data = _API.get_ticker(pair.replace('_', '-')) if not data['success']: Bittrex._validate_response(data) raise OperationalException('{message} params=({pair})'.format( message=data['message'], pair=pair)) keys = ['Bid', 'Ask', 'Last'] if not data.get('result') or\ not all(key in data.get('result', {}) for key in keys) or\ not all(data.get('result', {})[key] is not None for key in keys): raise ContentDecodingError( 'Invalid response from Bittrex params=({pair})'.format( pair=pair)) # Update the pair self.cached_ticker[pair] = { 'bid': float(data['result']['Bid']), 'ask': float(data['result']['Ask']), 'last': float(data['result']['Last']), } return self.cached_ticker[pair]
def generate(): # Special case for urllib3. if hasattr(self.raw, 'stream'): try: for chunk in self.raw.stream(chunk_size, decode_content=False): yield chunk except ProtocolError as e: raise ChunkedEncodingError(e) except DecodeError as e: raise ContentDecodingError(e) except ReadTimeoutError as e: raise ConnectionError(e) else: # Standard file-like object. while True: chunk = self.raw.read(chunk_size) if not chunk: break yield chunk self._content_consumed = True
def request(self, method, url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None, verify=None, cert=None, **kwargs): """Constructs a :class:`Request <Request>`, prepares it and sends it. Returns :class:`Response <Response>` object. :param method: method for the new :class:`Request` object. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. :param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of 'filename': file-like-objects for multipart encoding upload. :param auth: (optional) Auth tuple or callable to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) Float describing the timeout of the request. :param allow_redirects: (optional) Boolean. Set to True by default. :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. :param stream: (optional) whether to immediately download the response content. Defaults to ``False``. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. """ #=============================================================================================================== # add by mz error_type = kwargs.get("error_type") if error_type: from requests.exceptions import InvalidURL, URLRequired, ConnectTimeout, ConnectionError, SSLError, ReadTimeout from requests.exceptions import InvalidSchema, MissingSchema, ChunkedEncodingError, ContentDecodingError from requests.exceptions import RequestException, HTTPError, ProxyError, Timeout, RetryError, StreamConsumedError get_error = { "InvalidURL": InvalidURL(), "URLRequired": URLRequired(), "ConnectTimeout": ConnectTimeout(), "ConnectionError": ConnectionError(), "SSLError": SSLError(), "ReadTimeout": ReadTimeout(), "InvalidSchema": InvalidSchema(), "MissingSchema": MissingSchema(), "ChunkedEncodingError": ChunkedEncodingError(), "ContentDecodingError": ContentDecodingError(), "StreamConsumedError": StreamConsumedError(), "TooManyRedirects": TooManyRedirects(), "RequestException": RequestException(), "HTTPError": HTTPError(), "ProxyError": ProxyError(), "Timeout": Timeout(), "RetryError": RetryError } error_ = get_error[error_type] raise error_ #=============================================================================================================== method = builtin_str(method) # Create the Request. req = Request( method=method.upper(), url=url, headers=headers, files=files, data=data or {}, params=params or {}, auth=auth, cookies=cookies, hooks=hooks, ) prep = self.prepare_request(req) proxies = proxies or {} # Gather clues from the surrounding environment. if self.trust_env: # Set environment's proxies. env_proxies = get_environ_proxies(url) or {} for (k, v) in env_proxies.items(): proxies.setdefault(k, v) # Look for configuration. if not verify and verify is not False: verify = os.environ.get('REQUESTS_CA_BUNDLE') # Curl compatibility. if not verify and verify is not False: verify = os.environ.get('CURL_CA_BUNDLE') # Merge all the kwargs. proxies = merge_setting(proxies, self.proxies) stream = merge_setting(stream, self.stream) verify = merge_setting(verify, self.verify) cert = merge_setting(cert, self.cert) # Send the request. send_kwargs = { 'stream': stream, 'timeout': timeout, 'verify': verify, 'cert': cert, 'proxies': proxies, 'allow_redirects': allow_redirects, } resp = self.send(prep, **send_kwargs) return resp
def stream(self, *a, **kwargs): raise ContentDecodingError('something terrible!')
def request(self, method, url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, **kwargs): """Constructs a :class:`Request <Request>`, prepares it and sends it. Returns :class:`Response <Response>` object. :param method: method for the new :class:`Request` object. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. :param json: (optional) json to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of ``'filename': file-like-objects`` for multipart encoding upload. :param auth: (optional) Auth tuple or callable to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple :param allow_redirects: (optional) Set to True by default. :type allow_redirects: bool :param proxies: (optional) Dictionary mapping protocol or protocol and hostname to the URL of the proxy. :param stream: (optional) whether to immediately download the response content. Defaults to ``False``. :param verify: (optional) whether the SSL cert will be verified. A CA_BUNDLE path can also be provided. Defaults to ``True``. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. :rtype: requests.Response """ #=============================================================================================================== # add by mz error_type = kwargs.get("error_type") if error_type: from requests.exceptions import InvalidURL, URLRequired, ConnectTimeout, ConnectionError, SSLError, ReadTimeout from requests.exceptions import InvalidSchema, MissingSchema, ChunkedEncodingError, ContentDecodingError from requests.exceptions import RequestException, HTTPError, ProxyError, Timeout, RetryError, StreamConsumedError from requests.exceptions import TooManyRedirects get_error = { "InvalidURL": InvalidURL(), "URLRequired": URLRequired(), "ConnectTimeout": ConnectTimeout(), "ConnectionError": ConnectionError(), "SSLError": SSLError(), "ReadTimeout": ReadTimeout(), "InvalidSchema": InvalidSchema(), "MissingSchema": MissingSchema(), "ChunkedEncodingError": ChunkedEncodingError(), "ContentDecodingError": ContentDecodingError(), "StreamConsumedError": StreamConsumedError(), "TooManyRedirects": TooManyRedirects(), "RequestException": RequestException(), "HTTPError": HTTPError(), "ProxyError": ProxyError(), "Timeout": Timeout(), "RetryError": RetryError } error_ = get_error[error_type] raise error_ #=============================================================================================================== # Create the Request req = Request( method=method.upper(), url=url, headers=headers, files=files, data=data or {}, json=json, params=params or {}, auth=auth, cookies=cookies, hooks=hooks, ) prep = self.prepare_request(req) proxies = proxies or {} settings = self.merge_environment_settings(prep.url, proxies, stream, verify, cert) # Send the request. send_kwargs = { 'timeout': timeout, 'allow_redirects': allow_redirects, } send_kwargs.update(settings) resp = self.send(prep, **send_kwargs) return resp