diff --git a/.github/workflows/base.yml b/.github/workflows/base.yml index 5f5098e..3ba416a 100644 --- a/.github/workflows/base.yml +++ b/.github/workflows/base.yml @@ -60,6 +60,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Install python ${{ matrix.nox_session.python }} for tests + if: ${{ ! contains(fromJson('["3.13"]'), matrix.nox_session.python ) }} uses: MatteoH2O1999/setup-python@v3.2.1 # actions/setup-python@v5.0.0 id: set-py with: @@ -68,6 +69,18 @@ jobs: allow-build: info cache-build: true + - name: Install python ${{ matrix.nox_session.python }} for tests (3.13) + if: contains(fromJson('["3.13"]'), matrix.nox_session.python ) + uses: actions/setup-python@v5 + id: set-py-latest + with: + # Include all versions including pre releases + # See https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#specifying-a-python-version + python-version: ${{ format('~{0}.0-alpha.0', matrix.nox_session.python) }} + architecture: x64 + allow-build: info + cache-build: true + - name: Install python 3.12 for nox uses: actions/setup-python@v5.0.0 with: diff --git a/ci_tools/nox_utils.py b/ci_tools/nox_utils.py index d565e81..3c4df0f 100644 --- a/ci_tools/nox_utils.py +++ b/ci_tools/nox_utils.py @@ -12,8 +12,8 @@ nox_logger = logging.getLogger("nox") -PY27, PY35, PY36, PY37, PY38, PY39, PY310, PY311, PY312 = ("2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", - "3.12") +PY27, PY35, PY36, PY37, PY38, PY39, PY310, PY311, PY312, PY313 = ("2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", + "3.11", "3.12", "3.13") DONT_INSTALL = "dont_install" diff --git a/docs/changelog.md b/docs/changelog.md index 942cdaa..6e16ec7 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,10 @@ # Changelog +### 1.15.4 - Python 3.13 official support + + - Python 3.13 is now supported. PR [#108](https://github.com/smarie/python-makefun/pull/108) and PR + [#104](https://github.com/smarie/python-makefun/pull/104) by [mgorny](https://github.com/mgorny) + ### 1.15.3 - bugfix - Fixed `SyntaxError: invalid syntax` happening when the default value of one argument of the created function is a diff --git a/noxfile.py b/noxfile.py index 9e8d5b6..de817d8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -9,7 +9,7 @@ # add parent folder to python path so that we can import noxfile_utils.py # note that you need to "pip install -r noxfile-requiterements.txt" for this file to work. sys.path.append(str(Path(__file__).parent / "ci_tools")) -from nox_utils import (PY27, PY37, PY36, PY38, PY39, PY310, PY311, PY312, install_reqs, rm_folder, rm_file, +from nox_utils import (PY27, PY37, PY36, PY38, PY39, PY310, PY311, PY312, PY313, install_reqs, rm_folder, rm_file, DONT_INSTALL) # noqa @@ -54,6 +54,7 @@ class Folders: ENVS = { + PY313: {"coverage": False, "pkg_specs": {"pip": ">19"}}, PY312: {"coverage": False, "pkg_specs": {"pip": ">19"}}, PY311: {"coverage": False, "pkg_specs": {"pip": ">19"}}, PY310: {"coverage": False, "pkg_specs": {"pip": ">19"}}, diff --git a/setup.cfg b/setup.cfg index fbbbcba..429824b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ classifiers = Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 [options] # one day these will be able to come from requirement files, see https://github.com/pypa/setuptools/issues/1951. But will it be better ? diff --git a/tests/test_partial_and_macros.py b/tests/test_partial_and_macros.py index 822e896..afa8ed6 100644 --- a/tests/test_partial_and_macros.py +++ b/tests/test_partial_and_macros.py @@ -1,5 +1,6 @@ import functools import pytest +import re import sys import makefun @@ -11,6 +12,11 @@ PY2 = sys.version_info < (3, ) +# Python 3.13 dedents docstrings, earlier versions just strip initial +# whitespace. Use a regexp to get a consistently dedented docstring +# for comparison across Python versions. +DOCSTRING_NORMALIZE_RE = re.compile(r"^ +", re.MULTILINE) + def test_doc(): def foo(x, y): @@ -41,15 +47,15 @@ def foo(x, y): sig_actual_call = ref_sig_str.replace("*, ", "") - assert bar.__doc__ \ + assert DOCSTRING_NORMALIZE_RE.sub("", bar.__doc__) \ == """ - a `foo` function +a `foo` function - :param x: - :param y: - :return: - """ % sig_actual_call +:param x: +:param y: +:return: +""" % sig_actual_call def test_partial(): @@ -78,16 +84,16 @@ def foo(x, y, a): sig_actual_call = "(x, y='hello', a)" # if PY2 else "(x, *, y='hello', a)" - assert foo.__doc__.replace("=KW_ONLY_ARG!", "") \ + assert DOCSTRING_NORMALIZE_RE.sub("", foo.__doc__.replace("=KW_ONLY_ARG!", "")) \ == """ - a `foo` function +a `foo` function - :param x: - :param y: - :param a: - :return: - """ % sig_actual_call +:param x: +:param y: +:param a: +:return: +""" % sig_actual_call def test_issue_57(): @@ -127,9 +133,7 @@ def f(b=0): assert m() == -1 assert m.i == 1 # the doc remains untouched in create_function as opposed to wraps, this is normal - assert m.__doc__ == """partial(func, *args, **keywords) - new function with partial application - of the given arguments and keywords. -""" + assert m.__doc__ == functools.partial.__doc__ def test_args_order_and_kind():