From 2a30de418553397eccc285ff0ade7d53afb04d70 Mon Sep 17 00:00:00 2001 From: Kevin Mills Date: Wed, 25 Oct 2023 14:43:36 -0500 Subject: [PATCH 01/14] Add cli option to supply path to the construct yaml file Signed-off-by: Kevin Mills --- constructor/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/constructor/main.py b/constructor/main.py index 130198487..80f47cf7f 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -303,6 +303,12 @@ def main(): action="store", metavar="CONDA_EXE") + p.add_argument('--construct-yaml-path', + help="path to construct YAML file ready by constructor", + action="store", + metavar="CONSTRUCT_YAML_PATH", + default="construct.yaml") + p.add_argument('dir_path', help="directory containing construct.yaml", action="store", From 4f86998476cbb8808ba2b4acc51e6e292c4e7c4b Mon Sep 17 00:00:00 2001 From: Kevin Mills Date: Wed, 25 Oct 2023 14:57:46 -0500 Subject: [PATCH 02/14] Add construct_yaml_path to main_build --- constructor/main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index 80f47cf7f..62361f90f 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -66,7 +66,8 @@ def get_output_filename(info): def main_build(dir_path, output_dir='.', platform=cc_platform, verbose=True, cache_dir=DEFAULT_CACHE_DIR, - dry_run=False, conda_exe="conda.exe"): + dry_run=False, conda_exe="conda.exe", + construct_yaml_path="construct.yaml"): logger.info('platform: %s', platform) if not os.path.isfile(conda_exe): sys.exit("Error: Conda executable '%s' does not exist!" % conda_exe) @@ -76,7 +77,7 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, except ValueError: sys.exit("Error: invalid platform string '%s'" % platform) - construct_path = join(dir_path, 'construct.yaml') + construct_path = construct_yaml_path info = construct_parse(construct_path, platform) construct_verify(info) info['CONSTRUCTOR_VERSION'] = __version__ @@ -307,7 +308,8 @@ def main(): help="path to construct YAML file ready by constructor", action="store", metavar="CONSTRUCT_YAML_PATH", - default="construct.yaml") + default=join(os.getcwd(), 'construct.yaml') +) p.add_argument('dir_path', help="directory containing construct.yaml", @@ -317,6 +319,7 @@ def main(): metavar='DIRECTORY') args = p.parse_args() + logger.info("Got the following cli arguments: '%s'", args) if args.verbose or args.debug: @@ -356,7 +359,8 @@ def main(): out_dir = normalize_path(args.output_dir) main_build(dir_path, output_dir=out_dir, platform=args.platform, verbose=args.verbose, cache_dir=args.cache_dir, - dry_run=args.dry_run, conda_exe=conda_exe) + dry_run=args.dry_run, conda_exe=conda_exe, + construct_yaml_path=normalize_path(args.construct_yaml_path)) if __name__ == '__main__': From 030ed6916a06e5551687f2de4ca665bdb37f1ba2 Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:46:32 -0500 Subject: [PATCH 03/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index 62361f90f..9213b9dff 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -77,7 +77,7 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, except ValueError: sys.exit("Error: invalid platform string '%s'" % platform) - construct_path = construct_yaml_path + construct_path = join(dir_path, construct_yaml_filename) info = construct_parse(construct_path, platform) construct_verify(info) info['CONSTRUCTOR_VERSION'] = __version__ From 75816cee44e12768744f1759c3aa947c53f1ce2d Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:46:40 -0500 Subject: [PATCH 04/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index 9213b9dff..170950204 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -67,7 +67,7 @@ def get_output_filename(info): def main_build(dir_path, output_dir='.', platform=cc_platform, verbose=True, cache_dir=DEFAULT_CACHE_DIR, dry_run=False, conda_exe="conda.exe", - construct_yaml_path="construct.yaml"): + construct_yaml_filename="construct.yaml"): logger.info('platform: %s', platform) if not os.path.isfile(conda_exe): sys.exit("Error: Conda executable '%s' does not exist!" % conda_exe) From 56a495464878d8ac76272cf72d0d268521aa9fd3 Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:46:47 -0500 Subject: [PATCH 05/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index 170950204..fe59ea4a4 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -304,7 +304,7 @@ def main(): action="store", metavar="CONDA_EXE") - p.add_argument('--construct-yaml-path', + p.add_argument('--construct-yaml-fn', help="path to construct YAML file ready by constructor", action="store", metavar="CONSTRUCT_YAML_PATH", From 2246820074a7f614885cd4ea0ffd5304eae2a533 Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:47:09 -0500 Subject: [PATCH 06/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index fe59ea4a4..170a63651 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -308,7 +308,7 @@ def main(): help="path to construct YAML file ready by constructor", action="store", metavar="CONSTRUCT_YAML_PATH", - default=join(os.getcwd(), 'construct.yaml') + default="construct.yaml", ) p.add_argument('dir_path', From 3100659cb3f6cf2c65a60a51f20c20cddbe21d23 Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:47:30 -0500 Subject: [PATCH 07/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index 170a63651..c5d5d6cc8 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -307,7 +307,8 @@ def main(): p.add_argument('--construct-yaml-fn', help="path to construct YAML file ready by constructor", action="store", - metavar="CONSTRUCT_YAML_PATH", + metavar="FILENAME", + dest="construct_yaml_filename", default="construct.yaml", ) From 9262142648d6f9a901d29577e101f5636df2a709 Mon Sep 17 00:00:00 2001 From: Kevin Mills <35641675+millsks@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:47:44 -0500 Subject: [PATCH 08/14] Update constructor/main.py Co-authored-by: jaimergp --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index c5d5d6cc8..c2ce139fb 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -361,7 +361,7 @@ def main(): main_build(dir_path, output_dir=out_dir, platform=args.platform, verbose=args.verbose, cache_dir=args.cache_dir, dry_run=args.dry_run, conda_exe=conda_exe, - construct_yaml_path=normalize_path(args.construct_yaml_path)) + construct_yaml_path=args.construct_yaml_path if __name__ == '__main__': From 69602dc4b595508e7be2ce5c0a8e5674c439ca6b Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 2 Jan 2024 17:09:17 +0100 Subject: [PATCH 09/14] fix syntax --- constructor/main.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index c2ce139fb..7bc4998da 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -309,8 +309,7 @@ def main(): action="store", metavar="FILENAME", dest="construct_yaml_filename", - default="construct.yaml", -) + default="construct.yaml") p.add_argument('dir_path', help="directory containing construct.yaml", @@ -320,7 +319,6 @@ def main(): metavar='DIRECTORY') args = p.parse_args() - logger.info("Got the following cli arguments: '%s'", args) if args.verbose or args.debug: @@ -361,7 +359,7 @@ def main(): main_build(dir_path, output_dir=out_dir, platform=args.platform, verbose=args.verbose, cache_dir=args.cache_dir, dry_run=args.dry_run, conda_exe=conda_exe, - construct_yaml_path=args.construct_yaml_path + construct_yaml_filename=args.construct_yaml_path) if __name__ == '__main__': From d0f2b0d0e987268a14b18fda819bb5eacce7338b Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 2 Jan 2024 17:12:31 +0100 Subject: [PATCH 10/14] add test --- .../noconda/{construct.yaml => constructor_input.yaml} | 0 tests/test_examples.py | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) rename examples/noconda/{construct.yaml => constructor_input.yaml} (100%) diff --git a/examples/noconda/construct.yaml b/examples/noconda/constructor_input.yaml similarity index 100% rename from examples/noconda/construct.yaml rename to examples/noconda/constructor_input.yaml diff --git a/tests/test_examples.py b/tests/test_examples.py index 55f3b27d2..9ae5d3553 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -234,6 +234,7 @@ def create_installer( debug=CONSTRUCTOR_DEBUG, with_spaces=False, timeout=420, + construct_yaml_filename="construct.yaml", **env_vars, ) -> Tuple[Path, Path]: if sys.platform.startswith("win") and conda_exe and _is_micromamba(conda_exe): @@ -248,6 +249,8 @@ def create_installer( str(input_dir), "--output-dir", str(output_dir), + "--construct-yaml-fn", + construct_yaml_filename, ] if conda_exe: cmd.extend(["--conda-exe", conda_exe]) @@ -346,7 +349,9 @@ def test_example_miniforge(tmp_path, request): def test_example_noconda(tmp_path, request): input_path = _example_path("noconda") - for installer, install_dir in create_installer(input_path, tmp_path, with_spaces=True): + for installer, install_dir in create_installer( + input_path, tmp_path, construct_yaml_filename="constructor_input.yaml", with_spaces=True + ): _run_installer(input_path, installer, install_dir, request=request) From 1308f49a77675eda64f387c4c930446d63bd3670 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 27 Feb 2024 11:20:23 +0100 Subject: [PATCH 11/14] add news --- news/758-yaml-filename | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 news/758-yaml-filename diff --git a/news/758-yaml-filename b/news/758-yaml-filename new file mode 100644 index 000000000..8d33f9c9f --- /dev/null +++ b/news/758-yaml-filename @@ -0,0 +1,19 @@ +### Enhancements + +* Add a new `--construct-yaml-fn` argument to specify an input file not named `construct.yaml`. (#727 via #758) + +### Bug fixes + +* + +### Deprecations + +* + +### Docs + +* + +### Other + +* From 3d0387722e48b70b14363195c8684ccb234c5c8d Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 27 Feb 2024 12:09:36 +0100 Subject: [PATCH 12/14] fix attribute name --- constructor/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/main.py b/constructor/main.py index 27b0070ae..b07bf6c0a 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -413,7 +413,7 @@ def main(): main_build(dir_path, output_dir=out_dir, platform=args.platform, verbose=args.verbose, cache_dir=args.cache_dir, dry_run=args.dry_run, conda_exe=conda_exe, - construct_yaml_filename=args.construct_yaml_path) + construct_yaml_filename=args.construct_yaml_filename) if __name__ == '__main__': From bc00ed1c56e83f5024657c16f95cc58004fdc45a Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 29 Feb 2024 11:38:08 +0100 Subject: [PATCH 13/14] validate --config-filename --- constructor/main.py | 15 ++++++++++----- news/758-yaml-filename | 2 +- tests/test_examples.py | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index b07bf6c0a..76f483aea 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -69,7 +69,7 @@ def get_output_filename(info): def main_build(dir_path, output_dir='.', platform=cc_platform, verbose=True, cache_dir=DEFAULT_CACHE_DIR, dry_run=False, conda_exe="conda.exe", - construct_yaml_filename="construct.yaml"): + config_filename="construct.yaml"): logger.info('platform: %s', platform) if not os.path.isfile(conda_exe): sys.exit("Error: Conda executable '%s' does not exist!" % conda_exe) @@ -79,7 +79,7 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, except ValueError: sys.exit("Error: invalid platform string '%s'" % platform) - construct_path = join(dir_path, construct_yaml_filename) + construct_path = join(dir_path, config_filename) info = construct_parse(construct_path, platform) construct_verify(info) info['CONSTRUCTOR_VERSION'] = __version__ @@ -358,11 +358,11 @@ def main(): action="store", metavar="CONDA_EXE") - p.add_argument('--construct-yaml-fn', + p.add_argument('--config-filename', help="path to construct YAML file ready by constructor", action="store", metavar="FILENAME", - dest="construct_yaml_filename", + dest="config_filename", default="construct.yaml") p.add_argument('dir_path', @@ -389,6 +389,11 @@ def main(): dir_path = args.dir_path if not isdir(dir_path): p.error("no such directory: %s" % dir_path) + if os.sep in args.config_filename: + p.error("--config-filename can only be a filename, not a path") + full_config_path = os.path.join(dir_path, args.config_filename) + if not os.path.isfile(full_config_path): + p.error("no such file: %s" % full_config_path) conda_exe = args.conda_exe conda_exe_default_path = os.path.join(sys.prefix, "standalone_conda", "conda.exe") @@ -413,7 +418,7 @@ def main(): main_build(dir_path, output_dir=out_dir, platform=args.platform, verbose=args.verbose, cache_dir=args.cache_dir, dry_run=args.dry_run, conda_exe=conda_exe, - construct_yaml_filename=args.construct_yaml_filename) + config_filename=args.config_filename) if __name__ == '__main__': diff --git a/news/758-yaml-filename b/news/758-yaml-filename index 8d33f9c9f..394550aea 100644 --- a/news/758-yaml-filename +++ b/news/758-yaml-filename @@ -1,6 +1,6 @@ ### Enhancements -* Add a new `--construct-yaml-fn` argument to specify an input file not named `construct.yaml`. (#727 via #758) +* Add a new `--config-filename` argument to specify an input file not named `construct.yaml`. (#727 via #758) ### Bug fixes diff --git a/tests/test_examples.py b/tests/test_examples.py index 8edcf4af1..d6b8e3f43 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -250,7 +250,7 @@ def create_installer( debug=CONSTRUCTOR_DEBUG, with_spaces=False, timeout=420, - construct_yaml_filename="construct.yaml", + config_filename="construct.yaml", extra_constructor_args: Iterable[str] = None, **env_vars, ) -> Generator[Tuple[Path, Path], None, None]: @@ -267,7 +267,7 @@ def create_installer( "--output-dir", str(output_dir), "--construct-yaml-fn", - construct_yaml_filename, + config_filename, ] if conda_exe: cmd.extend(["--conda-exe", conda_exe]) @@ -387,7 +387,7 @@ def test_example_miniforge(tmp_path, request): def test_example_noconda(tmp_path, request): input_path = _example_path("noconda") for installer, install_dir in create_installer( - input_path, tmp_path, construct_yaml_filename="constructor_input.yaml", with_spaces=True + input_path, tmp_path, config_filename="constructor_input.yaml", with_spaces=True ): _run_installer(input_path, installer, install_dir, request=request) From 29d0393fa2cbef9553a410891fec1a65e1e908da Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 29 Feb 2024 11:46:17 +0100 Subject: [PATCH 14/14] fix tests --- tests/test_examples.py | 52 +++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index d6b8e3f43..90ea18c75 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -179,7 +179,13 @@ def _run_installer_sh(installer, install_dir, installer_input=None, timeout=420) return _execute(cmd, installer_input=installer_input, timeout=timeout) -def _run_installer_pkg(installer, install_dir, example_path=None, timeout=420): +def _run_installer_pkg( + installer, + install_dir, + example_path=None, + config_filename="construct.yaml", + timeout=420, +): if os.environ.get("CI"): # We want to run it in an arbitrary directory, but the options # are limited here... We can only install to $HOME :shrug: @@ -193,7 +199,7 @@ def _run_installer_pkg(installer, install_dir, example_path=None, timeout=420): "CurrentUserHomeDirectory", ] if example_path: - install_dir = calculate_install_dir(example_path / "construct.yaml") + install_dir = calculate_install_dir(example_path / config_filename) install_dir = Path(os.environ["HOME"]) / install_dir else: # This command only expands the PKG, but does not install @@ -222,6 +228,7 @@ def _run_installer( installer: Path, install_dir: Path, installer_input: Optional[str] = None, + config_filename="construct.yaml", check_sentinels=True, request=None, uninstall=True, @@ -234,7 +241,13 @@ def _run_installer( elif installer.suffix == ".pkg": if request and ON_CI: request.addfinalizer(lambda: shutil.rmtree(str(install_dir))) - _run_installer_pkg(installer, install_dir, example_path=example_path, timeout=timeout) + _run_installer_pkg( + installer, + install_dir, + example_path=example_path, + config_filename=config_filename, + timeout=timeout, + ) else: raise ValueError(f"Unknown installer type: {installer.suffix}") if check_sentinels: @@ -266,7 +279,7 @@ def create_installer( str(input_dir), "--output-dir", str(output_dir), - "--construct-yaml-fn", + "--config-filename", config_filename, ] if conda_exe: @@ -288,7 +301,7 @@ def _sort_by_extension(path): for installer in sorted(installers, key=_sort_by_extension): if installer.suffix == ".pkg" and ON_CI: install_dir = Path("~").expanduser() / calculate_install_dir( - input_dir / "construct.yaml" + input_dir / config_filename ) else: install_dir = ( @@ -389,7 +402,13 @@ def test_example_noconda(tmp_path, request): for installer, install_dir in create_installer( input_path, tmp_path, config_filename="constructor_input.yaml", with_spaces=True ): - _run_installer(input_path, installer, install_dir, request=request) + _run_installer( + input_path, + installer, + install_dir, + config_filename="constructor_input.yaml", + request=request, + ) @pytest.mark.skipif(sys.platform != "darwin", reason="macOS only") @@ -530,28 +549,28 @@ def test_register_envs(tmp_path, request): assert str(install_dir) not in environments_txt -@pytest.mark.skipif(sys.platform != 'darwin', reason='MacOS only') -@pytest.mark.parametrize('domains', ({}, {'enable_anywhere': 'false', 'enable_localSystem': True})) +@pytest.mark.skipif(sys.platform != "darwin", reason="MacOS only") +@pytest.mark.parametrize("domains", ({}, {"enable_anywhere": "false", "enable_localSystem": True})) def test_pkg_distribution_domains(tmp_path, domains): - recipe_path = _example_path('osxpkg') - input_path = tmp_path / 'input' - output_path = tmp_path / 'output' + recipe_path = _example_path("osxpkg") + input_path = tmp_path / "input" + output_path = tmp_path / "output" shutil.copytree(str(recipe_path), str(input_path)) if domains: with open(input_path / "construct.yaml", "a") as cyml: - cyml.write('pkg_domains:\n') + cyml.write("pkg_domains:\n") for key, val in domains.items(): cyml.write(f" {key}: {val}\n") installer, install_dir = next(create_installer(input_path, output_path)) - cmd = ['pkgutil', '--expand', installer, output_path / "expanded"] + cmd = ["pkgutil", "--expand", installer, output_path / "expanded"] _execute(cmd) - domains_file = output_path / "expanded" / 'Distribution' + domains_file = output_path / "expanded" / "Distribution" assert domains_file.exists() tree = ET.parse(domains_file) - found = {key: val for key, val in tree.find('domains').items()} - defaults = {'enable_anywhere': 'true', 'enable_currentUserHome': 'true'} + found = {key: val for key, val in tree.find("domains").items()} + defaults = {"enable_anywhere": "true", "enable_currentUserHome": "true"} expected = {key: str(val).lower() for key, val in domains.items()} if domains else defaults assert expected == found @@ -579,4 +598,5 @@ def test_cross_osx_building(tmp_path): tmp_path, conda_exe=micromamba_arm64, extra_constructor_args=["--platform", "osx-arm64"], + config_filename="constructor_input.yaml", )