Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Clean up code related to old versions of python #3414

Merged
merged 5 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions tornado/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ def is_coroutine_function(func: Any) -> bool:
class Return(Exception):
"""Special exception to return a value from a `coroutine`.

This exception exists for compatibility with older versions of
Python (before 3.3). In newer code use the ``return`` statement
instead.

If this exception is raised, its value argument is used as the
result of the coroutine::

Expand All @@ -283,14 +287,7 @@ def fetch_json(url):
response = yield AsyncHTTPClient().fetch(url)
raise gen.Return(json_decode(response.body))

In Python 3.3, this exception is no longer necessary: the ``return``
statement can be used directly to return a value (previously
``yield`` and ``return`` with a value could not be combined in the
same function).

By analogy with the return statement, the value argument is optional,
but it is never necessary to ``raise gen.Return()``. The ``return``
statement can be used with no arguments instead.
By analogy with the return statement, the value argument is optional.
"""

def __init__(self, value: Any = None) -> None:
Expand Down Expand Up @@ -337,7 +334,7 @@ class WaitIterator:
arguments were used in the construction of the `WaitIterator`,
``current_index`` will use the corresponding keyword).

On Python 3.5, `WaitIterator` implements the async iterator
`WaitIterator` implements the async iterator
protocol, so it can be used with the ``async for`` statement (note
that in this version the entire iteration is aborted if any value
raises an exception, while the previous example can continue past
Expand Down
9 changes: 1 addition & 8 deletions tornado/iostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -1147,8 +1147,7 @@ class is recommended instead of calling this method directly.

In SSL mode, the ``server_hostname`` parameter will be used
for certificate validation (unless disabled in the
``ssl_options``) and SNI (if supported; requires Python
2.7.9+).
``ssl_options``) and SNI.

Note that it is safe to call `IOStream.write
<BaseIOStream.write>` while the connection is pending, in
Expand Down Expand Up @@ -1381,12 +1380,6 @@ def _do_ssl_handshake(self) -> None:
)
return self.close(exc_info=err)
raise
except ssl.CertificateError as err:
# CertificateError can happen during handshake (hostname
# verification) and should be passed to user. Starting
# in Python 3.7, this error is a subclass of SSLError
# and will be handled by the previous block instead.
return self.close(exc_info=err)
except OSError as err:
# Some port scans (e.g. nmap in -sT mode) have been known
# to cause do_handshake to raise EBADF and ENOTCONN, so make
Expand Down
18 changes: 6 additions & 12 deletions tornado/netutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,6 @@ def initialize(self) -> None: # type: ignore
class ThreadedResolver(ExecutorResolver):
"""Multithreaded non-blocking `Resolver` implementation.

Requires the `concurrent.futures` package to be installed
(available in the standard library since Python 3.2,
installable with ``pip install futures`` in older versions).

The thread pool size can be configured with::

Resolver.configure('tornado.netutil.ThreadedResolver',
Expand Down Expand Up @@ -598,17 +594,15 @@ def ssl_options_to_context(
"""Try to convert an ``ssl_options`` dictionary to an
`~ssl.SSLContext` object.

The ``ssl_options`` dictionary contains keywords to be passed to
``ssl.SSLContext.wrap_socket``. In Python 2.7.9+, `ssl.SSLContext` objects can
be used instead. This function converts the dict form to its
`~ssl.SSLContext` equivalent, and may be used when a component which
accepts both forms needs to upgrade to the `~ssl.SSLContext` version
to use features like SNI or NPN.
The ``ssl_options`` argument may be either an `ssl.SSLContext` object or a dictionary containing
keywords to be passed to ``ssl.SSLContext.wrap_socket``. This function converts the dict form
to its `~ssl.SSLContext` equivalent, and may be used when a component which accepts both forms
needs to upgrade to the `~ssl.SSLContext` version to use features like SNI or ALPN.

.. versionchanged:: 6.2

