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


Reply via email to