Skip to content

Commit cb48061

Browse files
committed
Merge branch 'master' into exceptiongroup
2 parents f9f56f1 + 39d01b2 commit cb48061

15 files changed

+22
-221
lines changed

ci.sh

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,6 @@ python -m pip --version
7272
python setup.py sdist --formats=zip
7373
python -m pip install dist/*.zip
7474

75-
if python -c 'import sys; sys.exit(sys.version_info >= (3, 7))'; then
76-
# Python < 3.7, select last ipython with 3.6 support
77-
# macOS requires the suffix for --in-place or you get an undefined label error
78-
sed -i'.bak' 's/ipython==[^ ]*/ipython==7.16.1/' test-requirements.txt
79-
sed -i'.bak' 's/traitlets==[^ ]*/traitlets==4.3.3/' test-requirements.txt
80-
git diff test-requirements.txt
81-
fi
82-
8375
if [ "$CHECK_FORMATTING" = "1" ]; then
8476
python -m pip install -r test-requirements.txt
8577
source check.sh

docs/source/reference-io.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ other constants and functions in the :mod:`ssl` module.
237237

238238
.. warning:: Avoid instantiating :class:`ssl.SSLContext` directly.
239239
A newly constructed :class:`~ssl.SSLContext` has less secure
240-
defaults than one returned by :func:`ssl.create_default_context`,
241-
dramatically so before Python 3.6.
240+
defaults than one returned by :func:`ssl.create_default_context`.
242241

243242
Instead of using :meth:`ssl.SSLContext.wrap_socket`, you
244243
create a :class:`SSLStream`:
@@ -722,7 +721,7 @@ subprocess`` in order to access constants such as ``PIPE`` or
722721

723722
Currently, Trio always uses unbuffered byte streams for communicating
724723
with a process, so it does not support the ``encoding``, ``errors``,
725-
``universal_newlines`` (alias ``text`` in 3.7+), and ``bufsize``
724+
``universal_newlines`` (alias ``text``), and ``bufsize``
726725
options.
727726

