Hello community,

here is the log from the commit of package python-h2 for openSUSE:Factory 
checked in at 2019-03-29 20:38:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-h2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-h2.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-h2"

Fri Mar 29 20:38:42 2019 rev:3 rq:689263 version:3.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-h2/python-h2.changes      2018-12-27 
00:26:27.347807172 +0100
+++ /work/SRC/openSUSE:Factory/.python-h2.new.25356/python-h2.changes   
2019-03-29 20:38:43.850680088 +0100
@@ -1,0 +2,25 @@
+Thu Mar 28 04:06:48 UTC 2019 - John Vandenberg <jay...@gmail.com>
+
+- Set URL to more useful https://github.com/python-hyper/hyper-h2
+- Update to v3.1.0
+  * API Changes (Backward-Incompatible)
+    +  h2.connection.H2Connection.data_to_send first and only
+       argument ``amt`` was renamed to ``amount``
+    + Support for Python 3.3 has been removed.
+  * API Changes (Backward-Compatible)
+    + h2.connection.H2Connection.send_data now supports ``data``
+      parameter being a ``memoryview`` object.
+    + Refactor ping-related events: a h2.events.PingReceived event is
+      fired when a PING frame is received and a h2.events.PingAckReceived
+      event is fired when a PING frame with an ACK flag is received
+    + h2.events.PingAcknowledged is deprecated in favour of the
+      identical h2.events.PingAckReceived
+    + Added ENABLE_CONNECT_PROTOCOL to h2.settings.SettingCodes
+    + Support CONNECT requests with a ``:protocol`` pseudo header
+      thereby supporting RFC 8441.
+    + A limit to the number of closed streams kept in memory by the
+      connection is applied. It can be configured by
+      h2.connection.H2Connection.MAX_CLOSED_STREAMS
+ * Debug logging when stream_id is None is now fixed and no longer errors.
+
+-------------------------------------------------------------------

Old:
----
  h2-3.0.1.tar.gz

New:
----
  h2-3.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-h2.spec ++++++
--- /var/tmp/diff_new_pack.0WqcQq/_old  2019-03-29 20:38:44.462680400 +0100
+++ /var/tmp/diff_new_pack.0WqcQq/_new  2019-03-29 20:38:44.470680404 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-h2
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,25 +18,25 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-h2
-Version:        3.0.1
+Version:        3.1.0
 Release:        0
 Summary:        HTTP/2 State-Machine based protocol implementation
 License:        MIT
 Group:          Development/Languages/Python
-URL:            http://hyper.rtfd.org
+URL:            https://github.com/python-hyper/hyper-h2
 Source0:        
https://files.pythonhosted.org/packages/source/h/h2/h2-%{version}.tar.gz
 # test requirements
 BuildRequires:  %{python_module coverage}
-BuildRequires:  %{python_module hpack}
-BuildRequires:  %{python_module hyperframe >= 5.0}
+BuildRequires:  %{python_module hpack >= 2.3}
+BuildRequires:  %{python_module hyperframe >= 5.2.0}
 BuildRequires:  %{python_module hypothesis}
 BuildRequires:  %{python_module pytest-cov}
 BuildRequires:  %{python_module pytest-xdist}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-hpack >= 2.2
-Requires:       python-hyperframe >= 5.0
+Requires:       python-hpack >= 2.3
+Requires:       python-hyperframe >= 5.2.0
 BuildArch:      noarch
 %python_subpackages
 

++++++ h2-3.0.1.tar.gz -> h2-3.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/CONTRIBUTORS.rst 
new/h2-3.1.0/CONTRIBUTORS.rst
--- old/h2-3.0.1/CONTRIBUTORS.rst       2017-04-03 09:47:32.000000000 +0200
+++ new/h2-3.1.0/CONTRIBUTORS.rst       2019-01-22 18:41:43.000000000 +0100
@@ -111,4 +111,5 @@
 - Fred Thomsen (@fredthomsen)
 
   - Added logging.
-
+  - Enhance equality testing of ``h2.settings.Settings`` objects with
+    ``hypothesis``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/HISTORY.rst new/h2-3.1.0/HISTORY.rst
--- old/h2-3.0.1/HISTORY.rst    2017-04-03 09:58:48.000000000 +0200
+++ new/h2-3.1.0/HISTORY.rst    2019-01-22 18:41:49.000000000 +0100
@@ -1,6 +1,38 @@
 Release History
 ===============
 
+3.1.0 (2019-01-22)
+------------------
+
+API Changes (Backward-Incompatible)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- ``h2.connection.H2Connection.data_to_send`` first and only argument ``amt``
+  was renamed to ``amount``.
+- Support for Python 3.3 has been removed.
+
+API Changes (Backward-Compatible)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- ``h2.connection.H2Connection.send_data`` now supports ``data`` parameter
+  being a ``memoryview`` object.
+- Refactor ping-related events: a ``h2.events.PingReceived`` event is fired
+  when a PING frame is received and a ``h2.events.PingAckReceived`` event is
+  fired when a PING frame with an ACK flag is received.
+  ``h2.events.PingAcknowledged`` is deprecated in favour of the identical
+  ``h2.events.PingAckReceived``.
+- Added ``ENABLE_CONNECT_PROTOCOL`` to ``h2.settings.SettingCodes``.
+- Support ``CONNECT`` requests with a ``:protocol`` pseudo header
+  thereby supporting RFC 8441.
+- A limit to the number of closed streams kept in memory by the
+  connection is applied. It can be configured by
+  ``h2.connection.H2Connection.MAX_CLOSED_STREAMS``.
+
+Bugfixes
+~~~~~~~~
+
+- Debug logging when stream_id is None is now fixed and no longer errors.
+
 3.0.1 (2017-04-03)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/PKG-INFO new/h2-3.1.0/PKG-INFO
--- old/h2-3.0.1/PKG-INFO       2017-04-03 10:07:26.000000000 +0200
+++ new/h2-3.1.0/PKG-INFO       2019-01-22 18:42:26.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: h2
-Version: 3.0.1
+Version: 3.1.0
 Summary: HTTP/2 State-Machine based protocol implementation
 Home-page: http://hyper.rtfd.org
 Author: Cory Benfield
@@ -76,6 +76,38 @@
         Release History
         ===============
         
+        3.1.0 (2019-01-22)
+        ------------------
+        
+        API Changes (Backward-Incompatible)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        - ``h2.connection.H2Connection.data_to_send`` first and only argument 
``amt``
+          was renamed to ``amount``.
+        - Support for Python 3.3 has been removed.
+        
+        API Changes (Backward-Compatible)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        - ``h2.connection.H2Connection.send_data`` now supports ``data`` 
parameter
+          being a ``memoryview`` object.
+        - Refactor ping-related events: a ``h2.events.PingReceived`` event is 
fired
+          when a PING frame is received and a ``h2.events.PingAckReceived`` 
event is
+          fired when a PING frame with an ACK flag is received.
+          ``h2.events.PingAcknowledged`` is deprecated in favour of the 
identical
+          ``h2.events.PingAckReceived``.
+        - Added ``ENABLE_CONNECT_PROTOCOL`` to ``h2.settings.SettingCodes``.
+        - Support ``CONNECT`` requests with a ``:protocol`` pseudo header
+          thereby supporting RFC 8441.
+        - A limit to the number of closed streams kept in memory by the
+          connection is applied. It can be configured by
+          ``h2.connection.H2Connection.MAX_CLOSED_STREAMS``.
+        
+        Bugfixes
+        ~~~~~~~~
+        
+        - Debug logging when stream_id is None is now fixed and no longer 
errors.
+        
         3.0.1 (2017-04-03)
         ------------------
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/docs/source/api.rst 
new/h2-3.1.0/docs/source/api.rst
--- old/h2-3.0.1/docs/source/api.rst    2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/docs/source/api.rst    2019-01-22 18:41:43.000000000 +0100
@@ -53,7 +53,10 @@
 .. autoclass:: h2.events.RemoteSettingsChanged
    :members:
 
