smart_open icon indicating copy to clipboard operation
smart_open copied to clipboard

Test failures with urllib3 2.0.4

Open mweinelt opened this issue 2 years ago • 6 comments

Problem description

We are building smart-open 0.4.0 for nixpkgs, thereby running the test suite. After updating urllib3 from 1.26.16 to 2.0.4 we started seeing failures in the smart-open testsuite.

=========================== short test summary info ============================
FAILED smart_open/tests/test_http.py::HttpTest::test_https_seek_forward - requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRe...
FAILED smart_open/tests/test_http.py::HttpTest::test_seek_from_current - requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRe...
FAILED smart_open/tests/test_http.py::HttpTest::test_seek_from_end - requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRe...
FAILED smart_open/tests/test_http.py::HttpTest::test_seek_from_start - requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRe...
======= 4 failed, 368 passed, 4 skipped, 27 warnings in 70.45s (0:01:10) =======
Test protocol
smart-open> _______________________ HttpTest.test_https_seek_forward _______________________
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open> >               yield
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:710: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = , amt = 131072
smart-open> 
smart-open>     def _raw_read(
smart-open>         self,
smart-open>         amt: int | None = None,
smart-open>     ) -> bytes:
smart-open>         """
smart-open>         Reads `amt` of bytes from the socket.
smart-open>         """
smart-open>         if self._fp is None:
smart-open>             return None  # type: ignore[return-value]
smart-open>     
smart-open>         fp_closed = getattr(self._fp, "closed", False)
smart-open>     
smart-open>         with self._error_catcher():
smart-open>             data = self._fp_read(amt) if not fp_closed else b""
smart-open>             if amt is not None and amt != 0 and not data:
smart-open>                 # Platform-specific: Buggy versions of Python.
smart-open>                 # Close the connection when no data is returned
smart-open>                 #
smart-open>                 # This is redundant to what httplib/http.client _should_
smart-open>                 # already do.  However, versions of python released before
smart-open>                 # December 15, 2012 (http://bugs.python.org/issue16298) do
smart-open>                 # not properly close the connection in all cases. There is
smart-open>                 # no harm in redundantly calling close.
smart-open>                 self._fp.close()
smart-open>                 if (
smart-open>                     self.enforce_content_length
smart-open>                     and self.length_remaining is not None
smart-open>                     and self.length_remaining != 0
smart-open>                 ):
smart-open>                     # This is an edge case that httplib failed to cover due
smart-open>                     # to concerns of backward compatibility. We're
smart-open>                     # addressing it here to make sure IncompleteRead is
smart-open>                     # raised during streaming, so all calls with incorrect
smart-open>                     # Content-Length are caught.
smart-open> >                   raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
smart-open> E                   urllib3.exceptions.IncompleteRead: IncompleteRead(58 bytes read, 10 more expected)
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:835: IncompleteRead
smart-open> 
smart-open> The above exception was the direct cause of the following exception:
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open> >               yield from self.raw.stream(chunk_size, decode_content=True)
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:816: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:940: in stream
smart-open>     data = self.read(amt=amt, decode_content=decode_content)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:911: in read
smart-open>     data = self._raw_read(amt)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:813: in _raw_read
smart-open>     with self._error_catcher():
smart-open> /nix/store/15djm2sxy19yyvicydzwrzfchq7nkmh1-python3-3.11.5/lib/python3.11/contextlib.py:155: in __exit__
smart-open>     self.gen.throw(typ, value, traceback)
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open>                 yield
smart-open>     
smart-open>             except SocketTimeout as e:
smart-open>                 # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
smart-open>                 # there is yet no clean way to get at it from this context.
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except BaseSSLError as e:
smart-open>                 # FIXME: Is there a better way to differentiate between SSLErrors?
smart-open>                 if "read operation timed out" not in str(e):
smart-open>                     # SSL errors related to framing/MAC get wrapped and reraised here
smart-open>                     raise SSLError(e) from e
smart-open>     
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except (HTTPException, OSError) as e:
smart-open>                 # This includes IncompleteRead.
smart-open> >               raise ProtocolError(f"Connection broken: {e!r}", e) from e
smart-open> E               urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:727: ProtocolError
smart-open> 
smart-open> During handling of the above exception, another exception occurred:
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @responses.activate
smart-open>     def test_https_seek_forward(self):
smart-open>         """Did the seek forward over HTTPS work?"""
smart-open>         responses.add_callback(responses.GET, HTTPS_URL, callback=request_callback)
smart-open>     
smart-open>         with smart_open.open(HTTPS_URL, "rb") as fin:
smart-open>             fin.seek(10)
smart-open> >           read_bytes = fin.read(size=10)
smart-open> 
smart-open> smart_open/tests/test_http.py:142: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> smart_open/http.py:183: in read
smart-open>     bytes_read = self._read_buffer.fill(self._read_iter)
smart-open> smart_open/bytebuffer.py:155: in fill
smart-open>     for more_bytes in source:
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open>                 yield from self.raw.stream(chunk_size, decode_content=True)
smart-open>             except ProtocolError as e:
smart-open> >               raise ChunkedEncodingError(e)
smart-open> E               requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:818: ChunkedEncodingError
smart-open> _______________________ HttpTest.test_seek_from_current ________________________
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open> >               yield
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:710: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = , amt = 131072
smart-open> 
smart-open>     def _raw_read(
smart-open>         self,
smart-open>         amt: int | None = None,
smart-open>     ) -> bytes:
smart-open>         """
smart-open>         Reads `amt` of bytes from the socket.
smart-open>         """
smart-open>         if self._fp is None:
smart-open>             return None  # type: ignore[return-value]
smart-open>     
smart-open>         fp_closed = getattr(self._fp, "closed", False)
smart-open>     
smart-open>         with self._error_catcher():
smart-open>             data = self._fp_read(amt) if not fp_closed else b""
smart-open>             if amt is not None and amt != 0 and not data:
smart-open>                 # Platform-specific: Buggy versions of Python.
smart-open>                 # Close the connection when no data is returned
smart-open>                 #
smart-open>                 # This is redundant to what httplib/http.client _should_
smart-open>                 # already do.  However, versions of python released before
smart-open>                 # December 15, 2012 (http://bugs.python.org/issue16298) do
smart-open>                 # not properly close the connection in all cases. There is
smart-open>                 # no harm in redundantly calling close.
smart-open>                 self._fp.close()
smart-open>                 if (
smart-open>                     self.enforce_content_length
smart-open>                     and self.length_remaining is not None
smart-open>                     and self.length_remaining != 0
smart-open>                 ):
smart-open>                     # This is an edge case that httplib failed to cover due
smart-open>                     # to concerns of backward compatibility. We're
smart-open>                     # addressing it here to make sure IncompleteRead is
smart-open>                     # raised during streaming, so all calls with incorrect
smart-open>                     # Content-Length are caught.
smart-open> >                   raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
smart-open> E                   urllib3.exceptions.IncompleteRead: IncompleteRead(58 bytes read, 10 more expected)
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:835: IncompleteRead
smart-open> 
smart-open> The above exception was the direct cause of the following exception:
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open> >               yield from self.raw.stream(chunk_size, decode_content=True)
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:816: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:940: in stream
smart-open>     data = self.read(amt=amt, decode_content=decode_content)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:911: in read
smart-open>     data = self._raw_read(amt)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:813: in _raw_read
smart-open>     with self._error_catcher():
smart-open> /nix/store/15djm2sxy19yyvicydzwrzfchq7nkmh1-python3-3.11.5/lib/python3.11/contextlib.py:155: in __exit__
smart-open>     self.gen.throw(typ, value, traceback)
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open>                 yield
smart-open>     
smart-open>             except SocketTimeout as e:
smart-open>                 # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
smart-open>                 # there is yet no clean way to get at it from this context.
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except BaseSSLError as e:
smart-open>                 # FIXME: Is there a better way to differentiate between SSLErrors?
smart-open>                 if "read operation timed out" not in str(e):
smart-open>                     # SSL errors related to framing/MAC get wrapped and reraised here
smart-open>                     raise SSLError(e) from e
smart-open>     
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except (HTTPException, OSError) as e:
smart-open>                 # This includes IncompleteRead.
smart-open> >               raise ProtocolError(f"Connection broken: {e!r}", e) from e
smart-open> E               urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:727: ProtocolError
smart-open> 
smart-open> During handling of the above exception, another exception occurred:
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @responses.activate
smart-open>     def test_seek_from_current(self):
smart-open>         responses.add_callback(responses.GET, URL, callback=request_callback)
smart-open>         reader = smart_open.http.SeekableBufferedInputBase(URL)
smart-open>     
smart-open>         reader.seek(10)
smart-open> >       read_bytes = reader.read(size=10)
smart-open> 
smart-open> smart_open/tests/test_http.py:79: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> smart_open/http.py:183: in read
smart-open>     bytes_read = self._read_buffer.fill(self._read_iter)
smart-open> smart_open/bytebuffer.py:155: in fill
smart-open>     for more_bytes in source:
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open>                 yield from self.raw.stream(chunk_size, decode_content=True)
smart-open>             except ProtocolError as e:
smart-open> >               raise ChunkedEncodingError(e)
smart-open> E               requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:818: ChunkedEncodingError
smart-open> _________________________ HttpTest.test_seek_from_end __________________________
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open> >               yield
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:710: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = , amt = 131072
smart-open> 
smart-open>     def _raw_read(
smart-open>         self,
smart-open>         amt: int | None = None,
smart-open>     ) -> bytes:
smart-open>         """
smart-open>         Reads `amt` of bytes from the socket.
smart-open>         """
smart-open>         if self._fp is None:
smart-open>             return None  # type: ignore[return-value]
smart-open>     
smart-open>         fp_closed = getattr(self._fp, "closed", False)
smart-open>     
smart-open>         with self._error_catcher():
smart-open>             data = self._fp_read(amt) if not fp_closed else b""
smart-open>             if amt is not None and amt != 0 and not data:
smart-open>                 # Platform-specific: Buggy versions of Python.
smart-open>                 # Close the connection when no data is returned
smart-open>                 #
smart-open>                 # This is redundant to what httplib/http.client _should_
smart-open>                 # already do.  However, versions of python released before
smart-open>                 # December 15, 2012 (http://bugs.python.org/issue16298) do
smart-open>                 # not properly close the connection in all cases. There is
smart-open>                 # no harm in redundantly calling close.
smart-open>                 self._fp.close()
smart-open>                 if (
smart-open>                     self.enforce_content_length
smart-open>                     and self.length_remaining is not None
smart-open>                     and self.length_remaining != 0
smart-open>                 ):
smart-open>                     # This is an edge case that httplib failed to cover due
smart-open>                     # to concerns of backward compatibility. We're
smart-open>                     # addressing it here to make sure IncompleteRead is
smart-open>                     # raised during streaming, so all calls with incorrect
smart-open>                     # Content-Length are caught.
smart-open> >                   raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
smart-open> E                   urllib3.exceptions.IncompleteRead: IncompleteRead(10 bytes read, 58 more expected)
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:835: IncompleteRead
smart-open> 
smart-open> The above exception was the direct cause of the following exception:
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open> >               yield from self.raw.stream(chunk_size, decode_content=True)
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:816: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:940: in stream
smart-open>     data = self.read(amt=amt, decode_content=decode_content)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:911: in read
smart-open>     data = self._raw_read(amt)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:813: in _raw_read
smart-open>     with self._error_catcher():
smart-open> /nix/store/15djm2sxy19yyvicydzwrzfchq7nkmh1-python3-3.11.5/lib/python3.11/contextlib.py:155: in __exit__
smart-open>     self.gen.throw(typ, value, traceback)
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open>                 yield
smart-open>     
smart-open>             except SocketTimeout as e:
smart-open>                 # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
smart-open>                 # there is yet no clean way to get at it from this context.
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except BaseSSLError as e:
smart-open>                 # FIXME: Is there a better way to differentiate between SSLErrors?
smart-open>                 if "read operation timed out" not in str(e):
smart-open>                     # SSL errors related to framing/MAC get wrapped and reraised here
smart-open>                     raise SSLError(e) from e
smart-open>     
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except (HTTPException, OSError) as e:
smart-open>                 # This includes IncompleteRead.
smart-open> >               raise ProtocolError(f"Connection broken: {e!r}", e) from e
smart-open> E               urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(10 bytes read, 58 more expected)', IncompleteRead(10 bytes read, 58 more expected))
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:727: ProtocolError
smart-open> 
smart-open> During handling of the above exception, another exception occurred:
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @responses.activate
smart-open>     def test_seek_from_end(self):
smart-open>         responses.add_callback(responses.GET, URL, callback=request_callback)
smart-open>         reader = smart_open.http.SeekableBufferedInputBase(URL)
smart-open>     
smart-open>         reader.seek(-10, whence=smart_open.constants.WHENCE_END)
smart-open>         self.assertEqual(reader.tell(), len(BYTES) - 10)
smart-open> >       read_bytes = reader.read(size=10)
smart-open> 
smart-open> smart_open/tests/test_http.py:96: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> smart_open/http.py:183: in read
smart-open>     bytes_read = self._read_buffer.fill(self._read_iter)
smart-open> smart_open/bytebuffer.py:155: in fill
smart-open>     for more_bytes in source:
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open>                 yield from self.raw.stream(chunk_size, decode_content=True)
smart-open>             except ProtocolError as e:
smart-open> >               raise ChunkedEncodingError(e)
smart-open> E               requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(10 bytes read, 58 more expected)', IncompleteRead(10 bytes read, 58 more expected))
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:818: ChunkedEncodingError
smart-open> ________________________ HttpTest.test_seek_from_start _________________________
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open> >               yield
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:710: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = , amt = 131072
smart-open> 
smart-open>     def _raw_read(
smart-open>         self,
smart-open>         amt: int | None = None,
smart-open>     ) -> bytes:
smart-open>         """
smart-open>         Reads `amt` of bytes from the socket.
smart-open>         """
smart-open>         if self._fp is None:
smart-open>             return None  # type: ignore[return-value]
smart-open>     
smart-open>         fp_closed = getattr(self._fp, "closed", False)
smart-open>     
smart-open>         with self._error_catcher():
smart-open>             data = self._fp_read(amt) if not fp_closed else b""
smart-open>             if amt is not None and amt != 0 and not data:
smart-open>                 # Platform-specific: Buggy versions of Python.
smart-open>                 # Close the connection when no data is returned
smart-open>                 #
smart-open>                 # This is redundant to what httplib/http.client _should_
smart-open>                 # already do.  However, versions of python released before
smart-open>                 # December 15, 2012 (http://bugs.python.org/issue16298) do
smart-open>                 # not properly close the connection in all cases. There is
smart-open>                 # no harm in redundantly calling close.
smart-open>                 self._fp.close()
smart-open>                 if (
smart-open>                     self.enforce_content_length
smart-open>                     and self.length_remaining is not None
smart-open>                     and self.length_remaining != 0
smart-open>                 ):
smart-open>                     # This is an edge case that httplib failed to cover due
smart-open>                     # to concerns of backward compatibility. We're
smart-open>                     # addressing it here to make sure IncompleteRead is
smart-open>                     # raised during streaming, so all calls with incorrect
smart-open>                     # Content-Length are caught.
smart-open> >                   raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
smart-open> E                   urllib3.exceptions.IncompleteRead: IncompleteRead(58 bytes read, 10 more expected)
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:835: IncompleteRead
smart-open> 
smart-open> The above exception was the direct cause of the following exception:
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open> >               yield from self.raw.stream(chunk_size, decode_content=True)
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:816: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:940: in stream
smart-open>     data = self.read(amt=amt, decode_content=decode_content)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:911: in read
smart-open>     data = self._raw_read(amt)
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:813: in _raw_read
smart-open>     with self._error_catcher():
smart-open> /nix/store/15djm2sxy19yyvicydzwrzfchq7nkmh1-python3-3.11.5/lib/python3.11/contextlib.py:155: in __exit__
smart-open>     self.gen.throw(typ, value, traceback)
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @contextmanager
smart-open>     def _error_catcher(self) -> typing.Generator[None, None, None]:
smart-open>         """
smart-open>         Catch low-level python exceptions, instead re-raising urllib3
smart-open>         variants, so that low-level exceptions are not leaked in the
smart-open>         high-level api.
smart-open>     
smart-open>         On exit, release the connection back to the pool.
smart-open>         """
smart-open>         clean_exit = False
smart-open>     
smart-open>         try:
smart-open>             try:
smart-open>                 yield
smart-open>     
smart-open>             except SocketTimeout as e:
smart-open>                 # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
smart-open>                 # there is yet no clean way to get at it from this context.
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except BaseSSLError as e:
smart-open>                 # FIXME: Is there a better way to differentiate between SSLErrors?
smart-open>                 if "read operation timed out" not in str(e):
smart-open>                     # SSL errors related to framing/MAC get wrapped and reraised here
smart-open>                     raise SSLError(e) from e
smart-open>     
smart-open>                 raise ReadTimeoutError(self._pool, None, "Read timed out.") from e  # type: ignore[arg-type]
smart-open>     
smart-open>             except (HTTPException, OSError) as e:
smart-open>                 # This includes IncompleteRead.
smart-open> >               raise ProtocolError(f"Connection broken: {e!r}", e) from e
smart-open> E               urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/dxqvdy0rggdg8zqja3m3wf34dx5wqq3q-python3.11-urllib3-2.0.4/lib/python3.11/site-packages/urllib3/response.py:727: ProtocolError
smart-open> 
smart-open> During handling of the above exception, another exception occurred:
smart-open> 
smart-open> self = 
smart-open> 
smart-open>     @responses.activate
smart-open>     def test_seek_from_start(self):
smart-open>         responses.add_callback(responses.GET, URL, callback=request_callback)
smart-open>         reader = smart_open.http.SeekableBufferedInputBase(URL)
smart-open>     
smart-open>         reader.seek(10)
smart-open>         self.assertEqual(reader.tell(), 10)
smart-open> >       read_bytes = reader.read(size=10)
smart-open> 
smart-open> smart_open/tests/test_http.py:61: 
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> smart_open/http.py:183: in read
smart-open>     bytes_read = self._read_buffer.fill(self._read_iter)
smart-open> smart_open/bytebuffer.py:155: in fill
smart-open>     for more_bytes in source:
smart-open> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
smart-open> 
smart-open>     def generate():
smart-open>         # Special case for urllib3.
smart-open>         if hasattr(self.raw, "stream"):
smart-open>             try:
smart-open>                 yield from self.raw.stream(chunk_size, decode_content=True)
smart-open>             except ProtocolError as e:
smart-open> >               raise ChunkedEncodingError(e)
smart-open> E               requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(58 bytes read, 10 more expected)', IncompleteRead(58 bytes read, 10 more expected))
smart-open> 
smart-open> /nix/store/0ywyi98av0590s5idss3c13zas1cd1a0-python3.11-requests-2.31.0/lib/python3.11/site-packages/requests/models.py:818: ChunkedEncodingError

