From c60bf4988b3251c928b91ce04efaac776f46bc09 Mon Sep 17 00:00:00 2001 From: Kubilay Kocak Date: Fri, 17 May 2019 12:43:14 +0000 Subject: [PATCH] wwww/py-hyper: Update to 0.8.0.dev0 (g20171217) Latest PyPI released (0.7.0) fails several tests that have been resolved in branch:development but not yet released. - Add patches to make hyper work with h2 > 3.0 [1] Changelog: https://github.com/Lukasa/hyper/blob/development/HISTORY.rst [1] https://github.com/Lukasa/hyper/pull/402 git-svn-id: svn+ssh://svn.freebsd.org/ports/head@501865 35697150-7ecd-e111-bb59-0022644237b5 --- www/py-hyper/Makefile | 32 ++-- www/py-hyper/distinfo | 5 +- www/py-hyper/files/files-server.py | 144 ------------------ .../files/patch-hyper_http20_connection.py | 32 ++++ www/py-hyper/files/patch-setup.py | 53 ++----- www/py-hyper/files/patch-test_test__hyper.py | 35 +++++ 6 files changed, 101 insertions(+), 200 deletions(-) delete mode 100644 www/py-hyper/files/files-server.py create mode 100644 www/py-hyper/files/patch-hyper_http20_connection.py create mode 100644 www/py-hyper/files/patch-test_test__hyper.py diff --git a/www/py-hyper/Makefile b/www/py-hyper/Makefile index da114de11c12..391d72aba814 100644 --- a/www/py-hyper/Makefile +++ b/www/py-hyper/Makefile @@ -2,9 +2,8 @@ # $FreeBSD$ PORTNAME= hyper -PORTVERSION= 0.5.0 +DISTVERSION= 0.8.0.g20171217 CATEGORIES= www python -MASTER_SITES= CHEESESHOP PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} MAINTAINER= koobs@FreeBSD.org @@ -13,22 +12,33 @@ COMMENT= HTTP/2 Client for Python LICENSE= MIT LICENSE_FILE= ${WRKSRC}/LICENSE +RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}h2>=2.4:www/py-h2@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}hyperframe>=3.2:www/py-hyperframe@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}brotlipy>=0.7.0:archivers/py-brotlipy@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}rfc3986>=1.1.0,<2.0:www/py-rfc3986@${PY_FLAVOR} TEST_DEPENDS= ${PYTHON_PKGNAMEPREFIX}pytest>0:devel/py-pytest@${PY_FLAVOR} \ ${PYTHON_PKGNAMEPREFIX}requests>0:www/py-requests@${PY_FLAVOR} \ - ${PYTHON_PKGNAMEPREFIX}mock>0:devel/py-mock@${PY_FLAVOR} + ${PYTHON_PKGNAMEPREFIX}mock>0:devel/py-mock@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}hpack>0:www/py-hpack@${PY_FLAVOR} USES= python -USE_PYTHON= autoplist distutils +USE_GITHUB= yes +USE_PYTHON= autoplist concurrent distutils + +GH_ACCOUNT= Lukasa +GH_TAGNAME= 18b629b NO_ARCH= yes -post-extract: - @${MKDIR} ${WRKSRC}/test/certs/ - @${CP} ${FILESDIR}/files-server.py ${WRKSRC}/test/server.py - @${CP} ${FILESDIR}/files-server.key ${WRKSRC}/test/certs/server.key - @${CP} ${FILESDIR}/files-server.crt ${WRKSRC}/test/certs/server.crt +py27_RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}enum34>=1.0.4,<2:devel/py-enum34@${PY_FLAVOR} do-test: - @cd ${WRKSRC} && ${PYTHON_CMD} ${PYDISTUTILS_SETUP} test --pytest-args "-k 'not test_integration'" + @cd ${WRKSRC} && ${PYTHON_CMD} -m pytest -v -rs -k 'not test_HTTPConnection_with_custom_context' test + +.include + +.if ${PYTHON_VER} < 3.0 +TEST_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}futures>0:devel/py-futures@${PY_FLAVOR} +.endif -.include +.include diff --git a/www/py-hyper/distinfo b/www/py-hyper/distinfo index fdc5004019ff..08731caaf06c 100644 --- a/www/py-hyper/distinfo +++ b/www/py-hyper/distinfo @@ -1,2 +1,3 @@ -SHA256 (hyper-0.5.0.tar.gz) = 034b6ad6d0ba2dafa948e5d893337ffa376ececa5725f7cc59f9319a11b0b3f3 -SIZE (hyper-0.5.0.tar.gz) = 255589 +TIMESTAMP = 1558088018 +SHA256 (Lukasa-hyper-0.8.0.g20171217-18b629b_GH0.tar.gz) = 2a3f656de9d6824ea3f70c8f3ca9857794e225e647698f5df9b20b33e2694a6e +SIZE (Lukasa-hyper-0.8.0.g20171217-18b629b_GH0.tar.gz) = 402869 diff --git a/www/py-hyper/files/files-server.py b/www/py-hyper/files/files-server.py deleted file mode 100644 index 610b4b9a02dd..000000000000 --- a/www/py-hyper/files/files-server.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -""" -test/server -~~~~~~~~~~~ - -This module defines some testing infrastructure that is very useful for -integration-type testing of hyper. It works by spinning up background threads -that run test-defined logic while listening to a background thread. - -This very-clever idea and most of its implementation are ripped off from -Andrey Petrov's excellent urllib3 project. I owe him a substantial debt in -ingenuity and about a million beers. The license is available in NOTICES. -""" - -import threading -import socket -import sys - -from hyper import HTTP20Connection -from hyper.compat import ssl -from hyper.http11.connection import HTTP11Connection -from hyper.packages.hpack.hpack import Encoder -from hyper.packages.hpack.huffman import HuffmanEncoder -from hyper.packages.hpack.huffman_constants import ( - REQUEST_CODES, REQUEST_CODES_LENGTH -) -from hyper.tls import NPN_PROTOCOL - -class SocketServerThread(threading.Thread): - """ - This method stolen wholesale from shazow/urllib3 under license. See NOTICES. - - :param socket_handler: Callable which receives a socket argument for one - request. - :param ready_event: Event which gets set when the socket handler is - ready to receive requests. - """ - def __init__(self, - socket_handler, - host='localhost', - ready_event=None, - h2=True, - secure=True): - threading.Thread.__init__(self) - - self.socket_handler = socket_handler - self.host = host - self.secure = secure - self.ready_event = ready_event - self.daemon = True - - if self.secure: - self.cxt = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - if ssl.HAS_NPN and h2: - self.cxt.set_npn_protocols([NPN_PROTOCOL]) - self.cxt.load_cert_chain(certfile='test/certs/server.crt', - keyfile='test/certs/server.key') - - def _start_server(self): - sock = socket.socket(socket.AF_INET6) - if sys.platform != 'win32': - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - if self.secure: - sock = self.cxt.wrap_socket(sock, server_side=True) - sock.bind((self.host, 0)) - self.port = sock.getsockname()[1] - - # Once listen() returns, the server socket is ready - sock.listen(1) - - if self.ready_event: - self.ready_event.set() - - self.socket_handler(sock) - sock.close() - - def _wrap_socket(self, sock): - raise NotImplementedError() - - def run(self): - self.server = self._start_server() - - -class SocketLevelTest(object): - """ - A test-class that defines a few helper methods for running socket-level - tests. - """ - def set_up(self, secure=True, proxy=False): - self.host = None - self.port = None - self.secure = secure if not proxy else False - self.proxy = proxy - self.server_thread = None - - def _start_server(self, socket_handler): - """ - Starts a background thread that runs the given socket handler. - """ - ready_event = threading.Event() - self.server_thread = SocketServerThread( - socket_handler=socket_handler, - ready_event=ready_event, - h2=self.h2, - secure=self.secure - ) - self.server_thread.start() - ready_event.wait() - - self.host = self.server_thread.host - self.port = self.server_thread.port - self.secure = self.server_thread.secure - - def get_connection(self): - if self.h2: - if not self.proxy: - return HTTP20Connection(self.host, self.port, self.secure) - else: - return HTTP20Connection('http2bin.org', secure=self.secure, - proxy_host=self.host, - proxy_port=self.port) - else: - if not self.proxy: - return HTTP11Connection(self.host, self.port, self.secure) - else: - return HTTP11Connection('httpbin.org', secure=self.secure, - proxy_host=self.host, - proxy_port=self.port) - - - def get_encoder(self): - """ - Returns a HPACK encoder set up for responses. - """ - e = Encoder() - e.huffman_coder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH) - return e - - def tear_down(self): - """ - Tears down the testing thread. - """ - self.server_thread.join(0.1) diff --git a/www/py-hyper/files/patch-hyper_http20_connection.py b/www/py-hyper/files/patch-hyper_http20_connection.py new file mode 100644 index 000000000000..356635dc8a57 --- /dev/null +++ b/www/py-hyper/files/patch-hyper_http20_connection.py @@ -0,0 +1,32 @@ +# HTTP20Connection: Fix use of ENABLE_PUSH +# https://github.com/Lukasa/hyper/pull/402 + +--- hyper/http20/connection.py.orig 2019-05-17 10:15:20 UTC ++++ hyper/http20/connection.py +@@ -7,7 +7,7 @@ Objects that build hyper's connection-level HTTP/2 abs + """ + import h2.connection + import h2.events +-import h2.settings ++from h2.settings import SettingCodes + + from ..compat import ssl + from ..tls import wrap_socket, H2_NPN_PROTOCOLS, H2C_PROTOCOL +@@ -403,7 +403,7 @@ class HTTP20Connection(object): + with self._conn as conn: + conn.initiate_upgrade_connection() + conn.update_settings( +- {h2.settings.ENABLE_PUSH: int(self._enable_push)} ++ {SettingCodes.ENABLE_PUSH: int(self._enable_push)} + ) + self._send_outstanding_data() + +@@ -424,7 +424,7 @@ class HTTP20Connection(object): + with self._conn as conn: + conn.initiate_connection() + conn.update_settings( +- {h2.settings.ENABLE_PUSH: int(self._enable_push)} ++ {SettingCodes.ENABLE_PUSH: int(self._enable_push)} + ) + self._send_outstanding_data() + diff --git a/www/py-hyper/files/patch-setup.py b/www/py-hyper/files/patch-setup.py index 7060de4430a2..4618247e3786 100644 --- a/www/py-hyper/files/patch-setup.py +++ b/www/py-hyper/files/patch-setup.py @@ -1,44 +1,11 @@ ---- setup.py.orig 2015-10-28 10:21:14 UTC +--- setup.py.orig 2019-05-17 11:59:54 UTC +++ setup.py -@@ -7,6 +7,7 @@ import sys - - try: - from setuptools import setup -+ from setuptools.command.test import test as TestCommand - except ImportError: - from distutils.core import setup - -@@ -48,6 +49,24 @@ def resolve_install_requires(): - return deps - return [] - -+class PyTest(TestCommand): -+ user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] -+ -+ def initialize_options(self): -+ TestCommand.initialize_options(self) -+ self.pytest_args = [] -+ -+ def finalize_options(self): -+ TestCommand.finalize_options(self) -+ self.test_args = [] -+ self.test_suite = True -+ -+ def run_tests(self): -+ #import here, cause outside the eggs aren't loaded -+ import pytest -+ errno = pytest.main(self.pytest_args) -+ sys.exit(errno) -+ - packages = [ - 'hyper', - 'hyper.http20', -@@ -90,5 +109,7 @@ setup( - }, - extras_require={ - 'fast': ['pycohttpparser'], -- } -+ }, -+ tests_require=['pytest'], -+ cmdclass = {'test': PyTest}, - ) +@@ -77,7 +77,7 @@ setup( + 'Programming Language :: Python :: Implementation :: CPython', + ], + install_requires=[ +- 'h2>=2.4,<3.0,!=2.5.0', 'hyperframe>=3.2,<4.0', 'rfc3986>=1.1.0,<2.0', 'brotlipy>=0.7.0,<1.0' ++ 'h2>=2.4,!=2.5.0', 'hyperframe>=3.2', 'rfc3986>=1.1.0,<2.0', 'brotlipy>=0.7.0,<1.0' + ], + tests_require=['pytest', 'requests', 'mock'], + cmdclass={'test': PyTest}, diff --git a/www/py-hyper/files/patch-test_test__hyper.py b/www/py-hyper/files/patch-test_test__hyper.py new file mode 100644 index 000000000000..ebd4ee1dd7c5 --- /dev/null +++ b/www/py-hyper/files/patch-test_test__hyper.py @@ -0,0 +1,35 @@ +# Fix use of h2.settings -> h2.settings.SettingCodes.* Based on: +# HTTP20Connection: Fix use of ENABLE_PUSH +# https://github.com/Lukasa/hyper/pull/402 + +# Fix hpack import (hpack_compat is gone now) +# https://github.com/python-hyper/hpack/pull/60 + +--- test/test_hyper.py.orig 2019-05-17 10:17:07 UTC ++++ test/test_hyper.py +@@ -1,14 +1,13 @@ + # -*- coding: utf-8 -*- +-import h2.settings +- + from h2.frame_buffer import FrameBuffer + from h2.connection import ConnectionState ++from h2.settings import SettingCodes + from hyperframe.frame import ( + Frame, DataFrame, RstStreamFrame, SettingsFrame, PushPromiseFrame, + WindowUpdateFrame, HeadersFrame, ContinuationFrame, GoAwayFrame, + PingFrame, FRAME_MAX_ALLOWED_LEN + ) +-from hpack.hpack_compat import Encoder ++from hpack import Encoder + from hyper.common.connection import HTTPConnection + from hyper.http20.connection import HTTP20Connection + from hyper.http20.response import HTTP20Response, HTTP20Push +@@ -766,7 +765,7 @@ class TestHyperConnection(object): + # the default max frame size (16,384 bytes). That will, on the third + # frame, trigger the processing to increment the flow control window, + # which should then not happen. +- f = SettingsFrame(0, settings={h2.settings.INITIAL_WINDOW_SIZE: 100}) ++ f = SettingsFrame(0, settings={SettingCodes.INITIAL_WINDOW_SIZE: 100}) + + c = HTTP20Connection('www.google.com') + c._sock = DummySocket()