r47218 - applying patch from lukasa, refs #8194

hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Tue, 12 Apr 2016 04:17:30 -0600 (MDT)
Newsgroups gmane.comp.python.twisted.commits
Message-ID <[email protected]>
Author: hawkowl
Date: Tue Apr 12 04:17:26 2016
New Revision: 47218

Added:
   branches/h2channel-8194-6/twisted/web/http2.py
   branches/h2channel-8194-6/twisted/web/test/test_http2.py
Modified:
   branches/h2channel-8194-6/tox.ini
   branches/h2channel-8194-6/twisted/python/_release.py
   branches/h2channel-8194-6/twisted/python/dist.py
   branches/h2channel-8194-6/twisted/python/dist3.py
   branches/h2channel-8194-6/twisted/python/test/test_dist.py
   branches/h2channel-8194-6/twisted/web/error.py
   branches/h2channel-8194-6/twisted/web/http.py
   branches/h2channel-8194-6/twisted/web/test/test_http.py

Log:
applying patch from lukasa, refs #8194

Modified: branches/h2channel-8194-6/tox.ini
==============================================================================
--- branches/h2channel-8194-6/tox.ini	(original)
+++ branches/h2channel-8194-6/tox.ini	Tue Apr 12 04:17:26 2016
@@ -21,6 +21,8 @@
      {tests,coverage}: python-subunit
      {tests,coverage}: pycrypto
      {tests,coverage}: appdirs
+     {tests,coverage}: h2
+     {tests,coverage}: priority
 
      py27-{tests,coverage}-posix: pysqlite
      py27-{tests,coverage}: soappy

Modified: branches/h2channel-8194-6/twisted/python/_release.py
==============================================================================
--- branches/h2channel-8194-6/twisted/python/_release.py	(original)
+++ branches/h2channel-8194-6/twisted/python/_release.py	Tue Apr 12 04:17:26 2016
@@ -586,6 +586,8 @@
              "--html-viewsource-base", sourceURL,
              "--add-package", packagePath.path,
              "--html-output", outputPath.path,
+             "--intersphinx",
+             "https://python-hyper.org/h2/en/stable/objects.inv",
              "--html-write-function-pages", "--quiet", "--make-html"])
 
 

Modified: branches/h2channel-8194-6/twisted/python/dist.py
==============================================================================
--- branches/h2channel-8194-6/twisted/python/dist.py	(original)
+++ branches/h2channel-8194-6/twisted/python/dist.py	Tue Apr 12 04:17:26 2016
@@ -80,14 +80,17 @@
     soap=['soappy'],
     serial=['pyserial'],
     osx=['pyobjc'],