Added server_side argument. Omitting this argument will
result in a DeprecationWarning on Python 3.10.
Added server_side argument. Omitting this argument will result in a DeprecationWarning on
Python 3.10.

"""
if isinstance(ssl_options, ssl.SSLContext):
Expand Down
17 changes: 6 additions & 11 deletions tornado/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,15 +482,11 @@ def run_parse_callbacks(self) -> None:

def mockable(self) -> "_Mockable":
"""Returns a wrapper around self that is compatible with
`mock.patch <unittest.mock.patch>`.
`unittest.mock.patch`.

The `mock.patch <unittest.mock.patch>` function (included in
the standard library `unittest.mock` package since Python 3.3,
or in the third-party ``mock`` package for older versions of
Python) is incompatible with objects like ``options`` that
override ``__getattr__`` and ``__setattr__``. This function
returns an object that can be used with `mock.patch.object
<unittest.mock.patch.object>` to modify option values::
The `unittest.mock.patch` function is incompatible with objects like ``options`` that
override ``__getattr__`` and ``__setattr__``. This function returns an object that can be
used with `mock.patch.object <unittest.mock.patch.object>` to modify option values::

with mock.patch.object(options.mockable(), 'name', value):
assert options.name == value
Expand Down Expand Up @@ -664,9 +660,8 @@ def _parse_timedelta(self, value: str) -> datetime.timedelta:
num = float(m.group(1))
units = m.group(2) or "seconds"
units = self._TIMEDELTA_ABBREV_DICT.get(units, units)
# This line confuses mypy when setup.py sets python_version=3.6
# https://github.com/python/mypy/issues/9676
sum += datetime.timedelta(**{units: num}) # type: ignore

