diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8149f9c561..9f250211a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,7 +168,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.14t'] + python: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.14t', '3.15-dev'] arch: ['x86', 'x64'] lsp: [''] lsp_extract_file: [''] @@ -242,7 +242,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t'] + python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t', '3.15-dev'] check_formatting: ['0'] no_test_requirements: ['0'] extra_name: [''] @@ -320,7 +320,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t'] + python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t', '3.15-dev'] continue-on-error: >- ${{ ( diff --git a/newsfragments/3456.feature.rst b/newsfragments/3456.feature.rst new file mode 100644 index 0000000000..c0024829fb --- /dev/null +++ b/newsfragments/3456.feature.rst @@ -0,0 +1,2 @@ +Support Python 3.15, as of beta 4. Things may still change and so this +support may break in the future. diff --git a/src/trio/_core/_tests/test_thread_cache.py b/src/trio/_core/_tests/test_thread_cache.py index 3abdd59e43..8fdcfba8be 100644 --- a/src/trio/_core/_tests/test_thread_cache.py +++ b/src/trio/_core/_tests/test_thread_cache.py @@ -1,8 +1,10 @@ from __future__ import annotations import os +import sys import threading import time +import warnings from contextlib import contextmanager from queue import Queue from typing import TYPE_CHECKING, NoReturn @@ -210,7 +212,19 @@ def foo() -> None: start_thread_soon(foo, lambda _: done.set()) done.wait() - child_pid = os.fork() + with warnings.catch_warnings(record=True) as emitted: + # unfortunately, we can't use pytest.warns() because the child + # does not warn. + warnings.simplefilter("default") + child_pid = os.fork() + + if child_pid != 0 and sys.version_info >= (3, 12): + # the warning is only emitted in the parent + assert len(emitted) == 1 + assert isinstance(emitted[0].message, DeprecationWarning) + assert "fork() may lead to" in str(emitted[0].message) + else: + assert not emitted # try using it done = threading.Event() diff --git a/src/trio/_tests/test_exports.py b/src/trio/_tests/test_exports.py index 17ca27aa59..f70da41b0d 100644 --- a/src/trio/_tests/test_exports.py +++ b/src/trio/_tests/test_exports.py @@ -426,6 +426,10 @@ def lookup_symbol(symbol: str) -> dict[str, Any]: # type: ignore[misc, explicit extra = {e for e in extra if not e.endswith("AttrsAttributes__")} assert len(extra) == before - 1 + if issubclass(class_, trio.Path) and sys.version_info >= (3, 15): + # needs a typeshed update for https://github.com/python/typeshed/pull/15737 + extra.remove("is_reserved") + if attrs.has(class_): # dynamically created attribute by attrs? missing.remove("__attrs_props__") diff --git a/src/trio/socket.py b/src/trio/socket.py index 64519c3db1..4aee184331 100644 --- a/src/trio/socket.py +++ b/src/trio/socket.py @@ -253,6 +253,33 @@ CAN_ERR_FLAG as CAN_ERR_FLAG, CAN_ERR_MASK as CAN_ERR_MASK, CAN_ISOTP as CAN_ISOTP, + CAN_ISOTP_CHK_PAD_DATA as CAN_ISOTP_CHK_PAD_DATA, + CAN_ISOTP_CHK_PAD_LEN as CAN_ISOTP_CHK_PAD_LEN, + CAN_ISOTP_DEFAULT_EXT_ADDRESS as CAN_ISOTP_DEFAULT_EXT_ADDRESS, + CAN_ISOTP_DEFAULT_FLAGS as CAN_ISOTP_DEFAULT_FLAGS, + CAN_ISOTP_DEFAULT_FRAME_TXTIME as CAN_ISOTP_DEFAULT_FRAME_TXTIME, + CAN_ISOTP_DEFAULT_LL_MTU as CAN_ISOTP_DEFAULT_LL_MTU, + CAN_ISOTP_DEFAULT_LL_TX_DL as CAN_ISOTP_DEFAULT_LL_TX_DL, + CAN_ISOTP_DEFAULT_LL_TX_FLAGS as CAN_ISOTP_DEFAULT_LL_TX_FLAGS, + CAN_ISOTP_DEFAULT_PAD_CONTENT as CAN_ISOTP_DEFAULT_PAD_CONTENT, + CAN_ISOTP_DEFAULT_RECV_BS as CAN_ISOTP_DEFAULT_RECV_BS, + CAN_ISOTP_DEFAULT_RECV_STMIN as CAN_ISOTP_DEFAULT_RECV_STMIN, + CAN_ISOTP_DEFAULT_RECV_WFTMAX as CAN_ISOTP_DEFAULT_RECV_WFTMAX, + CAN_ISOTP_EXTEND_ADDR as CAN_ISOTP_EXTEND_ADDR, + CAN_ISOTP_FORCE_RXSTMIN as CAN_ISOTP_FORCE_RXSTMIN, + CAN_ISOTP_FORCE_TXSTMIN as CAN_ISOTP_FORCE_TXSTMIN, + CAN_ISOTP_HALF_DUPLEX as CAN_ISOTP_HALF_DUPLEX, + CAN_ISOTP_LISTEN_MODE as CAN_ISOTP_LISTEN_MODE, + CAN_ISOTP_LL_OPTS as CAN_ISOTP_LL_OPTS, + CAN_ISOTP_OPTS as CAN_ISOTP_OPTS, + CAN_ISOTP_RECV_FC as CAN_ISOTP_RECV_FC, + CAN_ISOTP_RX_EXT_ADDR as CAN_ISOTP_RX_EXT_ADDR, + CAN_ISOTP_RX_PADDING as CAN_ISOTP_RX_PADDING, + CAN_ISOTP_RX_STMIN as CAN_ISOTP_RX_STMIN, + CAN_ISOTP_SF_BROADCAST as CAN_ISOTP_SF_BROADCAST, + CAN_ISOTP_TX_PADDING as CAN_ISOTP_TX_PADDING, + CAN_ISOTP_TX_STMIN as CAN_ISOTP_TX_STMIN, + CAN_ISOTP_WAIT_TX_DONE as CAN_ISOTP_WAIT_TX_DONE, CAN_J1939 as CAN_J1939, CAN_RAW as CAN_RAW, CAN_RAW_ERR_FILTER as CAN_RAW_ERR_FILTER, @@ -400,6 +427,7 @@ IPV6_CHECKSUM as IPV6_CHECKSUM, IPV6_DONTFRAG as IPV6_DONTFRAG, IPV6_DSTOPTS as IPV6_DSTOPTS, + IPV6_HDRINCL as IPV6_HDRINCL, IPV6_HOPLIMIT as IPV6_HOPLIMIT, IPV6_HOPOPTS as IPV6_HOPOPTS, IPV6_JOIN_GROUP as IPV6_JOIN_GROUP, @@ -575,6 +603,7 @@ SOL_ALG as SOL_ALG, SOL_BLUETOOTH as SOL_BLUETOOTH, SOL_CAN_BASE as SOL_CAN_BASE, + SOL_CAN_ISOTP as SOL_CAN_ISOTP, SOL_CAN_RAW as SOL_CAN_RAW, SOL_HCI as SOL_HCI, SOL_IP as SOL_IP, diff --git a/test-requirements.in b/test-requirements.in index 272da6a34c..11a1bee5a7 100644 --- a/test-requirements.in +++ b/test-requirements.in @@ -1,6 +1,6 @@ # For tests pytest >= 8.4 # for pytest.RaisesGroup -coverage >= 7.2.5 +coverage >= 7.15.0 async_generator >= 1.9 pyright pyOpenSSL >= 22.0.0 # for the ssl + DTLS tests diff --git a/test-requirements.txt b/test-requirements.txt index b20fbc4cdd..02404ee66f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -38,7 +38,7 @@ colorama==0.4.6 ; sys_platform == 'win32' # pylint # pytest # sphinx -coverage==7.14.3 +coverage==7.15.2 # via -r test-requirements.in cryptography==48.0.0 # via