mqtt-tools / pytest-mqtt

pytest-mqtt supports testing systems based on MQTT.
MIT License
9 stars 2 forks source link

Error message when docker daemon is not running is too long to understand #4

Closed horta closed 6 months ago

horta commented 1 year ago

First of all, thank your for this package!

I'm running tests on a mac m1 machine. If I forget to start Docker and try to test using mosquitto fixture I get the following very long error:

self = <docker.transport.unixconn.UnixHTTPConnectionPool object at 0x11153db10>, method = 'GET', url = '/version', body = None, headers = {'User-Agent': 'docker-sdk-python/6.1.3', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}, retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False
assert_same_host = False, timeout = Timeout(connect=60, read=60, total=None), pool_timeout = None, release_conn = False, chunked = False, body_pos = None, response_kw = {'decode_content': False, 'preload_content': False}, parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/version', query=None, fragment=None), destination_scheme = None
conn = None, release_this_conn = True, http_tunnel_required = False, err = None, clean_exit = False

    def urlopen(
        self,
        method,
        url,
        body=None,
        headers=None,
        retries=None,
        redirect=True,
        assert_same_host=True,
        timeout=_Default,
        pool_timeout=None,
        release_conn=None,
        chunked=False,
        body_pos=None,
        **response_kw
    ):
        """
        Get a connection from the pool and perform an HTTP request. This is the
        lowest level call for making a request, so you'll need to specify all
        the raw details.

        .. note::

           More commonly, it's appropriate to use a convenience method provided
           by :class:`.RequestMethods`, such as :meth:`request`.

        .. note::

           `release_conn` will only behave as expected if
           `preload_content=False` because we want to make
           `preload_content=False` the default behaviour someday soon without
           breaking backwards compatibility.

        :param method:
            HTTP request method (such as GET, POST, PUT, etc.)

        :param url:
            The URL to perform the request on.

        :param body:
            Data to send in the request body, either :class:`str`, :class:`bytes`,
            an iterable of :class:`str`/:class:`bytes`, or a file-like object.

        :param headers:
            Dictionary of custom headers to send, such as User-Agent,
            If-None-Match, etc. If None, pool headers are used. If provided,
            these headers completely replace any pool-specific headers.

        :param retries:
            Configure the number of retries to allow before raising a
            :class:`~urllib3.exceptions.MaxRetryError` exception.

            Pass ``None`` to retry until you receive a response. Pass a
            :class:`~urllib3.util.retry.Retry` object for fine-grained control
            over different types of retries.
            Pass an integer number to retry connection errors that many times,
            but no other types of errors. Pass zero to never retry.

            If ``False``, then retries are disabled and any exception is raised
            immediately. Also, instead of raising a MaxRetryError on redirects,
            the redirect response will be returned.

        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

        :param redirect:
            If True, automatically handle redirects (status codes 301, 302,
            303, 307, 308). Each redirect counts as a retry. Disabling retries
            will disable redirect, too.

        :param assert_same_host:
            If ``True``, will make sure that the host of the pool requests is
            consistent else will raise HostChangedError. When ``False``, you can
            use the pool on an HTTP proxy and request foreign hosts.

        :param timeout:
            If specified, overrides the default timeout for this one
            request. It may be a float (in seconds) or an instance of
            :class:`urllib3.util.Timeout`.

        :param pool_timeout:
            If set and the pool is set to block=True, then this method will
            block for ``pool_timeout`` seconds and raise EmptyPoolError if no
            connection is available within the time period.

        :param release_conn:
            If False, then the urlopen call will not release the connection
            back into the pool once a response is received (but will release if
            you read the entire contents of the response such as when
            `preload_content=True`). This is useful if you're not preloading
            the response's content immediately. You will need to call
            ``r.release_conn()`` on the response ``r`` to return the connection
            back into the pool. If None, it takes the value of
            ``response_kw.get('preload_content', True)``.

        :param chunked:
            If True, urllib3 will send the body using chunked transfer
            encoding. Otherwise, urllib3 will send the body using the standard
            content-length form. Defaults to False.

        :param int body_pos:
            Position to seek to in file-like body in the event of a retry or
            redirect. Typically this won't need to be set because urllib3 will
            auto-populate the value when needed.

        :param \\**response_kw:
            Additional parameters are passed to
            :meth:`urllib3.response.HTTPResponse.from_httplib`
        """

        parsed_url = parse_url(url)
        destination_scheme = parsed_url.scheme

        if headers is None:
            headers = self.headers

        if not isinstance(retries, Retry):
            retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

        if release_conn is None:
            release_conn = response_kw.get("preload_content", True)

        # Check host
        if assert_same_host and not self.is_same_host(url):
            raise HostChangedError(self, url, retries)

        # Ensure that the URL we're connecting to is properly encoded
        if url.startswith("/"):
            url = six.ensure_str(_encode_target(url))
        else:
            url = six.ensure_str(parsed_url.url)

        conn = None

        # Track whether `conn` needs to be released before
        # returning/raising/recursing. Update this variable if necessary, and
        # leave `release_conn` constant throughout the function. That way, if
        # the function recurses, the original value of `release_conn` will be
        # passed down into the recursive call, and its value will be respected.
        #
        # See issue #651 [1] for details.
        #
        # [1] <https://github.com/urllib3/urllib3/issues/651>
        release_this_conn = release_conn

        http_tunnel_required = connection_requires_http_tunnel(
            self.proxy, self.proxy_config, destination_scheme
        )

        # Merge the proxy headers. Only done when not using HTTP CONNECT. We
        # have to copy the headers dict so we can safely change it without those
        # changes being reflected in anyone else's copy.
        if not http_tunnel_required:
            headers = headers.copy()
            headers.update(self.proxy_headers)

        # Must keep the exception bound to a separate variable or else Python 3
        # complains about UnboundLocalError.
        err = None

        # Keep track of whether we cleanly exited the except block. This
        # ensures we do proper cleanup in finally.
        clean_exit = False

        # Rewind body position, if needed. Record current position
        # for future rewinds in the event of a redirect/retry.
        body_pos = set_file_position(body, body_pos)

        try:
            # Request a connection from the queue.
            timeout_obj = self._get_timeout(timeout)
            conn = self._get_conn(timeout=pool_timeout)

            conn.timeout = timeout_obj.connect_timeout

            is_new_proxy_conn = self.proxy is not None and not getattr(
                conn, "sock", None
            )
            if is_new_proxy_conn and http_tunnel_required:
                self._prepare_proxy(conn)

            # Make the request on the httplib connection object.