sum += datetime.timedelta(**{units: num})
start = m.end()
return sum
except Exception:
Expand Down
2 changes: 1 addition & 1 deletion tornado/tcpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def handle_stream(

def _handle_connection(self, connection: socket.socket, address: Any) -> None:
if self.ssl_options is not None:
assert ssl, "Python 2.6+ and OpenSSL required for SSL"
assert ssl, "OpenSSL required for SSL"
try:
connection = ssl_wrap_socket(
connection,
Expand Down
2 changes: 0 additions & 2 deletions tornado/test/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"""Shim to allow python -m tornado.test.

This only works in python 2.7+.
"""

from tornado.test.runtests import all, main
Expand Down
7 changes: 1 addition & 6 deletions tornado/test/gen_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tornado.concurrent import Future
from tornado.log import app_log
from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test
from tornado.test.util import skipOnTravis, skipNotCPython
from tornado.test.util import skipNotCPython
from tornado.web import Application, RequestHandler, HTTPError

from tornado import gen
Expand Down Expand Up @@ -139,7 +139,6 @@ def f():

self.io_loop.run_sync(f)

@skipOnTravis
@gen_test
def test_multi_performance(self):
# Yielding a list used to have quadratic performance; make
Expand Down Expand Up @@ -442,7 +441,6 @@ def f():

@gen_test
def test_async_return_no_value(self):
# Without a return value we don't need python 3.3.
@gen.coroutine
def f():
yield gen.moment
Expand Down Expand Up @@ -573,9 +571,6 @@ def inner(iteration):
self.finished = True

@skipNotCPython
@unittest.skipIf(
(3,) < sys.version_info < (3, 6), "asyncio.Future has reference cycles"
)
def test_coroutine_refcounting(self):
# On CPython, tasks and their arguments should be released immediately
# without waiting for garbage collection.
Expand Down
3 changes: 1 addition & 2 deletions tornado/test/httpclient_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from tornado.log import gen_log, app_log
from tornado import netutil
from tornado.testing import AsyncHTTPTestCase, bind_unused_port, gen_test, ExpectLog
from tornado.test.util import skipOnTravis, ignore_deprecation
from tornado.test.util import ignore_deprecation
from tornado.web import Application, RequestHandler, url
from tornado.httputil import format_timestamp, HTTPHeaders

Expand Down Expand Up @@ -191,7 +191,6 @@ def test_patch_receives_payload(self):
self.assertEqual(response.code, 200)
self.assertEqual(response.body, body)

@skipOnTravis
def test_hello_world(self):
response = self.fetch("/hello")
self.assertEqual(response.code, 200)
Expand Down
3 changes: 1 addition & 2 deletions tornado/test/httpserver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
ExpectLog,
gen_test,
)
from tornado.test.util import skipOnTravis, abstract_base_test
from tornado.test.util import abstract_base_test
from tornado.web import Application, RequestHandler, stream_request_body

from contextlib import closing
Expand Down Expand Up @@ -1267,7 +1267,6 @@ def test_large_headers(self):
self.assertIn(e.response.code, (431, 599))


@skipOnTravis
class IdleTimeoutTest(AsyncHTTPTestCase):
def get_app(self):
return Application([("/", HelloWorldRequestHandler)])
Expand Down
3 changes: 0 additions & 3 deletions tornado/test/ioloop_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from tornado.test.util import (
ignore_deprecation,
skipIfNonUnix,
skipOnTravis,
)
from tornado.concurrent import Future

Expand Down Expand Up @@ -58,7 +57,6 @@ def add_callback(self, callback, *args, **kwargs):
loop.start()
self.assertLess(self.calls, 10)

@skipOnTravis
def test_add_callback_wakeup(self):
# Make sure that add_callback from inside a running IOLoop
# wakes up the IOLoop immediately instead of waiting for a timeout.
Expand All @@ -77,7 +75,6 @@ def schedule_callback():
self.assertAlmostEqual(time.time(), self.start_time, places=2)
self.assertTrue(self.called)

@skipOnTravis
def test_add_callback_wakeup_other_thread(self):
def target():
# sleep a bit to let the ioloop go into its poll loop
Expand Down
5 changes: 0 additions & 5 deletions tornado/test/iostream_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from tornado.test.util import (
skipIfNonUnix,
refusing_port,
skipPypy3V58,
ignore_deprecation,
abstract_base_test,
)
Expand Down Expand Up @@ -828,7 +827,6 @@ def test_read_until_close_with_error(self):
client.close()

@skipIfNonUnix
@skipPypy3V58
@gen_test
def test_inline_read_error(self):
# An error on an inline read is raised without logging (on the
Expand Down Expand Up @@ -862,7 +860,6 @@ def test_inline_read_error(self):
server.close()
client.close()

@skipPypy3V58
@gen_test
def test_async_read_error_logging(self):
# Socket errors on asynchronous reads should be logged (but only
Expand Down Expand Up @@ -1081,8 +1078,6 @@ def test_handshake_fail(self):
@gen_test
def test_check_hostname(self):
# Test that server_hostname parameter to start_tls is being used.
# The check_hostname functionality is only available in python 2.7 and
# up and in python 3.4 and up.
server_future = self.server_start_tls(_server_ssl_options())
with ExpectLog(gen_log, "SSL Error"):
client_future = self.client_start_tls(
Expand Down
3 changes: 0 additions & 3 deletions tornado/test/netutil_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import errno
import os
import signal
import socket
from subprocess import Popen
Expand Down Expand Up @@ -188,8 +187,6 @@ def test_is_valid_ip(self):

class TestPortAllocation(unittest.TestCase):
def test_same_port_allocation(self):
if "TRAVIS" in os.environ:
self.skipTest("dual-stack servers often have port conflicts on travis")
sockets = bind_sockets(0, "localhost")
try:
port = sockets[0].getsockname()[1]
Expand Down
3 changes: 1 addition & 2 deletions tornado/test/options_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from tornado.options import OptionParser, Error
from tornado.util import basestring_type
from tornado.test.util import subTest

import typing

Expand Down Expand Up @@ -277,7 +276,7 @@ def test_error_redefine_underscore(self):
("foo_bar", "foo-bar"),
]
for a, b in tests:
with subTest(self, a=a, b=b):
with self.subTest(self, a=a, b=b):
options = OptionParser()
options.define(a)
with self.assertRaises(Error) as cm:
Expand Down
3 changes: 0 additions & 3 deletions tornado/test/simple_httpclient_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
)
from tornado.test.util import (
abstract_base_test,
skipOnTravis,
skipIfNoIPv6,
refusing_port,
)
Expand Down Expand Up @@ -288,7 +287,6 @@ def test_see_other_redirect(self):
# request is the original request, is a POST still
self.assertEqual("POST", response.request.method)