-.. autoclass:: h2.events.PingAcknowledged
+.. autoclass:: h2.events.PingReceived
+   :members:
+
+.. autoclass:: h2.events.PingAckReceived
    :members:
 
 .. autoclass:: h2.events.StreamEnded
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/docs/source/basic-usage.rst 
new/h2-3.1.0/docs/source/basic-usage.rst
--- old/h2-3.0.1/docs/source/basic-usage.rst    2017-03-16 10:02:02.000000000 
+0100
+++ new/h2-3.1.0/docs/source/basic-usage.rst    2019-01-22 18:41:43.000000000 
+0100
@@ -251,9 +251,11 @@
 .. code-block:: python
 
     import h2.connection
+    import h2.config
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
 
         while True:
             data = sock.recv(65535)
@@ -267,9 +269,11 @@
     import socket
 
     import h2.connection
+    import h2.config
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
 
         while True:
             data = sock.recv(65535)
@@ -331,7 +335,8 @@
 .. code-block:: python
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
         conn.initiate_connection()
         sock.sendall(conn.data_to_send())
 
@@ -359,9 +364,11 @@
     import socket
 
     import h2.connection
+    import h2.config
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
         conn.initiate_connection()
         sock.sendall(conn.data_to_send())
 
@@ -493,9 +500,11 @@
 .. code-block:: python
 
     import h2.events
+    import h2.config
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
         conn.initiate_connection()
         sock.sendall(conn.data_to_send())
 
@@ -528,6 +537,7 @@
 
     import h2.connection
     import h2.events
+    import h2.config
 
     def send_response(conn, event):
         stream_id = event.stream_id
@@ -545,7 +555,8 @@
         )
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
         conn.initiate_connection()
         sock.sendall(conn.data_to_send())
 
@@ -633,6 +644,7 @@
 
     import h2.connection
     import h2.events
+    import h2.config
 
     def send_response(conn, event):
         stream_id = event.stream_id
@@ -654,7 +666,8 @@
         )
 
     def handle(sock):
-        conn = h2.connection.H2Connection(client_side=False)
+        config = h2.config.H2Configuration(client_side=False)
+        conn = h2.connection.H2Connection(config=config)
         conn.initiate_connection()
         sock.sendall(conn.data_to_send())
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/docs/source/conf.py 
new/h2-3.1.0/docs/source/conf.py
--- old/h2-3.0.1/docs/source/conf.py    2017-04-03 09:58:57.000000000 +0200
+++ new/h2-3.1.0/docs/source/conf.py    2019-01-22 18:41:49.000000000 +0100
@@ -55,9 +55,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '3.0.1'
+version = '3.1.0'
 # The full version, including alpha/beta/rc tags.
-release = '3.0.1'
+release = '3.1.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.0.1/docs/source/negotiating-http2.rst 
new/h2-3.1.0/docs/source/negotiating-http2.rst
--- old/h2-3.0.1/docs/source/negotiating-http2.rst      2017-04-03 
09:47:32.000000000 +0200
+++ new/h2-3.1.0/docs/source/negotiating-http2.rst      2019-01-22 
18:41:43.000000000 +0100
@@ -5,15 +5,19 @@
 
 .. _starting-alpn:
 
-HTTPS URLs (ALPN and NPN)
+HTTPS URLs (ALPN)
 -------------------------
 
-Starting HTTP/2 for HTTPS URLs is outlined in `RFC 7540 Section 3.3`_. In this 
case, the client and server use a TLS extension to negotiate HTTP/2: typically 
either or both of `NPN`_ or `ALPN`_. How to use NPN and ALPN is currently not 
covered in this document: please consult the documentation for either the 
:mod:`ssl module <python:ssl>` in the standard library, or the :mod:`PyOpenSSL 
<pyopenssl:OpenSSL.SSL>` third-party modules, for more on this topic.
+Starting HTTP/2 for HTTPS URLs is outlined in `RFC 7540 Section 3.3`_. In this 
case, the client and server use a TLS extension to negotiate HTTP/2: `ALPN`_. 
How to use ALPN is currently not covered in this document: please consult the 
documentation for either the :mod:`ssl module <python:ssl>` in the standard 
library, or the :mod:`PyOpenSSL <pyopenssl:OpenSSL.SSL>` third-party modules, 
for more on this topic.
 
 This method is the simplest to use once the TLS connection is established. To 
use it with Hyper-h2, after you've established the connection and confirmed 
that HTTP/2 has been negotiated with `ALPN`_, create a :class:`H2Connection 
<h2.connection.H2Connection>` object and call 
:meth:`H2Connection.initiate_connection 
<h2.connection.H2Connection.initiate_connection>`. This will ensure that the 
appropriate preamble data is placed in the data buffer. You should then 
immediately send the data returned by :meth:`H2Connection.data_to_send 
<h2.connection.H2Connection.data_to_send>` on your TLS connection.
 
 At this point, you're free to use all the HTTP/2 functionality provided by 
Hyper-h2.
 
+.. note::
+   Although Hyper-h2 is not concerned with negotiating protocol versions, it 
is important to note that support for `ALPN`_ is not available in the standard 
library of Python versions < 2.7.9.
+   As a consequence, clients may encounter various errors due to protocol 
versions mismatch.
+
 Server Setup Example
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -90,11 +94,10 @@
 Prior Knowledge
 ---------------
 
-It's possible that you as a client know that a particular server supports 
HTTP/2, and that you do not need to perform any of the negotiations described 
above. In that case, you may follow the steps in :ref:`starting-alpn`, ignoring 
all references to ALPN and NPN: there's no need to perform the upgrade dance 
described in :ref:`starting-upgrade`.
+It's possible that you as a client know that a particular server supports 
HTTP/2, and that you do not need to perform any of the negotiations described 
above. In that case, you may follow the steps in :ref:`starting-alpn`, ignoring 
all references to ALPN: there's no need to perform the upgrade dance described 
in :ref:`starting-upgrade`.
 
 .. _RFC 7540: https://tools.ietf.org/html/rfc7540
 .. _RFC 7540 Section 3.2: https://tools.ietf.org/html/rfc7540#section-3.2
 .. _RFC 7540 Section 3.3: https://tools.ietf.org/html/rfc7540#section-3.3