Steps/code to reproduce the problem

Install requests, with urllib3>2 and run the test suite.

Versions

  • Linux-6.1.46-x86_64-with-glibc2.37
  • Python 3.11.5 (main, Aug 24 2023, 12:23:19) [GCC 12.3.0]
  • smart_open 6.4.0

Checklist

Before you create the issue, please make sure you have:

  • [x] Described the problem clearly
  • [x] Provided a minimal reproducible example, including any required data
  • [x] Provided the version numbers of the relevant software

mweinelt avatar Sep 20 '23 12:09 mweinelt

I'm also experiencing this issue, does anyone have an update?

fionnmk avatar Jun 05 '24 17:06 fionnmk

Can you post full stack traces? The original error report truncates the error messages.

mpenkov avatar Jun 05 '24 22:06 mpenkov

Did you see the "Test protocol" detail fold-out? It is too easy to miss.

image

mweinelt avatar Jun 05 '24 22:06 mweinelt

I missed that. Thank you!

mpenkov avatar Jun 05 '24 23:06 mpenkov

Hello, we are also seeing this on Debian. I can provide a Dockerfile to reproduce the bug if that would be helpful

https://bugs.debian.org/1073421

mr-c avatar Jun 26 '24 19:06 mr-c

interestingly pip install smart_open[test] is selecting urllib3 v1 in the CI pipeline (hence this is being missed).

