diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c9640ac2..c79de05a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -100,22 +100,22 @@ jobs: python_version: '3.13' - tox_env: py313-m_ans-ans8 python_version: '3.13' - - tox_env: py313-m_ans-ans9 - python_version: '3.13' - - tox_env: py313-m_ans-ans10 - python_version: '3.13' - - tox_env: py313-m_ans-ans11 - python_version: '3.13' - - tox_env: py313-m_ans-ans12 - python_version: '3.13' - - - tox_env: py313-m_ans-ans11-s_lin - python_version: '3.13' - - tox_env: py313-m_ans-ans12-s_lin - python_version: '3.13' - - - tox_env: py313-m_mtg - python_version: '3.13' + - tox_env: py314-m_ans-ans9 + python_version: '3.14.0-rc.3' + - tox_env: py314-m_ans-ans10 + python_version: '3.14.0-rc.3' + - tox_env: py314-m_ans-ans11 + python_version: '3.14.0-rc.3' + - tox_env: py314-m_ans-ans12 + python_version: '3.14.0-rc.3' + + - tox_env: py314-m_ans-ans11-s_lin + python_version: '3.14.0-rc.3' + - tox_env: py314-m_ans-ans12-s_lin + python_version: '3.14.0-rc.3' + + - tox_env: py314-m_mtg + python_version: '3.14.0-rc.3' steps: - uses: actions/checkout@v4 @@ -161,14 +161,19 @@ jobs: fail-fast: false matrix: include: - - tox_env: py313-m_lcl-ans11 + - tox_env: py314-m_lcl-ans11 + python_version: '3.14.0-rc.3' sshpass_version: "1.10" - - tox_env: py313-m_lcl-ans11-s_lin + - tox_env: py314-m_lcl-ans11-s_lin + python_version: '3.14.0-rc.3' sshpass_version: "1.10" - - tox_env: py313-m_lcl-ans12 - - tox_env: py313-m_lcl-ans12-s_lin + - tox_env: py314-m_lcl-ans12 + python_version: '3.14.0-rc.3' + - tox_env: py314-m_lcl-ans12-s_lin + python_version: '3.14.0-rc.3' - - tox_env: py313-m_mtg + - tox_env: py314-m_mtg + python_version: '3.14.0-rc.3' steps: - uses: actions/checkout@v4 diff --git a/docs/ansible_detailed.rst b/docs/ansible_detailed.rst index 06aa4955..e692c43a 100644 --- a/docs/ansible_detailed.rst +++ b/docs/ansible_detailed.rst @@ -138,11 +138,11 @@ Noteworthy Differences | 8 | 3.9 - 3.13 | +-----------------+-----------------+ | 9 | | - +-----------------+ 3.10 - 3.13 | + +-----------------+ 3.10 - 3.14 | | 10 | | +-----------------+-----------------+ | 11 | | - +-----------------+ 3.11 - 3.13+ | + +-----------------+ 3.11 - 3.14 | | 12 | | +-----------------+-----------------+ diff --git a/docs/changelog.rst b/docs/changelog.rst index b2ba15ee..fc822498 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -21,6 +21,7 @@ To avail of fixes in an unreleased version, please download a ZIP file In progress (unreleased) ------------------------ +* :gh:issue:`1287` Python 3.14 support * :gh:issue:`1287` tests: Bump dependencies diff --git a/mitogen/imports/__init__.py b/mitogen/imports/__init__.py index ecbdb795..a54e9b01 100644 --- a/mitogen/imports/__init__.py +++ b/mitogen/imports/__init__.py @@ -4,7 +4,9 @@ import sys -if sys.version_info >= (3, 6): +if sys.version_info >= (3, 14): + from mitogen.imports._py314 import _code_imports +elif sys.version_info >= (3, 6): from mitogen.imports._py36 import _code_imports elif sys.version_info >= (2, 5): from mitogen.imports._py2 import _code_imports_py25 as _code_imports diff --git a/mitogen/imports/_py314.py b/mitogen/imports/_py314.py new file mode 100644 index 00000000..7fa69cff --- /dev/null +++ b/mitogen/imports/_py314.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2025 Mitogen authors +# SPDX-License-Identifier: MIT +# !mitogen: minify_safe + +import opcode + +IMPORT_NAME = opcode.opmap['IMPORT_NAME'] +LOAD_CONST = opcode.opmap['LOAD_CONST'] +LOAD_SMALL_INT = opcode.opmap['LOAD_SMALL_INT'] + + +def _code_imports(code, consts, names): + start = 4 + while True: + op3_idx = code.find(IMPORT_NAME, start, -1) + if op3_idx < 0: + return + if op3_idx % 2: + start = op3_idx + 1 + continue + if code[op3_idx-4] != LOAD_SMALL_INT or code[op3_idx-2] != LOAD_CONST: + start = op3_idx + 2 + continue + start = op3_idx + 6 + arg1, arg2, arg3 = code[op3_idx-3], code[op3_idx-1], code[op3_idx+1] + yield (arg1, names[arg3], consts[arg2] or ()) diff --git a/setup.py b/setup.py index f8aeffea..fe561fd4 100644 --- a/setup.py +++ b/setup.py @@ -102,6 +102,7 @@ setup( 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: System :: Distributed Computing', 'Topic :: System :: Systems Administration', diff --git a/tests/ansible/regression/issue_766__get_with_context.yml b/tests/ansible/regression/issue_766__get_with_context.yml index 5dae142f..56a10123 100644 --- a/tests/ansible/regression/issue_766__get_with_context.yml +++ b/tests/ansible/regression/issue_766__get_with_context.yml @@ -9,6 +9,8 @@ netconf_container_image: ghcr.io/mitogen-hq/sysrepo-netopeer2:latest netconf_container_name: sysrepo netconf_container_port: 8030 + # https://github.com/ansible-collections/ansible.netcommon/issues/698#issuecomment-2910082548 + ansible_network_import_modules: "{{ (ansible_version_major_minor is version('2.19', '==', strict=True)) | bool }}" tasks: - meta: end_play @@ -28,13 +30,6 @@ - ansible_version_major_minor is version('2.11', '>=', strict=True) - ansible_version_major_minor is version('2.12', '<', strict=True) - - meta: end_play - when: - # TASK [Get running configuration and state data ] - # Error: : Task failed: ActionBase._parse_returned_data() missing 1 required positional argument: 'profile' - # https://github.com/ansible-collections/ansible.netcommon/issues/698#issuecomment-2910082548 - - ansible_version_major_minor is version('2.19', '>=', strict=True) - - block: - name: Start container command: @@ -63,6 +58,9 @@ ansible.netcommon.netconf_get: always: + - name: Close connections + meta: reset_connection + - name: Cleanup container command: cmd: podman stop "{{ netconf_container_name }}" diff --git a/tests/bench/scan_code b/tests/bench/scan_code index 118dd9d7..302db869 100755 --- a/tests/bench/scan_code +++ b/tests/bench/scan_code @@ -10,7 +10,7 @@ BIG_MODULE_PATH="$(dirname -- "$0")/data/big_module.py" IMPORTS="from collections import deque; from mitogen.imports import $BENCH_FUNC" COMPILE="co=compile(open('$BIG_MODULE_PATH').read(), '$BIG_MODULE_PATH', 'exec')" PYTHONS=( - python2.7 python3.9 python3.10 python3.11 python3.12 python3.13 + python2.7 python3.{9..14} ) for p in "${PYTHONS[@]}"; do echo -e -n "$BENCH_FUNC $p " diff --git a/tox.ini b/tox.ini index da44ff0d..aac84fa8 100644 --- a/tox.ini +++ b/tox.ini @@ -59,8 +59,9 @@ envlist = init, py{27,36}-m_ans-ans{2.10,3,4} py{311}-m_ans-ans{2.10,3-5} - py{313}-m_ans-ans{6-12} - py{27,36,313}-m_mtg + py{313}-m_ans-ans{6-9} + py{314}-m_ans-ans{10-12} + py{27,36,314}-m_mtg report, [testenv] @@ -76,6 +77,7 @@ basepython = py311: python3.11 py312: python3.12 py313: python3.13 + py314: python3.14 deps = -r{toxinidir}/tests/requirements.txt m_ans: -r{toxinidir}/tests/ansible/requirements.txt