-.. _NPN: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
 .. _ALPN: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
 .. _RFC 7230 Section 6.7: https://tools.ietf.org/html/rfc7230#section-6.7
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/examples/curio/curio-server.py 
new/h2-3.1.0/examples/curio/curio-server.py
--- old/h2-3.0.1/examples/curio/curio-server.py 2017-04-03 09:57:46.000000000 
+0200
+++ new/h2-3.1.0/examples/curio/curio-server.py 2019-01-22 18:41:43.000000000 
+0100
@@ -12,7 +12,7 @@
 import os
 import sys
 
-from curio import Kernel, Event, spawn, socket, ssl
+from curio import Event, spawn, socket, ssl, run
 
 import h2.config
 import h2.connection
@@ -23,7 +23,7 @@
 READ_CHUNK_SIZE = 8192
 
 
-def create_listening_ssl_socket(address, certfile, keyfile):
+async def create_listening_ssl_socket(address, certfile, keyfile):
     """
     Create and return a listening TLS socket on a given address.
     """
@@ -37,7 +37,7 @@
 
     sock = socket.socket()
     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-    sock = ssl_context.wrap_socket(sock)
+    sock = await ssl_context.wrap_socket(sock)
     sock.bind(address)
     sock.listen()
 
@@ -48,7 +48,7 @@
     """
     Create an HTTP/2 server at the given address.
     """
-    sock = create_listening_ssl_socket(address, certfile, keyfile)
+    sock = await create_listening_ssl_socket(address, certfile, keyfile)
     print("Now listening on %s:%d" % address)
 
     async with sock:
@@ -196,13 +196,11 @@
 
 if __name__ == '__main__':
     host = sys.argv[2] if len(sys.argv) > 2 else "localhost"