-    windows=['pypiwin32']
+    windows=['pypiwin32'],
+    http2=['h2 >= 2.2.0, < 3.0',
+           'priority >= 1.1.0, < 2.0'],
 )
 
 _PLATFORM_INDEPENDENT = (
     _EXTRA_OPTIONS['tls'] +
     _EXTRA_OPTIONS['conch'] +
     _EXTRA_OPTIONS['soap'] +
-    _EXTRA_OPTIONS['serial']
+    _EXTRA_OPTIONS['serial'] +
+    _EXTRA_OPTIONS['http2']
 )
 
 _EXTRAS_REQUIRE = {
@@ -96,6 +99,7 @@
     'conch': _EXTRA_OPTIONS['conch'],
     'soap': _EXTRA_OPTIONS['soap'],
     'serial': _EXTRA_OPTIONS['serial'],
+    'http2': _EXTRA_OPTIONS['http2'],
     'all_non_platform': _PLATFORM_INDEPENDENT,
     'osx_platform': (
         _EXTRA_OPTIONS['osx'] + _PLATFORM_INDEPENDENT

Modified: branches/h2channel-8194-6/twisted/python/dist3.py
==============================================================================
--- branches/h2channel-8194-6/twisted/python/dist3.py	(original)
+++ branches/h2channel-8194-6/twisted/python/dist3.py	Tue Apr 12 04:17:26 2016
@@ -253,6 +253,7 @@
     "twisted.web.demo",
     "twisted.web.error",
     "twisted.web.guard",
+    "twisted.web.http2",
     "twisted.web.http_headers",
     "twisted.web.proxy",
     "twisted.web.resource",
@@ -425,6 +426,7 @@
     "twisted.web.test.test_error",
     # The downloadPage tests weren't ported:
     "twisted.web.test.test_http",
+    "twisted.web.test.test_http2",
     "twisted.web.test.test_flatten",
     "twisted.web.test.test_http_headers",
     "twisted.web.test.test_httpauth",

Modified: branches/h2channel-8194-6/twisted/python/test/test_dist.py
==============================================================================
--- branches/h2channel-8194-6/twisted/python/test/test_dist.py	(original)
+++ branches/h2channel-8194-6/twisted/python/test/test_dist.py	Tue Apr 12 04:17:26 2016
@@ -93,6 +93,7 @@
         self.assertIn('all_non_platform', _EXTRAS_REQUIRE)
         self.assertIn('osx_platform', _EXTRAS_REQUIRE)
         self.assertIn('windows_platform', _EXTRAS_REQUIRE)
+        self.assertIn('http2', _EXTRAS_REQUIRE)
 
 
     def test_extrasRequiresDevDeps(self):
@@ -156,6 +157,16 @@
         )
 
 
+    def test_extrasRequiresHttp2Deps(self):
+        """
+        L{_EXTRAS_REQUIRE}'s C{http2} extra contains setuptools requirements
+        for the packages required to make Twisted HTTP/2 support work.
+        """
+        deps = _EXTRAS_REQUIRE['http2']
+        self.assertIn('h2 >= 2.2.0, < 3.0', deps)
+        self.assertIn('priority >= 1.1.0, < 2.0', deps)
+
+
     def test_extrasRequiresAllNonPlatformDeps(self):
         """
         L{_EXTRAS_REQUIRE}'s C{all_non_platform} extra contains setuptools
@@ -172,6 +183,8 @@
         self.assertIn('soappy', deps)
         self.assertIn('pyserial', deps)
         self.assertIn('appdirs >= 1.4.0', deps)
+        self.assertIn('h2 >= 2.2.0, < 3.0', deps)
+        self.assertIn('priority >= 1.1.0, < 2.0', deps)
 
 
     def test_extrasRequiresOsxPlatformDeps(self):
@@ -189,6 +202,8 @@
         self.assertIn('cryptography >= 0.9.1', deps)
         self.assertIn('soappy', deps)
         self.assertIn('pyserial', deps)
+        self.assertIn('h2 >= 2.2.0, < 3.0', deps)
+        self.assertIn('priority >= 1.1.0, < 2.0', deps)
         self.assertIn('pyobjc', deps)
 
 
@@ -207,6 +222,8 @@
         self.assertIn('cryptography >= 0.9.1', deps)
         self.assertIn('soappy', deps)
         self.assertIn('pyserial', deps)
+        self.assertIn('h2 >= 2.2.0, < 3.0', deps)
+        self.assertIn('priority >= 1.1.0, < 2.0', deps)
         self.assertIn('pypiwin32', deps)
 
 

Modified: branches/h2channel-8194-6/twisted/web/error.py
==============================================================================
--- branches/h2channel-8194-6/twisted/web/error.py	(original)
+++ branches/h2channel-8194-6/twisted/web/error.py	Tue Apr 12 04:17:26 2016
@@ -385,3 +385,11 @@
 
     def __str__(self):
         return repr(self)
+
+
+
+class UnsupportedSpecialHeader(Exception):
+    """
+    A HTTP/2 request was received that contained a HTTP/2 pseudo-header field
+    that is not recognised by Twisted.
+    """

Modified: branches/h2channel-8194-6/twisted/web/http.py
==============================================================================
--- branches/h2channel-8194-6/twisted/web/http.py	(original)
+++ branches/h2channel-8194-6/twisted/web/http.py	Tue Apr 12 04:17:26 2016
@@ -104,7 +104,12 @@
 from twisted.web.iweb import IRequest, IAccessLogFormatter
 from twisted.web.http_headers import Headers
 
-H2_ENABLED = False
+try:
+    from twisted.web.http2 import H2Connection
+    H2_ENABLED = True
+except ImportError:
+    H2Connection = None
+    H2_ENABLED = False
 
 from twisted.web._responses import (
     SWITCHING,
@@ -951,7 +956,8 @@
             self._transport.write(b"0\r\n\r\n")
 
         # log request
-        if hasattr(self._channel, "factory"):
+        if (hasattr(self._channel, "factory") and
+            self._channel.factory is not None):
             self._channel.factory.log(self)
 
         self.finished = 1
@@ -2255,9 +2261,13 @@
 
     @ivar _site: A reference to the creating L{twisted.web.server.Site} object.
     @type _site: L{twisted.web.server.Site}
+
+    @ivar _factory: A reference to the creating L{HTTPFactory} object.
+    @type _factory: L{HTTPFactory}
     """
     _negotiatedProtocol = None
     _requestFactory = Request
+    _factory = None
     _site = None
 
 
@@ -2274,6 +2284,7 @@
         """
         @see: L{HTTPChannel.factory}
         """
+        self._factory = value
         self._channel.factory = value
 
 
@@ -2316,6 +2327,12 @@
 
             if negotiatedProtocol == b'h2':
                 assert H2_ENABLED, "Cannot negotiate HTTP/2 without support."
+                transport = self._channel.transport
+                self._channel = H2Connection()
+                self._channel.requestFactory = self._requestFactory
+                self._channel.site = self._site
+                self._channel.factory = self._factory
+                self._channel.makeConnection(transport)
             else:
                 # Only HTTP/2 and HTTP/1.1 are supported right now.
                 assert negotiatedProtocol == b'http/1.1', \

Modified: branches/h2channel-8194-6/twisted/web/test/test_http.py
==============================================================================
--- branches/h2channel-8194-6/twisted/web/test/test_http.py	(original)
+++ branches/h2channel-8194-6/twisted/web/test/test_http.py	Tue Apr 12 04:17:26 2016
@@ -299,11 +299,23 @@
         self.assertEqual(negotiatedProtocol, b'http/1.1')
 
 
-    def test_http2(self):
+    def test_http2_present(self):
         """
-        If the transport reports that HTTP/2 is negotiated, that's what's
-        negotiated. Currently HTTP/2 is unsupported, so this raises an
-        AssertionError.
+        If the transport reports that HTTP/2 is negotiated and HTTP/2 is
+        present, that's what's negotiated.
+        """
+        b = StringTransport()
+        b.negotiatedProtocol = b'h2'
+        negotiatedProtocol = self._negotiatedProtocolForTransportInstance(b)
+        self.assertEqual(negotiatedProtocol, b'h2')
+    if not http.H2_ENABLED:
+        test_http2_present.skip = "HTTP/2 support not present"
+
+
+    def test_http2_absent(self):
+        """
+        If the transport reports that HTTP/2 is negotiated and HTTP/2 is not
+        present, an error is encountered.
         """
         b = StringTransport()
         b.negotiatedProtocol = b'h2'
@@ -312,6 +324,8 @@
             self._negotiatedProtocolForTransportInstance,
             b,
         )
+    if http.H2_ENABLED:
+        test_http2_absent.skip = "HTTP/2 support present"
 
 
     def test_unknownProtocol(self):