>           httplib_response = self._make_request(
                conn,
                method,
                url,
                timeout=timeout_obj,
                body=body,
                headers=headers,
                chunked=chunked,
            )

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:714: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:415: in _make_request
    conn.request(method, url, **httplib_request_kw)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connection.py:244: in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1286: in request
    self._send_request(method, url, body, headers, encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1332: in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1281: in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1041: in _send_output
    self.send(msg)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:979: in send
    self.connect()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <docker.transport.unixconn.UnixHTTPConnection object at 0x11153c690>

    def connect(self):
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.settimeout(self.timeout)
>       sock.connect(self.unix_socket)
E       FileNotFoundError: [Errno 2] No such file or directory

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/transport/unixconn.py:27: FileNotFoundError

During handling of the above exception, another exception occurred:

self = <docker.transport.unixconn.UnixHTTPAdapter object at 0x11150bb10>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=60, read=60, total=None), verify = True, cert = None, proxies = OrderedDict()

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple or urllib3 Timeout object
        :param verify: (optional) Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        :rtype: requests.Response
        """

        try:
            conn = self.get_connection(request.url, proxies)
        except LocationValueError as e:
            raise InvalidURL(e, request=request)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(
            request,
            stream=stream,
            timeout=timeout,
            verify=verify,
            cert=cert,
            proxies=proxies,
        )

        chunked = not (request.body is None or "Content-Length" in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError:
                raise ValueError(
                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
                    f"or a single float to set both timeouts to the same value."
                )
        elif isinstance(timeout, TimeoutSauce):
            pass
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
>           resp = conn.urlopen(
                method=request.method,
                url=url,
                body=request.body,
                headers=request.headers,
                redirect=False,
                assert_same_host=False,
                preload_content=False,
                decode_content=False,
                retries=self.max_retries,
                timeout=timeout,
                chunked=chunked,
            )

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/requests/adapters.py:486: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:798: in urlopen
    retries = retries.increment(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/util/retry.py:550: in increment
    raise six.reraise(type(error), error, _stacktrace)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/packages/six.py:769: in reraise
    raise value.with_traceback(tb)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:714: in urlopen
    httplib_response = self._make_request(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:415: in _make_request
    conn.request(method, url, **httplib_request_kw)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/urllib3/connection.py:244: in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1286: in request
    self._send_request(method, url, body, headers, encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1332: in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1281: in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1041: in _send_output
    self.send(msg)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:979: in send
    self.connect()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <docker.transport.unixconn.UnixHTTPConnection object at 0x11153c690>

    def connect(self):
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.settimeout(self.timeout)
>       sock.connect(self.unix_socket)
E       urllib3.exceptions.ProtocolError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/transport/unixconn.py:27: ProtocolError

During handling of the above exception, another exception occurred:

self = <docker.api.client.APIClient object at 0x111509250>

    def _retrieve_server_version(self):
        try:
>           return self.version(api_version=False)["ApiVersion"]

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/api/client.py:214: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/api/daemon.py:181: in version
    return self._result(self._get(url), json=True)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/utils/decorators.py:46: in inner
    return f(self, *args, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/api/client.py:237: in _get
    return self.get(url, **self._set_request_timeout(kwargs))
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/requests/sessions.py:602: in get
    return self.request("GET", url, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/requests/sessions.py:589: in request
    resp = self.send(prep, **send_kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/requests/sessions.py:703: in send
    r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <docker.transport.unixconn.UnixHTTPAdapter object at 0x11150bb10>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=60, read=60, total=None), verify = True, cert = None, proxies = OrderedDict()

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple or urllib3 Timeout object
        :param verify: (optional) Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        :rtype: requests.Response
        """

        try:
            conn = self.get_connection(request.url, proxies)
        except LocationValueError as e:
            raise InvalidURL(e, request=request)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(
            request,
            stream=stream,
            timeout=timeout,
            verify=verify,
            cert=cert,
            proxies=proxies,
        )

        chunked = not (request.body is None or "Content-Length" in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError:
                raise ValueError(
                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
                    f"or a single float to set both timeouts to the same value."
                )
        elif isinstance(timeout, TimeoutSauce):
            pass
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
            resp = conn.urlopen(
                method=request.method,
                url=url,
                body=request.body,
                headers=request.headers,
                redirect=False,
                assert_same_host=False,
                preload_content=False,
                decode_content=False,
                retries=self.max_retries,
                timeout=timeout,
                chunked=chunked,
            )

        except (ProtocolError, OSError) as err:
>           raise ConnectionError(err, request=request)
E           requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/requests/adapters.py:501: ConnectionError

During handling of the above exception, another exception occurred:

    @pytest.fixture(scope="session")
    def mosquitto():

        # Gracefully skip spinning up the Docker container if Mosquitto is already running.
        if is_mosquitto_running():
            yield "localhost", 1883
            return

        # Spin up Mosquitto container.
        if os.environ.get("MOSQUITTO"):
            yield os.environ["MOSQUITTO"].split(":")
        else:
>           yield mosquitto_image.run()

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:81: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:58: in run
    self.pull_image()
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:53: in pull_image
    docker_client = docker.from_env(version=self.docker_version)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/client.py:96: in from_env
    return cls(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/client.py:45: in __init__
    self.api = APIClient(*args, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/api/client.py:197: in __init__
    self._version = self._retrieve_server_version()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <docker.api.client.APIClient object at 0x111509250>

    def _retrieve_server_version(self):
        try:
            return self.version(api_version=False)["ApiVersion"]
        except KeyError:
            raise DockerException(
                'Invalid response from docker daemon: key "ApiVersion"'
                ' is missing.'
            )
        except Exception as e:
>           raise DockerException(
                f'Error while fetching server API version: {e}'
            )
E           docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-sched-wNW51EpV-py3.11/lib/python3.11/site-packages/docker/api/client.py:221: DockerException

It would be nice to have a simple exception message telling the developer to make sure Docker is running.

amotl commented 1 year ago

Dear Danilo,

thanks for the report. GH-5 may have a fix that helps already. Let me know if you think that will fit your needs.

With kind regards, Andreas.

amotl commented 1 year ago

Hi again. pytest-mqtt 0.3.0 has been released, including the improvement referenced above.

horta commented 1 year ago

Thanks a lot!

Nearly there. Look:

> /Users/horta/Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py(59)run()
-> docker_client = docker.from_env(version=self.docker_version)
(Pdb) n
docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
> /Users/horta/Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py(59)run()
-> docker_client = docker.from_env(version=self.docker_version)
(Pdb) exit

The call docker.from_env already tries to contact docker daemon!

Minimum example:

~ ❱ cat script.py
import docker

docker.from_env()

~ ❱ python script.py                                                                                                                                                                                               (docker)
Traceback (most recent call last):
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 790, in urlopen
    response = self._make_request(
               ^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connection.py", line 388, in request
    self.endheaders()
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 1281, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 1041, in _send_output
    self.send(msg)
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 979, in send
    self.connect()
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/transport/unixconn.py", line 27, in connect
    sock.connect(self.unix_socket)
FileNotFoundError: [Errno 2] No such file or directory

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/requests/adapters.py", line 486, in send
    resp = conn.urlopen(
           ^^^^^^^^^^^^^
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 844, in urlopen
    retries = retries.increment(
              ^^^^^^^^^^^^^^^^^^
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/util/retry.py", line 470, in increment
    raise reraise(type(error), error, _stacktrace)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/util/util.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 790, in urlopen
    response = self._make_request(
               ^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
  File "/Users/horta/.local/lib/python3.11/site-packages/urllib3/connection.py", line 388, in request
    self.endheaders()
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 1281, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 1041, in _send_output
    self.send(msg)
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/http/client.py", line 979, in send
    self.connect()
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/transport/unixconn.py", line 27, in connect
    sock.connect(self.unix_socket)
urllib3.exceptions.ProtocolError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/api/client.py", line 214, in _retrieve_server_version
    return self.version(api_version=False)["ApiVersion"]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/api/daemon.py", line 181, in version
    return self._result(self._get(url), json=True)
                        ^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/utils/decorators.py", line 46, in inner
    return f(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/api/client.py", line 237, in _get
    return self.get(url, **self._set_request_timeout(kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/requests/sessions.py", line 602, in get
    return self.request("GET", url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/requests/adapters.py", line 501, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/horta/script.py", line 3, in <module>
    docker.from_env()
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/client.py", line 96, in from_env
    return cls(
           ^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/client.py", line 45, in __init__
    self.api = APIClient(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/api/client.py", line 197, in __init__
    self._version = self._retrieve_server_version()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/horta/micromamba/envs/docker/lib/python3.11/site-packages/docker/api/client.py", line 221, in _retrieve_server_version
    raise DockerException(
docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
amotl commented 1 year ago

Oh my. It looks like it was too late at night for doing this properly. Will try to revisit later. Thanks!

amotl commented 1 year ago

Dear Danilo,

let's try again with the changes from GH-7. May I ask you to verify it will work better now by temporarily installing directly from this branch?

pip install --upgrade 'git+https://github.com/mqtt-tools/pytest-mqtt@improve-docker-down'

With kind regards, Andreas.

horta commented 1 year ago

The error has improved =) It now says "ConnectionError: Cannot connect to the Docker daemon. Is the docker daemon running?"

I'm satisfied =)

self = <docker.transport.unixconn.UnixHTTPConnectionPool object at 0x106bb7a10>, method = 'GET', url = '/version', body = None
headers = {'User-Agent': 'docker-sdk-python/6.1.3', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=60, read=60, total=None)
pool_timeout = None, release_conn = False, chunked = False, body_pos = None, response_kw = {'decode_content': False, 'preload_content': False}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/version', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

    def urlopen(
        self,
        method,
        url,
        body=None,
        headers=None,
        retries=None,
        redirect=True,
        assert_same_host=True,
        timeout=_Default,
        pool_timeout=None,
        release_conn=None,
        chunked=False,
        body_pos=None,
        **response_kw
    ):
        """
        Get a connection from the pool and perform an HTTP request. This is the
        lowest level call for making a request, so you'll need to specify all
        the raw details.

        .. note::

           More commonly, it's appropriate to use a convenience method provided
           by :class:`.RequestMethods`, such as :meth:`request`.

        .. note::

           `release_conn` will only behave as expected if
           `preload_content=False` because we want to make
           `preload_content=False` the default behaviour someday soon without
           breaking backwards compatibility.

        :param method:
            HTTP request method (such as GET, POST, PUT, etc.)

        :param url:
            The URL to perform the request on.

        :param body:
            Data to send in the request body, either :class:`str`, :class:`bytes`,
            an iterable of :class:`str`/:class:`bytes`, or a file-like object.

        :param headers:
            Dictionary of custom headers to send, such as User-Agent,
            If-None-Match, etc. If None, pool headers are used. If provided,
            these headers completely replace any pool-specific headers.

        :param retries:
            Configure the number of retries to allow before raising a
            :class:`~urllib3.exceptions.MaxRetryError` exception.

            Pass ``None`` to retry until you receive a response. Pass a
            :class:`~urllib3.util.retry.Retry` object for fine-grained control
            over different types of retries.
            Pass an integer number to retry connection errors that many times,
            but no other types of errors. Pass zero to never retry.

            If ``False``, then retries are disabled and any exception is raised
            immediately. Also, instead of raising a MaxRetryError on redirects,
            the redirect response will be returned.

        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

        :param redirect:
            If True, automatically handle redirects (status codes 301, 302,
            303, 307, 308). Each redirect counts as a retry. Disabling retries
            will disable redirect, too.

        :param assert_same_host:
            If ``True``, will make sure that the host of the pool requests is
            consistent else will raise HostChangedError. When ``False``, you can
            use the pool on an HTTP proxy and request foreign hosts.

        :param timeout:
            If specified, overrides the default timeout for this one
            request. It may be a float (in seconds) or an instance of
            :class:`urllib3.util.Timeout`.

        :param pool_timeout:
            If set and the pool is set to block=True, then this method will
            block for ``pool_timeout`` seconds and raise EmptyPoolError if no
            connection is available within the time period.

        :param release_conn:
            If False, then the urlopen call will not release the connection
            back into the pool once a response is received (but will release if
            you read the entire contents of the response such as when
            `preload_content=True`). This is useful if you're not preloading
            the response's content immediately. You will need to call
            ``r.release_conn()`` on the response ``r`` to return the connection
            back into the pool. If None, it takes the value of
            ``response_kw.get('preload_content', True)``.

        :param chunked:
            If True, urllib3 will send the body using chunked transfer
            encoding. Otherwise, urllib3 will send the body using the standard
            content-length form. Defaults to False.

        :param int body_pos:
            Position to seek to in file-like body in the event of a retry or
            redirect. Typically this won't need to be set because urllib3 will
            auto-populate the value when needed.

        :param \\**response_kw:
            Additional parameters are passed to
            :meth:`urllib3.response.HTTPResponse.from_httplib`
        """

        parsed_url = parse_url(url)
        destination_scheme = parsed_url.scheme

        if headers is None:
            headers = self.headers

        if not isinstance(retries, Retry):
            retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

        if release_conn is None:
            release_conn = response_kw.get("preload_content", True)

        # Check host
        if assert_same_host and not self.is_same_host(url):
            raise HostChangedError(self, url, retries)

        # Ensure that the URL we're connecting to is properly encoded
        if url.startswith("/"):
            url = six.ensure_str(_encode_target(url))
        else:
            url = six.ensure_str(parsed_url.url)

        conn = None

        # Track whether `conn` needs to be released before
        # returning/raising/recursing. Update this variable if necessary, and
        # leave `release_conn` constant throughout the function. That way, if
        # the function recurses, the original value of `release_conn` will be
        # passed down into the recursive call, and its value will be respected.
        #
        # See issue #651 [1] for details.
        #
        # [1] <https://github.com/urllib3/urllib3/issues/651>
        release_this_conn = release_conn

        http_tunnel_required = connection_requires_http_tunnel(
            self.proxy, self.proxy_config, destination_scheme
        )

        # Merge the proxy headers. Only done when not using HTTP CONNECT. We
        # have to copy the headers dict so we can safely change it without those
        # changes being reflected in anyone else's copy.
        if not http_tunnel_required:
            headers = headers.copy()
            headers.update(self.proxy_headers)

        # Must keep the exception bound to a separate variable or else Python 3
        # complains about UnboundLocalError.
        err = None

        # Keep track of whether we cleanly exited the except block. This
        # ensures we do proper cleanup in finally.
        clean_exit = False

        # Rewind body position, if needed. Record current position
        # for future rewinds in the event of a redirect/retry.
        body_pos = set_file_position(body, body_pos)

        try:
            # Request a connection from the queue.
            timeout_obj = self._get_timeout(timeout)
            conn = self._get_conn(timeout=pool_timeout)

            conn.timeout = timeout_obj.connect_timeout

            is_new_proxy_conn = self.proxy is not None and not getattr(
                conn, "sock", None
            )
            if is_new_proxy_conn and http_tunnel_required:
                self._prepare_proxy(conn)

            # Make the request on the httplib connection object.
>           httplib_response = self._make_request(
                conn,
                method,
                url,
                timeout=timeout_obj,
                body=body,
                headers=headers,
                chunked=chunked,
            )

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:714: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:415: in _make_request
    conn.request(method, url, **httplib_request_kw)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connection.py:244: in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1286: in request
    self._send_request(method, url, body, headers, encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1332: in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1281: in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1041: in _send_output
    self.send(msg)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:979: in send
    self.connect()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <docker.transport.unixconn.UnixHTTPConnection object at 0x106bc9590>

    def connect(self):
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.settimeout(self.timeout)
>       sock.connect(self.unix_socket)
E       FileNotFoundError: [Errno 2] No such file or directory

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/transport/unixconn.py:27: FileNotFoundError

During handling of the above exception, another exception occurred:

self = <docker.transport.unixconn.UnixHTTPAdapter object at 0x1069663d0>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=60, read=60, total=None)
verify = True, cert = None, proxies = OrderedDict()

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple or urllib3 Timeout object
        :param verify: (optional) Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        :rtype: requests.Response
        """

        try:
            conn = self.get_connection(request.url, proxies)
        except LocationValueError as e:
            raise InvalidURL(e, request=request)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(
            request,
            stream=stream,
            timeout=timeout,
            verify=verify,
            cert=cert,
            proxies=proxies,
        )

        chunked = not (request.body is None or "Content-Length" in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError:
                raise ValueError(
                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
                    f"or a single float to set both timeouts to the same value."
                )
        elif isinstance(timeout, TimeoutSauce):
            pass
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
>           resp = conn.urlopen(
                method=request.method,
                url=url,
                body=request.body,
                headers=request.headers,
                redirect=False,
                assert_same_host=False,
                preload_content=False,
                decode_content=False,
                retries=self.max_retries,
                timeout=timeout,
                chunked=chunked,
            )

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/requests/adapters.py:486: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:798: in urlopen
    retries = retries.increment(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/util/retry.py:550: in increment
    raise six.reraise(type(error), error, _stacktrace)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/packages/six.py:769: in reraise
    raise value.with_traceback(tb)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:714: in urlopen
    httplib_response = self._make_request(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:415: in _make_request
    conn.request(method, url, **httplib_request_kw)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/urllib3/connection.py:244: in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1286: in request
    self._send_request(method, url, body, headers, encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1332: in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1281: in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:1041: in _send_output
    self.send(msg)
../../../.pyenv/versions/3.11.4/lib/python3.11/http/client.py:979: in send
    self.connect()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <docker.transport.unixconn.UnixHTTPConnection object at 0x106bc9590>

    def connect(self):
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.settimeout(self.timeout)
>       sock.connect(self.unix_socket)
E       urllib3.exceptions.ProtocolError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/transport/unixconn.py:27: ProtocolError

During handling of the above exception, another exception occurred:

self = <docker.api.client.APIClient object at 0x106bb78d0>

    def _retrieve_server_version(self):
        try:
>           return self.version(api_version=False)["ApiVersion"]

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/api/client.py:214: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/api/daemon.py:181: in version
    return self._result(self._get(url), json=True)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/utils/decorators.py:46: in inner
    return f(self, *args, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/api/client.py:237: in _get
    return self.get(url, **self._set_request_timeout(kwargs))
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/requests/sessions.py:602: in get
    return self.request("GET", url, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/requests/sessions.py:589: in request
    resp = self.send(prep, **send_kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/requests/sessions.py:703: in send
    r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <docker.transport.unixconn.UnixHTTPAdapter object at 0x1069663d0>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=60, read=60, total=None)
verify = True, cert = None, proxies = OrderedDict()

    def send(
        self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
    ):
        """Sends PreparedRequest object. Returns Response object.

        :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
        :param stream: (optional) Whether to stream the request content.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple or urllib3 Timeout object
        :param verify: (optional) Either a boolean, in which case it controls whether
            we verify the server's TLS certificate, or a string, in which case it
            must be a path to a CA bundle to use
        :param cert: (optional) Any user-provided SSL certificate to be trusted.
        :param proxies: (optional) The proxies dictionary to apply to the request.
        :rtype: requests.Response
        """

        try:
            conn = self.get_connection(request.url, proxies)
        except LocationValueError as e:
            raise InvalidURL(e, request=request)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(
            request,
            stream=stream,
            timeout=timeout,
            verify=verify,
            cert=cert,
            proxies=proxies,
        )

        chunked = not (request.body is None or "Content-Length" in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError:
                raise ValueError(
                    f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
                    f"or a single float to set both timeouts to the same value."
                )
        elif isinstance(timeout, TimeoutSauce):
            pass
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
            resp = conn.urlopen(
                method=request.method,
                url=url,
                body=request.body,
                headers=request.headers,
                redirect=False,
                assert_same_host=False,
                preload_content=False,
                decode_content=False,
                retries=self.max_retries,
                timeout=timeout,
                chunked=chunked,
            )

        except (ProtocolError, OSError) as err:
>           raise ConnectionError(err, request=request)
E           requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/requests/adapters.py:501: ConnectionError

During handling of the above exception, another exception occurred:

self = <pytest_mqtt.mosquitto.Mosquitto object at 0x104d703d0>

    def run(self):
        try:
>           docker_client = docker.from_env(version=self.docker_version)

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:59: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/client.py:96: in from_env
    return cls(
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/client.py:45: in __init__
    self.api = APIClient(*args, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/api/client.py:197: in __init__
    self._version = self._retrieve_server_version()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <docker.api.client.APIClient object at 0x106bb78d0>

    def _retrieve_server_version(self):
        try:
            return self.version(api_version=False)["ApiVersion"]
        except KeyError:
            raise DockerException(
                'Invalid response from docker daemon: key "ApiVersion"'
                ' is missing.'
            )
        except Exception as e:
>           raise DockerException(
                f'Error while fetching server API version: {e}'
            )
E           docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/docker/api/client.py:221: DockerException

During handling of the above exception, another exception occurred:

    @pytest.fixture(scope="session")
    def mosquitto():

        # Gracefully skip spinning up the Docker container if Mosquitto is already running.
        if is_mosquitto_running():
            yield "localhost", 1883
            return

        # Spin up Mosquitto container.
        if os.environ.get("MOSQUITTO"):
            yield os.environ["MOSQUITTO"].split(":")
        else:
>           yield mosquitto_image.run()

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:90: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pytest_mqtt.mosquitto.Mosquitto object at 0x104d703d0>

    def run(self):
        try:
            docker_client = docker.from_env(version=self.docker_version)
            docker_url = docker_client.api.base_url
        except Exception:
>           raise ConnectionError("Cannot connect to the Docker daemon. Is the docker daemon running?")
E           ConnectionError: Cannot connect to the Docker daemon. Is the docker daemon running?

../../../Library/Caches/pypoetry/virtualenvs/deciphon-scheduler-HJ-pAcdm-py3.11/lib/python3.11/site-packages/pytest_mqtt/mosquitto.py:62: ConnectionError
amotl commented 1 year ago

Excellent, thanks. While I also agree that this kind of stacktrace is way too much, I do not want to prematurely hide anything which could help others in edge case situations, when connectivity may be broken by not so obvious reasons. Do you agree, or do you have different suggestions whether/how to improve on this detail?

horta commented 1 year ago

I agree. The noise doesn't seem to do with your package...

amotl commented 1 year ago

All right, so be it. Version 0.3.1 has been released, including that fix. Thanks for your support!

amotl commented 6 months ago

Hi Danilo,

we guess it will be fine to close this issue. Please let us know if you are still observing any issues, or if you think your report has not been handled well enough. Thanks!

With kind regards, Andreas.