-    kernel = Kernel(with_monitor=True)
     print("Try GETting:")
     print("    On OSX after 'brew install curl --with-c-ares --with-libidn 
--with-nghttp2 --with-openssl':")
     print("/usr/local/opt/curl/bin/curl --tlsv1.2 --http2 -k 
https://localhost:5000/bundle.js";)
     print("Or open a browser to: https://localhost:5000/";)
     print("   (Accept all the warnings)")
-    kernel.run(h2_server((host, 5000),
-                         sys.argv[1],
-                         "{}.crt.pem".format(host),
-                         "{}.key".format(host)))
+    run(h2_server((host, 5000), sys.argv[1],
+                  "{}.crt.pem".format(host),
+                  "{}.key".format(host)), with_monitor=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/examples/eventlet/eventlet-server.py 
new/h2-3.1.0/examples/eventlet/eventlet-server.py
--- old/h2-3.0.1/examples/eventlet/eventlet-server.py   2017-04-03 
09:57:46.000000000 +0200
+++ new/h2-3.1.0/examples/eventlet/eventlet-server.py   2019-01-22 
18:41:43.000000000 +0100
@@ -51,7 +51,7 @@
         response_headers = (
             (':status', '200'),
             ('content-type', 'application/json'),
-            ('content-length', len(data)),
+            ('content-length', str(len(data))),
             ('server', 'eventlet-h2'),
         )
         self.conn.send_headers(stream_id, response_headers)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/h2-3.0.1/examples/fragments/client_upgrade_fragment.py 
new/h2-3.1.0/examples/fragments/client_upgrade_fragment.py
--- old/h2-3.0.1/examples/fragments/client_upgrade_fragment.py  2017-03-16 
10:02:02.000000000 +0100
+++ new/h2-3.1.0/examples/fragments/client_upgrade_fragment.py  2019-01-22 
18:41:43.000000000 +0100
@@ -38,7 +38,7 @@
         b"GET / HTTP/1.1\r\n" +
         b"Host: localhost\r\n" +
         b"Upgrade: h2c\r\n" +
-        b"HTTP2-Settings: " + settings + "\r\n"
+        b"HTTP2-Settings: " + settings + b"\r\n" +
         b"\r\n"
     )
     connection.sendall(request)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/h2-3.0.1/examples/fragments/server_upgrade_fragment.py 
new/h2-3.1.0/examples/fragments/server_upgrade_fragment.py
--- old/h2-3.0.1/examples/fragments/server_upgrade_fragment.py  2017-04-03 
09:57:46.000000000 +0200
+++ new/h2-3.1.0/examples/fragments/server_upgrade_fragment.py  2019-01-22 
18:41:43.000000000 +0100
@@ -45,14 +45,14 @@
         data += connection.recv(8192)
 
     match = re.search(b'Upgrade: h2c\r\n', data)
-    if match is not None:
+    if match is None:
         raise RuntimeError("HTTP/2 upgrade not requested!")
 
     # We need to look for the HTTP2-Settings header field. Again, in production
     # code you shouldn't use regular expressions for this, but it's good enough
     # for the example.
     match = re.search(b'HTTP2-Settings: (\\S+)\r\n', data)
-    if match is not None:
+    if match is None:
         raise RuntimeError("HTTP2-Settings header field not present!")
 
     return match.group(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/__init__.py new/h2-3.1.0/h2/__init__.py
--- old/h2-3.0.1/h2/__init__.py 2017-04-03 09:58:51.000000000 +0200
+++ new/h2-3.1.0/h2/__init__.py 2019-01-22 18:41:49.000000000 +0100
@@ -5,4 +5,4 @@
 
 A HTTP/2 implementation.
 """
-__version__ = '3.0.1'
+__version__ = '3.1.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/connection.py 
new/h2-3.1.0/h2/connection.py
--- old/h2-3.0.1/h2/connection.py       2017-04-03 09:57:49.000000000 +0200
+++ new/h2-3.1.0/h2/connection.py       2019-01-22 18:41:43.000000000 +0100
@@ -21,7 +21,7 @@
 from .config import H2Configuration
 from .errors import ErrorCodes, _error_code_from_int
 from .events import (
-    WindowUpdated, RemoteSettingsChanged, PingAcknowledged,
+    WindowUpdated, RemoteSettingsChanged, PingReceived, PingAckReceived,
     SettingsAcknowledged, ConnectionTerminated, PriorityUpdated,
     AlternativeServiceAvailable, UnknownFrameReceived
 )
@@ -33,7 +33,7 @@
 from .frame_buffer import FrameBuffer
 from .settings import Settings, SettingCodes
 from .stream import H2Stream, StreamClosedBy
-from .utilities import guard_increment_window
+from .utilities import SizeLimitDict, guard_increment_window
 from .windows import WindowManager
 
 
@@ -281,6 +281,9 @@
     # The initial default value of SETTINGS_MAX_HEADER_LIST_SIZE.
     DEFAULT_MAX_HEADER_LIST_SIZE = 2**16
 
+    # Keep in memory limited amount of results for streams closes
+    MAX_CLOSED_STREAMS = 2**16
+
     def __init__(self, config=None):
         self.state_machine = H2ConnectionStateMachine()
         self.streams = {}
@@ -325,7 +328,7 @@
         )
         self.remote_settings = Settings(client=not self.config.client_side)
 
-        # The curent value of the connection flow control windows on the
+        # The current value of the connection flow control windows on the
         # connection.
         self.outbound_flow_control_window = (
             self.remote_settings.initial_window_size
@@ -355,7 +358,9 @@
         # Also used to determine whether we should consider a frame received
         # while a stream is closed as either a stream error or a connection
         # error.
-        self._closed_streams = {}
+        self._closed_streams = SizeLimitDict(
+            size_limit=self.MAX_CLOSED_STREAMS
+        )
 
         # The flow control window manager for the connection.
         self._inbound_flow_control_window_manager = WindowManager(
@@ -909,16 +914,21 @@
             frames = stream.increase_flow_control_window(
                 increment
             )
+
+            self.config.logger.debug(
+                "Increase stream ID %d flow control window by %d",
+                stream_id, increment
+            )
         else:
             self._inbound_flow_control_window_manager.window_opened(increment)
             f = WindowUpdateFrame(0)
             f.window_increment = increment
             frames = [f]
 
-        self.config.logger.debug(
-            "Increase stream ID %d flow control window by %d",
-            stream_id, increment
-        )
+            self.config.logger.debug(
+                "Increase connection flow control window by %d", increment
+            )
+
         self._prepare_for_sending(frames)
 
     def push_stream(self, stream_id, promised_stream_id, request_headers):
@@ -1327,7 +1337,7 @@
 
         self._prepare_for_sending(frames)
 
-    def data_to_send(self, amt=None):
+    def data_to_send(self, amount=None):
         """
         Returns some data for sending out of the internal data buffer.
 
@@ -1336,19 +1346,19 @@
         or less if that much data is not available. It does not perform any
         I/O, and so uses a different name.
 
-        :param amt: (optional) The maximum amount of data to return. If not
+        :param amount: (optional) The maximum amount of data to return. If not
             set, or set to ``None``, will return as much data as possible.
-        :type amt: ``int``
+        :type amount: ``int``
         :returns: A bytestring containing the data to send on the wire.
         :rtype: ``bytes``
         """
-        if amt is None:
+        if amount is None:
             data = self._data_to_send
             self._data_to_send = b''
             return data
         else:
-            data = self._data_to_send[:amt]
-            self._data_to_send = self._data_to_send[amt:]
+            data = self._data_to_send[:amount]
+            self._data_to_send = self._data_to_send[amount:]
             return data
 
     def clear_outbound_data_buffer(self):
@@ -1717,15 +1727,19 @@
         flags = []
 
         if 'ACK' in frame.flags:
-            evt = PingAcknowledged()
-            evt.ping_data = frame.opaque_data
-            events.append(evt)
+            evt = PingAckReceived()
         else:
+            evt = PingReceived()
+
+            # automatically ACK the PING with the same 'opaque data'
             f = PingFrame(0)
             f.flags = {'ACK'}
             f.opaque_data = frame.opaque_data
             flags.append(f)
 
+        evt.ping_data = frame.opaque_data
+        events.append(evt)
+
         return flags, events
 
     def _receive_rst_stream_frame(self, frame):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/events.py new/h2-3.1.0/h2/events.py
--- old/h2-3.0.1/h2/events.py   2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/h2/events.py   2019-01-22 18:41:43.000000000 +0100
@@ -356,22 +356,51 @@
         )
 
 
+class PingReceived(Event):
+    """
+    The PingReceived event is fired whenever a PING is received. It contains
+    the 'opaque data' of the PING frame. A ping acknowledgment with the same
+    'opaque data' is automatically emitted after receiving a ping.
+
+    .. versionadded:: 3.1.0
+    """
+    def __init__(self):
+        #: The data included on the ping.
+        self.ping_data = None
+
+    def __repr__(self):
+        return "<PingReceived ping_data:%s>" % (
+            _bytes_representation(self.ping_data),
+        )
+
+
 class PingAcknowledged(Event):
     """
-    The PingAcknowledged event is fired whenever a user-emitted PING is
-    acknowledged. This contains the data in the ACK'ed PING, allowing the
-    user to correlate PINGs and calculate RTT.
+    Same as PingAckReceived.
+
+    .. deprecated:: 3.1.0
     """
     def __init__(self):
         #: The data included on the ping.
         self.ping_data = None
 
     def __repr__(self):
-        return "<PingAcknowledged ping_data:%s>" % (
+        return "<PingAckReceived ping_data:%s>" % (
             _bytes_representation(self.ping_data),
         )
 
 
+class PingAckReceived(PingAcknowledged):
+    """
+    The PingAckReceived event is fired whenever a PING acknowledgment is
+    received. It contains the 'opaque data' of the PING+ACK frame, allowing the
+    user to correlate PINGs and calculate RTT.
+
+    .. versionadded:: 3.1.0
+    """
+    pass
+
+
 class StreamEnded(Event):
     """
     The StreamEnded event is fired whenever a stream is ended by a remote
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/settings.py new/h2-3.1.0/h2/settings.py
--- old/h2-3.0.1/h2/settings.py 2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/h2/settings.py 2019-01-22 18:41:43.000000000 +0100
@@ -15,6 +15,12 @@
 from h2.errors import ErrorCodes
 from h2.exceptions import InvalidSettingsValueError
 
+try:
+    from collections.abc import MutableMapping
+except ImportError:  # pragma: no cover
+    # Python 2.7 compatibility
+    from collections import MutableMapping
+
 
 class SettingCodes(enum.IntEnum):
     """
@@ -49,6 +55,10 @@
     #: and value in octets plus an overhead of 32 octets for each header field.
     MAX_HEADER_LIST_SIZE = SettingsFrame.MAX_HEADER_LIST_SIZE
 
+    #: This setting can be used to enable the connect protocol. To enable on a
+    #: client set this to 1.
+    ENABLE_CONNECT_PROTOCOL = SettingsFrame.ENABLE_CONNECT_PROTOCOL
+
 
 def _setting_code_from_int(code):
     """
@@ -88,7 +98,7 @@
         )
 
 
-class Settings(collections.MutableMapping):
+class Settings(MutableMapping):
     """
     An object that encapsulates HTTP/2 settings state.
 
@@ -135,6 +145,7 @@
             SettingCodes.ENABLE_PUSH: collections.deque([int(client)]),
             SettingCodes.INITIAL_WINDOW_SIZE: collections.deque([65535]),
             SettingCodes.MAX_FRAME_SIZE: collections.deque([16384]),
+            SettingCodes.ENABLE_CONNECT_PROTOCOL: collections.deque([0]),
         }
         if initial_values is not None:
             for key, value in initial_values.items():
@@ -243,6 +254,18 @@
     def max_header_list_size(self, value):
         self[SettingCodes.MAX_HEADER_LIST_SIZE] = value
 
+    @property
+    def enable_connect_protocol(self):
+        """
+        The current value of the :data:`ENABLE_CONNECT_PROTOCOL
+        <h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL>` setting.
+        """
+        return self[SettingCodes.ENABLE_CONNECT_PROTOCOL]
+
+    @enable_connect_protocol.setter
+    def enable_connect_protocol(self, value):
+        self[SettingCodes.ENABLE_CONNECT_PROTOCOL] = value
+
     # Implement the MutableMapping API.
     def __getitem__(self, key):
         val = self._settings[key][0]
@@ -292,7 +315,7 @@
             return NotImplemented
 
 
-def _validate_setting(setting, value):
+def _validate_setting(setting, value):  # noqa: C901
     """
     Confirms that a specific setting has a well-formed value. If the setting is
     invalid, returns an error code. Otherwise, returns 0 (NO_ERROR).
@@ -309,5 +332,8 @@
     elif setting == SettingCodes.MAX_HEADER_LIST_SIZE:
         if value < 0:
             return ErrorCodes.PROTOCOL_ERROR
+    elif setting == SettingCodes.ENABLE_CONNECT_PROTOCOL:
+        if value not in (0, 1):
+            return ErrorCodes.PROTOCOL_ERROR
 
     return 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/stream.py new/h2-3.1.0/h2/stream.py
--- old/h2-3.0.1/h2/stream.py   2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/h2/stream.py   2019-01-22 18:41:43.000000000 +0100
@@ -788,7 +788,7 @@
         self.max_outbound_frame_size = None
         self.request_method = None
 
-        # The curent value of the outbound stream flow control window
+        # The current value of the outbound stream flow control window
         self.outbound_flow_control_window = outbound_window_size
 
         # The flow control manager.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2/utilities.py new/h2-3.1.0/h2/utilities.py
--- old/h2-3.0.1/h2/utilities.py        2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/h2/utilities.py        2019-01-22 18:41:43.000000000 +0100
@@ -33,6 +33,7 @@
     b':authority', u':authority',
     b':path', u':path',
     b':status', u':status',
+    b':protocol', u':protocol',
 ])
 
 