728727

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
Vital statistics:
4545
4646
* Supported environments: Linux, macOS, or Windows running some kind of Python
47-
3.6-or-better (either CPython or PyPy3 is fine). \\*BSD and illumos likely
47+
3.7-or-better (either CPython or PyPy3 is fine). \\*BSD and illumos likely
4848
work too, but are not tested.
4949
5050
* Install: ``python3 -m pip install -U trio`` (or on Windows, maybe

test-requirements.in

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,9 @@ typing-extensions; implementation_name == "cpython"
2323

2424
# Trio's own dependencies
2525
cffi; os_name == "nt"
26-
contextvars; python_version < "3.7"
2726
attrs >= 19.2.0
2827
sortedcontainers
2928
async_generator >= 1.9
3029
idna
3130
outcome
3231
sniffio
33-
34-
# Required by contextvars, but harmless to install everywhere.
35-
# dependabot drops the contextvars dependency because it runs
36-
# on 3.7.
37-
immutables >= 0.6

trio/_core/_entry_queue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ class EntryQueue:
1515
# not signal-safe. deque is implemented in C, so each operation is atomic
1616
# WRT threads (and this is guaranteed in the docs), AND each operation is
1717
# atomic WRT signal delivery (signal handlers can run on either side, but
18-
# not *during* a deque operation). dict makes similar guarantees - and on
19-
# CPython 3.6 and PyPy, it's even ordered!
18+
# not *during* a deque operation). dict makes similar guarantees - and
19+
# it's even ordered!
2020
queue = attr.ib(factory=deque)
2121
idempotent_queue = attr.ib(factory=dict)
2222

trio/_core/_run.py

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
# coding: utf-8
2-
31
import functools
42
import itertools
5-
import logging
6-
import os
73
import random
84
import select
95
import sys
106
import threading
117
from collections import deque
12-
import collections.abc
138
from contextlib import contextmanager
149
import warnings
15-
import weakref
1610
import enum
1711

1812
from contextvars import copy_context
@@ -46,7 +40,6 @@
4640
from ._thread_cache import start_thread_soon
4741
from ._instrumentation import Instruments
4842
from .. import _core
49-
from .._deprecate import warn_deprecated
5043
from .._util import Final, NoPublicConstructor, coroutine_or_error
5144

5245
if sys.version_info < (3, 11):
@@ -72,13 +65,8 @@ def _public(fn):
7265
_r = random.Random()
7366

7467

75-
# On 3.7+, Context.run() is implemented in C and doesn't show up in
76-
# tracebacks. On 3.6, we use the contextvars backport, which is
77-
# currently implemented in Python and adds 1 frame to tracebacks. So this
78-
# function is a super-overkill version of "0 if sys.version_info >= (3, 7)
79-
# else 1". But if Context.run ever changes, we'll be ready!
80-
#
81-
# This can all be removed once we drop support for 3.6.
68+
# On CPython, Context.run() is implemented in C and doesn't show up in
69+
# tracebacks. On PyPy, it is implemented in Python and adds 1 frame to tracebacks.
8270
def _count_context_run_tb_frames():
8371
def function_with_unique_name_xyzzy():
8472
1 / 0
@@ -2202,7 +2190,7 @@ def unrolled_run(runner, async_fn, args, host_uses_signal_set_wakeup_fd=False):
22022190
try:
22032191
# We used to unwrap the Outcome object here and send/throw
22042192
# its contents in directly, but it turns out that .throw()
2205-
# is buggy, at least on CPython 3.6:
2193+
# is buggy, at least before CPython 3.9:
22062194
# https://bugs.python.org/issue29587
22072195
# https://bugs.python.org/issue29590
22082196
# So now we send in the Outcome object and unwrap it on the

trio/_core/_wakeup_socketpair.py

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
11
import socket
2-
import sys
32
import signal
43
import warnings
54

65
from .. import _core
76
from .._util import is_main_thread
87

98

10-
def _has_warn_on_full_buffer():
11-
if "__pypy__" not in sys.builtin_module_names:
12-
# CPython has warn_on_full_buffer. Don't need to inspect.
13-
# Also, CPython doesn't support inspecting built-in functions.
14-
return True
15-
16-
import inspect
17-
18-
args_spec = inspect.getfullargspec(signal.set_wakeup_fd)
19-
return "warn_on_full_buffer" in args_spec.kwonlyargs
20-
21-
22-
HAVE_WARN_ON_FULL_BUFFER = _has_warn_on_full_buffer()
23-
24-
259
class WakeupSocketpair:
2610
def __init__(self):
2711
self.wakeup_sock, self.write_sock = socket.socketpair()
@@ -35,13 +19,8 @@ def __init__(self):
3519
# Windows 10: 525347
3620
# Windows you're weird. (And on Windows setting SNDBUF to 0 makes send
3721
# blocking, even on non-blocking sockets, so don't do that.)
38-
#
39-
# But, if we're on an old Python and can't control the signal module's
40-
# warn-on-full-buffer behavior, then we need to leave things alone, so
41-
# the signal module won't spam the console with spurious warnings.
42-
if HAVE_WARN_ON_FULL_BUFFER:
43-
self.wakeup_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1)
44-
self.write_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
22+
self.wakeup_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1)
23+
self.write_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
4524
# On Windows this is a TCP socket so this might matter. On other
4625
# platforms this fails b/c AF_UNIX sockets aren't actually TCP.
4726
try:
@@ -72,10 +51,7 @@ def wakeup_on_signals(self):
7251
if not is_main_thread():
7352
return
7453
fd = self.write_sock.fileno()
75-
if HAVE_WARN_ON_FULL_BUFFER:
76-
self.old_wakeup_fd = signal.set_wakeup_fd(fd, warn_on_full_buffer=False)
77-
else:
78-
self.old_wakeup_fd = signal.set_wakeup_fd(fd)
54+
self.old_wakeup_fd = signal.set_wakeup_fd(fd, warn_on_full_buffer=False)
7955
if self.old_wakeup_fd != -1:
8056
warnings.warn(
8157
RuntimeWarning(

trio/_core/tests/test_ki.py

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -490,115 +490,3 @@ async def inner():
490490
_core.run(inner)
491491
finally:
492492
threading._active[thread.ident] = original
493-
494-
495-
# For details on why this test is non-trivial, see:
496-
# https://github.com/python-trio/trio/issues/42
497-
# https://github.com/python-trio/trio/issues/109
498-
@slow
499-
def test_ki_wakes_us_up():
500-
assert is_main_thread()
501-
502-
# This test is flaky due to a race condition on Windows; see:
503-
# https://github.com/python-trio/trio/issues/119
504-
# https://bugs.python.org/issue30038
505-
# I think the only fix is to wait for fixed CPython to be released, so in
506-
# the mean time, on affected versions we send two signals (equivalent to
507-
# hitting control-C twice). This works because the problem is that the C
508-
# level signal handler does
509-
#
510-
# write-to-fd -> set-flags
511-
#
512-
# and we need
513-
#
514-
# set-flags -> write-to-fd
515-
#
516-
# so running the C level signal handler twice does
517-
#
518-
# write-to-fd -> set-flags -> write-to-fd -> set-flags
519-
#
520-
# which contains the desired sequence.
521-
#
522-
# Affected version of CPython include 3.6.1 and earlier.
523-
# It's fixed in 3.6.2 and 3.7+
524-
#
525-
# PyPy was never affected.
526-
#
527-
# The problem technically can occur on Unix as well, if a signal is
528-
# delivered to a non-main thread, though we haven't observed this in
529-
# practice.
530-
#
531-
# There's also this theoretical problem, but hopefully it won't actually
532-
# bite us in practice:
533-
# https://bugs.python.org/issue31119
534-
# https://bitbucket.org/pypy/pypy/issues/2623
535-
import platform
536-
537-
# lock is only needed to avoid an annoying race condition where the
538-
# *second* ki_self() call arrives *after* the first one woke us up and its
539-
# KeyboardInterrupt was caught, and then generates a second
540-
# KeyboardInterrupt that aborts the test run. The kill_soon thread holds
541-
# the lock while doing the calls to ki_self, which means that it holds it
542-
# while the C-level signal handler is running. Then in the main thread,
543-
# when we're woken up we know that ki_self() has been run at least once;
544-
# if we then take the lock it guaranteeds that ki_self() has been run
545-
# twice, so if a second KeyboardInterrupt is going to arrive it should
546-
# arrive by the time we've acquired the lock. This lets us force it to
547-
# happen inside the pytest.raises block.
548-
#
549-
# It will be very nice when the buggy_wakeup_fd bug is fixed.
550-
lock = threading.Lock()
551-
552-
def kill_soon():
553-
# We want the signal to be raised after the main thread has entered
554-
# the IO manager blocking primitive. There really is no way to
555-
# deterministically interlock with that, so we have to use sleep and
556-
# hope it's long enough.
557-
time.sleep(1.1)
558-
with lock:
559-
print("thread doing ki_self()")
560-
ki_self()
561-
562-
async def main():
563-
thread = threading.Thread(target=kill_soon)
564-
print("Starting thread")
565-
thread.start()
566-
try:
567-
with pytest.raises(KeyboardInterrupt):
568-
# To limit the damage on CI if this does get broken (as
569-
# compared to sleep_forever())
570-
print("Going to sleep")
571-
try:
572-
await sleep(20)
573-
print("Woke without raising?!") # pragma: no cover
574-
# The only purpose of this finally: block is to soak up the
575-
# second KeyboardInterrupt that might arrive on
576-
# buggy_wakeup_fd platforms. So it might get aborted at any
577-
# moment randomly on some runs, so pragma: no cover avoids
578-
# coverage flapping:
579-
finally: # pragma: no cover
580-
print("waiting for lock")
581-
with lock:
582-
print("got lock")
583-
# And then we want to force a PyErr_CheckSignals. Which is
584-
# not so easy on Windows. Weird kluge: builtin_repr calls
585-
# PyObject_Repr, which does an unconditional
586-
# PyErr_CheckSignals for some reason.
587-
print(repr(None))
588-
# And finally, it's possible that the signal was delivered
589-
# but at a moment when we had KI protection enabled, so we
590-
# need to execute a checkpoint to ensure it's delivered
591-
# before we exit main().
592-
await _core.checkpoint()
593-
finally:
594-
print("joining thread", sys.exc_info())
595-
thread.join()
596-
597-
start = time.perf_counter()
598-
try:
599-
_core.run(main)
600-
finally:
601-
end = time.perf_counter()
602-
print("duration", end - start)
603-
print("sys.exc_info", sys.exc_info())
604-
assert 1.0 <= (end - start) < 2

trio/_core/tests/test_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ async def child2():
10601060
]
10611061

10621062

1063-
# At least as of CPython 3.6, using .throw() to raise an exception inside a
1063+
# Before CPython 3.9, using .throw() to raise an exception inside a
10641064
# coroutine/generator causes the original exc_info state to be lost, so things
10651065
# like re-raising and exception chaining are broken.
10661066
#

trio/_highlevel_ssl_helpers.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ async def open_ssl_over_tcp_stream(
1919
*,
2020
https_compatible=False,
2121
ssl_context=None,
22-
# No trailing comma b/c bpo-9232 (fixed in py36)
2322
happy_eyeballs_delay=DEFAULT_DELAY,
2423
):
2524
"""Make a TLS-encrypted Connection to the given host and port over TCP.

trio/_socket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def __aexit__(self, etype, value, tb):
5050
try:
5151
from socket import IPPROTO_IPV6
5252
except ImportError:
53-
# As of at least 3.6, python on Windows is missing IPPROTO_IPV6
53+
# Before Python 3.8, Windows is missing IPPROTO_IPV6
5454
# https://bugs.python.org/issue29515
5555
if sys.platform == "win32": # pragma: no branch
5656
IPPROTO_IPV6 = 41

trio/_util.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,7 @@ def __getitem__(self, _):
266266
return self
267267

268268

269-
# If a new class inherits from any ABC, then the new class's metaclass has to
270-
# inherit from ABCMeta. If a new class inherits from typing.Generic, and
271-
# you're using Python 3.6, then the new class's metaclass has to
272-
# inherit from typing.GenericMeta. Some of the classes that want to use Final
273-
# or NoPublicConstructor inherit from ABCs and generics, so Final has to
274-
# inherit from these metaclasses. Fortunately, GenericMeta inherits from
275-
# ABCMeta, so inheriting from GenericMeta alone is sufficient (when it
276-
# exists at all).
277-
if not t.TYPE_CHECKING and hasattr(t, "GenericMeta"):
278-
BaseMeta = t.GenericMeta
279-
else:
280-
BaseMeta = ABCMeta
281-
282-
283-
class Final(BaseMeta):
269+
class Final(ABCMeta):
284270
"""Metaclass that enforces a class to be final (i.e., subclass not allowed).
285271
286272
If a class uses this metaclass like this::

trio/socket.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,6 @@
188188
# get names used by Trio that we define on our own
189189
from ._socket import IPPROTO_IPV6
190190

191-
# Not defined in all python versions and platforms but sometimes needed
192-
if not _t.TYPE_CHECKING:
193-
try:
194-
TCP_NOTSENT_LOWAT
195-
except NameError:
196-
# Hopefully will show up in 3.7:
197-
# https://github.com/python/cpython/pull/477
198-
if sys.platform == "darwin":
199-
TCP_NOTSENT_LOWAT = 0x201
200-
elif sys.platform == "linux":
201-
TCP_NOTSENT_LOWAT = 25
202-
203191
if _t.TYPE_CHECKING:
204192
IP_BIND_ADDRESS_NO_PORT: int
205193
else:

trio/tests/test_ssl.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,14 @@
5959

6060
TRIO_TEST_1_CERT.configure_cert(SERVER_CTX)
6161

62+
6263
# TLS 1.3 has a lot of changes from previous versions. So we want to run tests
6364
# with both TLS 1.3, and TLS 1.2.
64-
if hasattr(ssl, "OP_NO_TLSv1_3"):
65-
# "tls13" means that we're willing to negotiate TLS 1.3. Usually that's
66-
# what will happen, but the renegotiation tests explicitly force a
67-
# downgrade on the server side. "tls12" means we refuse to negotiate TLS
68-
# 1.3, so we'll almost certainly use TLS 1.2.
69-
client_ctx_params = ["tls13", "tls12"]
70-
else:
71-
# We can't control whether we use TLS 1.3, so we just have to accept
72-
# whatever openssl wants to use. This might be TLS 1.2 (if openssl is
73-
# old), or it might be TLS 1.3 (if openssl is new, but our python version
74-
# is too old to expose the configuration knobs).
75-
client_ctx_params = ["default"]
76-
77-
78-
@pytest.fixture(scope="module", params=client_ctx_params)
65+
# "tls13" means that we're willing to negotiate TLS 1.3. Usually that's
66+
# what will happen, but the renegotiation tests explicitly force a
67+
# downgrade on the server side. "tls12" means we refuse to negotiate TLS
68+
# 1.3, so we'll almost certainly use TLS 1.2.
69+
@pytest.fixture(scope="module", params=["tls13", "tls12"])
7970
def client_ctx(request):
8071
ctx = ssl.create_default_context()
8172

0 commit comments

Comments
 (0)