there is however no package that explicitly disallows urllib3 v2, so the pip resolver is choosing some interesting branch of the dependency tree to end up with urllib3 v1 🤔

pipgrip --tree -vv smart_open[test] shows no need to fallback to urllib3 v1:

Dependency tree
smart-open[test] (7.0.4)
├── azure-common (1.1.28)
├── azure-core (1.30.2)
│   ├── requests>=2.21.0 (2.32.3)
│   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   ├── idna<4,>=2.5 (3.7)
│   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   ├── six>=1.11.0 (1.16.0)
│   └── typing-extensions>=4.6.0 (4.12.2)
├── azure-storage-blob (12.20.0)
│   ├── azure-core>=1.28.0 (1.30.2)
│   │   ├── requests>=2.21.0 (2.32.3)
│   │   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   │   ├── idna<4,>=2.5 (3.7)
│   │   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   │   ├── six>=1.11.0 (1.16.0)
│   │   └── typing-extensions>=4.6.0 (4.12.2)
│   ├── cryptography>=2.1.4 (42.0.8)
│   │   └── cffi>=1.12 (1.16.0)
│   │       └── pycparser (2.22)
│   ├── isodate>=0.6.1 (0.6.1)
│   │   └── six (1.16.0)
│   └── typing-extensions>=4.6.0 (4.12.2)
├── boto3 (1.34.135)
│   ├── botocore<1.35.0,>=1.34.135 (1.34.135)
│   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   └── six>=1.5 (1.16.0)
│   │   └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   └── s3transfer<0.11.0,>=0.10.0 (0.10.2)
│       └── botocore<2.0a.0,>=1.33.2 (1.34.135)
│           ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│           ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│           │   └── six>=1.5 (1.16.0)
│           └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
├── google-cloud-storage>=2.6.0 (2.17.0)
│   ├── google-api-core<3.0.0dev,>=2.15.0 (2.19.1)
│   │   ├── google-auth<3.0.dev0,>=2.14.1 (2.30.0)
│   │   │   ├── cachetools<6.0,>=2.0.0 (5.3.3)
│   │   │   ├── pyasn1-modules>=0.2.1 (0.4.0)
│   │   │   │   └── pyasn1<0.7.0,>=0.4.6 (0.6.0)
│   │   │   └── rsa<5,>=3.1.4 (4.9)
│   │   │       └── pyasn1>=0.1.3 (0.6.0)
│   │   ├── googleapis-common-protos<2.0.dev0,>=1.56.2 (1.63.2)
│   │   │   └── protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.20.2 (5.27.2)
│   │   ├── proto-plus<2.0.0dev,>=1.22.3 (1.24.0)
│   │   │   └── protobuf<6.0.0dev,>=3.19.0 (5.27.2)
│   │   ├── protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.19.5 (5.27.2)
│   │   └── requests<3.0.0.dev0,>=2.18.0 (2.32.3)
│   │       ├── certifi>=2017.4.17 (2024.6.2)
│   │       ├── charset-normalizer<4,>=2 (3.3.2)
│   │       ├── idna<4,>=2.5 (3.7)
│   │       └── urllib3<3,>=1.21.1 (2.2.2)
│   ├── google-auth<3.0dev,>=2.26.1 (2.30.0)
│   │   ├── cachetools<6.0,>=2.0.0 (5.3.3)
│   │   ├── pyasn1-modules>=0.2.1 (0.4.0)
│   │   │   └── pyasn1<0.7.0,>=0.4.6 (0.6.0)
│   │   └── rsa<5,>=3.1.4 (4.9)
│   │       └── pyasn1>=0.1.3 (0.6.0)
│   ├── google-cloud-core<3.0dev,>=2.3.0 (2.4.1)
│   │   ├── google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0dev,>=1.31.6 (2.19.1)
│   │   │   ├── google-auth<3.0.dev0,>=2.14.1 (2.30.0)
│   │   │   │   ├── cachetools<6.0,>=2.0.0 (5.3.3)
│   │   │   │   ├── pyasn1-modules>=0.2.1 (0.4.0)
│   │   │   │   │   └── pyasn1<0.7.0,>=0.4.6 (0.6.0)
│   │   │   │   └── rsa<5,>=3.1.4 (4.9)
│   │   │   │       └── pyasn1>=0.1.3 (0.6.0)
│   │   │   ├── googleapis-common-protos<2.0.dev0,>=1.56.2 (1.63.2)
│   │   │   │   └── protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.20.2 (5.27.2)
│   │   │   ├── proto-plus<2.0.0dev,>=1.22.3 (1.24.0)
│   │   │   │   └── protobuf<6.0.0dev,>=3.19.0 (5.27.2)
│   │   │   ├── protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.19.5 (5.27.2)
│   │   │   └── requests<3.0.0.dev0,>=2.18.0 (2.32.3)
│   │   │       ├── certifi>=2017.4.17 (2024.6.2)
│   │   │       ├── charset-normalizer<4,>=2 (3.3.2)
│   │   │       ├── idna<4,>=2.5 (3.7)
│   │   │       └── urllib3<3,>=1.21.1 (2.2.2)
│   │   └── google-auth<3.0dev,>=1.25.0 (2.30.0)
│   │       ├── cachetools<6.0,>=2.0.0 (5.3.3)
│   │       ├── pyasn1-modules>=0.2.1 (0.4.0)
│   │       │   └── pyasn1<0.7.0,>=0.4.6 (0.6.0)
│   │       └── rsa<5,>=3.1.4 (4.9)
│   │           └── pyasn1>=0.1.3 (0.6.0)
│   ├── google-crc32c<2.0dev,>=1.0 (1.5.0)
│   ├── google-resumable-media>=2.6.0 (2.7.1)
│   │   └── google-crc32c<2.0dev,>=1.0 (1.5.0)
│   └── requests<3.0.0dev,>=2.18.0 (2.32.3)
│       ├── certifi>=2017.4.17 (2024.6.2)
│       ├── charset-normalizer<4,>=2 (3.3.2)
│       ├── idna<4,>=2.5 (3.7)
│       └── urllib3<3,>=1.21.1 (2.2.2)
├── moto[server] (5.0.9)
│   ├── antlr4-python3-runtime (4.13.1)
│   ├── aws-xray-sdk!=0.96,>=0.93 (2.14.0)
│   │   ├── botocore>=1.11.3 (1.34.135)
│   │   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   │   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   │   └── six>=1.5 (1.16.0)
│   │   │   └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   │   └── wrapt (1.16.0)
│   ├── boto3>=1.9.201 (1.34.135)
│   │   ├── botocore<1.35.0,>=1.34.135 (1.34.135)
│   │   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   │   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   │   └── six>=1.5 (1.16.0)
│   │   │   └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   └── s3transfer<0.11.0,>=0.10.0 (0.10.2)
│   │       └── botocore<2.0a.0,>=1.33.2 (1.34.135)
│   │           ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │           ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │           │   └── six>=1.5 (1.16.0)
│   │           └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   ├── botocore>=1.14.0 (1.34.135)
│   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   └── six>=1.5 (1.16.0)
│   │   └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   ├── cfn-lint>=0.40.0 (1.4.2)
│   │   ├── aws-sam-translator>=1.89.0 (1.89.0)
│   │   │   ├── boto3==1.*,>=1.19.5 (1.34.135)
│   │   │   │   ├── botocore<1.35.0,>=1.34.135 (1.34.135)
│   │   │   │   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   │   │   │   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   │   │   │   └── six>=1.5 (1.16.0)
│   │   │   │   │   └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   │   │   │   ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   │   │   └── s3transfer<0.11.0,>=0.10.0 (0.10.2)
│   │   │   │       └── botocore<2.0a.0,>=1.33.2 (1.34.135)
│   │   │   │           ├── jmespath<2.0.0,>=0.7.1 (1.0.1)
│   │   │   │           ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   │   │           │   └── six>=1.5 (1.16.0)
│   │   │   │           └── urllib3!=2.2.0,<3,>=1.25.4 (2.2.2)
│   │   │   ├── jsonschema<5,>=3.2 (4.22.0)
│   │   │   │   ├── attrs>=22.2.0 (23.2.0)
│   │   │   │   ├── jsonschema-specifications>=2023.03.6 (2023.12.1)
│   │   │   │   │   └── referencing>=0.31.0 (0.35.1)
│   │   │   │   │       ├── attrs>=22.2.0 (23.2.0)
│   │   │   │   │       └── rpds-py>=0.7.0 (0.18.1)
│   │   │   │   ├── referencing>=0.28.4 (0.35.1)
│   │   │   │   │   ├── attrs>=22.2.0 (23.2.0)
│   │   │   │   │   └── rpds-py>=0.7.0 (0.18.1)
│   │   │   │   └── rpds-py>=0.7.1 (0.18.1)
│   │   │   ├── pydantic<3,>=1.8 (2.7.4)
│   │   │   │   ├── annotated-types>=0.4.0 (0.7.0)
│   │   │   │   ├── pydantic-core==2.18.4 (2.18.4)
│   │   │   │   │   └── typing-extensions!=4.7.0,>=4.6.0 (4.12.2)
│   │   │   │   └── typing-extensions>=4.6.1 (4.12.2)
│   │   │   └── typing-extensions>=4.4 (4.12.2)
│   │   ├── jsonpatch (1.33)
│   │   │   └── jsonpointer>=1.9 (3.0.0)
│   │   ├── networkx<4,>=2.4 (3.3)
│   │   ├── pyyaml>5.4 (6.0.1)
│   │   ├── regex (2024.5.15)
│   │   ├── sympy>=1.0.0 (1.12.1)
│   │   │   └── mpmath<1.4.0,>=1.1.0 (1.3.0)
│   │   └── typing-extensions (4.12.2)
│   ├── cryptography>=3.3.1 (42.0.8)
│   │   └── cffi>=1.12 (1.16.0)
│   │       └── pycparser (2.22)
│   ├── docker>=3.0.0 (7.1.0)
│   │   ├── requests>=2.26.0 (2.32.3)
│   │   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   │   ├── idna<4,>=2.5 (3.7)
│   │   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   │   └── urllib3>=1.26.0 (2.2.2)
│   ├── flask!=2.2.0,!=2.2.1 (3.0.3)
│   │   ├── blinker>=1.6.2 (1.8.2)
│   │   ├── click>=8.1.3 (8.1.7)
│   │   ├── itsdangerous>=2.1.2 (2.2.0)
│   │   ├── jinja2>=3.1.2 (3.1.4)
│   │   │   └── markupsafe>=2.0 (2.1.5)
│   │   └── werkzeug>=3.0.0 (3.0.3)
│   │       └── markupsafe>=2.1.1 (2.1.5)
│   ├── flask-cors (4.0.1)
│   │   └── flask>=0.9 (3.0.3)
│   │       ├── blinker>=1.6.2 (1.8.2)
│   │       ├── click>=8.1.3 (8.1.7)
│   │       ├── itsdangerous>=2.1.2 (2.2.0)
│   │       ├── jinja2>=3.1.2 (3.1.4)
│   │       │   └── markupsafe>=2.0 (2.1.5)
│   │       └── werkzeug>=3.0.0 (3.0.3)
│   │           └── markupsafe>=2.1.1 (2.1.5)
│   ├── graphql-core (3.2.3)
│   ├── jinja2>=2.10.1 (3.1.4)
│   │   └── markupsafe>=2.0 (2.1.5)
│   ├── joserfc>=0.9.0 (0.12.0)
│   │   └── cryptography (42.0.8)
│   │       └── cffi>=1.12 (1.16.0)
│   │           └── pycparser (2.22)
│   ├── jsondiff>=1.1.2 (2.0.0)
│   ├── jsonpath-ng (1.6.1)
│   │   └── ply (3.11)
│   ├── openapi-spec-validator>=0.5.0 (0.7.1)
│   │   ├── jsonschema-path<0.4.0,>=0.3.1 (0.3.3)
│   │   │   ├── pathable<0.5.0,>=0.4.1 (0.4.3)
│   │   │   ├── pyyaml>=5.1 (6.0.1)
│   │   │   ├── referencing<0.36.0,>=0.28.0 (0.35.1)
│   │   │   │   ├── attrs>=22.2.0 (23.2.0)
│   │   │   │   └── rpds-py>=0.7.0 (0.18.1)
│   │   │   └── requests<3.0.0,>=2.31.0 (2.32.3)
│   │   │       ├── certifi>=2017.4.17 (2024.6.2)
│   │   │       ├── charset-normalizer<4,>=2 (3.3.2)
│   │   │       ├── idna<4,>=2.5 (3.7)
│   │   │       └── urllib3<3,>=1.21.1 (2.2.2)
│   │   ├── jsonschema<5.0.0,>=4.18.0 (4.22.0)
│   │   │   ├── attrs>=22.2.0 (23.2.0)
│   │   │   ├── jsonschema-specifications>=2023.03.6 (2023.12.1)
│   │   │   │   └── referencing>=0.31.0 (0.35.1)
│   │   │   │       ├── attrs>=22.2.0 (23.2.0)
│   │   │   │       └── rpds-py>=0.7.0 (0.18.1)
│   │   │   ├── referencing>=0.28.4 (0.35.1)
│   │   │   │   ├── attrs>=22.2.0 (23.2.0)
│   │   │   │   └── rpds-py>=0.7.0 (0.18.1)
│   │   │   └── rpds-py>=0.7.1 (0.18.1)
│   │   ├── lazy-object-proxy<2.0.0,>=1.7.1 (1.10.0)
│   │   └── openapi-schema-validator<0.7.0,>=0.6.0 (0.6.2)
│   │       ├── jsonschema-specifications<2024.0.0,>=2023.5.2 (2023.12.1)
│   │       │   └── referencing>=0.31.0 (0.35.1)
│   │       │       ├── attrs>=22.2.0 (23.2.0)
│   │       │       └── rpds-py>=0.7.0 (0.18.1)
│   │       ├── jsonschema<5.0.0,>=4.19.1 (4.22.0)
│   │       │   ├── attrs>=22.2.0 (23.2.0)
│   │       │   ├── jsonschema-specifications>=2023.03.6 (2023.12.1)
│   │       │   │   └── referencing>=0.31.0 (0.35.1)
│   │       │   │       ├── attrs>=22.2.0 (23.2.0)
│   │       │   │       └── rpds-py>=0.7.0 (0.18.1)
│   │       │   ├── referencing>=0.28.4 (0.35.1)
│   │       │   │   ├── attrs>=22.2.0 (23.2.0)
│   │       │   │   └── rpds-py>=0.7.0 (0.18.1)
│   │       │   └── rpds-py>=0.7.1 (0.18.1)
│   │       └── rfc3339-validator (0.1.4)
│   │           └── six (1.16.0)
│   ├── py-partiql-parser==0.5.5 (0.5.5)
│   ├── pyparsing>=3.0.7 (3.1.2)
│   ├── python-dateutil<3.0.0,>=2.1 (2.9.0.post0)
│   │   └── six>=1.5 (1.16.0)
│   ├── pyyaml>=5.1 (6.0.1)
│   ├── requests>=2.5 (2.32.3)
│   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   ├── idna<4,>=2.5 (3.7)
│   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   ├── responses>=0.15.0 (0.25.3)
│   │   ├── pyyaml (6.0.1)
│   │   ├── requests<3.0,>=2.30.0 (2.32.3)
│   │   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   │   ├── idna<4,>=2.5 (3.7)
│   │   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   │   └── urllib3<3.0,>=1.25.10 (2.2.2)
│   ├── setuptools (70.1.1)
│   ├── werkzeug!=2.2.0,!=2.2.1,>=0.5 (3.0.3)
│   │   └── markupsafe>=2.1.1 (2.1.5)
│   └── xmltodict (0.13.0)
├── paramiko (3.4.0)
│   ├── bcrypt>=3.2 (4.1.3)
│   ├── cryptography>=3.3 (42.0.8)
│   │   └── cffi>=1.12 (1.16.0)
│   │       └── pycparser (2.22)
│   └── pynacl>=1.5 (1.5.0)
│       └── cffi>=1.4.1 (1.16.0)
│           └── pycparser (2.22)
├── pytest (8.2.2)
│   ├── iniconfig (2.0.0)
│   ├── packaging (24.1)
│   └── pluggy<2.0,>=1.5 (1.5.0)
├── pytest-rerunfailures (14.0)
│   ├── packaging>=17.1 (24.1)
│   └── pytest>=7.2 (8.2.2)
│       ├── iniconfig (2.0.0)
│       ├── packaging (24.1)
│       └── pluggy<2.0,>=1.5 (1.5.0)
├── requests (2.32.3)
│   ├── certifi>=2017.4.17 (2024.6.2)
│   ├── charset-normalizer<4,>=2 (3.3.2)
│   ├── idna<4,>=2.5 (3.7)
│   └── urllib3<3,>=1.21.1 (2.2.2)
├── responses (0.25.3)
│   ├── pyyaml (6.0.1)
│   ├── requests<3.0,>=2.30.0 (2.32.3)
│   │   ├── certifi>=2017.4.17 (2024.6.2)
│   │   ├── charset-normalizer<4,>=2 (3.3.2)
│   │   ├── idna<4,>=2.5 (3.7)
│   │   └── urllib3<3,>=1.21.1 (2.2.2)
│   └── urllib3<3.0,>=1.25.10 (2.2.2)
├── wrapt (1.16.0)
└── zstandard (0.22.0)

ddelange avatar Jun 28 '24 13:06 ddelange

@mr-c I worked ont the Debian packaging today, stumbled on this too. I don't want to rush anything before my Holliday, so I left it as-is.

a-detiste avatar Jul 22 '24 15:07 a-detiste

this commit is likely to blame as it was introduced in v2 and touches the IncompleteRead error from the traceback: https://github.com/urllib3/urllib3/commit/c35033f6cc54106ca66ef2d48a9e3564d4fb0e07

however, if you blame further, it turns out we're looking at 8 years old code: https://github.com/urllib3/urllib3/blame/9763f09d2ca93c2e10150bfddba341b6a54993ad/src/urllib3/response.py#L782

so there's no obvious change to account for here AFAICT

ddelange avatar Jul 22 '24 21:07 ddelange

I figured out why CI was running urllib3 v1: the CI python-package.yml had a typo, causing all the tests to run on python 3.7 instead of on 3.8--3.12. fixing in #828

ddelange avatar Jul 24 '24 10:07 ddelange