@@ -47,13 +48,19 @@
     b':scheme', u':scheme',
     b':path', u':path',
     b':authority', u':authority',
-    b':method', u':method'
+    b':method', u':method',
+    b':protocol', u':protocol',
 ])
 
 
 _RESPONSE_ONLY_HEADERS = frozenset([b':status', u':status'])
 
 
+# A Set of pseudo headers that are only valid if the method is
+# CONNECT, see RFC 8441 ยง 5
+_CONNECT_REQUEST_ONLY_HEADERS = frozenset([b':protocol', u':protocol'])
+
+
 if sys.version_info[0] == 2:  # Python 2.X
     _WHITESPACE = frozenset(whitespace)
 else:  # Python 3.3+
@@ -323,6 +330,7 @@
     """
     seen_pseudo_header_fields = set()
     seen_regular_header = False
+    method = None
 
     for header in headers:
         if _custom_startswith(header[0], b':', u':'):
@@ -344,6 +352,12 @@
                     "Received custom pseudo-header field %s" % header[0]
                 )
 
+            if header[0] in (b':method', u':method'):
+                if not isinstance(header[1], bytes):
+                    method = header[1].encode('utf-8')
+                else:
+                    method = header[1]
+
         else:
             seen_regular_header = True
 
@@ -351,11 +365,12 @@
 
     # Check the pseudo-headers we got to confirm they're acceptable.
     _check_pseudo_header_field_acceptability(
-        seen_pseudo_header_fields, hdr_validation_flags
+        seen_pseudo_header_fields, method, hdr_validation_flags
     )
 
 
 def _check_pseudo_header_field_acceptability(pseudo_headers,
+                                             method,
                                              hdr_validation_flags):
     """
     Given the set of pseudo-headers present in a header block and the
@@ -394,6 +409,13 @@
                 "Encountered response-only headers %s" %
                 invalid_request_headers
             )
+        if method != b'CONNECT':
+            invalid_headers = pseudo_headers & _CONNECT_REQUEST_ONLY_HEADERS
+            if invalid_headers:
+                raise ProtocolError(
+                    "Encountered connect-request-only headers %s" %
+                    invalid_headers
+                )
 
 
 def _validate_host_authority_header(headers):
@@ -617,3 +639,22 @@
     headers = _check_path_header(headers, hdr_validation_flags)
 
     return headers
+
+
+class SizeLimitDict(collections.OrderedDict):
+
+    def __init__(self, *args, **kwargs):
+        self._size_limit = kwargs.pop("size_limit", None)
+        super(SizeLimitDict, self).__init__(*args, **kwargs)
+
+        self._check_size_limit()
+
+    def __setitem__(self, key, value):
+        super(SizeLimitDict, self).__setitem__(key, value)
+
+        self._check_size_limit()
+
+    def _check_size_limit(self):
+        if self._size_limit is not None:
+            while len(self) > self._size_limit:
+                self.popitem(last=False)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2.egg-info/PKG-INFO 
new/h2-3.1.0/h2.egg-info/PKG-INFO
--- old/h2-3.0.1/h2.egg-info/PKG-INFO   2017-04-03 10:07:26.000000000 +0200
+++ new/h2-3.1.0/h2.egg-info/PKG-INFO   2019-01-22 18:42:26.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: h2
-Version: 3.0.1
+Version: 3.1.0
 Summary: HTTP/2 State-Machine based protocol implementation
 Home-page: http://hyper.rtfd.org
 Author: Cory Benfield
@@ -76,6 +76,38 @@
         Release History
         ===============
         
+        3.1.0 (2019-01-22)
+        ------------------
+        
+        API Changes (Backward-Incompatible)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        - ``h2.connection.H2Connection.data_to_send`` first and only argument 
``amt``
+          was renamed to ``amount``.
+        - Support for Python 3.3 has been removed.
+        
+        API Changes (Backward-Compatible)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        - ``h2.connection.H2Connection.send_data`` now supports ``data`` 
parameter
+          being a ``memoryview`` object.
+        - Refactor ping-related events: a ``h2.events.PingReceived`` event is 
fired
+          when a PING frame is received and a ``h2.events.PingAckReceived`` 
event is
+          fired when a PING frame with an ACK flag is received.
+          ``h2.events.PingAcknowledged`` is deprecated in favour of the 
identical
+          ``h2.events.PingAckReceived``.
+        - Added ``ENABLE_CONNECT_PROTOCOL`` to ``h2.settings.SettingCodes``.
+        - Support ``CONNECT`` requests with a ``:protocol`` pseudo header
+          thereby supporting RFC 8441.
+        - A limit to the number of closed streams kept in memory by the
+          connection is applied. It can be configured by
+          ``h2.connection.H2Connection.MAX_CLOSED_STREAMS``.
+        
+        Bugfixes
+        ~~~~~~~~
+        
+        - Debug logging when stream_id is None is now fixed and no longer 
errors.
+        
         3.0.1 (2017-04-03)
         ------------------
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2.egg-info/SOURCES.txt 
new/h2-3.1.0/h2.egg-info/SOURCES.txt
--- old/h2-3.0.1/h2.egg-info/SOURCES.txt        2017-04-03 10:07:26.000000000 
+0200
+++ new/h2-3.1.0/h2.egg-info/SOURCES.txt        2019-01-22 18:42:26.000000000 
+0100
@@ -95,6 +95,7 @@
 test/test_priority.py
 test/test_related_events.py
 test/test_rfc7838.py
+test/test_rfc8441.py
 test/test_settings.py
 test/test_state_machines.py
 test/test_stream_reset.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/h2.egg-info/requires.txt 
new/h2-3.1.0/h2.egg-info/requires.txt
--- old/h2-3.0.1/h2.egg-info/requires.txt       2017-04-03 10:07:26.000000000 
+0200
+++ new/h2-3.1.0/h2.egg-info/requires.txt       2019-01-22 18:42:26.000000000 
+0100
@@ -1,5 +1,5 @@
-hyperframe>=5.0, <6
-hpack>=2.3, <4
+hyperframe<6,>=5.2.0
+hpack<4,>=2.3
 
 [:python_version == "2.7" or python_version == "3.3"]
