Coverage for src/idiap_devtools/scripts/fullenv.py: 0%
44 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-04-22 14:46 +0200
« prev ^ index » next coverage.py v7.4.3, created at 2024-04-22 14:46 +0200
1# Copyright © 2022 Idiap Research Institute <contact@idiap.ch>
2#
3# SPDX-License-Identifier: BSD-3-Clause
5import pathlib
6import sys
8import click
10from ..click import PreserveIndentCommand, validate_profile, verbosity_option
11from ..logging import setup
13logger = setup(__name__.split(".", 1)[0])
16@click.command(
17 cls=PreserveIndentCommand,
18 epilog="""
19Examples:
21 1. Creates a development environment with all constrained packages (assumes
22 the ``default`` profile is configured):
24 .. code:: sh
26 $ conda activate base
27 (base) $ devtool fullenv -vv
28 (base) $ mamba env create -n dev -f environment.yaml
29 (base) $ conda activate dev
31 2. Creates a development environment with a specific profile:
33 .. code:: sh
35 $ conda activate base
36 (base) $ devtool fullenv -vv -P ../profile
37 (base) $ mamba env create -n dev -f environment.yaml
38 (base) $ conda activate dev
41 .. tip::
43 You may hand-edit the output file ``environment.yaml`` to adjust for
44 details, add conda or Python packages you'd like to complement your work
45 environment. An example would be adding debuggers such as ``ipdb`` to
46 the installation plan before calling ``mamba env create``.
48""",
49)
50@click.option(
51 "-P",
52 "--profile",
53 default="default",
54 show_default=True,
55 callback=validate_profile,
56 help="Directory containing the development profile (and a file named "
57 "profile.toml), or the name of a configuration key pointing to the "
58 "development profile to use",
59)
60@click.option(
61 "-p",
62 "--python",
63 default=("%d.%d" % sys.version_info[:2]),
64 show_default=True,
65 help="Version of python to build the environment for",
66)
67@click.option(
68 "-Y",
69 "--only-python/--no-only-python",
70 default=False,
71 show_default=True,
72 help="Only installs Python packages, and not conda packages "
73 "(except for Python itself, and pip)",
74)
75@click.option(
76 "-o",
77 "--output",
78 default="environment.yaml",
79 show_default=True,
80 help="The name of the environment plan file",
81 type=click.Path(path_type=pathlib.Path),
82)
83@verbosity_option(logger=logger)
84def fullenv(
85 profile,
86 python,
87 only_python,
88 output,
89 **_,
90) -> None:
91 """Create a development environment with all constrained packages."""
93 import shutil
94 import typing
96 import yaml
98 from ..profile import Profile
100 the_profile = Profile(profile)
102 base_environment = dict(python=python, pip=None)
104 if only_python:
105 conda_packages = None
106 else:
107 conda_packages = the_profile.conda_constraints(python)
109 if conda_packages is not None:
110 conda_packages.update(base_environment)
111 else:
112 conda_packages = base_environment
114 python_packages = the_profile.python_constraints()
115 if python_packages is None:
116 python_packages = []
118 # filter out all conda packages already in the list
119 conda_to_python = the_profile.get(("conda", "to_python"), {})
120 python_to_conda = {v: k for k, v in conda_to_python.items() if k != "__ignore__"}
121 python_packages = [
122 k
123 for k in python_packages
124 if python_to_conda.get(k.name, k.name) not in conda_packages
125 ]
127 data: dict[str, typing.Any] = dict(channels=["conda-forge"])
129 data["dependencies"] = sorted(
130 [f"{k} {v}" if v is not None else k for k, v in conda_packages.items()]
131 )
133 if python_packages:
134 data["dependencies"].append(dict(pip=sorted([str(k) for k in python_packages])))
136 # backup previous installation plan, if one exists
137 if output.exists():
138 backup = output.parent / (output.name + "~")
139 shutil.copy(output, backup)
141 with output.open("w") as f:
142 yaml.dump(data, f)
144 click.echo(
145 "Run the following commands to create and prepare your development environment:"
146 )
147 install_cmds = [
148 f"mamba env create --force -n dev -f {output}",
149 "conda activate dev",
150 ]
151 for k in install_cmds:
152 click.secho(k, fg="yellow", bold=True)