diff --git a/.cspell.json b/.cspell.json index 6d90d413..3216fc9b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -50,6 +50,7 @@ "mkdir", "mypy", "oneline", + "pixi", "pytest", "PYTHONHASHSEED", "rtoml", @@ -71,6 +72,8 @@ "colab", "commitlint", "conda", + "direnv", + "envrc", "fromdict", "indentless", "ipynb", diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..cce3aa58 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +layout anaconda diff --git a/.vscode/settings.json b/.vscode/settings.json index a6e7435d..8fd9d604 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -53,6 +53,7 @@ "python.analysis.autoImportCompletions": false, "python.analysis.inlayHints.pytestParameters": true, "python.analysis.typeCheckingMode": "strict", + "python.terminal.activateEnvironment": false, "python.testing.pytestArgs": ["--color=no", "--no-cov", "-vv"], "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, diff --git a/src/compwa_policy/check_dev_files/__init__.py b/src/compwa_policy/check_dev_files/__init__.py index 9bceadfb..2e9d05e5 100644 --- a/src/compwa_policy/check_dev_files/__init__.py +++ b/src/compwa_policy/check_dev_files/__init__.py @@ -14,6 +14,7 @@ conda, cspell, dependabot, + direnv, editorconfig, github_labels, github_workflows, @@ -58,6 +59,7 @@ def main(argv: Sequence[str] | None = None) -> int: do(conda.main, dev_python_version) do(cspell.main, precommit_config, args.no_cspell_update) do(dependabot.main, args.dependabot) + do(direnv.main) do(editorconfig.main, precommit_config, args.no_python) if not args.allow_labels: do(github_labels.main) diff --git a/src/compwa_policy/check_dev_files/direnv.py b/src/compwa_policy/check_dev_files/direnv.py new file mode 100644 index 00000000..ae267024 --- /dev/null +++ b/src/compwa_policy/check_dev_files/direnv.py @@ -0,0 +1,41 @@ +"""Update the :file:`.envrc` file for `direnv `_.""" + +from __future__ import annotations + +from textwrap import dedent + +from compwa_policy.errors import PrecommitError +from compwa_policy.utilities import CONFIG_PATH +from compwa_policy.utilities.pyproject import Pyproject + + +def main() -> None: + if ( + CONFIG_PATH.pixi_lock.exists() + or CONFIG_PATH.pixi_toml.exists() + or (CONFIG_PATH.pyproject.exists() and Pyproject.load().has_table("tool.pixi")) + ): + _update_envrc(""" + watch_file pixi.lock + eval "$(pixi shell-hook)" + """) + elif CONFIG_PATH.conda.exists(): + _update_envrc("layout anaconda") + + +def _update_envrc(expected: str) -> None: + expected = dedent(expected).strip() + "\n" + existing = __get_existing_envrc() + if existing == expected: + return + with open(".envrc", "w") as f: + f.write(expected) + msg = "Updated .envrc for direnv" + raise PrecommitError(msg) + + +def __get_existing_envrc() -> str | None: + if not CONFIG_PATH.envrc.exists(): + return None + with open(CONFIG_PATH.envrc) as f: + return f.read() diff --git a/src/compwa_policy/check_dev_files/vscode.py b/src/compwa_policy/check_dev_files/vscode.py index 4afa3897..ea7c1403 100644 --- a/src/compwa_policy/check_dev_files/vscode.py +++ b/src/compwa_policy/check_dev_files/vscode.py @@ -2,7 +2,7 @@ import os -from compwa_policy.utilities import vscode +from compwa_policy.utilities import CONFIG_PATH, vscode from compwa_policy.utilities.executor import Executor @@ -73,6 +73,8 @@ def _update_settings(has_notebooks: bool) -> None: if has_notebooks: do(_update_notebook_settings) do(_update_pytest_settings) + if CONFIG_PATH.envrc.exists(): + do(vscode.update_settings, {"python.terminal.activateEnvironment": False}) def _remove_outdated_settings() -> None: diff --git a/src/compwa_policy/utilities/__init__.py b/src/compwa_policy/utilities/__init__.py index 8317e1af..6d199336 100644 --- a/src/compwa_policy/utilities/__init__.py +++ b/src/compwa_policy/utilities/__init__.py @@ -22,12 +22,15 @@ class _ConfigFilePaths(NamedTuple): conda: Path = Path("environment.yml") cspell: Path = Path(".cspell.json") editorconfig: Path = Path(".editorconfig") + envrc: Path = Path(".envrc") github_workflow_dir: Path = Path(".github/workflows") gitpod: Path = Path(".gitpod.yml") pip_constraints: Path = Path(".constraints") + pixi_lock: Path = Path("pixi.lock") + pixi_toml: Path = Path("pixi.toml") precommit: Path = Path(".pre-commit-config.yaml") - prettier: Path = Path(".prettierrc") prettier_ignore: Path = Path(".prettierignore") + prettier: Path = Path(".prettierrc") pyproject: Path = Path("pyproject.toml") pytest_ini: Path = Path("pytest.ini") readme: Path = Path("README.md")