-enum34>=1.1.6, <2
+enum34<2,>=1.1.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/setup.py new/h2-3.1.0/setup.py
--- old/h2-3.0.1/setup.py       2017-04-03 09:57:49.000000000 +0200
+++ new/h2-3.1.0/setup.py       2019-01-22 18:41:43.000000000 +0100
@@ -62,8 +62,8 @@
         'Programming Language :: Python :: Implementation :: PyPy',
     ],
     install_requires=[
-        'hyperframe>=5.0, <6',
-        'hpack>=2.3, <4',
+        'hyperframe>=5.2.0, <6',
+        'hpack>=2.3,<4',
     ],
     extras_require={
         ':python_version == "2.7" or python_version == "3.3"': 
['enum34>=1.1.6, <2'],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_basic_logic.py 
new/h2-3.1.0/test/test_basic_logic.py
--- old/h2-3.0.1/test/test_basic_logic.py       2017-04-03 09:57:46.000000000 
+0200
+++ new/h2-3.1.0/test/test_basic_logic.py       2019-01-22 18:41:43.000000000 
+0100
@@ -114,6 +114,23 @@
             expected_data_frame_pad_length=0
         )
 
+    def test_sending_data_in_memoryview(self):
+        """
+        Support memoryview for sending data.
+        """
+        c = h2.connection.H2Connection()
+        c.initiate_connection()
+        c.send_headers(1, self.example_request_headers)
+
+        # Clear the data, then send some data.
+        c.clear_outbound_data_buffer()
+        events = c.send_data(1, memoryview(b'some data'))
+        assert not events
+        data_to_send = c.data_to_send()
+        assert (
+            data_to_send == b'\x00\x00\t\x00\x00\x00\x00\x00\x01some data'
+        )
+
     def test_sending_data_with_padding(self):
         """
         Single data frames with padding are encoded correctly.
@@ -1081,7 +1098,12 @@
         c.clear_outbound_data_buffer()
         events = c.receive_data(sent_frame.serialize())
 
-        assert not events
+        assert len(events) == 1
+        event = events[0]
+
+        assert isinstance(event, h2.events.PingReceived)
+        assert event.ping_data == ping_data
+
         assert c.data_to_send() == expected_data
 
     def test_receiving_settings_frame_event(self, frame_factory):
@@ -1324,7 +1346,7 @@
 
     def test_receiving_ping_acknowledgement(self, frame_factory):
         """
-        Receiving a PING acknolwedgement fires a PingAcknolwedged event.
+        Receiving a PING acknowledgement fires a PingAckReceived event.
         """
         c = h2.connection.H2Connection(config=self.server_config)
         c.receive_data(frame_factory.preamble())
@@ -1339,7 +1361,8 @@
         assert len(events) == 1
         event = events[0]
 
-        assert isinstance(event, h2.events.PingAcknowledged)
+        assert isinstance(event, h2.events.PingAckReceived)
+        assert isinstance(event, h2.events.PingAcknowledged)  # deprecated
         assert event.ping_data == ping_data
 
     def test_stream_ended_remotely(self, frame_factory):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_events.py 
new/h2-3.1.0/test/test_events.py
--- old/h2-3.0.1/test/test_events.py    2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/test/test_events.py    2019-01-22 18:41:43.000000000 +0100
@@ -213,14 +213,23 @@
             "new_value=32768)}>"
         )
 
-    def test_pingacknowledged_repr(self):
+    def test_pingreceived_repr(self):
         """
-        PingAcknowledged has a useful debug representation.
+        PingReceived has a useful debug representation.
         """
-        e = h2.events.PingAcknowledged()
+        e = h2.events.PingReceived()
         e.ping_data = b'abcdefgh'
 
-        assert repr(e) == "<PingAcknowledged ping_data:6162636465666768>"
+        assert repr(e) == "<PingReceived ping_data:6162636465666768>"
+
+    def test_pingackreceived_repr(self):
+        """
+        PingAckReceived has a useful debug representation.
+        """
+        e = h2.events.PingAckReceived()
+        e.ping_data = b'abcdefgh'
+
+        assert repr(e) == "<PingAckReceived ping_data:6162636465666768>"
 
     def test_streamended_repr(self):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_invalid_headers.py 
new/h2-3.1.0/test/test_invalid_headers.py
--- old/h2-3.0.1/test/test_invalid_headers.py   2017-04-03 09:57:49.000000000 
+0200
+++ new/h2-3.1.0/test/test_invalid_headers.py   2019-01-22 18:41:43.000000000 
+0100
@@ -54,6 +54,7 @@
         base_request_headers + [('name', 'value with trailing space ')],
         [header for header in base_request_headers
          if header[0] != ':authority'],
+        [(':protocol', 'websocket')] + base_request_headers,
     ]
     server_config = h2.config.H2Configuration(
         client_side=False, header_encoding='utf-8'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_rfc8441.py 
new/h2-3.1.0/test/test_rfc8441.py
--- old/h2-3.0.1/test/test_rfc8441.py   1970-01-01 01:00:00.000000000 +0100
+++ new/h2-3.1.0/test/test_rfc8441.py   2019-01-22 18:41:43.000000000 +0100
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+test_rfc8441
+~~~~~~~~~~~~
+
+Test the RFC 8441 extended connect request support.
+"""
+import h2.config
+import h2.connection
+import h2.events
+
+
+class TestRFC8441(object):
+    """
+    Tests that the client supports sending an extended connect request
+    and the server supports receiving it.
+    """
+
+    def test_can_send_headers(self, frame_factory):
+        headers = [
+            (b':authority', b'example.com'),
+            (b':path', b'/'),
+            (b':scheme', b'https'),
+            (b':method', b'CONNECT'),
+            (b':protocol', b'websocket'),
+            (b'user-agent', b'someua/0.0.1'),
+        ]
+
+        client = h2.connection.H2Connection()
+        client.initiate_connection()
+        client.send_headers(stream_id=1, headers=headers)
+
+        server = h2.connection.H2Connection(
+            config=h2.config.H2Configuration(client_side=False)
+        )
+        events = server.receive_data(client.data_to_send())
+        event = events[1]
+        assert isinstance(event, h2.events.RequestReceived)
+        assert event.stream_id == 1
+        assert event.headers == headers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_settings.py 
new/h2-3.1.0/test/test_settings.py
--- old/h2-3.0.1/test/test_settings.py  2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/test/test_settings.py  2019-01-22 18:41:43.000000000 +0100
@@ -12,7 +12,9 @@
 import h2.settings
 
 from hypothesis import given, assume
-from hypothesis.strategies import integers
+from hypothesis.strategies import (
+    integers, booleans, fixed_dictionaries, builds
+)
 
 
 class TestSettings(object):
@@ -29,6 +31,7 @@
         assert s[h2.settings.SettingCodes.ENABLE_PUSH] == 1
         assert s[h2.settings.SettingCodes.INITIAL_WINDOW_SIZE] == 65535
         assert s[h2.settings.SettingCodes.MAX_FRAME_SIZE] == 16384
