Skip to content

Commit

Permalink
Fix channels_remap handling in extra_envs configuration (#808)
Browse files Browse the repository at this point in the history
* Fix channels_remap handling in extra_envs configuration

* add news

* add channels_remap to examples

* map to itself

* to itself

* just use the name

* this time with https

* Mention that the channels must be passed as URLs in channels_remap

* Mention conda/conda-standalone in this error message

* more news

* fix TypeError in tests

* fix dep on Windows

* strip str for good measure

* do pass the dest

* do test channel remaps
  • Loading branch information
jaimergp committed Jun 22, 2024
1 parent 00fd9bb commit 319633c
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 14 deletions.
2 changes: 1 addition & 1 deletion CONSTRUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ See notes in `channels_remap` for details about local channels.
_required:_ no<br/>
_type:_ list<br/>

A list of `src/dest` channel pairs. When building the installer, conda will
A list of `src/dest` channel URL pairs. When building the installer, conda will
use the `src` channels to solve and fetch the packages. However, the resulting
installation will see the packages as coming from the `dest` equivalent.
This allows an installer to be built against a different set of channels than
Expand Down
2 changes: 1 addition & 1 deletion constructor/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
'''),

('channels_remap', False, list, '''
A list of `src/dest` channel pairs. When building the installer, conda will
A list of `src/dest` channel URL pairs. When building the installer, conda will
use the `src` channels to solve and fetch the packages. However, the resulting
installation will see the packages as coming from the `dest` equivalent.
This allows an installer to be built against a different set of channels than
Expand Down
15 changes: 12 additions & 3 deletions constructor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,18 @@ def main_build(dir_path, output_dir='.', platform=cc_platform,
if env_name in ("base", "root"):
raise ValueError(f"Environment name '{env_name}' cannot be used")
for config_key, value in env_config.copy().items():
if isinstance(value, (list, tuple)):
env_config[config_key] = [val.strip() for val in value]
if config_key == "environment_file":
env_config[config_key] = abspath(join(dir_path, value))
elif config_key == "channels_remap":
env_config[config_key] = [
{"src": item["src"].strip(), "dest": item["dest"].strip()} for item in value
]
elif isinstance(value, (list, tuple)):
env_config[config_key] = [val.strip() for val in value]
elif isinstance(value, str):
env_config[config_key] = value.strip()
else:
env_config[config_key] = value

try:
exe_name, exe_version = identify_conda_exe(info.get("_conda_exe"))
Expand Down Expand Up @@ -418,7 +426,8 @@ def main():
easiest way to obtain one is to install the 'conda-standalone' package.
Alternatively, you can download an executable manually and supply its
path with the --conda-exe argument. Self-contained executables can be
downloaded from https://repo.anaconda.com/pkgs/misc/conda-execs/""".lstrip())
downloaded from https://repo.anaconda.com/pkgs/misc/conda-execs/ and/or
https://github.com/conda/conda-standalone/releases""".lstrip())

out_dir = normalize_path(args.output_dir)
main_build(dir_path, output_dir=out_dir, platform=args.platform,
Expand Down
2 changes: 1 addition & 1 deletion docs/source/construct-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ See notes in `channels_remap` for details about local channels.
_required:_ no<br/>
_type:_ list<br/>

A list of `src/dest` channel pairs. When building the installer, conda will
A list of `src/dest` channel URL pairs. When building the installer, conda will
use the `src` channels to solve and fetch the packages. However, the resulting
installation will see the packages as coming from the `dest` equivalent.
This allows an installer to be built against a different set of channels than
Expand Down
7 changes: 5 additions & 2 deletions examples/extra_envs/construct.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ name: ExtraEnvs
version: X
installer_type: all
channels:
- http://repo.anaconda.com/pkgs/main/
- https://conda.anaconda.org/conda-forge
specs:
- python=3.9
- conda # conda is required for extra_envs
- console_shortcut # [win]
- miniforge_console_shortcut # [win]
exclude: # [unix]
- tk # [unix]
extra_envs:
Expand All @@ -16,6 +16,9 @@ extra_envs:
- pip
channels:
- conda-forge
channels_remap:
- src: https://conda.anaconda.org/conda-forge
dest: conda-forge
exclude:
- setuptools
dav1d:
Expand Down
19 changes: 19 additions & 0 deletions news/808-fix-env-channels-remap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Fix `channels_remap` sanitization when included as part of an item in `extra_envs`. (#808)

### Deprecations

* <news item>

### Docs

* Clarify that channels must be passed as URLs in `channels_remap`. (#808)

### Other

* Mention `conda/conda-standalone` repository as a source for conda-standalone downloads in relevant error messages. (#808)
21 changes: 15 additions & 6 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import getpass
import json
import os
import shutil
import subprocess
Expand Down Expand Up @@ -219,7 +220,7 @@ def _sentinel_file_checks(example_path, install_dir):
if (example_path / script).exists() and not (install_dir / sentinel).exists():
raise AssertionError(
f"Sentinel file for {script_prefix}_install not found! "
f"{install_dir} contents:\n" + "\n".join(sorted(install_dir.iterdir()))
f"{install_dir} contents:\n" + "\n".join(sorted(map(str, install_dir.iterdir())))
)


Expand Down Expand Up @@ -511,12 +512,12 @@ def test_example_signing(tmp_path, request):

@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
@pytest.mark.skipif(
not shutil.which("azuresigntool") and not os.environ.get("AZURE_SIGNTOOL_PATH"),
reason="AzureSignTool not available"
not shutil.which("azuresigntool") and not os.environ.get("AZURE_SIGNTOOL_PATH"),
reason="AzureSignTool not available",
)
@pytest.mark.parametrize(
"auth_method",
os.environ.get("AZURE_SIGNTOOL_TEST_AUTH_METHODS", "token,secret").split(","),
"auth_method",
os.environ.get("AZURE_SIGNTOOL_TEST_AUTH_METHODS", "token,secret").split(","),
)
def test_azure_signtool(tmp_path, request, monkeypatch, auth_method):
"""Test signing installers with AzureSignTool.
Expand Down Expand Up @@ -549,7 +550,15 @@ def test_azure_signtool(tmp_path, request, monkeypatch, auth_method):
def test_example_use_channel_remap(tmp_path, request):
input_path = _example_path("use_channel_remap")
for installer, install_dir in create_installer(input_path, tmp_path):
_run_installer(input_path, installer, install_dir, request=request)
_run_installer(input_path, installer, install_dir, request=request, uninstall=False)
p = subprocess.run(
[sys.executable, "-m", "conda", "list", "--prefix", install_dir, "--json"],
capture_output=True,
text=True,
)
packages = json.loads(p.stdout)
for pkg in packages:
assert pkg["channel"] == "private_repo"


def test_example_from_existing_env(tmp_path, request):
Expand Down

0 comments on commit 319633c

Please sign in to comment.