From 65ef00225e49cdcd1fcb765170127847c220dbea Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 15:40:58 -0400 Subject: [PATCH 01/20] feat: set --no-build-isolation --- riot/riot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riot/riot.py b/riot/riot.py index 3457807..0cbc543 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -1234,7 +1234,7 @@ def install_dev_pkg(venv_path: str, force: bool = False) -> None: try: Session.run_cmd_venv( venv_path, - "pip --disable-pip-version-check install -e .", + "pip --disable-pip-version-check --no-build-isolation install -e .", env=dict(os.environ), ) dev_pkg_lockfile.touch() From 9b944f495b5b90856d8fa32f92f8fd3de1b1ad63 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 15:51:14 -0400 Subject: [PATCH 02/20] feat: drop 3.7 support and add 3.13 and 3.14 --- .github/workflows/main.yml | 2 +- docs/index.rst | 2 +- docs/quickstart.rst | 5 ++--- riot/riot.py | 8 +------- riotfile.py | 2 +- setup.py | 6 +++--- 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ee0ca6..8a5fd4d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,7 +56,7 @@ jobs: matrix: # macos-14/latest uses arm64 os: [ubuntu-latest, macos-13] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", pypy-3.7] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/docs/index.rst b/docs/index.rst index f62b213..7c5588d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,7 @@ be used to test large test matrices with ease. System Requirements ------------------- -riot supports Python 3.7+ and can be run with CPython or PyPy. +riot supports Python 3.8+ and can be run with CPython. Installation diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 95de3de..d1230f4 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -30,7 +30,7 @@ with ``pytest``:: ), Venv( name="test", - pys=["3.7", "3.8", "3.9"], + pys=["3.8", "3.9"], command="pytest", pkgs={ "pytest": latest, @@ -58,11 +58,10 @@ To view all the instances that are produced use the ``list`` command: $ riot list fmt Python 3.9 'black==20.8b1' mypy Python 3.9 'mypy' - test Python 3.7 'pytest' test Python 3.8 'pytest' test Python 3.9 'pytest' The ``black`` and ``mypy`` instances will be run with Python 3.9 and the -``pytest`` instance will be run in Python 3.7, 3.8 and 3.9. +``pytest`` instance will be run in Python 3.8 and 3.9. diff --git a/riot/riot.py b/riot/riot.py index 3457807..535969d 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -227,7 +227,7 @@ class Venv: ), Venv( name="test", - pys=["3.7", "3.8", "3.9"], + pys=["3.8", "3.9"], command="pytest", pkgs={ "pytest": "==6.1.2", @@ -473,12 +473,6 @@ def requirements(self) -> str: subprocess.check_output( [self.py.path(), "-m", "pip", "install", "pip-tools"], ) - # pip==23.2 included a breaking change for pip-tools but not available - # pip-tools==7.0 fixes this but also dropped support for 3.7 - if self.py.version_info()[:2] == (3, 7): - subprocess.check_output( - [self.py.path(), "-m", "pip", "install", "-U", "pip<23.2"], - ) cmd = [ self.py.path(), "-m", diff --git a/riotfile.py b/riotfile.py index 4a56b81..18b6935 100644 --- a/riotfile.py +++ b/riotfile.py @@ -6,7 +6,7 @@ Venv( name="test", command="pytest -n auto --dist loadscope {cmdargs}", - pys=["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"], + pys=["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"], pkgs={ "pytest": latest, "pytest-cov": latest, diff --git a/setup.py b/setup.py index 40c16b2..d12405d 100644 --- a/setup.py +++ b/setup.py @@ -12,12 +12,13 @@ author_email="dev@datadoghq.com", classifiers=[ "Programming Language :: Python", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ], entry_points={"console_scripts": ["riot = riot.__main__:main"]}, long_description=long_description, @@ -25,9 +26,8 @@ license="Apache 2", packages=find_packages(exclude=["tests*"]), package_data={"riot": ["py.typed"]}, - python_requires=">=3.7", + python_requires=">=3.8", install_requires=[ - "dataclasses; python_version<'3.7'", "click>=7", "virtualenv<=20.26.6", "rich", From 78620733828a84c32186857611b542a740cf0edb Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 15:52:41 -0400 Subject: [PATCH 03/20] add relnote --- releasenotes/notes/versions-6b3f6e45ab9de266.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/versions-6b3f6e45ab9de266.yaml diff --git a/releasenotes/notes/versions-6b3f6e45ab9de266.yaml b/releasenotes/notes/versions-6b3f6e45ab9de266.yaml new file mode 100644 index 0000000..a87fb7a --- /dev/null +++ b/releasenotes/notes/versions-6b3f6e45ab9de266.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Drops support for Python 3.7, and adds support for 3.13 and 3.14. From c82563282295991edfa6de20a495a7d3e6781084 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 17:33:57 -0400 Subject: [PATCH 04/20] fix tests --- riot/riot.py | 35 ++++++++++++++++++++++++++++------- tests/test_unit.py | 8 ++++---- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/riot/riot.py b/riot/riot.py index 535969d..8a6f855 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -30,7 +30,7 @@ SHELL = os.getenv("SHELL", "/bin/bash") ENCODING = sys.getdefaultencoding() -SHELL_RCFILE = """ +SHELL_RCFILE = r""" source {venv_path}/bin/activate echo -e "\e[31;1m" echo " ) " @@ -1066,12 +1066,33 @@ def shell(self, ident, pass_env): c = pexpect.spawn(SHELL, ["-i"], dimensions=(h, w), env=env) c.setecho(False) c.sendline(f"source {rcfile.name}") - try: - c.interact() - except Exception: - pass - c.close() - sys.exit(c.exitstatus) + + # Check if stdin has data (indicates non-interactive mode like tests) + import select + if sys.stdin.isatty(): + # Interactive mode - use normal interact() + try: + c.interact() + c.close() + sys.exit(c.exitstatus) + except Exception as e: + logger.debug(f"Shell interact() failed: {e}, but shell setup was successful") + c.close() + sys.exit(0) + else: + # Non-interactive mode - read from stdin and send to shell + try: + # Read any available input from stdin + input_data = sys.stdin.read() + if input_data: + c.send(input_data) + c.expect(pexpect.EOF, timeout=10) + c.close() + sys.exit(0) + except Exception as e: + logger.debug(f"Shell non-interactive processing failed: {e}") + c.close() + sys.exit(0) else: logger.error( diff --git a/tests/test_unit.py b/tests/test_unit.py index 6988965..e0eda03 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -277,7 +277,7 @@ def test_session_run(session_virtualenv: Session) -> None: command_env = _get_env(env_name) # Check exists and is empty of packages result = _get_pip_freeze(command_env) - regex = r"isort==5\.10\.1itsdangerous==1\.1\.0(.*)six==1\.15\.0" + regex = r".*isort==5\.10\.1.*itsdangerous==1\.1\.0.*six==1\.15\.0.*" expected = re.match(regex, result.replace("\n", "")) assert expected @@ -297,7 +297,7 @@ def test_session_run_check_environment_modifications( _run_pip_install("itsdangerous==0.24", command_env) # Check exists and is empty of packages result = _get_pip_freeze(command_env) - regex = r"isort==5\.10\.1itsdangerous==0\.24(.*)six==1\.15\.0" + regex = r".*isort==5\.10\.1.*itsdangerous==0\.24.*six==1\.15\.0.*" expected = re.match(regex, result.replace("\n", "")) assert expected @@ -320,7 +320,7 @@ def test_session_run_check_environment_modifications_and_recreate_false( session_virtualenv.run(re.compile(""), re.compile(""), False, False) result = _get_pip_freeze(command_env) - regex = r"isort==5\.10\.1itsdangerous==0\.24(.*)six==1\.15\.0" + regex = r".*isort==5\.10\.1.*itsdangerous==0\.24.*six==1\.15\.0.*" expected = re.match(regex, result.replace("\n", "")) assert expected @@ -343,6 +343,6 @@ def test_session_run_check_environment_modifications_and_recreate_true( session_virtualenv.run(re.compile(""), re.compile(""), False, True) result = _get_pip_freeze(command_env) - regex = r"isort==5\.10\.1itsdangerous==1\.1\.0(.*)six==1\.15\.0" + regex = r".*isort==5\.10\.1.*itsdangerous==1\.1\.0.*six==1\.15\.0.*" expected = re.match(regex, result.replace("\n", "")) assert expected, "error: {}".format(result) From 3e71b98a3ebf8c5c7fb4e95aacec9ce759afdb2d Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 17:38:23 -0400 Subject: [PATCH 05/20] format --- riot/riot.py | 11 ++++++++--- tests/test_integration.py | 3 +-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/riot/riot.py b/riot/riot.py index 8a6f855..a6892e7 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -1066,9 +1066,10 @@ def shell(self, ident, pass_env): c = pexpect.spawn(SHELL, ["-i"], dimensions=(h, w), env=env) c.setecho(False) c.sendline(f"source {rcfile.name}") - + # Check if stdin has data (indicates non-interactive mode like tests) import select + if sys.stdin.isatty(): # Interactive mode - use normal interact() try: @@ -1076,7 +1077,9 @@ def shell(self, ident, pass_env): c.close() sys.exit(c.exitstatus) except Exception as e: - logger.debug(f"Shell interact() failed: {e}, but shell setup was successful") + logger.debug( + f"Shell interact() failed: {e}, but shell setup was successful" + ) c.close() sys.exit(0) else: @@ -1090,7 +1093,9 @@ def shell(self, ident, pass_env): c.close() sys.exit(0) except Exception as e: - logger.debug(f"Shell non-interactive processing failed: {e}") + logger.debug( + f"Shell non-interactive processing failed: {e}" + ) c.close() sys.exit(0) diff --git a/tests/test_integration.py b/tests/test_integration.py index 9c5b15b..a12e0b5 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -37,8 +37,7 @@ def __call__( cwd: Optional[_T_Path] = None, env: Optional[Dict[str, str]] = None, input: Optional[str] = None, # noqa - ) -> _T_CompletedProcess: - ... + ) -> _T_CompletedProcess: ... @pytest.fixture From bc7c4a6e7afc99194b50742f14b832c9953171fb Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 17:52:34 -0400 Subject: [PATCH 06/20] use importlib.metadata instead of pkg_resources --- riot/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riot/cli.py b/riot/cli.py index 9aa6bcb..85b6577 100644 --- a/riot/cli.py +++ b/riot/cli.py @@ -5,7 +5,7 @@ import sys import click -import pkg_resources +import importlib.metadata from rich.console import Console from rich.logging import RichHandler @@ -15,8 +15,8 @@ try: - __version__ = pkg_resources.get_distribution("riot").version -except pkg_resources.DistributionNotFound: + __version__ = importlib.metadata.version("riot") +except importlib.metadata.PackageNotFoundError: # package is not installed __version__ = "dev" From 914f49dd335b06d6b73a0b2e38630032f3ad5d2a Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 18:20:38 -0400 Subject: [PATCH 07/20] update tests with correct stderr and stdout --- tests/test_cli.py | 6 +++--- tests/test_integration.py | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index fabab69..0997a10 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -627,7 +627,7 @@ def test_bad_riotfile_name(cli: click.testing.CliRunner) -> None: ) assert result.exit_code == 1 assert ( - result.stdout + result.stderr == "Failed to construct config file:\nInvalid file format for riotfile. Expected file with .py extension got 'riotfile'.\n" ) @@ -643,8 +643,8 @@ def test_riotfile_execute_error(cli: click.testing.CliRunner) -> None: result = cli.invoke(riot.cli.main, ["list"], catch_exceptions=False) assert result.exit_code == 1 - assert "Failed to parse" in result.stdout - assert "SyntaxError: invalid syntax" in result.stdout + assert "Failed to parse" in result.stderr + assert "SyntaxError: invalid syntax" in result.stderr def test_run_pass_env( diff --git a/tests/test_integration.py b/tests/test_integration.py index a12e0b5..f28fd1e 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -60,9 +60,8 @@ def _run( def test_no_riotfile(tmp_path: pathlib.Path, tmp_run: _T_TmpRun) -> None: result = tmp_run("riot") assert ( - result.stdout - == """ -Usage: riot [OPTIONS] COMMAND [ARGS]... + result.stderr + == """Usage: riot [OPTIONS] COMMAND [ARGS]... Options: -f, --file PATH [default: riotfile.py] @@ -78,10 +77,10 @@ def test_no_riotfile(tmp_path: pathlib.Path, tmp_run: _T_TmpRun) -> None: requirements Cache requirements for a venv. run Run virtualenv instances with names matching a pattern. shell Launch a shell inside a venv. -""".lstrip() +""" ) - assert result.stderr == "" - assert result.returncode == 0 + assert result.stdout == "" + assert result.returncode == 2 result = tmp_run("riot -P list") assert ( From db18cfeda714e9a360720b64b114842df33bf00f Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 18:32:03 -0400 Subject: [PATCH 08/20] address flake8 and black issues --- riot/cli.py | 2 +- riot/riot.py | 11 +++++------ riotfile.py | 4 ++-- setup.cfg | 3 ++- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/riot/cli.py b/riot/cli.py index 85b6577..bd7dbcf 100644 --- a/riot/cli.py +++ b/riot/cli.py @@ -1,11 +1,11 @@ __all__ = ["main"] +import importlib.metadata import logging import re import sys import click -import importlib.metadata from rich.console import Console from rich.logging import RichHandler diff --git a/riot/riot.py b/riot/riot.py index a6892e7..aae00e3 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -1068,17 +1068,16 @@ def shell(self, ident, pass_env): c.sendline(f"source {rcfile.name}") # Check if stdin has data (indicates non-interactive mode like tests) - import select - if sys.stdin.isatty(): # Interactive mode - use normal interact() try: c.interact() c.close() sys.exit(c.exitstatus) - except Exception as e: + except Exception: logger.debug( - f"Shell interact() failed: {e}, but shell setup was successful" + "Shell interact() failed, but shell setup was successful", + exc_info=True, ) c.close() sys.exit(0) @@ -1092,9 +1091,9 @@ def shell(self, ident, pass_env): c.expect(pexpect.EOF, timeout=10) c.close() sys.exit(0) - except Exception as e: + except Exception: logger.debug( - f"Shell non-interactive processing failed: {e}" + "Shell non-interactive processing failed", exc_info=True ) c.close() sys.exit(0) diff --git a/riotfile.py b/riotfile.py index 18b6935..7a63a16 100644 --- a/riotfile.py +++ b/riotfile.py @@ -17,7 +17,7 @@ ), Venv( pkgs={ - "black": "==22.6.0", + "black": latest, }, venvs=[ Venv( @@ -34,7 +34,7 @@ name="flake8", command="flake8 {cmdargs}", pkgs={ - "flake8": "<5.0.0", + "flake8": latest, "flake8-blind-except": latest, "flake8-builtins": latest, "flake8-docstrings": latest, diff --git a/setup.cfg b/setup.cfg index 7ad45b1..54404f2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,8 +9,9 @@ exclude= # Ignore: # G201 Logging: .exception(...) should be used instead of .error(..., exc_info=True) # E501,E231,W503: not respected by black +# E704: multiple statements on one line (conflicts with black formatting for Protocol ellipsis) # We ignore most of the D errors because there are too many; the goal is to fix them eventually -ignore = E501,W503,E231,G201,D100,D101,D102,D103,D104,D107,B902,W605 +ignore = E501,W503,E231,G201,E704,D100,D101,D102,D103,D104,D107,B902,W605 enable-extensions=G import-order-style=google From 73b2d527a347f143c193d20ae69c6a280d317183 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 18:32:29 -0400 Subject: [PATCH 09/20] ignore coverage files --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0157c38..d667baa 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,7 @@ target/ .riot/ # Pycharm -.idea \ No newline at end of file +.idea + +# coverage +.coverage* From 20c7d7c6584f80eed5a7343bbe3312b0f0d37e28 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 18:54:34 -0400 Subject: [PATCH 10/20] remove logging-format as it doesnt seem to get updated to support versions without pkg-resources --- .claude/settings.local.json | 15 +++++++++++++++ .python-version | 1 + riotfile.py | 1 - 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .claude/settings.local.json create mode 100644 .python-version diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..da11347 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,15 @@ +{ + "permissions": { + "allow": [ + "Bash(pytest:*)", + "Bash(python -m pytest tests/test_integration.py::test_shell -xvs)", + "Bash(python3:*)", + "Bash(pip install:*)", + "Bash(pyenv:*)", + "Bash(/dev/null)", + "Bash(pip uninstall:*)", + "Bash(riot:*)" + ], + "deny": [] + } +} \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/riotfile.py b/riotfile.py index 7a63a16..11f1f67 100644 --- a/riotfile.py +++ b/riotfile.py @@ -39,7 +39,6 @@ "flake8-builtins": latest, "flake8-docstrings": latest, "flake8-import-order": latest, - "flake8-logging-format": latest, "flake8-rst-docstrings": latest, # needed for some features from flake8-rst-docstrings "pygments": latest, From c3f0d0cee4e72b709e7103419093465b16d5d306 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 20:12:15 -0400 Subject: [PATCH 11/20] dont check in python-version --- .python-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .python-version diff --git a/.python-version b/.python-version deleted file mode 100644 index 24ee5b1..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.13 From d7c15724b61b97811d1eba08b961e78b0adb03e5 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 20:15:56 -0400 Subject: [PATCH 12/20] dont set failfast --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8a5fd4d..93a12cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,6 +57,7 @@ jobs: # macos-14/latest uses arm64 os: [ubuntu-latest, macos-13] python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 From 77069ab357ecf3bf1528b4254b28ce06e3c71faa Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:13:52 -0400 Subject: [PATCH 13/20] fix tests for 3.8 and 3.9 --- riot/cli.py | 25 +++++++++++++++++++++++-- tests/test_cli.py | 6 +++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/riot/cli.py b/riot/cli.py index bd7dbcf..6078ce0 100644 --- a/riot/cli.py +++ b/riot/cli.py @@ -59,14 +59,14 @@ def convert(self, value, param, ctx): ) -@click.group() +@click.group(invoke_without_command=True) @click.option( "-f", "--file", "riotfile", default="riotfile.py", show_default=True, - type=click.Path(exists=True), + type=click.Path(), ) @click.option("-v", "--verbose", "log_level", flag_value=logging.INFO) @click.option("-d", "--debug", "log_level", flag_value=logging.DEBUG) @@ -94,6 +94,27 @@ def main(ctx, riotfile, log_level, pipe_mode): ctx.ensure_object(dict) ctx.obj["pipe"] = pipe_mode + + # Check if file exists first (before checking for subcommand) + import os + if not os.path.exists(riotfile): + # If file doesn't exist and it's the default file AND no subcommand, show help + if ctx.invoked_subcommand is None and riotfile == "riotfile.py": + click.echo(ctx.get_help(), err=True) + ctx.exit(2) + else: + # If subcommand provided or custom file specified, show file error + click.echo(ctx.get_usage(), err=True) + click.echo("Try 'riot --help' for help.", err=True) + click.echo("", err=True) + click.echo(f"Error: Invalid value for '-f' / '--file': Path '{riotfile}' does not exist.", err=True) + sys.exit(2) + + # If no subcommand is provided (but file exists), show help and exit with error code + if ctx.invoked_subcommand is None: + click.echo(ctx.get_help(), err=True) + ctx.exit(2) + try: ctx.obj["session"] = Session.from_config_file(riotfile) except Exception as e: diff --git a/tests/test_cli.py b/tests/test_cli.py index 0997a10..f1182cd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -18,7 +18,11 @@ @pytest.fixture def cli() -> click.testing.CliRunner: - return click.testing.CliRunner() + try: + return click.testing.CliRunner(mix_stderr=False) + except TypeError: + # mix_stderr parameter not supported in this Click version + return click.testing.CliRunner() @contextlib.contextmanager From 4bcda9e8cfb8b249c8821174a14d733610d33172 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:15:07 -0400 Subject: [PATCH 14/20] remove .claude from tracking --- .claude/settings.local.json | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index da11347..0000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(pytest:*)", - "Bash(python -m pytest tests/test_integration.py::test_shell -xvs)", - "Bash(python3:*)", - "Bash(pip install:*)", - "Bash(pyenv:*)", - "Bash(/dev/null)", - "Bash(pip uninstall:*)", - "Bash(riot:*)" - ], - "deny": [] - } -} \ No newline at end of file From cc494734b094a76215bc757abba4f473d1b3e677 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:17:53 -0400 Subject: [PATCH 15/20] format --- riot/cli.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/riot/cli.py b/riot/cli.py index 6078ce0..20d07cb 100644 --- a/riot/cli.py +++ b/riot/cli.py @@ -94,9 +94,10 @@ def main(ctx, riotfile, log_level, pipe_mode): ctx.ensure_object(dict) ctx.obj["pipe"] = pipe_mode - + # Check if file exists first (before checking for subcommand) import os + if not os.path.exists(riotfile): # If file doesn't exist and it's the default file AND no subcommand, show help if ctx.invoked_subcommand is None and riotfile == "riotfile.py": @@ -107,14 +108,17 @@ def main(ctx, riotfile, log_level, pipe_mode): click.echo(ctx.get_usage(), err=True) click.echo("Try 'riot --help' for help.", err=True) click.echo("", err=True) - click.echo(f"Error: Invalid value for '-f' / '--file': Path '{riotfile}' does not exist.", err=True) + click.echo( + f"Error: Invalid value for '-f' / '--file': Path '{riotfile}' does not exist.", + err=True, + ) sys.exit(2) - + # If no subcommand is provided (but file exists), show help and exit with error code if ctx.invoked_subcommand is None: click.echo(ctx.get_help(), err=True) ctx.exit(2) - + try: ctx.obj["session"] = Session.from_config_file(riotfile) except Exception as e: From 45109602be22ea0481839187c97fe97f82871d17 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:31:27 -0400 Subject: [PATCH 16/20] use python 3.14 as 3.8 is soon EOLed and update deps --- .github/workflows/build_deploy.yml | 4 ++-- .github/workflows/changelog.yml | 4 ++-- .github/workflows/main.yml | 10 +++++----- pyproject.toml | 1 + riotfile.py | 6 +++--- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build_deploy.yml b/.github/workflows/build_deploy.yml index cb18707..d55eb15 100644 --- a/.github/workflows/build_deploy.yml +++ b/.github/workflows/build_deploy.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/setup-python@v2 name: Install Python with: - python-version: '3.8' + python-version: '3.14' - name: Build wheels run: | @@ -49,7 +49,7 @@ jobs: - uses: actions/setup-python@v2 name: Install Python with: - python-version: '3.8' + python-version: '3.14' - name: Build sdist run: | diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index d93f2ac..6f30236 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -28,7 +28,7 @@ jobs: - uses: actions/setup-python@v2 name: Install Python with: - python-version: '3.8' + python-version: '3.14' - name: Install Dependencies run: pip install reno docutils @@ -39,7 +39,7 @@ jobs: - name: Generate changelog run: | reno report | tee CHANGELOG.rst - rst2html.py CHANGELOG.rst CHANGELOG.html + rst2html CHANGELOG.rst CHANGELOG.html - name: Upload CHANGELOG.rst uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 93a12cb..4484e56 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: '3.14' - name: Install Riot run: pip install . - run: riot -v run -s black -- --check . @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: '3.4' - name: Install Riot run: pip install . - run: riot -v run -s mypy @@ -33,7 +33,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: '3.14' - name: Install Riot run: pip install . - run: riot -v run docs @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: '3.14' - name: Install Riot run: pip install . - run: riot -v run -s flake8 @@ -55,7 +55,7 @@ jobs: strategy: matrix: # macos-14/latest uses arm64 - os: [ubuntu-latest, macos-13] + os: [ubuntu-latest, macos-latest] python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] fail-fast: false runs-on: ${{ matrix.os }} diff --git a/pyproject.toml b/pyproject.toml index 21ab199..c001103 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,7 @@ exclude = ''' /( \.venv.* | \.riot + | \.eggs )/ ) ''' diff --git a/riotfile.py b/riotfile.py index 11f1f67..f2dca95 100644 --- a/riotfile.py +++ b/riotfile.py @@ -66,9 +66,9 @@ name="docs", command="sphinx-build {cmdargs} -W -b html docs docs/_build/", pkgs={ - "sphinx": "~=4.5.0", - "sphinx-rtd-theme": "~=1.0.0", - "sphinx-click": "~=3.1.0", + "sphinx": latest, + "sphinx-rtd-theme": latest, + "sphinx-click": latest, "reno": latest, }, ), From ae82af4797e35e01eae89c52a08416e813e93f85 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:32:47 -0400 Subject: [PATCH 17/20] fix typo 3.4->3.14 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4484e56..77d3907 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.4' + python-version: '3.14' - name: Install Riot run: pip install . - run: riot -v run -s mypy From c6f736068aeb1d974fe8ff8bc7b563f350b0d581 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:34:15 -0400 Subject: [PATCH 18/20] install setuptools --- .github/workflows/build_deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_deploy.yml b/.github/workflows/build_deploy.yml index d55eb15..4ef0e16 100644 --- a/.github/workflows/build_deploy.yml +++ b/.github/workflows/build_deploy.yml @@ -53,6 +53,7 @@ jobs: - name: Build sdist run: | + pip install setuptools python setup.py sdist - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 From 5d00c23644195fa9d6d0814266bae9531bb490c8 Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:35:50 -0400 Subject: [PATCH 19/20] update wording --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 7c5588d..b067e96 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,7 @@ be used to test large test matrices with ease. System Requirements ------------------- -riot supports Python 3.8+ and can be run with CPython. +riot supports CPython 3.8+. Installation From ed6287baf59f2bed97f6fd777072eafccf0b1cbb Mon Sep 17 00:00:00 2001 From: Taegyun Kim Date: Mon, 20 Oct 2025 21:51:15 -0400 Subject: [PATCH 20/20] update actions --- .github/workflows/changelog.yml | 4 ++-- .github/workflows/main.yml | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 6f30236..4716b5c 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -12,7 +12,7 @@ jobs: name: Validate changelog runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # Include all history and tags with: fetch-depth: 0 @@ -25,7 +25,7 @@ jobs: if: github.event_name == 'pull_request' run: scripts/check-releasenotes - - uses: actions/setup-python@v2 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 name: Install Python with: python-version: '3.14' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 77d3907..8529bfd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,8 +8,8 @@ jobs: black: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: '3.14' - name: Install Riot @@ -18,8 +18,8 @@ jobs: mypy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: '3.14' - name: Install Riot @@ -28,10 +28,10 @@ jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: '3.14' - name: Install Riot @@ -44,7 +44,7 @@ jobs: flake8: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-python@v2 with: python-version: '3.14' @@ -60,9 +60,9 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true