Skip to content

Commit

Permalink
FEAT: create or remove Conda environment.yml (#375)
Browse files Browse the repository at this point in the history
* ENH: set `PRETTIER_LEGACY_CLI` as integer in YAML
  • Loading branch information
redeboer authored Aug 13, 2024
1 parent 2834e0e commit 6a5e511
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 17 deletions.
16 changes: 15 additions & 1 deletion src/compwa_policy/check_dev_files/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import sys
from argparse import ArgumentParser
from textwrap import dedent
from typing import TYPE_CHECKING, Any, Sequence

from compwa_policy.check_dev_files import (
Expand Down Expand Up @@ -52,12 +53,15 @@ def main(argv: Sequence[str] | None = None) -> int:
args.repo_title = args.repo_name
has_notebooks = not args.no_notebooks
dev_python_version = __get_python_version(args.dev_python_version)
package_managers: set[conda.PackageManagerChoice] = set(
_to_list(args.package_managers) # type: ignore[arg-type]
)
with Executor(
raise_exception=False
) as do, ModifiablePrecommit.load() as precommit_config:
do(citation.main, precommit_config)
do(commitlint.main)
do(conda.main, dev_python_version)
do(conda.main, dev_python_version, package_managers)
do(dependabot.main, args.dependabot)
do(editorconfig.main, precommit_config)
if not args.allow_labels:
Expand Down Expand Up @@ -268,6 +272,16 @@ def _create_argparse() -> ArgumentParser:
default=False,
help="Do not push to matching major/minor version branches upon tagging",
)
package_manager_choices = ", ".join(sorted(conda.PackageManagerChoice.__args__)) # type:ignore[attr-defined]
parser.add_argument(
"--package-managers",
default=package_manager_choices,
help=dedent(f"""
Specify which package managers to use for the project as a comma-separated
list. Possible options: {package_manager_choices}
""").replace("\n", " "),
type=str,
)
parser.add_argument(
"--pin-requirements",
choices=update_pip_constraints.Frequency.__args__, # type:ignore[attr-defined]
Expand Down
68 changes: 54 additions & 14 deletions src/compwa_policy/check_dev_files/conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,73 @@

from __future__ import annotations

from typing import TYPE_CHECKING
import sys
from typing import NoReturn

from ruamel.yaml.comments import CommentedMap, CommentedSeq
from ruamel.yaml.scalarstring import PlainScalarString

from compwa_policy.errors import PrecommitError
from compwa_policy.utilities import CONFIG_PATH
from compwa_policy.utilities.pyproject import (
Pyproject,
PythonVersion,
get_build_system,
get_constraints_file,
)
from compwa_policy.utilities.yaml import create_prettier_round_trip_yaml

if TYPE_CHECKING:
from ruamel.yaml.comments import CommentedMap, CommentedSeq
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal

PackageManagerChoice = Literal["conda", "pixi", "uv", "venv"]

def main(python_version: PythonVersion) -> None:
if not CONFIG_PATH.conda.exists():
return

def main(
python_version: PythonVersion, package_managers: set[PackageManagerChoice]
) -> None:
if "conda" in package_managers:
update_conda_environment(python_version)
elif CONFIG_PATH.conda.exists():
_remove_conda_configuration(package_managers)


def update_conda_environment(python_version: PythonVersion) -> None:
if get_build_system() is None:
return
yaml = create_prettier_round_trip_yaml()
conda_env: CommentedMap = yaml.load(CONFIG_PATH.conda)
conda_deps: CommentedSeq = conda_env.get("dependencies", [])

updated = _update_python_version(python_version, conda_deps)
updated |= _update_pip_dependencies(python_version, conda_deps)
updated = False
if CONFIG_PATH.conda.exists():
conda_env: CommentedMap = yaml.load(CONFIG_PATH.conda)
else:
conda_env = __create_conda_environment(python_version)
updated = True
if "dependencies" not in conda_env:
conda_env["dependencies"] = CommentedSeq()
conda_deps: CommentedSeq = conda_env["dependencies"]
updated |= __update_python_version(python_version, conda_deps)
updated |= __update_pip_dependencies(python_version, conda_deps)
if updated:
yaml.dump(conda_env, CONFIG_PATH.conda)
msg = f"Set the Python version in {CONFIG_PATH.conda} to {python_version}"
msg = f"Updated Conda environment for Python {python_version}"
raise PrecommitError(msg)


def _update_python_version(version: PythonVersion, conda_deps: CommentedSeq) -> bool:
def __create_conda_environment(python_version: PythonVersion) -> CommentedMap:
return CommentedMap({
"name": Pyproject.load().get_package_name(),
"channels": ["defaults"],
"dependencies": [
f"python=={python_version}.*",
"pip",
{"pip": ["-e .[dev]"]},
],
})


def __update_python_version(version: PythonVersion, conda_deps: CommentedSeq) -> bool:
idx = __find_python_dependency_index(conda_deps)
expected = f"python=={version}.*"
if idx is not None and conda_deps[idx] != expected:
Expand All @@ -45,7 +77,7 @@ def _update_python_version(version: PythonVersion, conda_deps: CommentedSeq) ->
return False


def _update_pip_dependencies(version: PythonVersion, conda_deps: CommentedSeq) -> bool:
def __update_pip_dependencies(version: PythonVersion, conda_deps: CommentedSeq) -> bool:
pip_deps = __get_pip_dependencies(conda_deps)
if pip_deps is None:
return False
Expand Down Expand Up @@ -77,3 +109,11 @@ def __get_pip_dependencies(dependencies: CommentedSeq) -> CommentedSeq | None:
if pip_deps is not None and isinstance(pip_deps, list):
return pip_deps
return None


def _remove_conda_configuration(
package_managers: set[PackageManagerChoice],
) -> NoReturn:
CONFIG_PATH.conda.unlink()
msg = f"Removed Conda configuration, because --package-managers={','.join(sorted(package_managers))}"
raise PrecommitError(msg)
3 changes: 1 addition & 2 deletions src/compwa_policy/check_dev_files/precommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import TYPE_CHECKING, cast

from ruamel.yaml.comments import CommentedMap
from ruamel.yaml.scalarstring import DoubleQuotedScalarString

from compwa_policy.errors import PrecommitError
from compwa_policy.utilities.executor import Executor
Expand Down Expand Up @@ -153,7 +152,7 @@ def _update_conda_environment(precommit: Precommit) -> None:
key = "PRETTIER_LEGACY_CLI"
if __has_prettier_v4alpha(precommit.document):
if key not in variables:
variables[key] = DoubleQuotedScalarString("1")
variables[key] = 1
conda_env["variables"] = variables
yaml.dump(conda_env, path)
msg = f"Set {key} environment variable in {path}"
Expand Down

0 comments on commit 6a5e511

Please sign in to comment.