From ee050c87f4d8fb4d200c2754a6f0825d15020848 Mon Sep 17 00:00:00 2001 From: "Gabriele N. Tornetta" Date: Wed, 17 Aug 2022 11:45:03 +0100 Subject: [PATCH] feat: re-instal dev package on setup file changes This change enables tracking changes in setup files so that the dev package can be re-installed if needed, when the -s option is passed to the run command. --- ...on-setup-hash-change-4bfc854dcc76c49c.yaml | 5 ++ riot/riot.py | 33 +++++++-- tests/test_integration.py | 72 ++++++++++++++++++- 3 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/feat-reinstall-on-setup-hash-change-4bfc854dcc76c49c.yaml diff --git a/releasenotes/notes/feat-reinstall-on-setup-hash-change-4bfc854dcc76c49c.yaml b/releasenotes/notes/feat-reinstall-on-setup-hash-change-4bfc854dcc76c49c.yaml new file mode 100644 index 0000000..e927a11 --- /dev/null +++ b/releasenotes/notes/feat-reinstall-on-setup-hash-change-4bfc854dcc76c49c.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Riot will attempt to re-install the development package if changes to the + setup files are detected when using the skip option with the run command. diff --git a/riot/riot.py b/riot/riot.py index 86fb63a..4ac853b 100644 --- a/riot/riot.py +++ b/riot/riot.py @@ -7,6 +7,7 @@ import itertools import logging import os +from pathlib import Path import shutil import subprocess import sys @@ -25,6 +26,7 @@ DEFAULT_RIOT_PATH = ".riot" DEFAULT_RIOT_ENV_PREFIX = "venv_py" +SETUP_FILES = ["setup.py", "pyproject.toml"] SHELL = os.getenv("SHELL", "/bin/bash") ENCODING = sys.getdefaultencoding() @@ -882,8 +884,16 @@ def generate_base_venvs( logger.error("Python version '%s' not found.", py) else: if existed and skip_deps: - logger.info("Skipping global deps install.") - continue + hash_file = Path(py.venv_path) / ".riot-setup-hash" + if ( + hash_file.exists() + and hash_file.read_text().strip() == setup_hash() + ): + logger.info("Skipping global deps install.") + continue + logger.info( + "Re-installing development package because of setup hash mismatch." + ) # Install the dev package into the base venv. install_dev_pkg(py.venv_path) @@ -1078,9 +1088,21 @@ def pip_deps(pkgs: t.Dict[str, str]) -> str: ) +def setup_hash() -> t.Optional[str]: + """Generate a hash from the current setup files.""" + setup_hash = "" + + for setup_file in SETUP_FILES: + path = Path(setup_file) + if path.exists(): + setup_hash += sha256(path.read_bytes()).hexdigest() + + return setup_hash or None + + def install_dev_pkg(venv_path): - for setup_file in {"setup.py", "pyproject.toml"}: - if os.path.exists(setup_file): + for setup_file in SETUP_FILES: + if Path(setup_file).exists(): break else: logger.warning("No Python setup file found. Skipping dev package installation.") @@ -1094,3 +1116,6 @@ def install_dev_pkg(venv_path): except CmdFailure as e: logger.error("Dev install failed, aborting!\n%s", e.proc.stdout) sys.exit(1) + + # Store setup hash in the interpreter venv + (Path(venv_path) / ".riot-setup-hash").write_text(setup_hash()) diff --git a/tests/test_integration.py b/tests/test_integration.py index fcd0c19..a7c25fa 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -485,7 +485,6 @@ def test_failure(): result.stdout, re.MULTILINE, ) - assert result.stderr == "" assert result.returncode == 1 @@ -545,7 +544,6 @@ def test_run_cmdargs(tmp_path: pathlib.Path, tmp_run: _T_TmpRun) -> None: ) result = tmp_run("riot run -s test_cmdargs -- -k filter") assert "cmdargs=-k filter" in result.stdout - assert result.stderr == "" assert result.returncode == 0 @@ -871,3 +869,73 @@ def test_shell_created(tmp_path: pathlib.Path, tmp_run: _T_TmpRun) -> None: r"Setting venv path to .+[.]riot/venv_py[0-9]+_requests", result.stderr ) assert result.returncode == 0, result.stderr + + +def test_setup_hash_changed(tmp_path: pathlib.Path, tmp_run: _T_TmpRun) -> None: + rf_path = tmp_path / "riotfile.py" + rf_path.write_text( + """ +from riot import Venv, latest +venv = Venv( + name="test", + pys=["3"], + pkgs={"requests": latest}, + command="python -c 'import requests'", +) +""", + ) + + setup_path = tmp_path / "setup.py" + setup_path.write_text( + """ +from setuptools import setup, find_packages + +setup( + name='foo', + version='1.0.0', + url='https://github.com/bar/foo.git', + author='Me', + author_email='author@email.com', + description='Noop', + packages=find_packages(), + install_requires=[], +) +""", + ) + result = tmp_run("riot -vd --pipe run -s test") + assert "Installing dev package (edit mode)" in result.stderr + assert result.returncode == 0, result.stderr + + # Check that we skip re-installing the dev packege if no changes to setup.py + result = tmp_run("riot -vd --pipe run -s test") + assert "Skipping global deps install." in result.stderr + assert result.returncode == 0, result.stderr + + # Modify setup.py and re-run to check that we are re-installing the dev package + setup_path.write_text( + """ +from setuptools import setup, find_packages + +setup( + name='foo', + version='2.0.0', + url='https://github.com/bar/foo.git', + author='Me', + author_email='author@email.com', + description='Noop', + packages=find_packages(), + install_requires=[], +) +""", + ) + result = tmp_run("riot -vd --pipe run -s test") + assert ( + "Re-installing development package because of setup hash mismatch." + in result.stderr + ) + assert result.returncode == 0, result.stderr + + # Check that we skip re-installing the dev packege if no changes to setup.py + result = tmp_run("riot -vd --pipe run -s test") + assert "Skipping global deps install." in result.stderr + assert result.returncode == 0, result.stderr