From: Ben Darnell Date: Sun, 18 Mar 2018 20:57:49 +0000 (-0400) Subject: concurrent,auth: Add deprecation warnings to concurrent.return_future X-Git-Tag: v5.1.0b1~38^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=089b5e7ed7fccfa3f54c8d861060ba0c78453a51;p=thirdparty%2Ftornado.git concurrent,auth: Add deprecation warnings to concurrent.return_future --- diff --git a/tornado/auth.py b/tornado/auth.py index bc14548aa..c9cec8d91 100644 --- a/tornado/auth.py +++ b/tornado/auth.py @@ -168,6 +168,11 @@ class OpenIdMixin(object): not strictly necessary as this method is synchronous, but they are supplied for consistency with `OAuthMixin.authorize_redirect`. + + .. deprecated:: 5.1 + + The ``callback`` argument and returned awaitable will be removed + in Tornado 6.0; this will be an ordinary synchronous function. """ callback_uri = callback_uri or self.request.uri args = self._openid_args(callback_uri, ax_attrs=ax_attrs) @@ -349,16 +354,18 @@ class OAuthMixin(object): subsequently used (and cleared) in `get_authenticated_user` for security purposes. - Note that this method is asynchronous, although it calls - `.RequestHandler.finish` for you so it may not be necessary - to pass a callback or use the `.Future` it returns. However, - if this method is called from a function decorated with - `.gen.coroutine`, you must call it with ``yield`` to keep the - response from being closed prematurely. + This method is asynchronous and must be called with ``await`` + or ``yield``. It calls `.RequestHandler.finish` for you so you + should not write any other response after it returns. .. versionchanged:: 3.1 Now returns a `.Future` and takes an optional callback, for compatibility with `.gen.coroutine`. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False): raise Exception("This service does not support oauth_callback") @@ -604,6 +611,11 @@ class OAuth2Mixin(object): not strictly necessary as this method is synchronous, but they are supplied for consistency with `OAuthMixin.authorize_redirect`. + + .. deprecated:: 5.1 + + The ``callback`` argument and returned awaitable will be removed + in Tornado 6.0; this will be an ordinary synchronous function. """ args = { "redirect_uri": redirect_uri, @@ -755,6 +767,11 @@ class TwitterMixin(OAuthMixin): .. versionchanged:: 3.1 Now returns a `.Future` and takes an optional callback, for compatibility with `.gen.coroutine`. + + .. deprecated:: 5.1 + + The ``callback`` argument is deprecated and will be removed in 6.0. + Use the returned awaitable object instead. """ http = self.get_auth_http_client() http.fetch(self._oauth_request_token_url(callback_uri=callback_uri), diff --git a/tornado/concurrent.py b/tornado/concurrent.py index aa38bb996..2245c0bd4 100644 --- a/tornado/concurrent.py +++ b/tornado/concurrent.py @@ -33,6 +33,7 @@ import platform import textwrap import traceback import sys +import warnings from tornado.log import app_log from tornado.stack_context import ExceptionStackContext, wrap @@ -496,6 +497,15 @@ def return_future(f): same function, provided ``@return_future`` appears first. However, consider using ``@gen.coroutine`` instead of this combination. + .. versionchanged:: 5.1 + + Now raises a `.DeprecationWarning` if a callback argument is passed to + the decorated function and deprecation warnings are enabled. + + .. deprecated:: 5.1 + + New code should use coroutines directly instead of wrapping + callback-based code with this decorator. """ replacer = ArgReplacer(f, 'callback') @@ -533,6 +543,9 @@ def return_future(f): # immediate exception, and again when the future resolves and # the callback triggers its exception by calling future.result()). if callback is not None: + warnings.warn("callback arguments are deprecated, use the returned Future instead", + DeprecationWarning) + def run_callback(future): result = future.result() if result is _NO_RESULT: diff --git a/tornado/test/concurrent_test.py b/tornado/test/concurrent_test.py index b00b80ddf..dca66547e 100644 --- a/tornado/test/concurrent_test.py +++ b/tornado/test/concurrent_test.py @@ -31,7 +31,7 @@ from tornado.log import app_log from tornado import stack_context from tornado.tcpserver import TCPServer from tornado.testing import AsyncTestCase, ExpectLog, bind_unused_port, gen_test -from tornado.test.util import unittest, skipBefore35, exec_test +from tornado.test.util import unittest, skipBefore35, exec_test, ignore_deprecation try: @@ -99,7 +99,8 @@ class ReturnFutureTest(AsyncTestCase): self.return_value(callback=self.stop) def test_callback_kw(self): - future = self.sync_future(callback=self.stop) + with ignore_deprecation(): + future = self.sync_future(callback=self.stop) result = self.wait() self.assertEqual(result, 42) self.assertEqual(future.result(), 42) @@ -107,7 +108,8 @@ class ReturnFutureTest(AsyncTestCase): def test_callback_positional(self): # When the callback is passed in positionally, future_wrap shouldn't # add another callback in the kwargs. - future = self.sync_future(self.stop) + with ignore_deprecation(): + future = self.sync_future(self.stop) result = self.wait() self.assertEqual(result, 42) self.assertEqual(future.result(), 42) @@ -154,20 +156,23 @@ class ReturnFutureTest(AsyncTestCase): self.assertEqual(future.result(), 42) def test_error_in_callback(self): - self.sync_future(callback=lambda future: 1 / 0) + with ignore_deprecation(): + self.sync_future(callback=lambda future: 1 / 0) # The exception gets caught by our StackContext and will be re-raised # when we wait. self.assertRaises(ZeroDivisionError, self.wait) def test_no_result_future(self): - future = self.no_result_future(self.stop) + with ignore_deprecation(): + future = self.no_result_future(self.stop) result = self.wait() self.assertIs(result, None) # result of this future is undefined, but not an error future.result() def test_no_result_future_callback(self): - future = self.no_result_future(callback=lambda: self.stop()) + with ignore_deprecation(): + future = self.no_result_future(callback=lambda: self.stop()) result = self.wait() self.assertIs(result, None) future.result() @@ -334,12 +339,14 @@ class ClientTestMixin(object): super(ClientTestMixin, self).tearDown() # type: ignore def test_callback(self): - self.client.capitalize("hello", callback=self.stop) + with ignore_deprecation(): + self.client.capitalize("hello", callback=self.stop) result = self.wait() self.assertEqual(result, "HELLO") def test_callback_error(self): - self.client.capitalize("HELLO", callback=self.stop) + with ignore_deprecation(): + self.client.capitalize("HELLO", callback=self.stop) self.assertRaisesRegexp(CapError, "already capitalized", self.wait) def test_future(self): diff --git a/tornado/test/util.py b/tornado/test/util.py index 63a9762f1..7c9db84a6 100644 --- a/tornado/test/util.py +++ b/tornado/test/util.py @@ -6,6 +6,7 @@ import platform import socket import sys import textwrap +import warnings from tornado.testing import bind_unused_port @@ -107,3 +108,11 @@ def subTest(test, *args, **kwargs): except AttributeError: subTest = contextlib.contextmanager(lambda *a, **kw: (yield)) return subTest(*args, **kwargs) + + +@contextlib.contextmanager +def ignore_deprecation(): + """Context manager to ignore deprecation warnings.""" + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + yield diff --git a/tornado/web.py b/tornado/web.py index a1d2aa5f0..8a9a80534 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -246,7 +246,7 @@ class RequestHandler(object): of the request method. Asynchronous support: Decorate this method with `.gen.coroutine` - or `.return_future` to make it asynchronous (the + or use ``async def`` to make it asynchronous (the `asynchronous` decorator cannot be used on `prepare`). If this method returns a `.Future` execution will not proceed until the `.Future` is done.