+        assert s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] == 0
 
     def test_settings_defaults_server(self):
         """
@@ -40,6 +43,7 @@
         assert s[h2.settings.SettingCodes.ENABLE_PUSH] == 0
         assert s[h2.settings.SettingCodes.INITIAL_WINDOW_SIZE] == 65535
         assert s[h2.settings.SettingCodes.MAX_FRAME_SIZE] == 16384
+        assert s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] == 0
 
     @pytest.mark.parametrize('client', [True, False])
     def test_can_set_initial_values(self, client):
@@ -52,6 +56,7 @@
             h2.settings.SettingCodes.MAX_FRAME_SIZE: 16388,
             h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 100,
             h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: 2**16,
+            h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL: 1,
         }
         s = h2.settings.Settings(client=client, initial_values=overrides)
 
@@ -61,6 +66,7 @@
         assert s[h2.settings.SettingCodes.MAX_FRAME_SIZE] == 16388
         assert s[h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS] == 100
         assert s[h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE] == 2**16
+        assert s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] == 1
 
     @pytest.mark.parametrize(
         'setting,value',
@@ -72,6 +78,7 @@
             (h2.settings.SettingCodes.MAX_FRAME_SIZE, 1),
             (h2.settings.SettingCodes.MAX_FRAME_SIZE, 2**30),
             (h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE, -1),
+            (h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL, -1),
         ]
     )
     def test_cannot_set_invalid_initial_values(self, setting, value):
@@ -106,6 +113,7 @@
             h2.settings.SettingCodes.ENABLE_PUSH: 0,
             h2.settings.SettingCodes.INITIAL_WINDOW_SIZE: 60,
             h2.settings.SettingCodes.MAX_FRAME_SIZE: 16385,
+            h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL: 1,
         }
         s.update(new_settings)
 
@@ -169,16 +177,16 @@
         Length is related only to the number of keys.
         """
         s = h2.settings.Settings(client=True)
-        assert len(s) == 4
+        assert len(s) == 5
 
         s[h2.settings.SettingCodes.HEADER_TABLE_SIZE] == 8000
-        assert len(s) == 4
+        assert len(s) == 5
 
         s.acknowledge()
-        assert len(s) == 4
+        assert len(s) == 5
 
         del s[h2.settings.SettingCodes.HEADER_TABLE_SIZE]
-        assert len(s) == 3
+        assert len(s) == 4
 
     def test_new_values_work(self):
         """
@@ -232,6 +240,9 @@
         assert s.max_frame_size == s[h2.settings.SettingCodes.MAX_FRAME_SIZE]
         assert s.max_concurrent_streams == 2**32 + 1  # A sensible default.
         assert s.max_header_list_size is None
+        assert s.enable_connect_protocol == s[
+            h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL
+        ]
 
     def test_settings_setters(self):
         """
@@ -245,6 +256,7 @@
         s.max_frame_size = 16385
         s.max_concurrent_streams = 4
         s.max_header_list_size = 2**16
+        s.enable_connect_protocol = 1
 
         s.acknowledge()
         assert s[h2.settings.SettingCodes.HEADER_TABLE_SIZE] == 0
@@ -253,6 +265,7 @@
         assert s[h2.settings.SettingCodes.MAX_FRAME_SIZE] == 16385
         assert s[h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS] == 4
         assert s[h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE] == 2**16
+        assert s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] == 1
 
     @given(integers())
     def test_cannot_set_invalid_values_for_enable_push(self, val):
@@ -361,131 +374,97 @@
             with pytest.raises(KeyError):
                 s[h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE]
 
-
-class TestSettingsEquality(object):
-    """
-    A class defining tests for the standard implementation of == and != .
-    """
-
-    def an_instance(self):
+    @given(integers())
+    def test_cannot_set_invalid_values_for_enable_connect_protocol(self, val):
         """
-        Return an instance of the class under test.  Each call to this method
-        must return a different object.  All objects returned must be equal to
-        each other.
+        SETTINGS_ENABLE_CONNECT_PROTOCOL only allows two values: 0, 1.
         """
-        overrides = {
-            h2.settings.SettingCodes.HEADER_TABLE_SIZE: 0,
-            h2.settings.SettingCodes.MAX_FRAME_SIZE: 16384,
-            h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 4,
-            h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: 2**16,
-        }
-        return h2.settings.Settings(client=True, initial_values=overrides)
+        assume(val not in (0, 1))
+        s = h2.settings.Settings()
 
-    def another_instance(self):
-        """
-        Return an instance of the class under test.  Each call to this method
-        must return a different object.  The objects must not be equal to the
-        objects returned by an_instance.  They may or may not be equal to
-        each other (they will not be compared against each other).
-        """
-        overrides = {
-            h2.settings.SettingCodes.HEADER_TABLE_SIZE: 8080,
-            h2.settings.SettingCodes.MAX_FRAME_SIZE: 16388,
-            h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 100,
-            h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: 2**16,
-        }
-        return h2.settings.Settings(client=False, initial_values=overrides)
+        with pytest.raises(h2.exceptions.InvalidSettingsValueError) as e:
+            s.enable_connect_protocol = val
 
-    def test_identical_eq(self):
-        """
-        An object compares equal to itself using the == operator.
-        """
-        o = self.an_instance()
-        assert (o == o)
+        s.acknowledge()
+        assert e.value.error_code == h2.errors.ErrorCodes.PROTOCOL_ERROR
+        assert s.enable_connect_protocol == 0
 
-    def test_identical_ne(self):
-        """
-        An object doesn't compare not equal to itself using the != operator.
-        """
-        o = self.an_instance()
-        assert not (o != o)
+        with pytest.raises(h2.exceptions.InvalidSettingsValueError) as e:
+            s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] = val
 
-    def test_same_eq(self):
-        """
-        Two objects that are equal to each other compare equal to each other
-        using the == operator.
-        """
-        a = self.an_instance()
-        b = self.an_instance()
-        assert (a == b)
+        s.acknowledge()
+        assert e.value.error_code == h2.errors.ErrorCodes.PROTOCOL_ERROR
+        assert s[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL] == 0
 
-    def test_same_ne(self):
-        """
-        Two objects that are equal to each other do not compare not equal to
-        each other using the != operator.
-        """
-        a = self.an_instance()
-        b = self.an_instance()
-        assert not (a != b)
 
-    def test_different_eq(self):
+class TestSettingsEquality(object):
+    """
+    A class defining tests for the standard implementation of == and != .
+    """
+
+    SettingsStrategy = builds(
+        h2.settings.Settings,
+        client=booleans(),
+        initial_values=fixed_dictionaries({
+            h2.settings.SettingCodes.HEADER_TABLE_SIZE:
+                integers(0, 2**32 - 1),
+            h2.settings.SettingCodes.ENABLE_PUSH: integers(0, 1),
+            h2.settings.SettingCodes.INITIAL_WINDOW_SIZE:
+                integers(0, 2**31 - 1),
+            h2.settings.SettingCodes.MAX_FRAME_SIZE:
+                integers(2**14, 2**24 - 1),
+            h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS:
+                integers(0, 2**32 - 1),
+            h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE:
+                integers(0, 2**32 - 1),
+        })
+    )
+
+    @given(settings=SettingsStrategy)
+    def test_equality_reflexive(self, settings):
         """
-        Two objects that are not equal to each other do not compare equal to
-        each other using the == operator.
+        An object compares equal to itself using the == operator and the !=
+        operator.
         """
