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
+
+- 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: cory@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: cory@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='cory@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