提交 0e43388c 编写于 作者: B Ben Darnell

gen: Deprecate gen.engine

上级 eecf05f0
......@@ -96,6 +96,7 @@ import itertools
import os
import sys
import types
import warnings
from tornado.concurrent import (Future, is_future, chain_future, future_set_exc_info,
future_add_done_callback, future_set_result_unless_cancelled)
......@@ -213,7 +214,14 @@ def engine(func):
they are finished. One notable exception is the
`~tornado.web.RequestHandler` :ref:`HTTP verb methods <verbs>`,
which use ``self.finish()`` in place of a callback argument.
.. deprecated:: 5.1
This decorator will be removed in 6.0. Use `coroutine` or
``async def`` instead.
"""
warnings.warn("gen.engine is deprecated, use gen.coroutine or async def instead",
DeprecationWarning)
func = _make_coroutine_wrapper(func, replace_callback=False)
@functools.wraps(func)
......
......@@ -252,16 +252,17 @@ class TwitterClientLoginHandler(TwitterClientHandler):
class TwitterClientLoginGenEngineHandler(TwitterClientHandler):
@asynchronous
@gen.engine
def get(self):
if self.get_argument("oauth_token", None):
user = yield self.get_authenticated_user()
self.finish(user)
else:
# Old style: with @gen.engine we can ignore the Future from
# authorize_redirect.
self.authorize_redirect()
with ignore_deprecation():
@asynchronous
@gen.engine
def get(self):
if self.get_argument("oauth_token", None):
user = yield self.get_authenticated_user()
self.finish(user)
else:
# Old style: with @gen.engine we can ignore the Future from
# authorize_redirect.
self.authorize_redirect()
class TwitterClientLoginGenCoroutineHandler(TwitterClientHandler):
......@@ -277,21 +278,22 @@ class TwitterClientLoginGenCoroutineHandler(TwitterClientHandler):
class TwitterClientShowUserHandlerLegacy(TwitterClientHandler):
@asynchronous
@gen.engine
def get(self):
# TODO: would be nice to go through the login flow instead of
# cheating with a hard-coded access token.
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
response = yield gen.Task(self.twitter_request,
'/users/show/%s' % self.get_argument('name'),
access_token=dict(key='hjkl', secret='vbnm'))
if response is None:
self.set_status(500)
self.finish('error from twitter request')
else:
self.finish(response)
with ignore_deprecation():
@asynchronous
@gen.engine
def get(self):
# TODO: would be nice to go through the login flow instead of
# cheating with a hard-coded access token.
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
response = yield gen.Task(self.twitter_request,
'/users/show/%s' % self.get_argument('name'),
access_token=dict(key='hjkl', secret='vbnm'))
if response is None:
self.set_status(500)
self.finish('error from twitter request')
else:
self.finish(response)
class TwitterClientShowUserHandler(TwitterClientHandler):
......@@ -310,22 +312,6 @@ class TwitterClientShowUserHandler(TwitterClientHandler):
self.finish(response)
class TwitterClientShowUserFutureHandler(TwitterClientHandler):
@asynchronous
@gen.engine
def get(self):
try:
response = yield self.twitter_request(
'/users/show/%s' % self.get_argument('name'),
access_token=dict(key='hjkl', secret='vbnm'))
except AuthError as e:
self.set_status(500)
self.finish(str(e))
return
assert response is not None
self.finish(response)
class TwitterServerAccessTokenHandler(RequestHandler):
def get(self):
self.write('oauth_token=hjkl&oauth_token_secret=vbnm&screen_name=foo')
......@@ -395,8 +381,6 @@ class AuthTest(AsyncHTTPTestCase):
TwitterClientShowUserHandlerLegacy, dict(test=self)),
('/twitter/client/show_user',
TwitterClientShowUserHandler, dict(test=self)),
('/twitter/client/show_user_future',
TwitterClientShowUserFutureHandler, dict(test=self)),
# simulated servers
('/openid/server/authenticate', OpenIdServerAuthenticateHandler),
......@@ -623,17 +607,6 @@ class AuthTest(AsyncHTTPTestCase):
self.assertEqual(response.code, 500)
self.assertEqual(response.body, b'error from twitter request')
def test_twitter_show_user_future(self):
response = self.fetch('/twitter/client/show_user_future?name=somebody')
response.rethrow()
self.assertEqual(json_decode(response.body),
{'name': 'Somebody', 'screen_name': 'somebody'})
def test_twitter_show_user_future_error(self):
response = self.fetch('/twitter/client/show_user_future?name=error')
self.assertEqual(response.code, 500)
self.assertIn(b'Error response HTTP 500', response.body)
class GoogleLoginHandler(RequestHandler, GoogleOAuth2Mixin):
def initialize(self, test):
......
......@@ -177,11 +177,30 @@ class ReturnFutureTest(AsyncTestCase):
self.assertIs(result, None)
future.result()
@gen_test
def test_future_traceback_legacy(self):
with ignore_deprecation():
@return_future
@gen.engine
def f(callback):
yield gen.Task(self.io_loop.add_callback)
try:
1 / 0
except ZeroDivisionError:
self.expected_frame = traceback.extract_tb(
sys.exc_info()[2], limit=1)[0]
raise
try:
yield f()
self.fail("didn't get expected exception")
except ZeroDivisionError:
tb = traceback.extract_tb(sys.exc_info()[2])
self.assertIn(self.expected_frame, tb)
@gen_test
def test_future_traceback(self):
@return_future
@gen.engine
def f(callback):
@gen.coroutine
def f():
yield gen.Task(self.io_loop.add_callback)
try:
1 / 0
......@@ -311,9 +330,8 @@ class DecoratorCapClient(BaseCapClient):
class GeneratorCapClient(BaseCapClient):
@return_future
@gen.engine
def capitalize(self, request_data, callback):
@gen.coroutine
def capitalize(self, request_data):
logging.debug('capitalize')
stream = IOStream(socket.socket())
logging.debug('connecting')
......@@ -323,7 +341,7 @@ class GeneratorCapClient(BaseCapClient):
data = yield gen.Task(stream.read_until, b'\n')
logging.debug('returning')
stream.close()
callback(self.process_response(data))
raise gen.Return(self.process_response(data))
class ClientTestMixin(object):
......@@ -362,22 +380,18 @@ class ClientTestMixin(object):
self.assertRaisesRegexp(CapError, "already capitalized", future.result)
def test_generator(self):
@gen.engine
@gen.coroutine
def f():
result = yield self.client.capitalize("hello")
self.assertEqual(result, "HELLO")
self.stop()
f()
self.wait()
self.io_loop.run_sync(f)
def test_generator_error(self):
@gen.engine
@gen.coroutine
def f():
with self.assertRaisesRegexp(CapError, "already capitalized"):
yield self.client.capitalize("HELLO")
self.stop()
f()
self.wait()
self.io_loop.run_sync(f)
class ManualClientTest(ClientTestMixin, AsyncTestCase):
......
......@@ -9,6 +9,7 @@ import sys
import textwrap
import time
import weakref
import warnings
from tornado.concurrent import return_future, Future
from tornado.escape import url_escape
......@@ -17,7 +18,7 @@ from tornado.ioloop import IOLoop
from tornado.log import app_log
from tornado import stack_context
from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test
from tornado.test.util import unittest, skipOnTravis, skipBefore33, skipBefore35, skipNotCPython, exec_test # noqa: E501
from tornado.test.util import unittest, skipOnTravis, skipBefore33, skipBefore35, skipNotCPython, exec_test, ignore_deprecation # noqa: E501
from tornado.web import Application, RequestHandler, asynchronous, HTTPError
from tornado import gen
......@@ -35,9 +36,16 @@ except ImportError:
class GenEngineTest(AsyncTestCase):
def setUp(self):
self.warning_catcher = warnings.catch_warnings()
self.warning_catcher.__enter__()
warnings.simplefilter('ignore', DeprecationWarning)
super(GenEngineTest, self).setUp()
self.named_contexts = []
def tearDown(self):
super(GenEngineTest, self).tearDown()
self.warning_catcher.__exit__(None, None, None)
def named_context(self, name):
@contextlib.contextmanager
def context():
......@@ -1085,20 +1093,21 @@ class GenCoroutineTest(AsyncTestCase):
class GenSequenceHandler(RequestHandler):
@asynchronous
@gen.engine
def get(self):
self.io_loop = self.request.connection.stream.io_loop
self.io_loop.add_callback((yield gen.Callback("k1")))
yield gen.Wait("k1")
self.write("1")
self.io_loop.add_callback((yield gen.Callback("k2")))
yield gen.Wait("k2")
self.write("2")
# reuse an old key
self.io_loop.add_callback((yield gen.Callback("k1")))
yield gen.Wait("k1")
self.finish("3")
with ignore_deprecation():
@asynchronous
@gen.engine
def get(self):
self.io_loop = self.request.connection.stream.io_loop
self.io_loop.add_callback((yield gen.Callback("k1")))
yield gen.Wait("k1")
self.write("1")
self.io_loop.add_callback((yield gen.Callback("k2")))
yield gen.Wait("k2")
self.write("2")
# reuse an old key
self.io_loop.add_callback((yield gen.Callback("k1")))
yield gen.Wait("k1")
self.finish("3")
class GenCoroutineSequenceHandler(RequestHandler):
......@@ -1136,8 +1145,7 @@ class GenCoroutineUnfinishedSequenceHandler(RequestHandler):
class GenTaskHandler(RequestHandler):
@asynchronous
@gen.engine
@gen.coroutine
def get(self):
client = AsyncHTTPClient()
response = yield gen.Task(client.fetch, self.get_argument('url'))
......@@ -1146,13 +1154,14 @@ class GenTaskHandler(RequestHandler):
class GenExceptionHandler(RequestHandler):
@asynchronous
@gen.engine
def get(self):
# This test depends on the order of the two decorators.
io_loop = self.request.connection.stream.io_loop
yield gen.Task(io_loop.add_callback)
raise Exception("oops")
with ignore_deprecation():
@asynchronous
@gen.engine
def get(self):
# This test depends on the order of the two decorators.
io_loop = self.request.connection.stream.io_loop
yield gen.Task(io_loop.add_callback)
raise Exception("oops")
class GenCoroutineExceptionHandler(RequestHandler):
......@@ -1165,8 +1174,7 @@ class GenCoroutineExceptionHandler(RequestHandler):
class GenYieldExceptionHandler(RequestHandler):
@asynchronous
@gen.engine
@gen.coroutine
def get(self):
io_loop = self.request.connection.stream.io_loop
# Test the interaction of the two stack_contexts.
......
......@@ -6,7 +6,7 @@ from tornado.log import app_log
from tornado.stack_context import (StackContext, wrap, NullContext, StackContextInconsistentError,
ExceptionStackContext, run_with_stack_context, _state)
from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test
from tornado.test.util import unittest
from tornado.test.util import unittest, ignore_deprecation
from tornado.web import asynchronous, Application, RequestHandler
import contextlib
import functools
......@@ -215,15 +215,16 @@ class StackContextTest(AsyncTestCase):
self.wait()
def test_yield_in_with(self):
@gen.engine
def f():
self.callback = yield gen.Callback('a')
with StackContext(functools.partial(self.context, 'c1')):
# This yield is a problem: the generator will be suspended
# and the StackContext's __exit__ is not called yet, so
# the context will be left on _state.contexts for anything
# that runs before the yield resolves.
yield gen.Wait('a')
with ignore_deprecation():
@gen.engine
def f():
self.callback = yield gen.Callback('a')
with StackContext(functools.partial(self.context, 'c1')):
# This yield is a problem: the generator will be suspended
# and the StackContext's __exit__ is not called yet, so
# the context will be left on _state.contexts for anything
# that runs before the yield resolves.
yield gen.Wait('a')
with self.assertRaises(StackContextInconsistentError):
f()
......@@ -244,14 +245,15 @@ class StackContextTest(AsyncTestCase):
def test_yield_in_with_exception_stack_context(self):
# As above, but with ExceptionStackContext instead of StackContext.
@gen.engine
def f():
with ExceptionStackContext(lambda t, v, tb: False):
yield gen.Task(self.io_loop.add_callback)
with self.assertRaises(StackContextInconsistentError):
f()
self.wait()
with ignore_deprecation():
@gen.engine
def f():
with ExceptionStackContext(lambda t, v, tb: False):
yield gen.Task(self.io_loop.add_callback)
with self.assertRaises(StackContextInconsistentError):
f()
self.wait()
@gen_test
def test_yield_outside_with_exception_stack_context(self):
......
......@@ -582,8 +582,7 @@ class RedirectHandler(RequestHandler):
class EmptyFlushCallbackHandler(RequestHandler):
@asynchronous
@gen.engine
@gen.coroutine
def get(self):
# Ensure that the flush callback is run whether or not there
# was any output. The gen.Task and direct yield forms are
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册