0.5.1: pytest is failing in `tests/test_async.py::test_httpx_fails` unit
kloczek opened this issue · comments
I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.
python3 -sBm build -w --no-isolation
- because I'm calling
build
with--no-isolation
I'm using during all processes only locally installed modules - install .whl file in </install/prefix>
- run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>
I'm not 100% sure but I just upgraded httpx
to 0.23.0.
Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.1-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.1-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1
plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2
collected 59 items
tests/test_async.py ..F [ 5%]
tests/test_combinations.py .. [ 8%]
tests/test_doctest.py . [ 10%]
tests/test_precedence.py ........ [ 23%]
tests/test_restrict_hosts.py ....................... [ 62%]
tests/test_socket.py ...................... [100%]
================================================================================= FAILURES =================================================================================
_____________________________________________________________________________ test_httpx_fails _____________________________________________________________________________
testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-114/test_httpx_fails0')>
@unix_sockets_only
def test_httpx_fails(testdir):
testdir.makepyfile(
"""
import pytest
import httpx
@pytest.fixture(autouse=True)
def anyio_backend():
return "asyncio"
async def test_httpx():
async with httpx.AsyncClient() as client:
await client.get("http://www.example.com/")
"""
)
result = testdir.runpytest("--disable-socket", "--allow-unix-socket")
> assert_socket_blocked(result)
/home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1/tests/test_async.py:75:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
result = <RunResult ret=ExitCode.TESTS_FAILED len(stdout.lines)=608 len(stderr.lines)=0 duration=0.46s>
def assert_socket_blocked(result):
result.assert_outcomes(passed=0, skipped=0, failed=1)
> result.stdout.fnmatch_lines(
"*SocketBlockedError: A test tried to use socket.socket.*"
)
E Failed: nomatch: '*SocketBlockedError: A test tried to use socket.socket.*'
E and: '============================= test session starts =============================='
E and: 'platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0'
E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-114/test_httpx_fails0'
E and: 'plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2'
E and: 'collected 1 item'
E and: ''
E and: 'test_httpx_fails.py F [100%]'
E and: ''
E and: '=================================== FAILURES ==================================='
E and: '__________________________________ test_httpx __________________________________'
E and: ''
E and: "map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}"
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:'
E and: ' try:'
E and: '> yield'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:8: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f64c7cdb430>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: typing.Optional[float] = None,'
E and: ' local_address: typing.Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' exc_map = {'
E and: ' TimeoutError: ConnectTimeout,'
E and: ' OSError: ConnectError,'
E and: ' anyio.BrokenResourceError: ConnectError,'
E and: ' }'
E and: ' with map_exceptions(exc_map):'
E and: ' with anyio.fail_after(timeout):'
E and: '> stream: anyio.abc.ByteStream = await anyio.connect_tcp('
E and: ' remote_host=host,'
E and: ' remote_port=port,'
E and: ' local_host=local_address,'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "remote_host = 'www.example.com', remote_port = 80"
E and: ''
E and: ' async def connect_tcp('
E and: ' remote_host: IPAddressType,'
E and: ' remote_port: int,'
E and: ' *,'
E and: ' local_host: Optional[IPAddressType] = None,'
E and: ' tls: bool = False,'
E and: ' ssl_context: Optional[ssl.SSLContext] = None,'
E and: ' tls_standard_compatible: bool = True,'
E and: ' tls_hostname: Optional[str] = None,'
E and: ' happy_eyeballs_delay: float = 0.25,'
E and: ' ) -> Union[SocketStream, TLSStream]:'
E and: ' """'
E and: ' Connect to a host using the TCP protocol.'
E and: ' '
E and: ' This function implements the stateless version of the Happy Eyeballs algorithm (RFC 6555).'
E and: ' If ``address`` is a host name that resolves to multiple IP addresses, each one is tried until'
E and: ' one connection attempt succeeds. If the first attempt does not connected within 250'
E and: ' milliseconds, a second attempt is started using the next address in the list, and so on.'
E and: ' On IPv6 enabled systems, an IPv6 address (if available) is tried first.'
E and: ' '
E and: ' When the connection has been established, a TLS handshake will be done if either'
E and: ' ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``.'
E and: ' '
E and: ' :param remote_host: the IP address or host name to connect to'
E and: ' :param remote_port: port on the target host to connect to'
E and: ' :param local_host: the interface address or name to bind the socket to before connecting'
E and: ' :param tls: ``True`` to do a TLS handshake with the connected stream and return a'
E and: ' :class:`~anyio.streams.tls.TLSStream` instead'
E and: ' :param ssl_context: the SSL context object to use (if omitted, a default context is created)'
E and: ' :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake before closing'
E and: ' the stream and requires that the server does this as well. Otherwise,'
E and: ' :exc:`~ssl.SSLEOFError` may be raised during reads from the stream.'
E and: ' Some protocols, such as HTTP, require this option to be ``False``.'
E and: ' See :meth:`~ssl.SSLContext.wrap_socket` for details.'
E and: ' :param tls_hostname: host name to check the server certificate against (defaults to the value'
E and: ' of ``remote_host``)'
E and: ' :param happy_eyeballs_delay: delay (in seconds) before starting the next connection attempt'
E and: ' :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream'
E and: ' :raises OSError: if the connection attempt fails'
E and: ' '
E and: ' """'
E and: ' # Placed here due to https://github.com/python/mypy/issues/7057'
E and: ' connected_stream: Optional[SocketStream] = None'
E and: ' '
E and: ' async def try_connect(remote_host: str, event: Event) -> None:'
E and: ' nonlocal connected_stream'
E and: ' try:'
E and: ' stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)'
E and: ' except OSError as exc:'
E and: ' oserrors.append(exc)'
E and: ' return'
E and: ' else:'
E and: ' if connected_stream is None:'
E and: ' connected_stream = stream'
E and: ' tg.cancel_scope.cancel()'
E and: ' else:'
E and: ' await stream.aclose()'
E and: ' finally:'
E and: ' event.set()'
E and: ' '
E and: ' asynclib = get_asynclib()'
E and: ' local_address: Optional[IPSockAddrType] = None'
E and: ' family = socket.AF_UNSPEC'
E and: ' if local_host:'
E and: ' gai_res = await getaddrinfo(str(local_host), None)'
E and: ' family, *_, local_address = gai_res[0]'
E and: ' '
E and: ' target_host = str(remote_host)'
E and: ' try:'
E and: ' addr_obj = ip_address(remote_host)'
E and: ' except ValueError:'
E and: ' # getaddrinfo() will raise an exception if name resolution fails'
E and: '> gai_res = await getaddrinfo('
E and: ' target_host, remote_port, family=family, type=socket.SOCK_STREAM'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:189: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = 'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo('
E and: ' host: Union[bytearray, bytes, str],'
E and: ' port: Union[str, int, None],'
E and: ' *,'
E and: ' family: Union[int, AddressFamily] = 0,'
E and: ' type: Union[int, SocketKind] = 0,'
E and: ' proto: int = 0,'
E and: ' flags: int = 0,'
E and: ' ) -> GetAddrInfoReturnType:'
E and: ' """'
E and: ' Look up a numeric IP address given a host name.'
E and: ' '
E and: ' Internationalized domain names are translated according to the (non-transitional) IDNA 2008'
E and: ' standard.'
E and: ' '
E and: ' .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of'
E and: ' (host, port), unlike what :func:`socket.getaddrinfo` does.'
E and: ' '
E and: ' :param host: host name'
E and: ' :param port: port number'
E and: " :param family: socket family (`'AF_INET``, ...)"
E and: ' :param type: socket type (``SOCK_STREAM``, ...)'
E and: ' :param proto: protocol number'
E and: ' :param flags: flags to pass to upstream ``getaddrinfo()``'
E and: ' :return: list of tuples containing (family, type, proto, canonname, sockaddr)'
E and: ' '
E and: ' .. seealso:: :func:`socket.getaddrinfo`'
E and: ' '
E and: ' """'
E and: ' # Handle unicode hostnames'
E and: ' if isinstance(host, str):'
E and: ' try:'
E and: ' encoded_host = host.encode("ascii")'
E and: ' except UnicodeEncodeError:'
E and: ' import idna'
E and: ' '
E and: ' encoded_host = idna.encode(host, uts46=True)'
E and: ' else:'
E and: ' encoded_host = host'
E and: ' '
E and: '> gai_res = await get_asynclib().getaddrinfo('
E and: ' encoded_host, port, family=family, type=type, proto=proto, flags=flags'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:496: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = b'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo('
E and: ' host: Union[bytes, str],'
E and: ' port: Union[str, int, None],'
E and: ' *,'
E and: ' family: Union[int, AddressFamily] = 0,'
E and: ' type: Union[int, SocketKind] = 0,'
E and: ' proto: int = 0,'
E and: ' flags: int = 0,'
E and: ' ) -> GetAddrInfoReturnType:'
E and: ' # https://github.com/python/typeshed/pull/4304'
E and: '> result = await get_running_loop().getaddrinfo('
E and: ' host, port, family=family, type=type, proto=proto, flags=flags'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_backends/_asyncio.py:1754: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <_UnixSelectorEventLoop running=False closed=True debug=False>'
E and: "host = b'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo(self, host, port, *,'
E and: ' family=0, type=0, proto=0, flags=0):'
E and: ' if self._debug:'
E and: ' getaddr_func = self._getaddrinfo_debug'
E and: ' else:'
E and: ' getaddr_func = socket.getaddrinfo'
E and: ' '
E and: '> return await self.run_in_executor('
E and: ' None, getaddr_func, host, port, family, type, proto, flags)'
E and: ''
E and: '/usr/lib64/python3.8/asyncio/base_events.py:825: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = None'
E and: ''
E and: ' def run(self):'
E and: ' if not self.future.set_running_or_notify_cancel():'
E and: ' return'
E and: ' '
E and: ' try:'
E and: '> result = self.fn(*self.args, **self.kwargs)'
E and: ''
E and: '/usr/lib64/python3.8/concurrent/futures/thread.py:57: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = b'www.example.com', port = 80, family = <AddressFamily.AF_UNSPEC: 0>"
E and: 'type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0'
E and: ''
E and: ' def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):'
E and: ' """Resolve host and port into list of address info entries.'
E and: ' '
E and: ' Translate the host/port argument into a sequence of 5-tuples that contain'
E and: ' all the necessary arguments for creating a socket connected to that service.'
E and: ' host is a domain name, a string representation of an IPv4/v6 address or'
E and: " None. port is a string service name such as 'http', a numeric port number or"
E and: ' None. By passing None as the value of host and port, you can pass NULL to'
E and: ' the underlying C API.'
E and: ' '
E and: ' The family, type and proto arguments can be optionally specified in order to'
E and: ' narrow the list of addresses returned. Passing zero as a value for each of'
E and: ' these arguments selects the full range of results.'
E and: ' """'
E and: ' # We override this function since we want to translate the numeric family'
E and: ' # and socket type values to enum constants.'
E and: ' addrlist = []'
E and: '> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):'
E and: 'E socket.gaierror: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib64/python3.8/socket.py:918: gaierror'
E and: ''
E and: 'During handling of the above exception, another exception occurred:'
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_httpcore_exceptions() -> typing.Iterator[None]:'
E and: ' try:'
E and: '> yield'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:60: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpx.AsyncHTTPTransport object at 0x7f64c7cc0e50>'
E and: "request = <Request('GET', 'http://www.example.com/')>"
E and: ''
E and: ' async def handle_async_request('
E and: ' self,'
E and: ' request: Request,'
E and: ' ) -> Response:'
E and: ' assert isinstance(request.stream, AsyncByteStream)'
E and: ' '
E and: ' req = httpcore.Request('
E and: ' method=request.method,'
E and: ' url=httpcore.URL('
E and: ' scheme=request.url.raw_scheme,'
E and: ' host=request.url.raw_host,'
E and: ' port=request.url.port,'
E and: ' target=request.url.raw_path,'
E and: ' ),'
E and: ' headers=request.headers.raw,'
E and: ' content=request.stream,'
E and: ' extensions=request.extensions,'
E and: ' )'
E and: ' with map_httpcore_exceptions():'
E and: '> resp = await self._pool.handle_async_request(req)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.AsyncConnectionPool object at 0x7f64c7cc0d30>'
E and: "request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' """'
E and: ' Send an HTTP request, and return an HTTP response.'
E and: ' '
E and: ' This is the core implementation that is called into by `.request()` or `.stream()`.'
E and: ' """'
E and: ' scheme = request.url.scheme.decode()'
E and: ' if scheme == "":'
E and: ' raise UnsupportedProtocol('
E and: ' "Request URL is missing an \'http://\' or \'https://\' protocol."'
E and: ' )'
E and: ' if scheme not in ("http", "https"):'
E and: ' raise UnsupportedProtocol('
E and: ' f"Request URL has an unsupported protocol \'{scheme}://\'."'
E and: ' )'
E and: ' '
E and: ' status = RequestStatus(request)'
E and: ' '
E and: ' async with self._pool_lock:'
E and: ' self._requests.append(status)'
E and: ' await self._close_expired_connections()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' '
E and: ' while True:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("pool", None)'
E and: ' try:'
E and: ' connection = await status.wait_for_connection(timeout=timeout)'
E and: ' except BaseException as exc:'
E and: ' # If we timeout here, or if the task is cancelled, then make'
E and: ' # sure to remove the request from the queue before bubbling'
E and: ' # up the exception.'
E and: ' async with self._pool_lock:'
E and: ' self._requests.remove(status)'
E and: ' raise exc'
E and: ' '
E and: ' try:'
E and: ' response = await connection.handle_async_request(request)'
E and: ' except ConnectionNotAvailable:'
E and: ' # The ConnectionNotAvailable exception is a special case, that'
E and: ' # indicates we need to retry the request on a new connection.'
E and: ' #'
E and: ' # The most common case where this can occur is when multiple'
E and: ' # requests are queued waiting for a single connection, which'
E and: ' # might end up as an HTTP/2 connection, but which actually ends'
E and: ' # up as HTTP/1.1.'
E and: ' async with self._pool_lock:'
E and: ' # Maintain our position in the request queue, but reset the'
E and: ' # status so that the request becomes queued again.'
E and: ' status.unset_connection()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' except BaseException as exc:'
E and: ' await self.response_closed(status)'
E and: '> raise exc'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:253: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.AsyncConnectionPool object at 0x7f64c7cc0d30>'
E and: "request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' """'
E and: ' Send an HTTP request, and return an HTTP response.'
E and: ' '
E and: ' This is the core implementation that is called into by `.request()` or `.stream()`.'
E and: ' """'
E and: ' scheme = request.url.scheme.decode()'
E and: ' if scheme == "":'
E and: ' raise UnsupportedProtocol('
E and: ' "Request URL is missing an \'http://\' or \'https://\' protocol."'
E and: ' )'
E and: ' if scheme not in ("http", "https"):'
E and: ' raise UnsupportedProtocol('
E and: ' f"Request URL has an unsupported protocol \'{scheme}://\'."'
E and: ' )'
E and: ' '
E and: ' status = RequestStatus(request)'
E and: ' '
E and: ' async with self._pool_lock:'
E and: ' self._requests.append(status)'
E and: ' await self._close_expired_connections()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' '
E and: ' while True:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("pool", None)'
E and: ' try:'
E and: ' connection = await status.wait_for_connection(timeout=timeout)'
E and: ' except BaseException as exc:'
E and: ' # If we timeout here, or if the task is cancelled, then make'
E and: ' # sure to remove the request from the queue before bubbling'
E and: ' # up the exception.'
E and: ' async with self._pool_lock:'
E and: ' self._requests.remove(status)'
E and: ' raise exc'
E and: ' '
E and: ' try:'
E and: '> response = await connection.handle_async_request(request)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:237: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' if not self.can_handle_request(request.url.origin):'
E and: ' raise RuntimeError('
E and: ' f"Attempted to send request to {request.url.origin} on connection to {self._origin}"'
E and: ' )'
E and: ' '
E and: ' async with self._request_lock:'
E and: ' if self._connection is None:'
E and: ' try:'
E and: ' stream = await self._connect(request)'
E and: ' '
E and: ' ssl_object = stream.get_extra_info("ssl_object")'
E and: ' http2_negotiated = ('
E and: ' ssl_object is not None'
E and: ' and ssl_object.selected_alpn_protocol() == "h2"'
E and: ' )'
E and: ' if http2_negotiated or (self._http2 and not self._http1):'
E and: ' from .http2 import AsyncHTTP2Connection'
E and: ' '
E and: ' self._connection = AsyncHTTP2Connection('
E and: ' origin=self._origin,'
E and: ' stream=stream,'
E and: ' keepalive_expiry=self._keepalive_expiry,'
E and: ' )'
E and: ' else:'
E and: ' self._connection = AsyncHTTP11Connection('
E and: ' origin=self._origin,'
E and: ' stream=stream,'
E and: ' keepalive_expiry=self._keepalive_expiry,'
E and: ' )'
E and: ' except Exception as exc:'
E and: ' self._connect_failed = True'
E and: '> raise exc'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:86: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' if not self.can_handle_request(request.url.origin):'
E and: ' raise RuntimeError('
E and: ' f"Attempted to send request to {request.url.origin} on connection to {self._origin}"'
E and: ' )'
E and: ' '
E and: ' async with self._request_lock:'
E and: ' if self._connection is None:'
E and: ' try:'
E and: '> stream = await self._connect(request)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:63: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def _connect(self, request: Request) -> AsyncNetworkStream:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("connect", None)'
E and: ' '
E and: ' retries_left = self._retries'
E and: ' delays = exponential_backoff(factor=RETRIES_BACKOFF_FACTOR)'
E and: ' '
E and: ' while True:'
E and: ' try:'
E and: ' if self._uds is None:'
E and: ' kwargs = {'
E and: ' "host": self._origin.host.decode("ascii"),'
E and: ' "port": self._origin.port,'
E and: ' "local_address": self._local_address,'
E and: ' "timeout": timeout,'
E and: ' }'
E and: ' async with Trace('
E and: ' "connection.connect_tcp", request, kwargs'
E and: ' ) as trace:'
E and: '> stream = await self._network_backend.connect_tcp(**kwargs)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:111: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.auto.AutoBackend object at 0x7f64c7cc0c10>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: Optional[float] = None,'
E and: ' local_address: Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' await self._init_backend()'
E and: '> return await self._backend.connect_tcp('
E and: ' host, port, timeout=timeout, local_address=local_address'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/auto.py:29: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f64c7cdb430>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: typing.Optional[float] = None,'
E and: ' local_address: typing.Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' exc_map = {'
E and: ' TimeoutError: ConnectTimeout,'
E and: ' OSError: ConnectError,'
E and: ' anyio.BrokenResourceError: ConnectError,'
E and: ' }'
E and: ' with map_exceptions(exc_map):'
E and: ' with anyio.fail_after(timeout):'
E and: '> stream: anyio.abc.ByteStream = await anyio.connect_tcp('
E and: ' remote_host=host,'
E and: ' remote_port=port,'
E and: ' local_host=local_address,'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <contextlib._GeneratorContextManager object at 0x7f64c7cdb460>'
E and: "type = <class 'socket.gaierror'>"
E and: "value = gaierror(-2, 'Name or service not known')"
E and: 'traceback = <traceback object at 0x7f64c7d6d440>'
E and: ''
E and: ' def __exit__(self, type, value, traceback):'
E and: ' if type is None:'
E and: ' try:'
E and: ' next(self.gen)'
E and: ' except StopIteration:'
E and: ' return False'
E and: ' else:'
E and: ' raise RuntimeError("generator didn\'t stop")'
E and: ' else:'
E and: ' if value is None:'
E and: ' # Need to force instantiation so we can reliably'
E and: ' # tell if we get the same exception back'
E and: ' value = type()'
E and: ' try:'
E and: '> self.gen.throw(type, value, traceback)'
E and: ''
E and: '/usr/lib64/python3.8/contextlib.py:131: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}"
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:'
E and: ' try:'
E and: ' yield'
E and: ' except Exception as exc: # noqa: PIE786'
E and: ' for from_exc, to_exc in map.items():'
E and: ' if isinstance(exc, from_exc):'
E and: '> raise to_exc(exc)'
E and: 'E httpcore.ConnectError: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:12: ConnectError'
E and: ''
E and: 'The above exception was the direct cause of the following exception:'
E and: ''
E and: ' async def test_httpx():'
E and: ' async with httpx.AsyncClient() as client:'
E and: '> await client.get("http://www.example.com/")'
E and: ''
E and: 'test_httpx_fails.py:11: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1751: in get'
E and: ' return await self.request('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1527: in request'
E and: ' return await self.send(request, auth=auth, follow_redirects=follow_redirects)'
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1614: in send'
E and: ' response = await self._send_handling_auth('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1642: in _send_handling_auth'
E and: ' response = await self._send_handling_redirects('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1679: in _send_handling_redirects'
E and: ' response = await self._send_single_request(request)'
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1716: in _send_single_request'
E and: ' response = await transport.handle_async_request(request)'
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: in handle_async_request'
E and: ' resp = await self._pool.handle_async_request(req)'
E and: '/usr/lib64/python3.8/contextlib.py:131: in __exit__'
E and: ' self.gen.throw(type, value, traceback)'
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_httpcore_exceptions() -> typing.Iterator[None]:'
E and: ' try:'
E and: ' yield'
E and: ' except Exception as exc: # noqa: PIE-786'
E and: ' mapped_exc = None'
E and: ' '
E and: ' for from_exc, to_exc in HTTPCORE_EXC_MAP.items():'
E and: ' if not isinstance(exc, from_exc):'
E and: ' continue'
E and: ' # We want to map to the most specific exception we can find.'
E and: ' # Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to'
E and: ' # `httpx.ReadTimeout`, not just `httpx.TimeoutException`.'
E and: ' if mapped_exc is None or issubclass(to_exc, mapped_exc):'
E and: ' mapped_exc = to_exc'
E and: ' '
E and: ' if mapped_exc is None: # pragma: nocover'
E and: ' raise'
E and: ' '
E and: ' message = str(exc)'
E and: '> raise mapped_exc(message) from exc'
E and: 'E httpx.ConnectError: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:77: ConnectError'
E and: '=========================== short test summary info ============================'
E and: 'FAILED test_httpx_fails.py::test_httpx - httpx.ConnectError: [Errno -2] Name ...'
E and: '============================== 1 failed in 0.41s ==============================='
E remains unmatched: '*SocketBlockedError: A test tried to use socket.socket.*'
/home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1/tests/test_socket.py:32: Failed
--------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
============================= test session starts ==============================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
rootdir: /tmp/pytest-of-tkloczko/pytest-114/test_httpx_fails0
plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2
collected 1 item
test_httpx_fails.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_httpx __________________________________
map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}
@contextlib.contextmanager
def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:
try:
> yield
/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:8:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f64c7cdb430>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: typing.Optional[float] = None,
local_address: typing.Optional[str] = None,
) -> AsyncNetworkStream:
exc_map = {
TimeoutError: ConnectTimeout,
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
with map_exceptions(exc_map):
with anyio.fail_after(timeout):
> stream: anyio.abc.ByteStream = await anyio.connect_tcp(
remote_host=host,
remote_port=port,
local_host=local_address,
)
/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
remote_host = 'www.example.com', remote_port = 80
async def connect_tcp(
remote_host: IPAddressType,
remote_port: int,
*,
local_host: Optional[IPAddressType] = None,
tls: bool = False,
ssl_context: Optional[ssl.SSLContext] = None,
tls_standard_compatible: bool = True,
tls_hostname: Optional[str] = None,
happy_eyeballs_delay: float = 0.25,
) -> Union[SocketStream, TLSStream]:
"""
Connect to a host using the TCP protocol.
This function implements the stateless version of the Happy Eyeballs algorithm (RFC 6555).
If ``address`` is a host name that resolves to multiple IP addresses, each one is tried until
one connection attempt succeeds. If the first attempt does not connected within 250
milliseconds, a second attempt is started using the next address in the list, and so on.
On IPv6 enabled systems, an IPv6 address (if available) is tried first.
When the connection has been established, a TLS handshake will be done if either
``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``.
:param remote_host: the IP address or host name to connect to
:param remote_port: port on the target host to connect to
:param local_host: the interface address or name to bind the socket to before connecting
:param tls: ``True`` to do a TLS handshake with the connected stream and return a
:class:`~anyio.streams.tls.TLSStream` instead
:param ssl_context: the SSL context object to use (if omitted, a default context is created)
:param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake before closing
the stream and requires that the server does this as well. Otherwise,
:exc:`~ssl.SSLEOFError` may be raised during reads from the stream.
Some protocols, such as HTTP, require this option to be ``False``.
See :meth:`~ssl.SSLContext.wrap_socket` for details.
:param tls_hostname: host name to check the server certificate against (defaults to the value
of ``remote_host``)
:param happy_eyeballs_delay: delay (in seconds) before starting the next connection attempt
:return: a socket stream object if no TLS handshake was done, otherwise a TLS stream
:raises OSError: if the connection attempt fails
"""
# Placed here due to https://github.com/python/mypy/issues/7057
connected_stream: Optional[SocketStream] = None
async def try_connect(remote_host: str, event: Event) -> None:
nonlocal connected_stream
try:
stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)
except OSError as exc:
oserrors.append(exc)
return
else:
if connected_stream is None:
connected_stream = stream
tg.cancel_scope.cancel()
else:
await stream.aclose()
finally:
event.set()
asynclib = get_asynclib()
local_address: Optional[IPSockAddrType] = None
family = socket.AF_UNSPEC
if local_host:
gai_res = await getaddrinfo(str(local_host), None)
family, *_, local_address = gai_res[0]
target_host = str(remote_host)
try:
addr_obj = ip_address(remote_host)
except ValueError:
# getaddrinfo() will raise an exception if name resolution fails
> gai_res = await getaddrinfo(
target_host, remote_port, family=family, type=socket.SOCK_STREAM
)
/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:189:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = 'www.example.com', port = 80
async def getaddrinfo(
host: Union[bytearray, bytes, str],
port: Union[str, int, None],
*,
family: Union[int, AddressFamily] = 0,
type: Union[int, SocketKind] = 0,
proto: int = 0,
flags: int = 0,
) -> GetAddrInfoReturnType:
"""
Look up a numeric IP address given a host name.
Internationalized domain names are translated according to the (non-transitional) IDNA 2008
standard.
.. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of
(host, port), unlike what :func:`socket.getaddrinfo` does.
:param host: host name
:param port: port number
:param family: socket family (`'AF_INET``, ...)
:param type: socket type (``SOCK_STREAM``, ...)
:param proto: protocol number
:param flags: flags to pass to upstream ``getaddrinfo()``
:return: list of tuples containing (family, type, proto, canonname, sockaddr)
.. seealso:: :func:`socket.getaddrinfo`
"""
# Handle unicode hostnames
if isinstance(host, str):
try:
encoded_host = host.encode("ascii")
except UnicodeEncodeError:
import idna
encoded_host = idna.encode(host, uts46=True)
else:
encoded_host = host
> gai_res = await get_asynclib().getaddrinfo(
encoded_host, port, family=family, type=type, proto=proto, flags=flags
)
/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:496:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = b'www.example.com', port = 80
async def getaddrinfo(
host: Union[bytes, str],
port: Union[str, int, None],
*,
family: Union[int, AddressFamily] = 0,
type: Union[int, SocketKind] = 0,
proto: int = 0,
flags: int = 0,
) -> GetAddrInfoReturnType:
# https://github.com/python/typeshed/pull/4304
> result = await get_running_loop().getaddrinfo(
host, port, family=family, type=type, proto=proto, flags=flags
)
/usr/lib/python3.8/site-packages/anyio/_backends/_asyncio.py:1754:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <_UnixSelectorEventLoop running=False closed=True debug=False>
host = b'www.example.com', port = 80
async def getaddrinfo(self, host, port, *,
family=0, type=0, proto=0, flags=0):
if self._debug:
getaddr_func = self._getaddrinfo_debug
else:
getaddr_func = socket.getaddrinfo
> return await self.run_in_executor(
None, getaddr_func, host, port, family, type, proto, flags)
/usr/lib64/python3.8/asyncio/base_events.py:825:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = None
def run(self):
if not self.future.set_running_or_notify_cancel():
return
try:
> result = self.fn(*self.args, **self.kwargs)
/usr/lib64/python3.8/concurrent/futures/thread.py:57:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = b'www.example.com', port = 80, family = <AddressFamily.AF_UNSPEC: 0>
type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.
Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.
The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno -2] Name or service not known
/usr/lib64/python3.8/socket.py:918: gaierror
During handling of the above exception, another exception occurred:
@contextlib.contextmanager
def map_httpcore_exceptions() -> typing.Iterator[None]:
try:
> yield
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpx.AsyncHTTPTransport object at 0x7f64c7cc0e50>
request = <Request('GET', 'http://www.example.com/')>
async def handle_async_request(
self,
request: Request,
) -> Response:
assert isinstance(request.stream, AsyncByteStream)
req = httpcore.Request(
method=request.method,
url=httpcore.URL(
scheme=request.url.raw_scheme,
host=request.url.raw_host,
port=request.url.port,
target=request.url.raw_path,
),
headers=request.headers.raw,
content=request.stream,
extensions=request.extensions,
)
with map_httpcore_exceptions():
> resp = await self._pool.handle_async_request(req)
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.AsyncConnectionPool object at 0x7f64c7cc0d30>
request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.
This is the core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
raise UnsupportedProtocol(
"Request URL is missing an 'http://' or 'https://' protocol."
)
if scheme not in ("http", "https"):
raise UnsupportedProtocol(
f"Request URL has an unsupported protocol '{scheme}://'."
)
status = RequestStatus(request)
async with self._pool_lock:
self._requests.append(status)
await self._close_expired_connections()
await self._attempt_to_acquire_connection(status)
while True:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("pool", None)
try:
connection = await status.wait_for_connection(timeout=timeout)
except BaseException as exc:
# If we timeout here, or if the task is cancelled, then make
# sure to remove the request from the queue before bubbling
# up the exception.
async with self._pool_lock:
self._requests.remove(status)
raise exc
try:
response = await connection.handle_async_request(request)
except ConnectionNotAvailable:
# The ConnectionNotAvailable exception is a special case, that
# indicates we need to retry the request on a new connection.
#
# The most common case where this can occur is when multiple
# requests are queued waiting for a single connection, which
# might end up as an HTTP/2 connection, but which actually ends
# up as HTTP/1.1.
async with self._pool_lock:
# Maintain our position in the request queue, but reset the
# status so that the request becomes queued again.
status.unset_connection()
await self._attempt_to_acquire_connection(status)
except BaseException as exc:
await self.response_closed(status)
> raise exc
/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:253:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.AsyncConnectionPool object at 0x7f64c7cc0d30>
request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.
This is the core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
raise UnsupportedProtocol(
"Request URL is missing an 'http://' or 'https://' protocol."
)
if scheme not in ("http", "https"):
raise UnsupportedProtocol(
f"Request URL has an unsupported protocol '{scheme}://'."
)
status = RequestStatus(request)
async with self._pool_lock:
self._requests.append(status)
await self._close_expired_connections()
await self._attempt_to_acquire_connection(status)
while True:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("pool", None)
try:
connection = await status.wait_for_connection(timeout=timeout)
except BaseException as exc:
# If we timeout here, or if the task is cancelled, then make
# sure to remove the request from the queue before bubbling
# up the exception.
async with self._pool_lock:
self._requests.remove(status)
raise exc
try:
> response = await connection.handle_async_request(request)
/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:237:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
)
async with self._request_lock:
if self._connection is None:
try:
stream = await self._connect(request)
ssl_object = stream.get_extra_info("ssl_object")
http2_negotiated = (
ssl_object is not None
and ssl_object.selected_alpn_protocol() == "h2"
)
if http2_negotiated or (self._http2 and not self._http1):
from .http2 import AsyncHTTP2Connection
self._connection = AsyncHTTP2Connection(
origin=self._origin,
stream=stream,
keepalive_expiry=self._keepalive_expiry,
)
else:
self._connection = AsyncHTTP11Connection(
origin=self._origin,
stream=stream,
keepalive_expiry=self._keepalive_expiry,
)
except Exception as exc:
self._connect_failed = True
> raise exc
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:86:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
)
async with self._request_lock:
if self._connection is None:
try:
> stream = await self._connect(request)
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:63:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def _connect(self, request: Request) -> AsyncNetworkStream:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("connect", None)
retries_left = self._retries
delays = exponential_backoff(factor=RETRIES_BACKOFF_FACTOR)
while True:
try:
if self._uds is None:
kwargs = {
"host": self._origin.host.decode("ascii"),
"port": self._origin.port,
"local_address": self._local_address,
"timeout": timeout,
}
async with Trace(
"connection.connect_tcp", request, kwargs
) as trace:
> stream = await self._network_backend.connect_tcp(**kwargs)
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:111:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.auto.AutoBackend object at 0x7f64c7cc0c10>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: Optional[float] = None,
local_address: Optional[str] = None,
) -> AsyncNetworkStream:
await self._init_backend()
> return await self._backend.connect_tcp(
host, port, timeout=timeout, local_address=local_address
)
/usr/lib/python3.8/site-packages/httpcore/backends/auto.py:29:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f64c7cdb430>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: typing.Optional[float] = None,
local_address: typing.Optional[str] = None,
) -> AsyncNetworkStream:
exc_map = {
TimeoutError: ConnectTimeout,
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
with map_exceptions(exc_map):
with anyio.fail_after(timeout):
> stream: anyio.abc.ByteStream = await anyio.connect_tcp(
remote_host=host,
remote_port=port,
local_host=local_address,
)
/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <contextlib._GeneratorContextManager object at 0x7f64c7cdb460>
type = <class 'socket.gaierror'>
value = gaierror(-2, 'Name or service not known')
traceback = <traceback object at 0x7f64c7d6d440>
def __exit__(self, type, value, traceback):
if type is None:
try:
next(self.gen)
except StopIteration:
return False
else:
raise RuntimeError("generator didn't stop")
else:
if value is None:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value = type()
try:
> self.gen.throw(type, value, traceback)
/usr/lib64/python3.8/contextlib.py:131:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}
@contextlib.contextmanager
def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:
try:
yield
except Exception as exc: # noqa: PIE786
for from_exc, to_exc in map.items():
if isinstance(exc, from_exc):
> raise to_exc(exc)
E httpcore.ConnectError: [Errno -2] Name or service not known
/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:12: ConnectError
The above exception was the direct cause of the following exception:
async def test_httpx():
async with httpx.AsyncClient() as client:
> await client.get("http://www.example.com/")
test_httpx_fails.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/httpx/_client.py:1751: in get
return await self.request(
/usr/lib/python3.8/site-packages/httpx/_client.py:1527: in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
/usr/lib/python3.8/site-packages/httpx/_client.py:1614: in send
response = await self._send_handling_auth(
/usr/lib/python3.8/site-packages/httpx/_client.py:1642: in _send_handling_auth
response = await self._send_handling_redirects(
/usr/lib/python3.8/site-packages/httpx/_client.py:1679: in _send_handling_redirects
response = await self._send_single_request(request)
/usr/lib/python3.8/site-packages/httpx/_client.py:1716: in _send_single_request
response = await transport.handle_async_request(request)
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: in handle_async_request
resp = await self._pool.handle_async_request(req)
/usr/lib64/python3.8/contextlib.py:131: in __exit__
self.gen.throw(type, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@contextlib.contextmanager
def map_httpcore_exceptions() -> typing.Iterator[None]:
try:
yield
except Exception as exc: # noqa: PIE-786
mapped_exc = None
for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
if not isinstance(exc, from_exc):
continue
# We want to map to the most specific exception we can find.
# Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
# `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
if mapped_exc is None or issubclass(to_exc, mapped_exc):
mapped_exc = to_exc
if mapped_exc is None: # pragma: nocover
raise
message = str(exc)
> raise mapped_exc(message) from exc
E httpx.ConnectError: [Errno -2] Name or service not known
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:77: ConnectError
=========================== short test summary info ============================
FAILED test_httpx_fails.py::test_httpx - httpx.ConnectError: [Errno -2] Name ...
============================== 1 failed in 0.41s ===============================
========================================================================= short test summary info ==========================================================================
FAILED tests/test_async.py::test_httpx_fails - Failed: nomatch: '*SocketBlockedError: A test tried to use socket.socket.*'
================================================================= 1 failed, 58 passed in 82.32s (0:01:22) ==================================================================
One sec let me check 😋
OK I see that my automationa alredy packaged httpx 0.23.0 so I need only retest this module 😄
Nope .. looks like it still fails 😞
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.1-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.1-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1
plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2
collected 59 items
tests/test_async.py ..F [ 5%]
tests/test_combinations.py .. [ 8%]
tests/test_doctest.py . [ 10%]
tests/test_precedence.py ........ [ 23%]
tests/test_restrict_hosts.py ....................... [ 62%]
tests/test_socket.py ...................... [100%]
================================================================================= FAILURES =================================================================================
_____________________________________________________________________________ test_httpx_fails _____________________________________________________________________________
testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-140/test_httpx_fails0')>
@unix_sockets_only
def test_httpx_fails(testdir):
testdir.makepyfile(
"""
import pytest
import httpx
@pytest.fixture(autouse=True)
def anyio_backend():
return "asyncio"
async def test_httpx():
async with httpx.AsyncClient() as client:
await client.get("http://www.example.com/")
"""
)
result = testdir.runpytest("--disable-socket", "--allow-unix-socket")
> assert_socket_blocked(result)
/home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1/tests/test_async.py:75:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
result = <RunResult ret=ExitCode.TESTS_FAILED len(stdout.lines)=608 len(stderr.lines)=0 duration=0.46s>
def assert_socket_blocked(result):
result.assert_outcomes(passed=0, skipped=0, failed=1)
> result.stdout.fnmatch_lines(
"*SocketBlockedError: A test tried to use socket.socket.*"
)
E Failed: nomatch: '*SocketBlockedError: A test tried to use socket.socket.*'
E and: '============================= test session starts =============================='
E and: 'platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0'
E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-140/test_httpx_fails0'
E and: 'plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2'
E and: 'collected 1 item'
E and: ''
E and: 'test_httpx_fails.py F [100%]'
E and: ''
E and: '=================================== FAILURES ==================================='
E and: '__________________________________ test_httpx __________________________________'
E and: ''
E and: "map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}"
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:'
E and: ' try:'
E and: '> yield'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:8: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f3b3408ebe0>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: typing.Optional[float] = None,'
E and: ' local_address: typing.Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' exc_map = {'
E and: ' TimeoutError: ConnectTimeout,'
E and: ' OSError: ConnectError,'
E and: ' anyio.BrokenResourceError: ConnectError,'
E and: ' }'
E and: ' with map_exceptions(exc_map):'
E and: ' with anyio.fail_after(timeout):'
E and: '> stream: anyio.abc.ByteStream = await anyio.connect_tcp('
E and: ' remote_host=host,'
E and: ' remote_port=port,'
E and: ' local_host=local_address,'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "remote_host = 'www.example.com', remote_port = 80"
E and: ''
E and: ' async def connect_tcp('
E and: ' remote_host: IPAddressType,'
E and: ' remote_port: int,'
E and: ' *,'
E and: ' local_host: Optional[IPAddressType] = None,'
E and: ' tls: bool = False,'
E and: ' ssl_context: Optional[ssl.SSLContext] = None,'
E and: ' tls_standard_compatible: bool = True,'
E and: ' tls_hostname: Optional[str] = None,'
E and: ' happy_eyeballs_delay: float = 0.25,'
E and: ' ) -> Union[SocketStream, TLSStream]:'
E and: ' """'
E and: ' Connect to a host using the TCP protocol.'
E and: ' '
E and: ' This function implements the stateless version of the Happy Eyeballs algorithm (RFC 6555).'
E and: ' If ``address`` is a host name that resolves to multiple IP addresses, each one is tried until'
E and: ' one connection attempt succeeds. If the first attempt does not connected within 250'
E and: ' milliseconds, a second attempt is started using the next address in the list, and so on.'
E and: ' On IPv6 enabled systems, an IPv6 address (if available) is tried first.'
E and: ' '
E and: ' When the connection has been established, a TLS handshake will be done if either'
E and: ' ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``.'
E and: ' '
E and: ' :param remote_host: the IP address or host name to connect to'
E and: ' :param remote_port: port on the target host to connect to'
E and: ' :param local_host: the interface address or name to bind the socket to before connecting'
E and: ' :param tls: ``True`` to do a TLS handshake with the connected stream and return a'
E and: ' :class:`~anyio.streams.tls.TLSStream` instead'
E and: ' :param ssl_context: the SSL context object to use (if omitted, a default context is created)'
E and: ' :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake before closing'
E and: ' the stream and requires that the server does this as well. Otherwise,'
E and: ' :exc:`~ssl.SSLEOFError` may be raised during reads from the stream.'
E and: ' Some protocols, such as HTTP, require this option to be ``False``.'
E and: ' See :meth:`~ssl.SSLContext.wrap_socket` for details.'
E and: ' :param tls_hostname: host name to check the server certificate against (defaults to the value'
E and: ' of ``remote_host``)'
E and: ' :param happy_eyeballs_delay: delay (in seconds) before starting the next connection attempt'
E and: ' :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream'
E and: ' :raises OSError: if the connection attempt fails'
E and: ' '
E and: ' """'
E and: ' # Placed here due to https://github.com/python/mypy/issues/7057'
E and: ' connected_stream: Optional[SocketStream] = None'
E and: ' '
E and: ' async def try_connect(remote_host: str, event: Event) -> None:'
E and: ' nonlocal connected_stream'
E and: ' try:'
E and: ' stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)'
E and: ' except OSError as exc:'
E and: ' oserrors.append(exc)'
E and: ' return'
E and: ' else:'
E and: ' if connected_stream is None:'
E and: ' connected_stream = stream'
E and: ' tg.cancel_scope.cancel()'
E and: ' else:'
E and: ' await stream.aclose()'
E and: ' finally:'
E and: ' event.set()'
E and: ' '
E and: ' asynclib = get_asynclib()'
E and: ' local_address: Optional[IPSockAddrType] = None'
E and: ' family = socket.AF_UNSPEC'
E and: ' if local_host:'
E and: ' gai_res = await getaddrinfo(str(local_host), None)'
E and: ' family, *_, local_address = gai_res[0]'
E and: ' '
E and: ' target_host = str(remote_host)'
E and: ' try:'
E and: ' addr_obj = ip_address(remote_host)'
E and: ' except ValueError:'
E and: ' # getaddrinfo() will raise an exception if name resolution fails'
E and: '> gai_res = await getaddrinfo('
E and: ' target_host, remote_port, family=family, type=socket.SOCK_STREAM'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:189: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = 'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo('
E and: ' host: Union[bytearray, bytes, str],'
E and: ' port: Union[str, int, None],'
E and: ' *,'
E and: ' family: Union[int, AddressFamily] = 0,'
E and: ' type: Union[int, SocketKind] = 0,'
E and: ' proto: int = 0,'
E and: ' flags: int = 0,'
E and: ' ) -> GetAddrInfoReturnType:'
E and: ' """'
E and: ' Look up a numeric IP address given a host name.'
E and: ' '
E and: ' Internationalized domain names are translated according to the (non-transitional) IDNA 2008'
E and: ' standard.'
E and: ' '
E and: ' .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of'
E and: ' (host, port), unlike what :func:`socket.getaddrinfo` does.'
E and: ' '
E and: ' :param host: host name'
E and: ' :param port: port number'
E and: " :param family: socket family (`'AF_INET``, ...)"
E and: ' :param type: socket type (``SOCK_STREAM``, ...)'
E and: ' :param proto: protocol number'
E and: ' :param flags: flags to pass to upstream ``getaddrinfo()``'
E and: ' :return: list of tuples containing (family, type, proto, canonname, sockaddr)'
E and: ' '
E and: ' .. seealso:: :func:`socket.getaddrinfo`'
E and: ' '
E and: ' """'
E and: ' # Handle unicode hostnames'
E and: ' if isinstance(host, str):'
E and: ' try:'
E and: ' encoded_host = host.encode("ascii")'
E and: ' except UnicodeEncodeError:'
E and: ' import idna'
E and: ' '
E and: ' encoded_host = idna.encode(host, uts46=True)'
E and: ' else:'
E and: ' encoded_host = host'
E and: ' '
E and: '> gai_res = await get_asynclib().getaddrinfo('
E and: ' encoded_host, port, family=family, type=type, proto=proto, flags=flags'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:496: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = b'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo('
E and: ' host: Union[bytes, str],'
E and: ' port: Union[str, int, None],'
E and: ' *,'
E and: ' family: Union[int, AddressFamily] = 0,'
E and: ' type: Union[int, SocketKind] = 0,'
E and: ' proto: int = 0,'
E and: ' flags: int = 0,'
E and: ' ) -> GetAddrInfoReturnType:'
E and: ' # https://github.com/python/typeshed/pull/4304'
E and: '> result = await get_running_loop().getaddrinfo('
E and: ' host, port, family=family, type=type, proto=proto, flags=flags'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/anyio/_backends/_asyncio.py:1754: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <_UnixSelectorEventLoop running=False closed=True debug=False>'
E and: "host = b'www.example.com', port = 80"
E and: ''
E and: ' async def getaddrinfo(self, host, port, *,'
E and: ' family=0, type=0, proto=0, flags=0):'
E and: ' if self._debug:'
E and: ' getaddr_func = self._getaddrinfo_debug'
E and: ' else:'
E and: ' getaddr_func = socket.getaddrinfo'
E and: ' '
E and: '> return await self.run_in_executor('
E and: ' None, getaddr_func, host, port, family, type, proto, flags)'
E and: ''
E and: '/usr/lib64/python3.8/asyncio/base_events.py:825: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = None'
E and: ''
E and: ' def run(self):'
E and: ' if not self.future.set_running_or_notify_cancel():'
E and: ' return'
E and: ' '
E and: ' try:'
E and: '> result = self.fn(*self.args, **self.kwargs)'
E and: ''
E and: '/usr/lib64/python3.8/concurrent/futures/thread.py:57: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "host = b'www.example.com', port = 80, family = <AddressFamily.AF_UNSPEC: 0>"
E and: 'type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0'
E and: ''
E and: ' def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):'
E and: ' """Resolve host and port into list of address info entries.'
E and: ' '
E and: ' Translate the host/port argument into a sequence of 5-tuples that contain'
E and: ' all the necessary arguments for creating a socket connected to that service.'
E and: ' host is a domain name, a string representation of an IPv4/v6 address or'
E and: " None. port is a string service name such as 'http', a numeric port number or"
E and: ' None. By passing None as the value of host and port, you can pass NULL to'
E and: ' the underlying C API.'
E and: ' '
E and: ' The family, type and proto arguments can be optionally specified in order to'
E and: ' narrow the list of addresses returned. Passing zero as a value for each of'
E and: ' these arguments selects the full range of results.'
E and: ' """'
E and: ' # We override this function since we want to translate the numeric family'
E and: ' # and socket type values to enum constants.'
E and: ' addrlist = []'
E and: '> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):'
E and: 'E socket.gaierror: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib64/python3.8/socket.py:918: gaierror'
E and: ''
E and: 'During handling of the above exception, another exception occurred:'
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_httpcore_exceptions() -> typing.Iterator[None]:'
E and: ' try:'
E and: '> yield'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:60: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpx.AsyncHTTPTransport object at 0x7f3b340730a0>'
E and: "request = <Request('GET', 'http://www.example.com/')>"
E and: ''
E and: ' async def handle_async_request('
E and: ' self,'
E and: ' request: Request,'
E and: ' ) -> Response:'
E and: ' assert isinstance(request.stream, AsyncByteStream)'
E and: ' '
E and: ' req = httpcore.Request('
E and: ' method=request.method,'
E and: ' url=httpcore.URL('
E and: ' scheme=request.url.raw_scheme,'
E and: ' host=request.url.raw_host,'
E and: ' port=request.url.port,'
E and: ' target=request.url.raw_path,'
E and: ' ),'
E and: ' headers=request.headers.raw,'
E and: ' content=request.stream,'
E and: ' extensions=request.extensions,'
E and: ' )'
E and: ' with map_httpcore_exceptions():'
E and: '> resp = await self._pool.handle_async_request(req)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.AsyncConnectionPool object at 0x7f3b34073250>'
E and: "request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' """'
E and: ' Send an HTTP request, and return an HTTP response.'
E and: ' '
E and: ' This is the core implementation that is called into by `.request()` or `.stream()`.'
E and: ' """'
E and: ' scheme = request.url.scheme.decode()'
E and: ' if scheme == "":'
E and: ' raise UnsupportedProtocol('
E and: ' "Request URL is missing an \'http://\' or \'https://\' protocol."'
E and: ' )'
E and: ' if scheme not in ("http", "https"):'
E and: ' raise UnsupportedProtocol('
E and: ' f"Request URL has an unsupported protocol \'{scheme}://\'."'
E and: ' )'
E and: ' '
E and: ' status = RequestStatus(request)'
E and: ' '
E and: ' async with self._pool_lock:'
E and: ' self._requests.append(status)'
E and: ' await self._close_expired_connections()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' '
E and: ' while True:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("pool", None)'
E and: ' try:'
E and: ' connection = await status.wait_for_connection(timeout=timeout)'
E and: ' except BaseException as exc:'
E and: ' # If we timeout here, or if the task is cancelled, then make'
E and: ' # sure to remove the request from the queue before bubbling'
E and: ' # up the exception.'
E and: ' async with self._pool_lock:'
E and: ' self._requests.remove(status)'
E and: ' raise exc'
E and: ' '
E and: ' try:'
E and: ' response = await connection.handle_async_request(request)'
E and: ' except ConnectionNotAvailable:'
E and: ' # The ConnectionNotAvailable exception is a special case, that'
E and: ' # indicates we need to retry the request on a new connection.'
E and: ' #'
E and: ' # The most common case where this can occur is when multiple'
E and: ' # requests are queued waiting for a single connection, which'
E and: ' # might end up as an HTTP/2 connection, but which actually ends'
E and: ' # up as HTTP/1.1.'
E and: ' async with self._pool_lock:'
E and: ' # Maintain our position in the request queue, but reset the'
E and: ' # status so that the request becomes queued again.'
E and: ' status.unset_connection()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' except BaseException as exc:'
E and: ' await self.response_closed(status)'
E and: '> raise exc'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:253: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.AsyncConnectionPool object at 0x7f3b34073250>'
E and: "request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' """'
E and: ' Send an HTTP request, and return an HTTP response.'
E and: ' '
E and: ' This is the core implementation that is called into by `.request()` or `.stream()`.'
E and: ' """'
E and: ' scheme = request.url.scheme.decode()'
E and: ' if scheme == "":'
E and: ' raise UnsupportedProtocol('
E and: ' "Request URL is missing an \'http://\' or \'https://\' protocol."'
E and: ' )'
E and: ' if scheme not in ("http", "https"):'
E and: ' raise UnsupportedProtocol('
E and: ' f"Request URL has an unsupported protocol \'{scheme}://\'."'
E and: ' )'
E and: ' '
E and: ' status = RequestStatus(request)'
E and: ' '
E and: ' async with self._pool_lock:'
E and: ' self._requests.append(status)'
E and: ' await self._close_expired_connections()'
E and: ' await self._attempt_to_acquire_connection(status)'
E and: ' '
E and: ' while True:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("pool", None)'
E and: ' try:'
E and: ' connection = await status.wait_for_connection(timeout=timeout)'
E and: ' except BaseException as exc:'
E and: ' # If we timeout here, or if the task is cancelled, then make'
E and: ' # sure to remove the request from the queue before bubbling'
E and: ' # up the exception.'
E and: ' async with self._pool_lock:'
E and: ' self._requests.remove(status)'
E and: ' raise exc'
E and: ' '
E and: ' try:'
E and: '> response = await connection.handle_async_request(request)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:237: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' if not self.can_handle_request(request.url.origin):'
E and: ' raise RuntimeError('
E and: ' f"Attempted to send request to {request.url.origin} on connection to {self._origin}"'
E and: ' )'
E and: ' '
E and: ' async with self._request_lock:'
E and: ' if self._connection is None:'
E and: ' try:'
E and: ' stream = await self._connect(request)'
E and: ' '
E and: ' ssl_object = stream.get_extra_info("ssl_object")'
E and: ' http2_negotiated = ('
E and: ' ssl_object is not None'
E and: ' and ssl_object.selected_alpn_protocol() == "h2"'
E and: ' )'
E and: ' if http2_negotiated or (self._http2 and not self._http1):'
E and: ' from .http2 import AsyncHTTP2Connection'
E and: ' '
E and: ' self._connection = AsyncHTTP2Connection('
E and: ' origin=self._origin,'
E and: ' stream=stream,'
E and: ' keepalive_expiry=self._keepalive_expiry,'
E and: ' )'
E and: ' else:'
E and: ' self._connection = AsyncHTTP11Connection('
E and: ' origin=self._origin,'
E and: ' stream=stream,'
E and: ' keepalive_expiry=self._keepalive_expiry,'
E and: ' )'
E and: ' except Exception as exc:'
E and: ' self._connect_failed = True'
E and: '> raise exc'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:86: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def handle_async_request(self, request: Request) -> Response:'
E and: ' if not self.can_handle_request(request.url.origin):'
E and: ' raise RuntimeError('
E and: ' f"Attempted to send request to {request.url.origin} on connection to {self._origin}"'
E and: ' )'
E and: ' '
E and: ' async with self._request_lock:'
E and: ' if self._connection is None:'
E and: ' try:'
E and: '> stream = await self._connect(request)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:63: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>"
E and: ''
E and: ' async def _connect(self, request: Request) -> AsyncNetworkStream:'
E and: ' timeouts = request.extensions.get("timeout", {})'
E and: ' timeout = timeouts.get("connect", None)'
E and: ' '
E and: ' retries_left = self._retries'
E and: ' delays = exponential_backoff(factor=RETRIES_BACKOFF_FACTOR)'
E and: ' '
E and: ' while True:'
E and: ' try:'
E and: ' if self._uds is None:'
E and: ' kwargs = {'
E and: ' "host": self._origin.host.decode("ascii"),'
E and: ' "port": self._origin.port,'
E and: ' "local_address": self._local_address,'
E and: ' "timeout": timeout,'
E and: ' }'
E and: ' async with Trace('
E and: ' "connection.connect_tcp", request, kwargs'
E and: ' ) as trace:'
E and: '> stream = await self._network_backend.connect_tcp(**kwargs)'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:111: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.auto.AutoBackend object at 0x7f3b34073d30>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: Optional[float] = None,'
E and: ' local_address: Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' await self._init_backend()'
E and: '> return await self._backend.connect_tcp('
E and: ' host, port, timeout=timeout, local_address=local_address'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/auto.py:29: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f3b3408ebe0>'
E and: "host = 'www.example.com', port = 80, timeout = 5.0, local_address = None"
E and: ''
E and: ' async def connect_tcp('
E and: ' self,'
E and: ' host: str,'
E and: ' port: int,'
E and: ' timeout: typing.Optional[float] = None,'
E and: ' local_address: typing.Optional[str] = None,'
E and: ' ) -> AsyncNetworkStream:'
E and: ' exc_map = {'
E and: ' TimeoutError: ConnectTimeout,'
E and: ' OSError: ConnectError,'
E and: ' anyio.BrokenResourceError: ConnectError,'
E and: ' }'
E and: ' with map_exceptions(exc_map):'
E and: ' with anyio.fail_after(timeout):'
E and: '> stream: anyio.abc.ByteStream = await anyio.connect_tcp('
E and: ' remote_host=host,'
E and: ' remote_port=port,'
E and: ' local_host=local_address,'
E and: ' )'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: 'self = <contextlib._GeneratorContextManager object at 0x7f3b3408eb50>'
E and: "type = <class 'socket.gaierror'>"
E and: "value = gaierror(-2, 'Name or service not known')"
E and: 'traceback = <traceback object at 0x7f3b3411fb40>'
E and: ''
E and: ' def __exit__(self, type, value, traceback):'
E and: ' if type is None:'
E and: ' try:'
E and: ' next(self.gen)'
E and: ' except StopIteration:'
E and: ' return False'
E and: ' else:'
E and: ' raise RuntimeError("generator didn\'t stop")'
E and: ' else:'
E and: ' if value is None:'
E and: ' # Need to force instantiation so we can reliably'
E and: ' # tell if we get the same exception back'
E and: ' value = type()'
E and: ' try:'
E and: '> self.gen.throw(type, value, traceback)'
E and: ''
E and: '/usr/lib64/python3.8/contextlib.py:131: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: "map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}"
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:'
E and: ' try:'
E and: ' yield'
E and: ' except Exception as exc: # noqa: PIE786'
E and: ' for from_exc, to_exc in map.items():'
E and: ' if isinstance(exc, from_exc):'
E and: '> raise to_exc(exc)'
E and: 'E httpcore.ConnectError: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:12: ConnectError'
E and: ''
E and: 'The above exception was the direct cause of the following exception:'
E and: ''
E and: ' async def test_httpx():'
E and: ' async with httpx.AsyncClient() as client:'
E and: '> await client.get("http://www.example.com/")'
E and: ''
E and: 'test_httpx_fails.py:11: '
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1751: in get'
E and: ' return await self.request('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1527: in request'
E and: ' return await self.send(request, auth=auth, follow_redirects=follow_redirects)'
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1614: in send'
E and: ' response = await self._send_handling_auth('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1642: in _send_handling_auth'
E and: ' response = await self._send_handling_redirects('
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1679: in _send_handling_redirects'
E and: ' response = await self._send_single_request(request)'
E and: '/usr/lib/python3.8/site-packages/httpx/_client.py:1716: in _send_single_request'
E and: ' response = await transport.handle_async_request(request)'
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: in handle_async_request'
E and: ' resp = await self._pool.handle_async_request(req)'
E and: '/usr/lib64/python3.8/contextlib.py:131: in __exit__'
E and: ' self.gen.throw(type, value, traceback)'
E and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
E and: ''
E and: ' @contextlib.contextmanager'
E and: ' def map_httpcore_exceptions() -> typing.Iterator[None]:'
E and: ' try:'
E and: ' yield'
E and: ' except Exception as exc: # noqa: PIE-786'
E and: ' mapped_exc = None'
E and: ' '
E and: ' for from_exc, to_exc in HTTPCORE_EXC_MAP.items():'
E and: ' if not isinstance(exc, from_exc):'
E and: ' continue'
E and: ' # We want to map to the most specific exception we can find.'
E and: ' # Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to'
E and: ' # `httpx.ReadTimeout`, not just `httpx.TimeoutException`.'
E and: ' if mapped_exc is None or issubclass(to_exc, mapped_exc):'
E and: ' mapped_exc = to_exc'
E and: ' '
E and: ' if mapped_exc is None: # pragma: nocover'
E and: ' raise'
E and: ' '
E and: ' message = str(exc)'
E and: '> raise mapped_exc(message) from exc'
E and: 'E httpx.ConnectError: [Errno -2] Name or service not known'
E and: ''
E and: '/usr/lib/python3.8/site-packages/httpx/_transports/default.py:77: ConnectError'
E and: '=========================== short test summary info ============================'
E and: 'FAILED test_httpx_fails.py::test_httpx - httpx.ConnectError: [Errno -2] Name ...'
E and: '============================== 1 failed in 0.41s ==============================='
E remains unmatched: '*SocketBlockedError: A test tried to use socket.socket.*'
/home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.1/tests/test_socket.py:32: Failed
--------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
============================= test session starts ==============================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
rootdir: /tmp/pytest-of-tkloczko/pytest-140/test_httpx_fails0
plugins: socket-0.5.1, anyio-3.6.1, httpbin-1.0.2
collected 1 item
test_httpx_fails.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_httpx __________________________________
map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}
@contextlib.contextmanager
def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:
try:
> yield
/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:8:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f3b3408ebe0>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: typing.Optional[float] = None,
local_address: typing.Optional[str] = None,
) -> AsyncNetworkStream:
exc_map = {
TimeoutError: ConnectTimeout,
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
with map_exceptions(exc_map):
with anyio.fail_after(timeout):
> stream: anyio.abc.ByteStream = await anyio.connect_tcp(
remote_host=host,
remote_port=port,
local_host=local_address,
)
/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
remote_host = 'www.example.com', remote_port = 80
async def connect_tcp(
remote_host: IPAddressType,
remote_port: int,
*,
local_host: Optional[IPAddressType] = None,
tls: bool = False,
ssl_context: Optional[ssl.SSLContext] = None,
tls_standard_compatible: bool = True,
tls_hostname: Optional[str] = None,
happy_eyeballs_delay: float = 0.25,
) -> Union[SocketStream, TLSStream]:
"""
Connect to a host using the TCP protocol.
This function implements the stateless version of the Happy Eyeballs algorithm (RFC 6555).
If ``address`` is a host name that resolves to multiple IP addresses, each one is tried until
one connection attempt succeeds. If the first attempt does not connected within 250
milliseconds, a second attempt is started using the next address in the list, and so on.
On IPv6 enabled systems, an IPv6 address (if available) is tried first.
When the connection has been established, a TLS handshake will be done if either
``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``.
:param remote_host: the IP address or host name to connect to
:param remote_port: port on the target host to connect to
:param local_host: the interface address or name to bind the socket to before connecting
:param tls: ``True`` to do a TLS handshake with the connected stream and return a
:class:`~anyio.streams.tls.TLSStream` instead
:param ssl_context: the SSL context object to use (if omitted, a default context is created)
:param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake before closing
the stream and requires that the server does this as well. Otherwise,
:exc:`~ssl.SSLEOFError` may be raised during reads from the stream.
Some protocols, such as HTTP, require this option to be ``False``.
See :meth:`~ssl.SSLContext.wrap_socket` for details.
:param tls_hostname: host name to check the server certificate against (defaults to the value
of ``remote_host``)
:param happy_eyeballs_delay: delay (in seconds) before starting the next connection attempt
:return: a socket stream object if no TLS handshake was done, otherwise a TLS stream
:raises OSError: if the connection attempt fails
"""
# Placed here due to https://github.com/python/mypy/issues/7057
connected_stream: Optional[SocketStream] = None
async def try_connect(remote_host: str, event: Event) -> None:
nonlocal connected_stream
try:
stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)
except OSError as exc:
oserrors.append(exc)
return
else:
if connected_stream is None:
connected_stream = stream
tg.cancel_scope.cancel()
else:
await stream.aclose()
finally:
event.set()
asynclib = get_asynclib()
local_address: Optional[IPSockAddrType] = None
family = socket.AF_UNSPEC
if local_host:
gai_res = await getaddrinfo(str(local_host), None)
family, *_, local_address = gai_res[0]
target_host = str(remote_host)
try:
addr_obj = ip_address(remote_host)
except ValueError:
# getaddrinfo() will raise an exception if name resolution fails
> gai_res = await getaddrinfo(
target_host, remote_port, family=family, type=socket.SOCK_STREAM
)
/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:189:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = 'www.example.com', port = 80
async def getaddrinfo(
host: Union[bytearray, bytes, str],
port: Union[str, int, None],
*,
family: Union[int, AddressFamily] = 0,
type: Union[int, SocketKind] = 0,
proto: int = 0,
flags: int = 0,
) -> GetAddrInfoReturnType:
"""
Look up a numeric IP address given a host name.
Internationalized domain names are translated according to the (non-transitional) IDNA 2008
standard.
.. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of
(host, port), unlike what :func:`socket.getaddrinfo` does.
:param host: host name
:param port: port number
:param family: socket family (`'AF_INET``, ...)
:param type: socket type (``SOCK_STREAM``, ...)
:param proto: protocol number
:param flags: flags to pass to upstream ``getaddrinfo()``
:return: list of tuples containing (family, type, proto, canonname, sockaddr)
.. seealso:: :func:`socket.getaddrinfo`
"""
# Handle unicode hostnames
if isinstance(host, str):
try:
encoded_host = host.encode("ascii")
except UnicodeEncodeError:
import idna
encoded_host = idna.encode(host, uts46=True)
else:
encoded_host = host
> gai_res = await get_asynclib().getaddrinfo(
encoded_host, port, family=family, type=type, proto=proto, flags=flags
)
/usr/lib/python3.8/site-packages/anyio/_core/_sockets.py:496:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = b'www.example.com', port = 80
async def getaddrinfo(
host: Union[bytes, str],
port: Union[str, int, None],
*,
family: Union[int, AddressFamily] = 0,
type: Union[int, SocketKind] = 0,
proto: int = 0,
flags: int = 0,
) -> GetAddrInfoReturnType:
# https://github.com/python/typeshed/pull/4304
> result = await get_running_loop().getaddrinfo(
host, port, family=family, type=type, proto=proto, flags=flags
)
/usr/lib/python3.8/site-packages/anyio/_backends/_asyncio.py:1754:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <_UnixSelectorEventLoop running=False closed=True debug=False>
host = b'www.example.com', port = 80
async def getaddrinfo(self, host, port, *,
family=0, type=0, proto=0, flags=0):
if self._debug:
getaddr_func = self._getaddrinfo_debug
else:
getaddr_func = socket.getaddrinfo
> return await self.run_in_executor(
None, getaddr_func, host, port, family, type, proto, flags)
/usr/lib64/python3.8/asyncio/base_events.py:825:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = None
def run(self):
if not self.future.set_running_or_notify_cancel():
return
try:
> result = self.fn(*self.args, **self.kwargs)
/usr/lib64/python3.8/concurrent/futures/thread.py:57:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
host = b'www.example.com', port = 80, family = <AddressFamily.AF_UNSPEC: 0>
type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.
Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.
The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno -2] Name or service not known
/usr/lib64/python3.8/socket.py:918: gaierror
During handling of the above exception, another exception occurred:
@contextlib.contextmanager
def map_httpcore_exceptions() -> typing.Iterator[None]:
try:
> yield
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpx.AsyncHTTPTransport object at 0x7f3b340730a0>
request = <Request('GET', 'http://www.example.com/')>
async def handle_async_request(
self,
request: Request,
) -> Response:
assert isinstance(request.stream, AsyncByteStream)
req = httpcore.Request(
method=request.method,
url=httpcore.URL(
scheme=request.url.raw_scheme,
host=request.url.raw_host,
port=request.url.port,
target=request.url.raw_path,
),
headers=request.headers.raw,
content=request.stream,
extensions=request.extensions,
)
with map_httpcore_exceptions():
> resp = await self._pool.handle_async_request(req)
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.AsyncConnectionPool object at 0x7f3b34073250>
request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.
This is the core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
raise UnsupportedProtocol(
"Request URL is missing an 'http://' or 'https://' protocol."
)
if scheme not in ("http", "https"):
raise UnsupportedProtocol(
f"Request URL has an unsupported protocol '{scheme}://'."
)
status = RequestStatus(request)
async with self._pool_lock:
self._requests.append(status)
await self._close_expired_connections()
await self._attempt_to_acquire_connection(status)
while True:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("pool", None)
try:
connection = await status.wait_for_connection(timeout=timeout)
except BaseException as exc:
# If we timeout here, or if the task is cancelled, then make
# sure to remove the request from the queue before bubbling
# up the exception.
async with self._pool_lock:
self._requests.remove(status)
raise exc
try:
response = await connection.handle_async_request(request)
except ConnectionNotAvailable:
# The ConnectionNotAvailable exception is a special case, that
# indicates we need to retry the request on a new connection.
#
# The most common case where this can occur is when multiple
# requests are queued waiting for a single connection, which
# might end up as an HTTP/2 connection, but which actually ends
# up as HTTP/1.1.
async with self._pool_lock:
# Maintain our position in the request queue, but reset the
# status so that the request becomes queued again.
status.unset_connection()
await self._attempt_to_acquire_connection(status)
except BaseException as exc:
await self.response_closed(status)
> raise exc
/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:253:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.AsyncConnectionPool object at 0x7f3b34073250>
request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.
This is the core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
raise UnsupportedProtocol(
"Request URL is missing an 'http://' or 'https://' protocol."
)
if scheme not in ("http", "https"):
raise UnsupportedProtocol(
f"Request URL has an unsupported protocol '{scheme}://'."
)
status = RequestStatus(request)
async with self._pool_lock:
self._requests.append(status)
await self._close_expired_connections()
await self._attempt_to_acquire_connection(status)
while True:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("pool", None)
try:
connection = await status.wait_for_connection(timeout=timeout)
except BaseException as exc:
# If we timeout here, or if the task is cancelled, then make
# sure to remove the request from the queue before bubbling
# up the exception.
async with self._pool_lock:
self._requests.remove(status)
raise exc
try:
> response = await connection.handle_async_request(request)
/usr/lib/python3.8/site-packages/httpcore/_async/connection_pool.py:237:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
)
async with self._request_lock:
if self._connection is None:
try:
stream = await self._connect(request)
ssl_object = stream.get_extra_info("ssl_object")
http2_negotiated = (
ssl_object is not None
and ssl_object.selected_alpn_protocol() == "h2"
)
if http2_negotiated or (self._http2 and not self._http1):
from .http2 import AsyncHTTP2Connection
self._connection = AsyncHTTP2Connection(
origin=self._origin,
stream=stream,
keepalive_expiry=self._keepalive_expiry,
)
else:
self._connection = AsyncHTTP11Connection(
origin=self._origin,
stream=stream,
keepalive_expiry=self._keepalive_expiry,
)
except Exception as exc:
self._connect_failed = True
> raise exc
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:86:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def handle_async_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
)
async with self._request_lock:
if self._connection is None:
try:
> stream = await self._connect(request)
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:63:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AsyncHTTPConnection [CONNECTION FAILED]>, request = <Request [b'GET']>
async def _connect(self, request: Request) -> AsyncNetworkStream:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("connect", None)
retries_left = self._retries
delays = exponential_backoff(factor=RETRIES_BACKOFF_FACTOR)
while True:
try:
if self._uds is None:
kwargs = {
"host": self._origin.host.decode("ascii"),
"port": self._origin.port,
"local_address": self._local_address,
"timeout": timeout,
}
async with Trace(
"connection.connect_tcp", request, kwargs
) as trace:
> stream = await self._network_backend.connect_tcp(**kwargs)
/usr/lib/python3.8/site-packages/httpcore/_async/connection.py:111:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.auto.AutoBackend object at 0x7f3b34073d30>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: Optional[float] = None,
local_address: Optional[str] = None,
) -> AsyncNetworkStream:
await self._init_backend()
> return await self._backend.connect_tcp(
host, port, timeout=timeout, local_address=local_address
)
/usr/lib/python3.8/site-packages/httpcore/backends/auto.py:29:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <httpcore.backends.asyncio.AsyncIOBackend object at 0x7f3b3408ebe0>
host = 'www.example.com', port = 80, timeout = 5.0, local_address = None
async def connect_tcp(
self,
host: str,
port: int,
timeout: typing.Optional[float] = None,
local_address: typing.Optional[str] = None,
) -> AsyncNetworkStream:
exc_map = {
TimeoutError: ConnectTimeout,
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
with map_exceptions(exc_map):
with anyio.fail_after(timeout):
> stream: anyio.abc.ByteStream = await anyio.connect_tcp(
remote_host=host,
remote_port=port,
local_host=local_address,
)
/usr/lib/python3.8/site-packages/httpcore/backends/asyncio.py:109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <contextlib._GeneratorContextManager object at 0x7f3b3408eb50>
type = <class 'socket.gaierror'>
value = gaierror(-2, 'Name or service not known')
traceback = <traceback object at 0x7f3b3411fb40>
def __exit__(self, type, value, traceback):
if type is None:
try:
next(self.gen)
except StopIteration:
return False
else:
raise RuntimeError("generator didn't stop")
else:
if value is None:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value = type()
try:
> self.gen.throw(type, value, traceback)
/usr/lib64/python3.8/contextlib.py:131:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
map = {<class 'TimeoutError'>: <class 'httpcore.ConnectTimeout'>, <class 'OSError'>: <class 'httpcore.ConnectError'>, <class 'anyio.BrokenResourceError'>: <class 'httpcore.ConnectError'>}
@contextlib.contextmanager
def map_exceptions(map: Dict[Type, Type]) -> Iterator[None]:
try:
yield
except Exception as exc: # noqa: PIE786
for from_exc, to_exc in map.items():
if isinstance(exc, from_exc):
> raise to_exc(exc)
E httpcore.ConnectError: [Errno -2] Name or service not known
/usr/lib/python3.8/site-packages/httpcore/_exceptions.py:12: ConnectError
The above exception was the direct cause of the following exception:
async def test_httpx():
async with httpx.AsyncClient() as client:
> await client.get("http://www.example.com/")
test_httpx_fails.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/httpx/_client.py:1751: in get
return await self.request(
/usr/lib/python3.8/site-packages/httpx/_client.py:1527: in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
/usr/lib/python3.8/site-packages/httpx/_client.py:1614: in send
response = await self._send_handling_auth(
/usr/lib/python3.8/site-packages/httpx/_client.py:1642: in _send_handling_auth
response = await self._send_handling_redirects(
/usr/lib/python3.8/site-packages/httpx/_client.py:1679: in _send_handling_redirects
response = await self._send_single_request(request)
/usr/lib/python3.8/site-packages/httpx/_client.py:1716: in _send_single_request
response = await transport.handle_async_request(request)
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:353: in handle_async_request
resp = await self._pool.handle_async_request(req)
/usr/lib64/python3.8/contextlib.py:131: in __exit__
self.gen.throw(type, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@contextlib.contextmanager
def map_httpcore_exceptions() -> typing.Iterator[None]:
try:
yield
except Exception as exc: # noqa: PIE-786
mapped_exc = None
for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
if not isinstance(exc, from_exc):
continue
# We want to map to the most specific exception we can find.
# Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
# `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
if mapped_exc is None or issubclass(to_exc, mapped_exc):
mapped_exc = to_exc
if mapped_exc is None: # pragma: nocover
raise
message = str(exc)
> raise mapped_exc(message) from exc
E httpx.ConnectError: [Errno -2] Name or service not known
/usr/lib/python3.8/site-packages/httpx/_transports/default.py:77: ConnectError
=========================== short test summary info ============================
FAILED test_httpx_fails.py::test_httpx - httpx.ConnectError: [Errno -2] Name ...
============================== 1 failed in 0.41s ===============================
========================================================================= short test summary info ==========================================================================
FAILED tests/test_async.py::test_httpx_fails - Failed: nomatch: '*SocketBlockedError: A test tried to use socket.socket.*'
======================================================================= 1 failed, 58 passed in 6.73s =======================================================================
Just in case here it is list of modules installed in build env
Package Version
------------------ --------------
anyio 3.6.1
asynctest 0.13.0
attrs 21.4.0
blinker 1.4
Brlapi 0.8.3
Brotli 1.0.9
build 0.8.0
certifi 2021.10.8
charset-normalizer 2.1.0
click 8.1.2
codespell 2.1.0
cycler 0.11.0
decorator 5.1.1
distro 1.7.0
extras 1.0.0
fixtures 4.0.0
Flask 2.1.2
fonttools 4.33.3
gpg 1.17.1-unknown
h11 0.13.0
httpbin 0.7.0
httpcore 0.15.0
httpx 0.23.0
idna 3.3
importlib-metadata 4.11.3
iniconfig 1.1.1
itsdangerous 2.1.2
Jinja2 3.1.1
kiwisolver 1.4.3
libcomps 0.1.18
louis 3.22.0
MarkupSafe 2.1.1
matplotlib 3.5.2
numpy 1.22.4
olefile 0.46
packaging 21.3
pbr 5.8.1
pep517 0.12.0
Pillow 9.1.1
pip 22.0.4
pluggy 1.0.0
poetry-core 1.0.8
py 1.11.0
PyGObject 3.42.1
pyparsing 3.0.9
pytest 7.1.2
pytest-httpbin 1.0.2
python-dateutil 2.8.2
raven 6.10.0
requests 2.28.0
rfc3986 2.0.0
rpm 4.17.0
six 1.16.0
sniffio 1.2.0
starlette 0.20.3
testtools 2.5.0
tomli 2.0.1
typing_extensions 4.2.0
urllib3 1.26.9
Werkzeug 2.1.2
wheel 0.37.1
zipp 3.8.0
I can't reproduce - I don't know how you're building the wheel, can you provide those commands? If I check out the repo, running python3 -sBm build -w --no-isolation
provides me No module named build
- so are there other steps you're taking to generate that module?
@kloczek is it possible that your test environment cannot perform a lookup for www.example.com
?
$ host www.example.com
Host www.example.com not found: 3(NXDOMAIN)
@kloczek seems like you've got a dns problem?
$ host www.example.com
www.example.com has address 93.184.216.34
www.example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
Issu is that that was on my system connected to public networ.,
Usyually oroduction buulds I'm performing on system which COMPLETLY cut oiff from that access (with DNDS access as well)
Looks like an environment-specific issue - if you have network restrictions in your environment that prevent a DNS lookup, you can always manipulate that environment to add an entry to your /etc/hosts
file so that www.example.com
resolves to a valid address for the purposes of executing this test.
Or you can skip the test - either way, the issue lies within your environment, not this library.