@skipOnTravis
@gen_test
def test_connect_timeout(self):
timeout = 0.1
Expand Down Expand Up @@ -317,7 +315,6 @@ async def resolve(self, *args, **kwargs):
cleanup_event.set()
yield gen.sleep(0.2)

@skipOnTravis
def test_request_timeout(self):
timeout = 0.1
if os.name == "nt":
Expand Down
3 changes: 0 additions & 3 deletions tornado/test/tcpclient_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# under the License.
from contextlib import closing
import getpass
import os
import socket
import unittest

Expand Down Expand Up @@ -64,8 +63,6 @@ def setUp(self):
self.client = TCPClient()

def start_server(self, family):
if family == socket.AF_UNSPEC and "TRAVIS" in os.environ:
self.skipTest("dual-stack servers often have port conflicts on travis")
self.server = TestTCPServer(family)
return self.server.port

Expand Down
30 changes: 1 addition & 29 deletions tornado/test/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@
os.name != "posix" or sys.platform == "cygwin", "non-unix platform"
)

# travis-ci.org runs our tests in an overworked virtual machine, which makes
# timing-related tests unreliable.
skipOnTravis = unittest.skipIf(
"TRAVIS" in os.environ, "timing tests unreliable on travis"
)

# Set the environment variable NO_NETWORK=1 to disable any tests that
# depend on an external network.
skipIfNoNetwork = unittest.skipIf("NO_NETWORK" in os.environ, "network access disabled")
Expand All @@ -30,16 +24,6 @@
platform.python_implementation() != "CPython", "Not CPython implementation"
)

# Used for tests affected by
# https://bitbucket.org/pypy/pypy/issues/2616/incomplete-error-handling-in
# TODO: remove this after pypy3 5.8 is obsolete.
skipPypy3V58 = unittest.skipIf(
platform.python_implementation() == "PyPy"
and sys.version_info > (3,)
and sys.pypy_version_info < (5, 9), # type: ignore
"pypy3 5.8 has buggy ssl module",
)


def _detect_ipv6():
if not socket.has_ipv6:
Expand Down Expand Up @@ -67,7 +51,7 @@ def refusing_port():
Return value is (cleanup_func, port); the cleanup function
must be called to free the port to be reused.
"""
# On travis-ci, port numbers are reassigned frequently. To avoid
# On travis-ci port numbers are reassigned frequently. To avoid
# collisions with other tests, we use an open client-side socket's
# ephemeral port number to ensure that nothing can listen on that
# port.
Expand Down Expand Up @@ -96,18 +80,6 @@ def exec_test(caller_globals, caller_locals, s):
return local_namespace


def subTest(test, *args, **kwargs):
"""Compatibility shim for unittest.TestCase.subTest.

Usage: ``with tornado.test.util.subTest(self, x=x):``
"""
try:
subTest = test.subTest # py34+
except AttributeError:
subTest = contextlib.contextmanager(lambda *a, **kw: (yield))
return subTest(*args, **kwargs)


@contextlib.contextmanager
def ignore_deprecation():
"""Context manager to ignore deprecation warnings."""
Expand Down
Loading