-        a = self.an_instance()
-        b = self.another_instance()
-        assert not (a == b)
+        assert (settings == settings)
+        assert not (settings != settings)
 
-    def test_different_ne(self):
+    @given(settings=SettingsStrategy, o_settings=SettingsStrategy)
+    def test_equality_multiple(self, settings, o_settings):
         """
-        Two objects that are not equal to each other compare not equal to each
-        other using the != operator.
+        Two objects compare themselves using the == operator and the !=
+        operator.
         """
-        a = self.an_instance()
-        b = self.another_instance()
-        assert (a != b)
+        if settings == o_settings:
+            assert settings == o_settings
+            assert not (settings != o_settings)
+        else:
+            assert settings != o_settings
+            assert not (settings == o_settings)
 
-    def test_another_type_eq(self):
+    @given(settings=SettingsStrategy)
+    def test_another_type_equality(self, settings):
         """
         The object does not compare equal to an object of an unrelated type
         (which does not implement the comparison) using the == operator.
         """
-        a = self.an_instance()
-        b = object()
-        assert not (a == b)
+        obj = object()
+        assert (settings != obj)
+        assert not (settings == obj)
 
-    def test_another_type_ne(self):
+    @given(settings=SettingsStrategy)
+    def test_delegated_eq(self, settings):
         """
-        The object compares not equal to an object of an unrelated type (which
-        does not implement the comparison) using the != operator.
-        """
-        a = self.an_instance()
-        b = object()
-        assert (a != b)
-
-    def test_delegated_eq(self):
-        """
-        The result of comparison using == is delegated to the right-hand
-        operand if it is of an unrelated type.
+        The result of comparison is delegated to the right-hand operand if
+        it is of an unrelated type.
         """
         class Delegate(object):
             def __eq__(self, other):
                 return [self]
 
-        a = self.an_instance()
-        b = Delegate()
-        assert (a == b) == [b]
-
-    def test_delegate_ne(self):
-        """
-        The result of comparison using != is delegated to the right-hand
-        operand if it is of an unrelated type.
-        """
-        class Delegate(object):
             def __ne__(self, other):
                 return [self]
 
-        a = self.an_instance()
-        b = Delegate()
-        assert (a != b) == [b]
+        delg = Delegate()
+        assert (settings == delg) == [delg]
+        assert (settings != delg) == [delg]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test/test_utility_functions.py 
new/h2-3.1.0/test/test_utility_functions.py
--- old/h2-3.0.1/test/test_utility_functions.py 2017-04-03 09:57:46.000000000 
+0200
+++ new/h2-3.1.0/test/test_utility_functions.py 2019-01-22 18:41:43.000000000 
+0100
@@ -12,7 +12,7 @@
 import h2.errors
 import h2.events
 import h2.exceptions
-from h2.utilities import extract_method_header
+from h2.utilities import SizeLimitDict, extract_method_header
 
 # These tests require a non-list-returning range function.
 try:
@@ -176,3 +176,51 @@
     )
     def test_extract_header_method(self, headers):
         assert extract_method_header(headers) == b'GET'
+
+
+def test_size_limit_dict_limit():
+    dct = SizeLimitDict(size_limit=2)
+
+    dct[1] = 1
+    dct[2] = 2
+
+    assert len(dct) == 2
+    assert dct[1] == 1
+    assert dct[2] == 2
+
+    dct[3] = 3
+
+    assert len(dct) == 2
+    assert dct[2] == 2
+    assert dct[3] == 3
+    assert 1 not in dct
+
+
+def test_size_limit_dict_limit_init():
+    initial_dct = {
+        1: 1,
+        2: 2,
+        3: 3,
+    }
+
+    dct = SizeLimitDict(initial_dct, size_limit=2)
+
+    assert len(dct) == 2
+
+
+def test_size_limit_dict_no_limit():
+    dct = SizeLimitDict(size_limit=None)
+
+    dct[1] = 1
+    dct[2] = 2
+
+    assert len(dct) == 2
+    assert dct[1] == 1
+    assert dct[2] == 2
+
+    dct[3] = 3
+
+    assert len(dct) == 3
+    assert dct[1] == 1
+    assert dct[2] == 2
+    assert dct[3] == 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/test_requirements.txt 
new/h2-3.1.0/test_requirements.txt
--- old/h2-3.0.1/test_requirements.txt  2017-03-31 17:30:40.000000000 +0200
+++ new/h2-3.1.0/test_requirements.txt  2019-01-22 18:41:43.000000000 +0100
@@ -1,5 +1,5 @@
-pytest==3.0.7
-pytest-cov==2.4.0
-coverage==4.3.4
-pytest-xdist==1.15.0
-hypothesis==3.7.0
+pytest==3.4.2
+pytest-cov==2.5.1
+coverage==4.5.1
+pytest-xdist==1.22.2
+hypothesis
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/tox.ini new/h2-3.1.0/tox.ini
--- old/h2-3.0.1/tox.ini        2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/tox.ini        2019-01-22 18:41:43.000000000 +0100
@@ -1,5 +1,5 @@
 [tox]
-envlist = py27, py33, py34, py35, py36, pypy, lint, packaging, docs
+envlist = py27, py34, py35, py36, py37, pypy, lint, packaging, docs
 
 [testenv]
 deps= -r{toxinidir}/test_requirements.txt
@@ -15,22 +15,17 @@
 # This is a validation test that confirms that Twisted's test cases haven't
 # broken.
 deps =
-    # [tls,http2] syntax doesn't work here so we enumerate all dependencies.
-    git+https://github.com/twisted/twisted
-    pyopenssl
-    service_identity
-    idna
-    priority
+    twisted[tls, http2, conch]
     sphinx
 commands = python -m twisted.trial --reporter=text twisted
 
 [testenv:lint]
-basepython=python3.4
-deps = flake8==3.3.0
+basepython=python3.7
+deps = flake8==3.5.0
 commands = flake8 --max-complexity 10 h2 test
 
 [testenv:docs]
-basepython=python3.5
+basepython=python3.7
 deps = sphinx==1.4.9
 changedir = {toxinidir}/docs
 whitelist_externals = rm
@@ -40,15 +35,15 @@
 
 [testenv:graphs]
 basepython=python2.7
-deps = graphviz==0.6
+deps = graphviz==0.8.2
 commands =
     python visualizer/visualize.py -i docs/source/_static
 
 [testenv:packaging]
-basepython=python2.7
+basepython=python3.7
 deps =
-    check-manifest==0.35
-    readme_renderer==17.2
+    check-manifest==0.36
+    readme-renderer==17.3
 commands =
     check-manifest
     python setup.py check --metadata --restructuredtext --strict
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-3.0.1/utils/backport.sh 
new/h2-3.1.0/utils/backport.sh
--- old/h2-3.0.1/utils/backport.sh      2017-04-03 09:57:46.000000000 +0200
+++ new/h2-3.1.0/utils/backport.sh      2019-01-22 18:41:43.000000000 +0100
@@ -16,6 +16,7 @@
 if ! git pull --ff-only; then
     echo "Unable to update $TARGET_BRANCH"
     exit 2
+fi
 
 if ! git checkout -b "$PR_BRANCH"; then
     echo "Failed to open new branch $PR_BRANCH"


Reply via email to