def _new_conn(self): """ Establish a new connection via the SOCKS proxy. """ extra_kw = {} if self.source_address: extra_kw['source_address'] = self.source_address if self.socket_options: extra_kw['socket_options'] = self.socket_options try: conn = socks.create_connection( (self.host, self.port), proxy_type=self._socks_options['socks_version'], proxy_addr=self._socks_options['proxy_host'], proxy_port=self._socks_options['proxy_port'], proxy_username=self._socks_options['username'], proxy_password=self._socks_options['password'], timeout=self.timeout, **extra_kw ) except SocketTimeout as e: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout)) except socks.ProxyError as e: # This is fragile as hell, but it seems to be the only way to raise # useful errors here. if e.socket_err: error = e.socket_err if isinstance(error, SocketTimeout): raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout) ) else: raise NewConnectionError( self, "Failed to establish a new connection: %s" % error ) else: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e ) except SocketError as e: # Defensive: PySocks should catch all these. raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) return conn
def test_retries_on_transport(execute_mock): """Testing retries on the transport level This forces us to override low-level APIs because the retry mechanism on the urllib3 (which uses requests) is pretty low-level itself. """ expected_retries = 3 execute_mock.side_effect = NewConnectionError("Should be HTTPConnection", "Fake connection error") transport = RequestsHTTPTransport( url="http://localhost:9999", retries=expected_retries, ) client = Client(transport=transport) query = gql(""" { myFavoriteFilm: film(id:"RmlsbToz") { id title episodeId } } """) with client: # We're using the client as context manager with pytest.raises(Exception): client.execute(query) # This might look strange compared to the previous test, but making 3 retries # means you're actually doing 4 calls. assert execute_mock.call_count == expected_retries + 1
def _new_conn(self): """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ extra_kw = {} if self.source_address: extra_kw["source_address"] = self.source_address if self.socket_options: extra_kw["socket_options"] = self.socket_options try: # HACK(mattrobenolt): All of this is to replace this one line # to establish our own connection. conn = safe_create_connection((self._dns_host, self.port), self.timeout, **extra_kw) except SocketTimeout: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout)) except SocketError as e: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) return conn
def _new_conn(self): extra_kw = {} if self.source_address: extra_kw['source_address'] = self.source_address if self.socket_options: extra_kw['socket_options'] = self.socket_options custom_host = self.custom_ip if self.custom_ip else self._dns_host #if self.custom_ip: # logging.debug('Using custom ip %s for host %s' % (self.custom_ip, self._dns_host)) try: conn = connection.create_connection( (custom_host, self.port), self.timeout, **extra_kw) except SocketTimeout as e: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout)) except SocketError as e: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) return conn
def _new_conn(self): """ Override a non-public member which is used to create the connection, yes, implementation detail, caveat emptor """ extra_kw = {} if self.socket_options: extra_kw["socket_options"] = self.socket_options try: conn = create_connection((self.host.rstrip("."), self.port), self.timeout, **extra_kw) except SocketTimeout: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout), ) except SocketError as e: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) return conn
def test_execute_connection_error(self): from urllib3.exceptions import NewConnectionError cursor = mock.Mock() cursor.execute.side_effect = NewConnectionError( "Dummypool", message="Exception with sensitive data") with pytest.raises(SupersetDBAPIDatabaseError) as ex: ClickHouseEngineSpec.execute(cursor, "SELECT col1 from table1")
def test_update_mastodon_pictures_get_actor_connection_failure(self): self.expect_requests_get( 'https://foo.com' + test_mastodon.API_ACCOUNT % 123, headers={'Authorization': 'Bearer towkin'}, ).AndRaise(NewConnectionError(None, None)) self.mox.ReplayAll() mastodon = self._setup_mastodon() resp = self.client.get('/cron/update_mastodon_pictures') self.assertEqual(200, resp.status_code) self.assertEqual('http://before', mastodon.key.get().picture)
def test_provide_registry_with_connection_error(): concept._BOOTSTRAP_CONNECTORS[0].get_loaders = MagicMock() concept._BOOTSTRAP_CONNECTORS[ 0].get_loaders.side_effect = NewConnectionError( None, "mock request error") with pytest.raises(NoSiibraConfigMirrorsAvailableException): concept.provide_registry(DummyCls) for connector in concept._BOOTSTRAP_CONNECTORS: connector.get_loaders.assert_called()
def test_index_document_handles_connection_error(self, current_app, index, error_status_code, service): index.return_value = (NewConnectionError( '', self.EXAMPLE_CONNECTION_ERROR), error_status_code) response = self.client.put(make_search_api_url(service), data=json.dumps(service), content_type='application/json') assert response.status_code == 500 current_app.logger.error.assert_called_once_with( f'API response error: ": {self.EXAMPLE_CONNECTION_ERROR}" Unexpected status code: "{error_status_code}"' )
def urlopen(self, method, url, redirect=True, **kw): """ Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` with custom cross-host redirect logic and only sends the request-uri portion of the ``url``. The given ``url`` parameter must be absolute, such that an appropriate :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. """ #=============================================================================================================== # add by mz error_type = kw.get('error_type') if error_type: from urllib3.exceptions import LocationValueError, HostChangedError, LocationParseError, ConnectTimeoutError from urllib3.exceptions import ProxyError, TimeoutError, ReadTimeoutError, ProtocolError, DecodeError from urllib3.exceptions import ResponseError, ResponseNotChunked, SSLError, HTTPError, HTTPWarning, PoolError from urllib3.exceptions import RequestError, MaxRetryError, TimeoutStateError, NewConnectionError from urllib3.exceptions import EmptyPoolError, ClosedPoolError, SecurityWarning, SubjectAltNameWarning from urllib3.exceptions import InsecureRequestWarning, SystemTimeWarning, InsecurePlatformWarning from urllib3.exceptions import SNIMissingWarning, DependencyWarning, ProxySchemeUnknown, HeaderParsingError get_error = { "LocationValueError": LocationValueError(), "HostChangedError": HostChangedError(pool=1, url=2), "LocationParseError": LocationParseError(url), "ConnectTimeoutError": ConnectTimeoutError(), "ProxyError": ProxyError(), "TimeoutError": TimeoutError(), "ReadTimeoutError": ReadTimeoutError(pool=1, url=2, message="ReadTimeoutError"), "ProtocolError": ProtocolError(), "DecodeError": DecodeError(), "ResponseError": ResponseError(), "ResponseNotChunked": ResponseNotChunked(), "SSLError": SSLError(), "HTTPError": HTTPError(), "HTTPWarning": HTTPWarning(), "PoolError": PoolError(pool=1, message=2), "RequestError": RequestError(pool=1, url=2, message="RequestError"), "MaxRetryError": MaxRetryError(pool=1, url=2, reason=None), "TimeoutStateError": TimeoutStateError(), "NewConnectionError": NewConnectionError(pool=1, message="NewConnectionError"), "EmptyPoolError": EmptyPoolError(pool=1, message="EmptyPoolError"), "ClosedPoolError": ClosedPoolError(pool=1, message="ClosedPoolError"), "SecurityWarning": SecurityWarning(), "SubjectAltNameWarning": SubjectAltNameWarning(), "InsecureRequestWarning": InsecureRequestWarning(), "SystemTimeWarning": SystemTimeWarning(), "InsecurePlatformWarning": InsecurePlatformWarning(), "SNIMissingWarning": SNIMissingWarning(), "DependencyWarning": DependencyWarning(), "ProxySchemeUnknown": ProxySchemeUnknown(scheme=1), "HeaderParsingError": HeaderParsingError(defects=1, unparsed_data=2) } error_ = get_error[error_type] raise error_ #=============================================================================================================== u = parse_url(url) conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) kw['assert_same_host'] = False kw['redirect'] = False if 'headers' not in kw: kw['headers'] = self.headers if self.proxy is not None and u.scheme == "http": response = conn.urlopen(method, url, **kw) else: response = conn.urlopen(method, u.request_uri, **kw) redirect_location = redirect and response.get_redirect_location() if not redirect_location: return response # Support relative URLs for redirecting. redirect_location = urljoin(url, redirect_location) # RFC 2616, Section 10.3.4 if response.status == 303: method = 'GET' log.info("Redirecting %s -> %s" % (url, redirect_location)) kw['retries'] = kw.get('retries', 3) - 1 # Persist retries countdown kw['redirect'] = redirect return self.urlopen(method, redirect_location, **kw)
def test_catches_new_connection_error(self): error = NewConnectionError(None, None) self.make_request_with_error(error)
class TestBaseApiClient(object): def _from_httplib_response_mock(self, status, response_data=None): response_mock = mock.Mock(status=status, headers={}, spec=[ 'get_redirect_location', 'getheader', 'read', 'reason', 'drain_conn' ]) response_mock.get_redirect_location.return_value = None response_mock.getheader.return_value = None response_mock.read.side_effect = [response_data, None, None, None] response_mock.reason = f'Mocked {status} response' return response_mock @pytest.mark.parametrize( "method,exc_factory", chain( ((m, lambda: NewConnectionError(mock.Mock(), "I'm a message")) for m in ( "GET", "PUT", "POST", "PATCH", )), ((m, lambda: ProtocolError(mock.Mock(), "I'm a message")) for m in ( "GET", "PUT", )), ((m, lambda: ReadTimeoutError(mock.Mock(), mock.Mock(), "I'm a message")) for m in ( "GET", "PUT", )), )) @pytest.mark.parametrize('retry_count', range(1, 4)) @mock.patch('urllib3.connectionpool.HTTPConnectionPool._make_request') @mock.patch('dmapiclient.base.BaseAPIClient._RETRIES_BACKOFF_FACTOR', 0) def test_client_retries_on_httperror_and_raises_api_error( self, _make_request, base_client, retry_count, exc_factory, method, ): _make_request.side_effect = exc_factory() with mock.patch('dmapiclient.base.BaseAPIClient._RETRIES', retry_count): with pytest.raises(HTTPError) as e: base_client._request(method, '/') requests = _make_request.call_args_list assert len(requests) == retry_count + 1 assert all((request[0][1], request[0][2]) == (method, '/') for request in requests) assert type(_make_request.side_effect).__name__ in e.value.message assert e.value.status_code == REQUEST_ERROR_STATUS_CODE @pytest.mark.parametrize("exc_factory", ( lambda: ProtocolError(mock.Mock(), "I'm a message"), lambda: ReadTimeoutError(mock.Mock(), mock.Mock(), "I'm a message"), )) @pytest.mark.parametrize("method", ( "POST", "PATCH", )) @pytest.mark.parametrize('retry_count', range(1, 4)) @mock.patch('urllib3.connectionpool.HTTPConnectionPool._make_request') @mock.patch('dmapiclient.base.BaseAPIClient._RETRIES_BACKOFF_FACTOR', 0) def test_client_doesnt_retry_non_whitelisted_methods_on_unsafe_errors( self, _make_request, base_client, retry_count, exc_factory, method, ): _make_request.side_effect = exc_factory() with mock.patch('dmapiclient.base.BaseAPIClient._RETRIES', retry_count): with pytest.raises(HTTPError) as e: base_client._request(method, '/') requests = _make_request.call_args_list assert len(requests) == 1 assert requests[0][0][1] == method assert requests[0][0][2] == "/" assert type(_make_request.side_effect).__name__ in e.value.message assert e.value.status_code == REQUEST_ERROR_STATUS_CODE @pytest.mark.parametrize(('retry_count'), range(1, 4)) @pytest.mark.parametrize(('status'), BaseAPIClient.RETRIES_FORCE_STATUS_CODES) @mock.patch( 'urllib3.connectionpool.HTTPConnectionPool.ResponseCls.from_httplib') @mock.patch('urllib3.connectionpool.HTTPConnectionPool._make_request') @mock.patch('dmapiclient.base.BaseAPIClient._RETRIES_BACKOFF_FACTOR', 0) def test_client_retries_on_status_error_and_raises_api_error( self, _make_request, from_httplib, base_client, status, retry_count): response_mock = self._from_httplib_response_mock(status) from_httplib.return_value = response_mock with mock.patch('dmapiclient.base.BaseAPIClient._RETRIES', retry_count): with pytest.raises(HTTPError) as e: base_client._request("GET", '/') requests = _make_request.call_args_list assert len(requests) == retry_count + 1 assert all((request[0][1], request[0][2]) == ('GET', '/') for request in requests) assert f'{status} Server Error: {response_mock.reason} for url: http://baseurl/\n' in e.value.message assert e.value.status_code == status @mock.patch( 'urllib3.connectionpool.HTTPConnectionPool.ResponseCls.from_httplib') @mock.patch('urllib3.connectionpool.HTTPConnectionPool._make_request') @mock.patch('dmapiclient.base.BaseAPIClient._RETRIES_BACKOFF_FACTOR', 0) def test_client_retries_and_returns_data_if_successful( self, _make_request, from_httplib, base_client): # The third response here would normally be a httplib response object. It's only use is to be passed in to # `from_httplib`, which we're mocking the return of below. `from_httplib` converts a httplib response into a # urllib3 response. The mock object we're returning is a mock for that urllib3 response. _make_request.side_effect = [ ProtocolError(mock.Mock(), '1st error'), ProtocolError(mock.Mock(), '2nd error'), ProtocolError(mock.Mock(), '3nd error'), 'httplib_response - success!', ] from_httplib.return_value = self._from_httplib_response_mock( 200, response_data=b'{"Success?": "Yes!"}') response = base_client._request("GET", '/') requests = _make_request.call_args_list assert len(requests) == 4 assert all((request[0][1], request[0][2]) == ('GET', '/') for request in requests) assert response == {'Success?': 'Yes!'} def test_non_2xx_response_raises_api_error(self, base_client, rmock): rmock.request("GET", "http://baseurl/", json={"error": "Not found"}, status_code=404) with pytest.raises(HTTPError) as e: base_client._request("GET", '/') assert e.value.message == "Not found" assert e.value.status_code == 404 def test_base_error_is_logged(self, base_client): with requests_mock.Mocker() as m: m.register_uri('GET', '/', exc=requests.RequestException()) with pytest.raises(HTTPError) as e: base_client._request("GET", "/") assert e.value.message == "\nRequestException()" assert e.value.status_code == 503 def test_invalid_json_raises_api_error(self, base_client, rmock): rmock.request("GET", "http://baseurl/", text="Internal Error", status_code=200) with pytest.raises(InvalidResponse) as e: base_client._request("GET", '/') assert e.value.message == "No JSON object could be decoded" assert e.value.status_code == 200 def test_user_agent_is_set(self, base_client, rmock): rmock.request("GET", "http://baseurl/", json={}, status_code=200) base_client._request('GET', '/') assert rmock.last_request.headers.get("User-Agent").startswith( "DM-API-Client/") def test_request_always_uses_base_url_scheme(self, base_client, rmock): rmock.request("GET", "http://baseurl/path/", json={}, status_code=200) base_client._request('GET', 'https://host/path/') assert rmock.called def test_null_api_throws(self): bad_client = BaseAPIClient(None, 'auth-token', True) with pytest.raises(ImproperlyConfigured): bad_client._request('GET', '/anything') def test_onwards_request_headers_added_if_available( self, base_client, rmock, app): rmock.get("http://baseurl/_status", json={"status": "ok"}, status_code=200) with app.test_request_context('/'): # add a simple mock callable instead of using a full request implementation request.get_onwards_request_headers = mock.Mock() request.get_onwards_request_headers.return_value = { "Douce": "bronze", "Kennedy": "gold", } base_client.get_status() assert rmock.last_request.headers["Douce"] == "bronze" assert rmock.last_request.headers["kennedy"] == "gold" assert request.get_onwards_request_headers.call_args_list == [ # just a single, arg-less call (), ] def test_onwards_request_headers_not_available(self, base_client, rmock, app): rmock.get("http://baseurl/_status", json={"status": "ok"}, status_code=200) with app.test_request_context('/'): # really just asserting no exception arose from performing a call without get_onwards_request_headers being # available base_client.get_status() def test_request_id_fallback(self, base_client, rmock, app): # request.request_id is an old interface which we're still supporting here just for compatibility rmock.get("http://baseurl/_status", json={"status": "ok"}, status_code=200) app.config["DM_REQUEST_ID_HEADER"] = "Bar" with app.test_request_context('/'): request.request_id = "Ormond" base_client.get_status() assert rmock.last_request.headers["bar"] == "Ormond" @pytest.mark.parametrize("dm_span_id_headers_setting", ( None, ( "X-Brian-Tweedy", "Major-Tweedy", ), )) @pytest.mark.parametrize( "has_request_context", (False, True), ) @mock.patch("dmapiclient.base.logger") def test_child_span_id_not_provided( self, logger, dm_span_id_headers_setting, has_request_context, base_client, rmock, app, ): rmock.get("http://baseurl/_status", json={"status": "ok"}, status_code=200) app.config["DM_SPAN_ID_HEADERS"] = dm_span_id_headers_setting with (app.test_request_context('/') if has_request_context else _empty_context_manager()): if has_request_context: request.get_onwards_request_headers = mock.Mock( return_value={ "impression": "arrested", }) base_client.get_status() assert rmock.called assert logger.log.call_args_list == [ mock.call( logging.DEBUG, "API request {method} {url}", extra={ "method": "GET", "url": "http://baseurl/_status", # childSpanId NOT provided }), mock.call( logging.INFO, "API {api_method} request on {api_url} finished in {api_time}", extra={ "api_method": "GET", "api_url": "http://baseurl/_status", "api_status": 200, "api_time": mock.ANY, # childSpanId NOT provided }), ] @pytest.mark.parametrize( "onwards_request_headers", ( { "X-Brian-Tweedy": "Amiens Street", }, { "major-TWEEDY": "Amiens Street", }, { "Major-Tweedy": "terminus", "x-brian-tweedy": "Amiens Street", }, { # note same header name, different capitalizations "X-BRIAN-TWEEDY": "great northern", "x-brian-tweedy": "Amiens Street", }, )) @pytest.mark.parametrize("response_status", ( 200, 500, )) @mock.patch("dmapiclient.base.logger") def test_child_span_id_provided( self, mock_logger, onwards_request_headers, response_status, base_client, rmock, app, ): rmock.get("http://baseurl/_status", json={"status": "foobar"}, status_code=response_status) app.config["DM_SPAN_ID_HEADERS"] = ( "X-Brian-Tweedy", "major-tweedy", ) with app.test_request_context('/'): request.get_onwards_request_headers = mock.Mock( return_value=onwards_request_headers) try: base_client.get_status() except HTTPError: # it is tested elsewhere whether this exception is raised in the *right* circumstances or not pass assert rmock.called # some of our scenarios test multiple header names differing only by capitalization - we care that the same # span id that was chosen for the log message is the same one that was sent in the onwards request header, # so we need two distinct values which are acceptable either_span_id = RestrictedAny( lambda value: value == "Amiens Street" or value == "great northern") assert mock_logger.log.call_args_list == [ mock.call(logging.DEBUG, "API request {method} {url}", extra={ "method": "GET", "url": "http://baseurl/_status", "childSpanId": either_span_id, }), (mock.call( logging.INFO, "API {api_method} request on {api_url} finished in {api_time}", extra={ "api_method": "GET", "api_url": "http://baseurl/_status", "api_status": response_status, "api_time": mock.ANY, "childSpanId": either_span_id, } ) if response_status == 200 else mock.call( logging.WARNING, "API {api_method} request on {api_url} failed with {api_status} '{api_error}'", extra={ "api_method": "GET", "api_url": "http://baseurl/_status", "api_status": response_status, "api_time": mock.ANY, "api_error": mock.ANY, "childSpanId": either_span_id, }, )) ] # both logging calls should have had the *same* childSpanId value assert mock_logger.log.call_args_list[0][1]["extra"]["childSpanId"] \ == mock_logger.log.call_args_list[1][1]["extra"]["childSpanId"] # that value should be the same one that was sent in the onwards request header assert ( rmock.last_request.headers.get("x-brian-tweedy") or rmock.last_request.headers.get("major-tweedy") ) == mock_logger.log.call_args_list[0][1]["extra"]["childSpanId"] @pytest.mark.parametrize( "thrown_exception", ( # requests can be slightly unpredictable in the exceptions it raises requests.exceptions.ConnectionError( MaxRetryError( mock.Mock(), "http://abc.net", ReadTimeoutError(mock.Mock(), mock.Mock(), mock.Mock()))), requests.exceptions.ConnectionError( ReadTimeoutError(mock.Mock(), mock.Mock(), mock.Mock())), requests.exceptions.ReadTimeout, )) @mock.patch("dmapiclient.base.logger") def test_nowait_times_out( self, mock_logger, base_client, rmock, app, thrown_exception, ): "test the case when a request with client_wait_for_response=False does indeed time out" rmock.post("http://baseurl/services/10000", exc=thrown_exception) retval = base_client._request( "POST", "/services/10000", {"serviceName": "Postcard"}, client_wait_for_response=False, ) assert retval is None assert rmock.called assert tuple( req.timeout for req in rmock.request_history) == (base_client.nowait_timeout, ) assert mock_logger.log.call_args_list == [ mock.call(logging.DEBUG, "API request {method} {url}", extra={ "method": "POST", "url": "http://baseurl/services/10000", }), mock.call( logging.INFO, "API {api_method} request on {api_url} dispatched but ignoring response", extra={ "api_method": "POST", "api_url": "http://baseurl/services/10000", "api_time": mock.ANY, "api_time_incomplete": True, }), ] @mock.patch("dmapiclient.base.logger") def test_nowait_completes( self, mock_logger, base_client, rmock, app, ): "test the case when a request with client_wait_for_response=False completes before it can time out" rmock.post("http://baseurl/services/10000", json={"services": { "id": "10000" }}, status_code=200) retval = base_client._request( "POST", "/services/10000", {"serviceName": "Postcard"}, client_wait_for_response=False, ) assert retval == {"services": {"id": "10000"}} assert rmock.called assert tuple( req.timeout for req in rmock.request_history) == (base_client.nowait_timeout, ) assert mock_logger.log.call_args_list == [ mock.call(logging.DEBUG, "API request {method} {url}", extra={ "method": "POST", "url": "http://baseurl/services/10000", }), mock.call( logging.INFO, "API {api_method} request on {api_url} finished in {api_time}", extra={ "api_method": "POST", "api_url": "http://baseurl/services/10000", "api_time": mock.ANY, "api_status": 200, }), ]
def _setup_https_tunnel(self): sock = self.sock host = self._tunnel_host port = self._tunnel_port try: lines = [] lines.append('CONNECT %s:%d HTTP/1.1' % (host, port)) lines.append('Host: %s:%d' % (host, port)) if self._tunnel_headers: for item in self._tunnel_headers.items(): lines.append('%s: %s' % item) data = '\r\n'.join(lines) + '\r\n\r\n' sock.sendall(data.encode()) data = b'' code = 0 pos = -1 while True: s = sock.recv(4096) if not s: if code == 0: raise SocketError("Tunnel connection failed: %r" % data) break data += s if code == 0 and b'\r\n' in data: version, code, message = data.split(b' ', 2) if code != b'200': sock.close() raise SocketError("Tunnel connection failed: %s %s" % (code, message.strip())) pos = data.find(b'\r\n\r\n') if pos > 0: break tls_conn = tlslite.TLSConnection(sock) try: tls_conn.handshakeClientCert(serverName=host) except Exception: sock.close() raise try: ssl.match_hostname(tlslite_getpeercert(tls_conn), host) except Exception: tls_conn.close() raise except SocketTimeout as e: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout)) except SocketError as e: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) # patch fileno, # let urllib3.util.connection.is_connection_dropped work as expected # tls_conn.fileno = partial(self._origin_sock.fileno) # here we always got fileno = -1 tls_conn.fileno = partial(sock.fileno) # patch getpeercert tls_conn.getpeercert = partial(tlslite_getpeercert, tls_conn) self.sock = tls_conn
def resolve_ip_for_target(rrsets, target): for rrset in rrsets: if rrset.name == target: return rrset.items[0].address raise NewConnectionError("Couldn't find A record for target %s" % target)
def test_catches_new_connection_error(self): error = NewConnectionError(None, None) with pytest.raises(EndpointConnectionError): self.make_request_with_error(error)