Hello community, here is the log from the commit of package python-h2 for openSUSE:Factory checked in at 2020-02-29 21:23:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-h2 (Old) and /work/SRC/openSUSE:Factory/.python-h2.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-h2" Sat Feb 29 21:23:21 2020 rev:9 rq:779741 version:3.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-h2/python-h2.changes 2019-12-07 15:23:08.967730795 +0100 +++ /work/SRC/openSUSE:Factory/.python-h2.new.26092/python-h2.changes 2020-02-29 21:23:26.910389926 +0100 @@ -1,0 +2,9 @@ +Thu Feb 27 05:43:42 UTC 2020 - Steve Kowalik <steven.kowa...@suse.com> + +- Update to 3.2.0: + * Receiving DATA frames on closed (or reset) streams now properly emit a + WINDOW_UPDATE to keep the connection flow window topped up. + * h2.config.logger now uses a trace(...) function, in addition to + debug(...). + +------------------------------------------------------------------- Old: ---- h2-3.1.1.tar.gz New: ---- h2-3.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-h2.spec ++++++ --- /var/tmp/diff_new_pack.pO2q8T/_old 2020-02-29 21:23:27.594391279 +0100 +++ /var/tmp/diff_new_pack.pO2q8T/_new 2020-02-29 21:23:27.598391287 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-h2 # -# Copyright (c) 2019 SUSE LLC +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-h2 -Version: 3.1.1 +Version: 3.2.0 Release: 0 Summary: HTTP/2 State-Machine based protocol implementation License: MIT ++++++ h2-3.1.1.tar.gz -> h2-3.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/HISTORY.rst new/h2-3.2.0/HISTORY.rst --- old/h2-3.1.1/HISTORY.rst 2019-08-02 15:10:28.000000000 +0200 +++ new/h2-3.2.0/HISTORY.rst 2020-02-08 17:39:21.000000000 +0100 @@ -1,6 +1,23 @@ Release History =============== +3.2.0 (2020-02-08) +------------------ + +Bugfixes +~~~~~~~~ + +- Receiving DATA frames on closed (or reset) streams now properly emit a + WINDOW_UPDATE to keep the connection flow window topped up. + +API Changes (Backward-Incompatible) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``h2.config.logger`` now uses a `trace(...)` function, in addition + to `debug(...)`. If you defined a custom logger object, you need to handle + these new function calls. + + 3.1.1 (2019-08-02) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/PKG-INFO new/h2-3.2.0/PKG-INFO --- old/h2-3.1.1/PKG-INFO 2019-08-02 15:10:46.000000000 +0200 +++ new/h2-3.2.0/PKG-INFO 2020-02-08 17:43:25.000000000 +0100 @@ -1,11 +1,13 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: h2 -Version: 3.1.1 +Version: 3.2.0 Summary: HTTP/2 State-Machine based protocol implementation -Home-page: http://hyper.rtfd.org +Home-page: https://github.com/python-hyper/hyper-h2 Author: Cory Benfield Author-email: c...@lukasa.co.uk License: MIT License +Project-URL: Documentation, https://python-hyper.org/projects/h2 +Project-URL: Source, https://github.com/python-hyper/hyper-h2 Description: =============================== hyper-h2: HTTP/2 Protocol Stack =============================== @@ -76,6 +78,23 @@ Release History =============== + 3.2.0 (2020-02-08) + ------------------ + + Bugfixes + ~~~~~~~~ + + - Receiving DATA frames on closed (or reset) streams now properly emit a + WINDOW_UPDATE to keep the connection flow window topped up. + + API Changes (Backward-Incompatible) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - ``h2.config.logger`` now uses a `trace(...)` function, in addition + to `debug(...)`. If you defined a custom logger object, you need to handle + these new function calls. + + 3.1.1 (2019-08-02) ------------------ @@ -825,9 +844,10 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/docs/source/conf.py new/h2-3.2.0/docs/source/conf.py --- old/h2-3.1.1/docs/source/conf.py 2019-08-02 15:10:28.000000000 +0200 +++ new/h2-3.2.0/docs/source/conf.py 2020-02-08 17:39:21.000000000 +0100 @@ -55,9 +55,9 @@ # built documents. # # The short X.Y version. -version = '3.1.1' +version = '3.2.0' # The full version, including alpha/beta/rc tags. -release = '3.1.1' +release = '3.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/examples/fragments/client_https_setup_fragment.py new/h2-3.2.0/examples/fragments/client_https_setup_fragment.py --- old/h2-3.1.1/examples/fragments/client_https_setup_fragment.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/examples/fragments/client_https_setup_fragment.py 2020-01-19 12:50:23.000000000 +0100 @@ -48,7 +48,7 @@ # RFC 7540 Section 9.2.2: "deployments of HTTP/2 that use TLS 1.2 MUST # support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256". In practice, the - # blacklist defined in this section allows only the AES GCM and ChaCha20 + # blocklist defined in this section allows only the AES GCM and ChaCha20 # cipher suites with ephemeral key negotiation. ctx.set_ciphers("ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/examples/fragments/server_https_setup_fragment.py new/h2-3.2.0/examples/fragments/server_https_setup_fragment.py --- old/h2-3.1.1/examples/fragments/server_https_setup_fragment.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/examples/fragments/server_https_setup_fragment.py 2020-01-19 12:50:23.000000000 +0100 @@ -51,7 +51,7 @@ # RFC 7540 Section 9.2.2: "deployments of HTTP/2 that use TLS 1.2 MUST # support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256". In practice, the - # blacklist defined in this section allows only the AES GCM and ChaCha20 + # blocklist defined in this section allows only the AES GCM and ChaCha20 # cipher suites with ephemeral key negotiation. ctx.set_ciphers("ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/h2/__init__.py new/h2-3.2.0/h2/__init__.py --- old/h2-3.1.1/h2/__init__.py 2019-08-02 15:10:28.000000000 +0200 +++ new/h2-3.2.0/h2/__init__.py 2020-02-08 17:39:21.000000000 +0100 @@ -5,4 +5,4 @@ A HTTP/2 implementation. """ -__version__ = '3.1.1' +__version__ = '3.2.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/h2/config.py new/h2-3.2.0/h2/config.py --- old/h2-3.1.1/h2/config.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/h2/config.py 2020-02-08 12:23:54.000000000 +0100 @@ -29,7 +29,7 @@ """ An Logger object that does not actual logging, hence a DummyLogger. - For the class the log operation is merely a no-op. The intent is to avoid + For the class the log operation is merely a no-op. The intent is to avoid conditionals being sprinkled throughout the hyper-h2 code for calls to logging functions when no logger is passed into the corresponding object. """ @@ -40,6 +40,12 @@ """ No-op logging. Only level needed for now. """ + pass + + def trace(self, *vargs, **kwargs): + """ + No-op logging. Only level needed for now. + """ pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/h2/connection.py new/h2-3.2.0/h2/connection.py --- old/h2-3.1.1/h2/connection.py 2019-08-02 15:10:17.000000000 +0200 +++ new/h2-3.2.0/h2/connection.py 2020-02-08 12:23:54.000000000 +0100 @@ -1450,7 +1450,7 @@ :returns: A list of events that the remote peer triggered by sending this data. """ - self.config.logger.debug( + self.config.logger.trace( "Process received data on connection. Received data: %r", data ) @@ -1634,6 +1634,35 @@ return frames, events + stream_events + def _handle_data_on_closed_stream(self, events, exc, frame): + # This stream is already closed - and yet we received a DATA frame. + # The received DATA frame counts towards the connection flow window. + # We need to manually to acknowledge the DATA frame to update the flow + # window of the connection. Otherwise the whole connection stalls due + # the inbound flow window being 0. + frames = [] + conn_manager = self._inbound_flow_control_window_manager + conn_increment = conn_manager.process_bytes( + frame.flow_controlled_length + ) + if conn_increment: + f = WindowUpdateFrame(0) + f.window_increment = conn_increment + frames.append(f) + self.config.logger.debug( + "Received DATA frame on closed stream %d - " + "auto-emitted a WINDOW_UPDATE by %d", + frame.stream_id, conn_increment + ) + f = RstStreamFrame(exc.stream_id) + f.error_code = exc.error_code + frames.append(f) + self.config.logger.debug( + "Stream %d already CLOSED or cleaned up - " + "auto-emitted a RST_FRAME" % frame.stream_id + ) + return frames, events + exc._events + def _receive_data_frame(self, frame): """ Receive a data frame on the connection. @@ -1646,12 +1675,19 @@ self._inbound_flow_control_window_manager.window_consumed( flow_controlled_length ) - stream = self._get_stream_by_id(frame.stream_id) - frames, stream_events = stream.receive_data( - frame.data, - 'END_STREAM' in frame.flags, - flow_controlled_length - ) + + try: + stream = self._get_stream_by_id(frame.stream_id) + frames, stream_events = stream.receive_data( + frame.data, + 'END_STREAM' in frame.flags, + flow_controlled_length + ) + except StreamClosedError as e: + # This stream is either marked as CLOSED or already gone from our + # internal state. + return self._handle_data_on_closed_stream(events, e, frame) + return frames, events + stream_events def _receive_settings_frame(self, frame): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/h2.egg-info/PKG-INFO new/h2-3.2.0/h2.egg-info/PKG-INFO --- old/h2-3.1.1/h2.egg-info/PKG-INFO 2019-08-02 15:10:46.000000000 +0200 +++ new/h2-3.2.0/h2.egg-info/PKG-INFO 2020-02-08 17:43:24.000000000 +0100 @@ -1,11 +1,13 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: h2 -Version: 3.1.1 +Version: 3.2.0 Summary: HTTP/2 State-Machine based protocol implementation -Home-page: http://hyper.rtfd.org +Home-page: https://github.com/python-hyper/hyper-h2 Author: Cory Benfield Author-email: c...@lukasa.co.uk License: MIT License +Project-URL: Documentation, https://python-hyper.org/projects/h2 +Project-URL: Source, https://github.com/python-hyper/hyper-h2 Description: =============================== hyper-h2: HTTP/2 Protocol Stack =============================== @@ -76,6 +78,23 @@ Release History =============== + 3.2.0 (2020-02-08) + ------------------ + + Bugfixes + ~~~~~~~~ + + - Receiving DATA frames on closed (or reset) streams now properly emit a + WINDOW_UPDATE to keep the connection flow window topped up. + + API Changes (Backward-Incompatible) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - ``h2.config.logger`` now uses a `trace(...)` function, in addition + to `debug(...)`. If you defined a custom logger object, you need to handle + these new function calls. + + 3.1.1 (2019-08-02) ------------------ @@ -825,9 +844,10 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/h2.egg-info/requires.txt new/h2-3.2.0/h2.egg-info/requires.txt --- old/h2-3.1.1/h2.egg-info/requires.txt 2019-08-02 15:10:46.000000000 +0200 +++ new/h2-3.2.0/h2.egg-info/requires.txt 2020-02-08 17:43:24.000000000 +0100 @@ -1,5 +1,5 @@ hyperframe<6,>=5.2.0 -hpack<4,>=2.3 +hpack<4,>=3.0 -[:python_version == "2.7" or python_version == "3.3"] +[:python_version == "2.7"] enum34<2,>=1.1.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/setup.cfg new/h2-3.2.0/setup.cfg --- old/h2-3.1.1/setup.cfg 2019-08-02 15:10:46.000000000 +0200 +++ new/h2-3.2.0/setup.cfg 2020-02-08 17:43:25.000000000 +0100 @@ -1,3 +1,6 @@ +[tool:pytest] +testpaths = test + [wheel] universal = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/setup.py new/h2-3.2.0/setup.py --- old/h2-3.1.1/setup.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/setup.py 2020-02-08 17:39:18.000000000 +0100 @@ -40,7 +40,11 @@ long_description=u'\n\n'.join([readme, history]), author='Cory Benfield', author_email='c...@lukasa.co.uk', - url='http://hyper.rtfd.org', + url='https://github.com/python-hyper/hyper-h2', + project_urls={ + 'Documentation': 'https://python-hyper.org/projects/h2', + 'Source': 'https://github.com/python-hyper/hyper-h2', + }, packages=packages, package_data={'': ['LICENSE', 'README.rst', 'CONTRIBUTORS.rst', 'HISTORY.rst', 'NOTICES']}, package_dir={'h2': 'h2'}, @@ -54,18 +58,19 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ], install_requires=[ 'hyperframe>=5.2.0, <6', - 'hpack>=2.3,<4', + 'hpack>=3.0,<4', ], extras_require={ - ':python_version == "2.7" or python_version == "3.3"': ['enum34>=1.1.6, <2'], + ':python_version == "2.7"': ['enum34>=1.1.6, <2'], } ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test/test_closed_streams.py new/h2-3.2.0/test/test_closed_streams.py --- old/h2-3.1.1/test/test_closed_streams.py 2019-08-02 15:10:17.000000000 +0200 +++ new/h2-3.2.0/test/test_closed_streams.py 2020-02-08 12:23:54.000000000 +0100 @@ -195,7 +195,6 @@ @pytest.mark.parametrize( "frame", [ - lambda self, ff: ff.build_data_frame(b'hello'), lambda self, ff: ff.build_headers_frame( self.example_request_headers, flags=['END_STREAM']), lambda self, ff: ff.build_headers_frame( @@ -245,7 +244,6 @@ @pytest.mark.parametrize( "frame", [ - lambda self, ff: ff.build_data_frame(b'hello'), lambda self, ff: ff.build_headers_frame( self.example_response_headers, flags=['END_STREAM']), lambda self, ff: ff.build_headers_frame( @@ -344,7 +342,6 @@ self.example_request_headers), lambda self, ff: ff.build_headers_frame( self.example_request_headers, flags=['END_STREAM']), - lambda self, ff: ff.build_data_frame(b'hello'), ] ) def test_resets_further_frames_after_recv_reset(self, @@ -352,7 +349,8 @@ frame): """ A stream that is closed by receive RST_STREAM can receive further - frames: it simply sends RST_STREAM for it. + frames: it simply sends RST_STREAM for it, and additionally + WINDOW_UPDATE for DATA frames. """ c = h2.connection.H2Connection(config=self.server_config) c.receive_data(frame_factory.preamble()) @@ -396,6 +394,59 @@ assert not events assert c.data_to_send() == rst_frame.serialize() * 3 + def test_resets_further_data_frames_after_recv_reset(self, + frame_factory): + """ + A stream that is closed by receive RST_STREAM can receive further + DATA frames: it simply sends WINDOW_UPDATE for the connection flow + window, and RST_STREAM for the stream. + """ + c = h2.connection.H2Connection(config=self.server_config) + c.receive_data(frame_factory.preamble()) + c.initiate_connection() + + header_frame = frame_factory.build_headers_frame( + self.example_request_headers, flags=['END_STREAM'] + ) + c.receive_data(header_frame.serialize()) + + c.send_headers( + stream_id=1, + headers=self.example_response_headers, + end_stream=False + ) + + rst_frame = frame_factory.build_rst_stream_frame( + 1, h2.errors.ErrorCodes.STREAM_CLOSED + ) + c.receive_data(rst_frame.serialize()) + c.clear_outbound_data_buffer() + + f = frame_factory.build_data_frame( + data=b'some data' + ) + + events = c.receive_data(f.serialize()) + assert not events + + expected = frame_factory.build_rst_stream_frame( + stream_id=1, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected + + events = c.receive_data(f.serialize() * 3) + assert not events + assert c.data_to_send() == expected * 3 + + # Iterate over the streams to make sure it's gone, then confirm the + # behaviour is unchanged. + c.open_outbound_streams + + events = c.receive_data(f.serialize() * 3) + assert not events + assert c.data_to_send() == expected * 3 + @pytest.mark.parametrize( "frame", [ @@ -403,7 +454,6 @@ self.example_request_headers), lambda self, ff: ff.build_headers_frame( self.example_request_headers, flags=['END_STREAM']), - lambda self, ff: ff.build_data_frame(b'hello'), ] ) def test_resets_further_frames_after_send_reset(self, @@ -455,3 +505,51 @@ events = c.receive_data(f.serialize() * 3) assert not events assert c.data_to_send() == rst_frame.serialize() * 3 + + def test_resets_further_data_frames_after_send_reset(self, + frame_factory): + """ + A stream that is closed by sent RST_STREAM can receive further + data frames: it simply sends WINDOW_UPDATE and RST_STREAM for it. + """ + c = h2.connection.H2Connection(config=self.server_config) + c.receive_data(frame_factory.preamble()) + c.initiate_connection() + + header_frame = frame_factory.build_headers_frame( + self.example_request_headers, flags=['END_STREAM'] + ) + c.receive_data(header_frame.serialize()) + + c.send_headers( + stream_id=1, + headers=self.example_response_headers, + end_stream=False + ) + + c.reset_stream(1, h2.errors.ErrorCodes.INTERNAL_ERROR) + + c.clear_outbound_data_buffer() + + f = frame_factory.build_data_frame( + data=b'some data' + ) + events = c.receive_data(f.serialize()) + assert not events + expected = frame_factory.build_rst_stream_frame( + stream_id=1, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected + + events = c.receive_data(f.serialize() * 3) + assert not events + assert c.data_to_send() == expected * 3 + + # Iterate over the streams to make sure it's gone, then confirm the + # behaviour is unchanged. + c.open_outbound_streams + + events = c.receive_data(f.serialize() * 3) + assert not events + assert c.data_to_send() == expected * 3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test/test_flow_control_window.py new/h2-3.2.0/test/test_flow_control_window.py --- old/h2-3.1.1/test/test_flow_control_window.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/test/test_flow_control_window.py 2020-02-08 12:23:54.000000000 +0100 @@ -638,6 +638,42 @@ with pytest.raises(h2.exceptions.FlowControlError): c.increment_flow_control_window(increment=increment, stream_id=1) + def test_send_update_on_closed_streams(self, frame_factory): + c = h2.connection.H2Connection() + c.initiate_connection() + c.send_headers(1, self.example_request_headers) + c.reset_stream(1) + + c.clear_outbound_data_buffer() + c.open_outbound_streams + c.open_inbound_streams + + f = frame_factory.build_data_frame(b'some data'*1500) + events = c.receive_data(f.serialize()*3) + assert not events + + expected = frame_factory.build_rst_stream_frame( + stream_id=1, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() * 2 + frame_factory.build_window_update_frame( + stream_id=0, + increment=40500, + ).serialize() + frame_factory.build_rst_stream_frame( + stream_id=1, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected + + f = frame_factory.build_data_frame(b'') + events = c.receive_data(f.serialize()) + assert not events + + expected = frame_factory.build_rst_stream_frame( + stream_id=1, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected + class TestAutomaticFlowControl(object): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test/test_h2_upgrade.py new/h2-3.2.0/test/test_h2_upgrade.py --- old/h2-3.1.1/test/test_h2_upgrade.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/test/test_h2_upgrade.py 2020-02-08 15:57:08.000000000 +0100 @@ -260,11 +260,11 @@ ) c.receive_data(f.serialize()) - expected_frame = frame_factory.build_rst_stream_frame( + expected = frame_factory.build_rst_stream_frame( stream_id=1, error_code=h2.errors.ErrorCodes.STREAM_CLOSED, - ) - assert c.data_to_send() == expected_frame.serialize() + ).serialize() + assert c.data_to_send() == expected def test_client_settings_are_applied(self, frame_factory): """ @@ -278,7 +278,7 @@ # start of the connection, do not agree on their initial settings # state. assert ( - client.local_settings._settings != server.remote_settings._settings + client.local_settings != server.remote_settings ) # Get the client header data and pass it to the server. @@ -297,10 +297,6 @@ ) assert server.data_to_send() == expected_frame.serialize() - # We violate abstraction layers here, but I don't think defining __eq__ - # for this is worth it. In this case, both the client and server should - # agree that these settings have been ACK'd, so their underlying - # dictionaries should be identical. assert ( - client.local_settings._settings == server.remote_settings._settings + client.local_settings == server.remote_settings ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test/test_invalid_frame_sequences.py new/h2-3.2.0/test/test_invalid_frame_sequences.py --- old/h2-3.1.1/test/test_invalid_frame_sequences.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/test/test_invalid_frame_sequences.py 2020-02-08 12:23:54.000000000 +0100 @@ -149,14 +149,16 @@ c.receive_data(f.serialize()) c.clear_outbound_data_buffer() - bad_frame = frame_factory.build_data_frame(data=b'hello') + bad_frame = frame_factory.build_data_frame( + data=b'some data' + ) c.receive_data(bad_frame.serialize()) - expected_frame = frame_factory.build_rst_stream_frame( + expected = frame_factory.build_rst_stream_frame( stream_id=1, - error_code=0x5, - ) - assert c.data_to_send() == expected_frame.serialize() + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected def test_unexpected_continuation_on_closed_stream(self, frame_factory): """ @@ -293,15 +295,15 @@ c.clear_outbound_data_buffer() bad_frame = frame_factory.build_data_frame( - data=b'hello' + data=b'some data' ) events = c.receive_data(bad_frame.serialize()) - expected_frame = frame_factory.build_rst_stream_frame( + expected = frame_factory.build_rst_stream_frame( stream_id=1, - error_code=0x5, - ) - assert c.data_to_send() == expected_frame.serialize() + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected assert len(events) == 1 event = events[0] @@ -327,16 +329,16 @@ c.clear_outbound_data_buffer() bad_frame = frame_factory.build_data_frame( - data=b'hello' + data=b'some data' ) # Receive 5 frames. events = c.receive_data(bad_frame.serialize() * 5) - expected_frame = frame_factory.build_rst_stream_frame( + expected = frame_factory.build_rst_stream_frame( stream_id=1, - error_code=0x5, - ) - assert c.data_to_send() == expected_frame.serialize() * 5 + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected * 5 assert len(events) == 1 event = events[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test/test_stream_reset.py new/h2-3.2.0/test/test_stream_reset.py --- old/h2-3.1.1/test/test_stream_reset.py 2019-01-22 18:41:43.000000000 +0100 +++ new/h2-3.2.0/test/test_stream_reset.py 2020-02-08 12:23:54.000000000 +0100 @@ -70,8 +70,8 @@ other_id, frame_factory): """ - A stream that has been reset still affects the connection flow control - window. + A stream that has been reset does not affect the connection flow + control window. """ c = h2.connection.H2Connection() c.initiate_connection() @@ -89,19 +89,19 @@ c.clear_outbound_data_buffer() f = frame_factory.build_data_frame( - data=b'some data!', + data=b'some data', stream_id=close_id ) - events = c.receive_data(f.serialize()) + c.receive_data(f.serialize()) - rst_frame = frame_factory.build_rst_stream_frame( - close_id, h2.errors.ErrorCodes.STREAM_CLOSED - ) - assert not events - assert c.data_to_send() == rst_frame.serialize() + expected = frame_factory.build_rst_stream_frame( + stream_id=close_id, + error_code=h2.errors.ErrorCodes.STREAM_CLOSED, + ).serialize() + assert c.data_to_send() == expected new_window = c.remote_flow_control_window(stream_id=other_id) - assert initial_window - len(b'some data!') == new_window + assert initial_window - len(b'some data') == new_window @pytest.mark.parametrize('clear_streams', [True, False]) def test_reset_stream_automatically_resets_pushed_streams(self, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/test_requirements.txt new/h2-3.2.0/test_requirements.txt --- old/h2-3.1.1/test_requirements.txt 2019-08-02 15:10:17.000000000 +0200 +++ new/h2-3.2.0/test_requirements.txt 2020-02-08 17:39:18.000000000 +0100 @@ -1,5 +1,5 @@ -pytest==4.6.2 -pytest-cov==2.7.1 -coverage==4.5.3 -pytest-xdist==1.29.0 +pytest==4.6.5 # rq.filter: < 5 +pytest-cov==2.8.1 +pytest-xdist==1.31.0 +coverage==4.5.4 hypothesis diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/h2-3.1.1/tox.ini new/h2-3.2.0/tox.ini --- old/h2-3.1.1/tox.ini 2019-08-02 15:10:17.000000000 +0200 +++ new/h2-3.2.0/tox.ini 2020-02-08 17:39:18.000000000 +0100 @@ -1,15 +1,15 @@ [tox] -envlist = py27, py34, py35, py36, py37, pypy, lint, packaging, docs +envlist = py27, py34, py35, py36, py37, py38, pypy, lint, packaging, docs [testenv] deps= -r{toxinidir}/test_requirements.txt commands= - coverage run -m py.test {posargs} {toxinidir}/test/ + coverage run -m py.test {posargs} coverage report [testenv:pypy] # temporarily disable coverage testing on PyPy due to performance problems -commands= py.test {posargs} {toxinidir}/test/ +commands= py.test {posargs} [testenv:lint] basepython=python3.7 @@ -18,7 +18,7 @@ [testenv:docs] basepython=python3.7 -deps = sphinx==1.4.9 +deps = sphinx==2.2.0 changedir = {toxinidir}/docs whitelist_externals = rm commands = @@ -27,7 +27,7 @@ [testenv:graphs] basepython=python2.7 -deps = graphviz==0.11.1 +deps = graphviz==0.13 commands = python visualizer/visualize.py -i docs/source/_static @@ -42,7 +42,7 @@ [testenv:h2spec] basepython=python3.6 -deps = twisted[tls]==17.1.0 +deps = twisted[tls]==19.7.0 whitelist_externals = {toxinidir}/test/h2spectest.sh commands = {toxinidir}/test/h2spectest.sh