From: Ben Darnell Date: Fri, 1 Mar 2019 20:03:31 +0000 (-0500) Subject: Fix importability on python 3.5.2 X-Git-Tag: v6.1.0b1~87^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61e1dbf98386e39dcb961d05da820778cede2999;p=thirdparty%2Ftornado.git Fix importability on python 3.5.2 The "provisional" typing module in 3.5.2 is kind of broken/incomplete so we need to use more forward references to avoid confusing it. The significance of this version in particular is that it was the one included in ubuntu 16.04. Fixes #2604 --- diff --git a/.travis.yml b/.travis.yml index f39bb7657..dd808b97c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,10 @@ language: python - libgnutls-dev jobs: include: + # 3.5.2 is interesting because it's the version in ubuntu 16.04, and due to python's + # "provisional feature" rules there are significant differences between patch + # versions for asyncio and typing. + - python: 3.5.2 - python: 3.5 - python: 3.6 - python: pypy3.5-5.10.1 @@ -85,7 +89,7 @@ script: - if [[ $TRAVIS_PYTHON_VERSION != nightly && $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then export RUN_COVERAGE=1; fi - if [[ "$RUN_COVERAGE" == 1 ]]; then export TARGET="-m coverage run $TARGET"; fi # See comments in tox.ini. Disabled on py35 because ResourceWarnings are too noisy there. - - if [[ $TRAVIS_PYTHON_VERSION != '3.5' ]]; then export PYTHONWARNINGS=error,ignore:::site; fi + - if [[ $TRAVIS_PYTHON_VERSION != '3.5'* ]]; then export PYTHONWARNINGS=error,ignore:::site; fi - python -bb $TARGET - python -O $TARGET - LANG=C python $TARGET diff --git a/tornado/concurrent.py b/tornado/concurrent.py index 9d77170c8..3a49940df 100644 --- a/tornado/concurrent.py +++ b/tornado/concurrent.py @@ -172,7 +172,7 @@ def chain_future(a: "Future[_T]", b: "Future[_T]") -> None: def future_set_result_unless_cancelled( - future: Union["futures.Future[_T]", "Future[_T]"], value: _T + future: "Union[futures.Future[_T], Future[_T]]", value: _T ) -> None: """Set the given ``value`` as the `Future`'s result, if not cancelled. @@ -186,7 +186,7 @@ def future_set_result_unless_cancelled( def future_set_exception_unless_cancelled( - future: Union["futures.Future[_T]", "Future[_T]"], exc: BaseException + future: "Union[futures.Future[_T], Future[_T]]", exc: BaseException ) -> None: """Set the given ``exc`` as the `Future`'s exception. @@ -208,7 +208,7 @@ def future_set_exception_unless_cancelled( def future_set_exc_info( - future: Union["futures.Future[_T]", "Future[_T]"], + future: "Union[futures.Future[_T], Future[_T]]", exc_info: Tuple[ Optional[type], Optional[BaseException], Optional[types.TracebackType] ], @@ -246,7 +246,7 @@ def future_add_done_callback( def future_add_done_callback( # noqa: F811 - future: Union["futures.Future[_T]", "Future[_T]"], callback: Callable[..., None] + future: "Union[futures.Future[_T], Future[_T]]", callback: Callable[..., None] ) -> None: """Arrange to call ``callback`` when ``future`` is complete. diff --git a/tornado/gen.py b/tornado/gen.py index 3c1deeae3..51f2a4f03 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -408,8 +408,8 @@ class WaitIterator(object): def multi( children: Union[List[_Yieldable], Dict[Any, _Yieldable]], - quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = (), -) -> Union["Future[List]", "Future[Dict]"]: + quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (), +) -> "Union[Future[List], Future[Dict]]": """Runs multiple asynchronous operations in parallel. ``children`` may either be a list or a dict whose values are @@ -462,8 +462,8 @@ Multi = multi def multi_future( children: Union[List[_Yieldable], Dict[Any, _Yieldable]], - quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = (), -) -> Union["Future[List]", "Future[Dict]"]: + quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (), +) -> "Union[Future[List], Future[Dict]]": """Wait for multiple asynchronous futures in parallel. Since Tornado 6.0, this function is exactly the same as `multi`. @@ -547,7 +547,7 @@ def maybe_future(x: Any) -> Future: def with_timeout( timeout: Union[float, datetime.timedelta], future: _Yieldable, - quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = (), + quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (), ) -> Future: """Wraps a `.Future` (or other yieldable object) in a timeout. diff --git a/tornado/http1connection.py b/tornado/http1connection.py index fd63be627..434f16a09 100644 --- a/tornado/http1connection.py +++ b/tornado/http1connection.py @@ -58,7 +58,7 @@ class _ExceptionLoggingContext(object): def __exit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: types.TracebackType, ) -> None: @@ -563,7 +563,7 @@ class HTTP1Connection(httputil.HTTPConnection): return connection_header == "keep-alive" return False - def _finish_request(self, future: Optional["Future[None]"]) -> None: + def _finish_request(self, future: "Optional[Future[None]]") -> None: self._clear_callbacks() if not self.is_client and self._disconnect_on_finish: self.close() diff --git a/tornado/httpclient.py b/tornado/httpclient.py index 73c9e7b57..33abe2e16 100644 --- a/tornado/httpclient.py +++ b/tornado/httpclient.py @@ -311,7 +311,7 @@ class AsyncHTTPClient(Configurable): @classmethod def configure( - cls, impl: Union[None, str, Type[Configurable]], **kwargs: Any + cls, impl: "Union[None, str, Type[Configurable]]", **kwargs: Any ) -> None: """Configures the `AsyncHTTPClient` subclass to use. diff --git a/tornado/ioloop.py b/tornado/ioloop.py index 0ed1fb61c..02794cb9d 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -165,7 +165,7 @@ class IOLoop(Configurable): @classmethod def configure( - cls, impl: Union[None, str, Type[Configurable]], **kwargs: Any + cls, impl: "Union[None, str, Type[Configurable]]", **kwargs: Any ) -> None: if asyncio is not None: from tornado.platform.asyncio import BaseAsyncIOLoop @@ -664,7 +664,7 @@ class IOLoop(Configurable): def add_future( self, - future: Union["Future[_T]", "concurrent.futures.Future[_T]"], + future: "Union[Future[_T], concurrent.futures.Future[_T]]", callback: Callable[["Future[_T]"], None], ) -> None: """Schedules a callback on the ``IOLoop`` when the given diff --git a/tornado/iostream.py b/tornado/iostream.py index 8c01cb5e9..6ea748a54 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -46,7 +46,6 @@ from typing import ( Optional, Awaitable, Callable, - Type, Pattern, Any, Dict, @@ -56,7 +55,7 @@ from typing import ( from types import TracebackType if typing.TYPE_CHECKING: - from typing import Deque, List # noqa: F401 + from typing import Deque, List, Type # noqa: F401 _IOStreamType = TypeVar("_IOStreamType", bound="IOStream") @@ -585,7 +584,7 @@ class BaseIOStream(object): bool, BaseException, Tuple[ - Optional[Type[BaseException]], + "Optional[Type[BaseException]]", Optional[BaseException], Optional[TracebackType], ], diff --git a/tornado/locks.py b/tornado/locks.py index 8b1a53410..699bb3015 100644 --- a/tornado/locks.py +++ b/tornado/locks.py @@ -275,7 +275,7 @@ class _ReleasingContextManager(object): def __exit__( self, - exc_type: Optional[Type[BaseException]], + exc_type: "Optional[Type[BaseException]]", exc_val: Optional[BaseException], exc_tb: Optional[types.TracebackType], ) -> None: @@ -444,7 +444,7 @@ class Semaphore(_TimeoutGarbageCollector): def __exit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], traceback: Optional[types.TracebackType], ) -> None: @@ -455,7 +455,7 @@ class Semaphore(_TimeoutGarbageCollector): async def __aexit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[types.TracebackType], ) -> None: @@ -552,7 +552,7 @@ class Lock(object): def __exit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[types.TracebackType], ) -> None: @@ -563,7 +563,7 @@ class Lock(object): async def __aexit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[types.TracebackType], ) -> None: diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 6e075aa63..1d82890bc 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -535,7 +535,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): def _handle_exception( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[TracebackType], ) -> bool: diff --git a/tornado/testing.py b/tornado/testing.py index fdfda44ae..ba13a525e 100644 --- a/tornado/testing.py +++ b/tornado/testing.py @@ -33,10 +33,14 @@ from tornado.util import raise_exc_info, basestring_type from tornado.web import Application import typing -from typing import Tuple, Any, Callable, Type, Dict, Union, Coroutine, Optional +from typing import Tuple, Any, Callable, Type, Dict, Union, Optional from types import TracebackType if typing.TYPE_CHECKING: + # Coroutine wasn't added to typing until 3.5.3, so only import it + # when mypy is running and use forward references. + from typing import Coroutine # noqa: F401 + _ExcInfoTuple = Tuple[ Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType] ] @@ -505,20 +509,20 @@ class AsyncHTTPSTestCase(AsyncHTTPTestCase): @typing.overload def gen_test( *, timeout: float = None -) -> Callable[[Callable[..., Union[Generator, Coroutine]]], Callable[..., None]]: +) -> Callable[[Callable[..., Union[Generator, "Coroutine"]]], Callable[..., None]]: pass @typing.overload # noqa: F811 -def gen_test(func: Callable[..., Union[Generator, Coroutine]]) -> Callable[..., None]: +def gen_test(func: Callable[..., Union[Generator, "Coroutine"]]) -> Callable[..., None]: pass def gen_test( # noqa: F811 - func: Callable[..., Union[Generator, Coroutine]] = None, timeout: float = None + func: Callable[..., Union[Generator, "Coroutine"]] = None, timeout: float = None ) -> Union[ Callable[..., None], - Callable[[Callable[..., Union[Generator, Coroutine]]], Callable[..., None]], + Callable[[Callable[..., Union[Generator, "Coroutine"]]], Callable[..., None]], ]: """Testing equivalent of ``@gen.coroutine``, to be applied to test methods. @@ -558,7 +562,7 @@ def gen_test( # noqa: F811 if timeout is None: timeout = get_async_test_timeout() - def wrap(f: Callable[..., Union[Generator, Coroutine]]) -> Callable[..., None]: + def wrap(f: Callable[..., Union[Generator, "Coroutine"]]) -> Callable[..., None]: # Stack up several decorators to allow us to access the generator # object itself. In the innermost wrapper, we capture the generator # and save it in an attribute of self. Next, we run the wrapped @@ -681,7 +685,7 @@ class ExpectLog(logging.Filter): def __exit__( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[TracebackType], ) -> None: diff --git a/tornado/web.py b/tornado/web.py index 6545430e1..6e6e9551a 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -1762,7 +1762,7 @@ class RequestHandler(object): def log_exception( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[TracebackType], ) -> None: diff --git a/tornado/websocket.py b/tornado/websocket.py index f1138e00d..00d08bab2 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -639,7 +639,7 @@ class WebSocketProtocol(abc.ABC): def _run_callback( self, callback: Callable, *args: Any, **kwargs: Any - ) -> Optional["Future[Any]"]: + ) -> "Optional[Future[Any]]": """Runs the given callback with exception handling. If the callback is a coroutine, returns its Future. On error, aborts the @@ -1204,7 +1204,7 @@ class WebSocketProtocol13(WebSocketProtocol): if handled_future is not None: await handled_future - def _handle_message(self, opcode: int, data: bytes) -> Optional["Future[None]"]: + def _handle_message(self, opcode: int, data: bytes) -> "Optional[Future[None]]": """Execute on_message, returning its Future if it is a coroutine.""" if self.client_terminated: return None @@ -1567,7 +1567,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): def log_exception( self, - typ: Optional[Type[BaseException]], + typ: "Optional[Type[BaseException]]", value: Optional[BaseException], tb: Optional[TracebackType], ) -> None: diff --git a/tornado/wsgi.py b/tornado/wsgi.py index 55e0da201..77124aaa3 100644 --- a/tornado/wsgi.py +++ b/tornado/wsgi.py @@ -35,11 +35,12 @@ from tornado import escape from tornado import httputil from tornado.log import access_log -from typing import List, Tuple, Optional, Type, Callable, Any, Dict, Text +from typing import List, Tuple, Optional, Callable, Any, Dict, Text from types import TracebackType import typing if typing.TYPE_CHECKING: + from typing import Type # noqa: F401 from wsgiref.types import WSGIApplication as WSGIAppType # noqa: F401 @@ -99,7 +100,7 @@ class WSGIContainer(object): headers: List[Tuple[str, str]], exc_info: Optional[ Tuple[ - Optional[Type[BaseException]], + "Optional[Type[BaseException]]", Optional[BaseException], Optional[TracebackType], ]