From 5ad9fff3d36bdd8d19db53eb557ec9b61e592234 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 10:25:04 -0500 Subject: [PATCH 01/14] api for print_info --- src/diffpy/cmi/packsmanager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/diffpy/cmi/packsmanager.py b/src/diffpy/cmi/packsmanager.py index 8c2f431..154fc2a 100644 --- a/src/diffpy/cmi/packsmanager.py +++ b/src/diffpy/cmi/packsmanager.py @@ -256,6 +256,10 @@ def _copy_new_example( shutil.copytree(example_origin, target) print(f"Copied example '{pack_name}/{example_name}'.") + def print_info(self) -> None: + """Print information about available packs and examples.""" + return + def _resolve_pack_file(self, identifier: Union[str, Path]) -> Path: """Resolve a pack identifier to an absolute .txt path. From 0465c801c8ffab0af80ccbd6ac9f97611e1877fb Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 10:26:36 -0500 Subject: [PATCH 02/14] temp dir for print_info test --- tests/conftest.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 263a20a..5214bd3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,26 @@ import pytest +@pytest.fixture(scope="function") +def temp_dir_print_info(tmp_path_factory): + root_temp_dir = tmp_path_factory.mktemp("temp") + examples_dir = root_temp_dir / "docs" / "examples" + packs_dir = root_temp_dir / "requirements" / "packs" + packs_dir.mkdir(parents=True, exist_ok=True) + fake_env = root_temp_dir / "fake_env" + fake_env.mkdir(parents=True, exist_ok=True) + + (packs_dir / "packa.txt").write_text("packaging") + (packs_dir / "packb.txt").write_text("matplotlib") + (examples_dir / "packA" / "ex1").mkdir(parents=True, exist_ok=True) + (examples_dir / "packA" / "ex2").mkdir(parents=True, exist_ok=True) + (examples_dir / "packB" / "ex1").mkdir(parents=True, exist_ok=True) + (examples_dir / "packB" / "ex3").mkdir(parents=True, exist_ok=True) + (examples_dir / "packB" / "ex4").mkdir(parents=True, exist_ok=True) + + yield root_temp_dir + + @pytest.fixture(scope="function") def example_cases(tmp_path_factory): """Copy the entire examples tree into a temp directory once per test From cdc14f7b94ec4be4fdec64baedf70029e58ebcf0 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 10:27:15 -0500 Subject: [PATCH 03/14] print_info test --- tests/test_packsmanager.py | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/test_packsmanager.py b/tests/test_packsmanager.py index 7f02b1a..77d927b 100644 --- a/tests/test_packsmanager.py +++ b/tests/test_packsmanager.py @@ -1,5 +1,7 @@ import os import re +import subprocess +import venv from pathlib import Path import pytest @@ -342,3 +344,45 @@ def test_copy_examples_force(example_cases, expected_paths, force): original_path = examples_dir / path if copied_path.is_file() and original_path.is_file(): assert copied_path.read_text() == original_path.read_text() + + +install_params = [ + ( # input: install requirements for packA + # expected: print_info output showing packA installed but not packB + ("packA",), + """Installed Packs: + packA + +Available Packs to Install: + packB + +Examples: + packA: + - ex1 + - ex2 + packB: + - ex1 + - ex3 + - ex4""", + ), +] + + +@pytest.mark.parametrize("packs_to_install,expected", install_params) +def test_print_info(packs_to_install, expected, temp_dir_print_info, capsys): + env_dir = temp_dir_print_info / "fake_env" + req_dir = temp_dir_print_info / "requirements" / "packs" + venv.EnvBuilder(with_pip=True).create(env_dir) + for pack in packs_to_install: + req_file = req_dir / f"{pack.lower()}.txt" + subprocess.run( + [str(env_dir / "bin" / "pip"), "install", "-r", str(req_file)], + check=True, + capture_output=True, + text=True, + ) + pm = PacksManager(root_path=temp_dir_print_info) + pm.print_info() + captured = capsys.readouterr() + actual = captured.out + assert actual.strip() == expected.strip() From 7283add88c69d02006d603ccea2db6ad8150849b Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 10:28:18 -0500 Subject: [PATCH 04/14] news --- news/printing-info.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/printing-info.rst diff --git a/news/printing-info.rst b/news/printing-info.rst new file mode 100644 index 0000000..bf89a6d --- /dev/null +++ b/news/printing-info.rst @@ -0,0 +1,23 @@ +**Added:** + +* Added test for ``print_info`` function. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From 794c93ec7e6301fd047b3b43e641dc778694d089 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 11:40:56 -0500 Subject: [PATCH 05/14] update news --- news/printing-info.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/news/printing-info.rst b/news/printing-info.rst index bf89a6d..7d48461 100644 --- a/news/printing-info.rst +++ b/news/printing-info.rst @@ -1,6 +1,6 @@ **Added:** -* Added test for ``print_info`` function. +* Added ``print_info`` function. **Changed:** From 5efb57163f41f3cc3d2cc4a12fce22df6e10cc7c Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 11:42:14 -0500 Subject: [PATCH 06/14] add req files to case5 dir --- tests/conftest.py | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5214bd3..ee1b5be 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,26 +5,6 @@ import pytest -@pytest.fixture(scope="function") -def temp_dir_print_info(tmp_path_factory): - root_temp_dir = tmp_path_factory.mktemp("temp") - examples_dir = root_temp_dir / "docs" / "examples" - packs_dir = root_temp_dir / "requirements" / "packs" - packs_dir.mkdir(parents=True, exist_ok=True) - fake_env = root_temp_dir / "fake_env" - fake_env.mkdir(parents=True, exist_ok=True) - - (packs_dir / "packa.txt").write_text("packaging") - (packs_dir / "packb.txt").write_text("matplotlib") - (examples_dir / "packA" / "ex1").mkdir(parents=True, exist_ok=True) - (examples_dir / "packA" / "ex2").mkdir(parents=True, exist_ok=True) - (examples_dir / "packB" / "ex1").mkdir(parents=True, exist_ok=True) - (examples_dir / "packB" / "ex3").mkdir(parents=True, exist_ok=True) - (examples_dir / "packB" / "ex4").mkdir(parents=True, exist_ok=True) - - yield root_temp_dir - - @pytest.fixture(scope="function") def example_cases(tmp_path_factory): """Copy the entire examples tree into a temp directory once per test @@ -116,6 +96,12 @@ def example_cases(tmp_path_factory): case5req_dir = root_temp_dir / "case5" / "requirements" / "packs" case5req_dir.mkdir(parents=True, exist_ok=True) + case5req_dir = root_temp_dir / "requirements" / "packs" + fake_env = root_temp_dir / "case5" / "fake_env" + fake_env.mkdir(parents=True, exist_ok=True) + (case5req_dir / "packa.txt").write_text("packaging") + (case5req_dir / "packb.txt").write_text("numpy") + yield root_temp_dir From 6d357450a661046b4344a513274dabf62489aef8 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 11:43:00 -0500 Subject: [PATCH 07/14] update test with example_cases fixture --- tests/test_packsmanager.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_packsmanager.py b/tests/test_packsmanager.py index 77d927b..d11da31 100644 --- a/tests/test_packsmanager.py +++ b/tests/test_packsmanager.py @@ -351,16 +351,16 @@ def test_copy_examples_force(example_cases, expected_paths, force): # expected: print_info output showing packA installed but not packB ("packA",), """Installed Packs: - packA + packa Available Packs to Install: - packB + packb Examples: - packA: + packa: - ex1 - ex2 - packB: + packb: - ex1 - ex3 - ex4""", @@ -369,9 +369,10 @@ def test_copy_examples_force(example_cases, expected_paths, force): @pytest.mark.parametrize("packs_to_install,expected", install_params) -def test_print_info(packs_to_install, expected, temp_dir_print_info, capsys): - env_dir = temp_dir_print_info / "fake_env" - req_dir = temp_dir_print_info / "requirements" / "packs" +def test_print_info(packs_to_install, expected, example_cases, capsys): + case5dir = example_cases / "case5" + env_dir = case5dir / "fake_env" + req_dir = case5dir / "requirements" / "packs" venv.EnvBuilder(with_pip=True).create(env_dir) for pack in packs_to_install: req_file = req_dir / f"{pack.lower()}.txt" @@ -381,7 +382,7 @@ def test_print_info(packs_to_install, expected, temp_dir_print_info, capsys): capture_output=True, text=True, ) - pm = PacksManager(root_path=temp_dir_print_info) + pm = PacksManager(root_path=case5dir) pm.print_info() captured = capsys.readouterr() actual = captured.out From d591fdd943d607d978edb3ede290ce2b98619d1b Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 11:53:05 -0500 Subject: [PATCH 08/14] fix bug in temp dir structure --- tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index ee1b5be..d6af927 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -96,7 +96,6 @@ def example_cases(tmp_path_factory): case5req_dir = root_temp_dir / "case5" / "requirements" / "packs" case5req_dir.mkdir(parents=True, exist_ok=True) - case5req_dir = root_temp_dir / "requirements" / "packs" fake_env = root_temp_dir / "case5" / "fake_env" fake_env.mkdir(parents=True, exist_ok=True) (case5req_dir / "packa.txt").write_text("packaging") From a9752b4ba8a524b2d813530306cef07269f10a13 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:22:58 -0500 Subject: [PATCH 09/14] use requests and attrs because theyre not listed in requirements --- tests/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index d6af927..af72bd5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -98,8 +98,8 @@ def example_cases(tmp_path_factory): fake_env = root_temp_dir / "case5" / "fake_env" fake_env.mkdir(parents=True, exist_ok=True) - (case5req_dir / "packa.txt").write_text("packaging") - (case5req_dir / "packb.txt").write_text("numpy") + (case5req_dir / "packA.txt").write_text("requests") + (case5req_dir / "packB.txt").write_text("attrs") yield root_temp_dir From fcfd47ed8845a7218aaad4e4bff2b457b735317b Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:23:30 -0500 Subject: [PATCH 10/14] add the print_info function --- src/diffpy/cmi/packsmanager.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/diffpy/cmi/packsmanager.py b/src/diffpy/cmi/packsmanager.py index 154fc2a..ab8ed98 100644 --- a/src/diffpy/cmi/packsmanager.py +++ b/src/diffpy/cmi/packsmanager.py @@ -256,10 +256,6 @@ def _copy_new_example( shutil.copytree(example_origin, target) print(f"Copied example '{pack_name}/{example_name}'.") - def print_info(self) -> None: - """Print information about available packs and examples.""" - return - def _resolve_pack_file(self, identifier: Union[str, Path]) -> Path: """Resolve a pack identifier to an absolute .txt path. @@ -351,3 +347,25 @@ def install_pack(self, identifier: str | Path) -> None: plog.info("Pack '%s' installation complete.", path.stem) else: plog.error("Pack '%s' installation failed.", path.stem) + + def print_info(self) -> None: + """Print information about available packs and examples.""" + uninstall_packs = [] + installed_packs = [] + for pack in self.available_packs(): + if self.check_pack(pack): + installed_packs.append(pack) + else: + uninstall_packs.append(pack) + print("Installed Packs:") + for pack in installed_packs: + print(f" {pack}") + print("\nAvailable Packs to Install:") + for pack in uninstall_packs: + print(f" {pack}") + print("\nExamples:") + examples_dict = self.available_examples() + for pack, examples in examples_dict.items(): + print(f" {pack}:") + for ex_name, _ in examples: + print(f" - {ex_name}") From 0a26ce283483dcbbe729a834a1209d61b75b5b38 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:23:57 -0500 Subject: [PATCH 11/14] fix capitalization on pack names --- tests/test_packsmanager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_packsmanager.py b/tests/test_packsmanager.py index d11da31..31bf926 100644 --- a/tests/test_packsmanager.py +++ b/tests/test_packsmanager.py @@ -351,16 +351,16 @@ def test_copy_examples_force(example_cases, expected_paths, force): # expected: print_info output showing packA installed but not packB ("packA",), """Installed Packs: - packa + packA Available Packs to Install: - packb + packB Examples: - packa: + packA: - ex1 - ex2 - packb: + packB: - ex1 - ex3 - ex4""", From aa0af1fac348468969c98c3ee3316db0ee2a0fa6 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:37:54 -0500 Subject: [PATCH 12/14] install with conda, not pip --- tests/test_packsmanager.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/test_packsmanager.py b/tests/test_packsmanager.py index 31bf926..f6b8985 100644 --- a/tests/test_packsmanager.py +++ b/tests/test_packsmanager.py @@ -1,7 +1,6 @@ import os import re import subprocess -import venv from pathlib import Path import pytest @@ -373,11 +372,24 @@ def test_print_info(packs_to_install, expected, example_cases, capsys): case5dir = example_cases / "case5" env_dir = case5dir / "fake_env" req_dir = case5dir / "requirements" / "packs" - venv.EnvBuilder(with_pip=True).create(env_dir) + subprocess.run( + ["conda", "create", "-y", "-p", str(env_dir)], + check=True, + capture_output=True, + text=True, + ) for pack in packs_to_install: req_file = req_dir / f"{pack.lower()}.txt" subprocess.run( - [str(env_dir / "bin" / "pip"), "install", "-r", str(req_file)], + [ + "conda", + "install", + "-y", + "--file", + str(req_file), + "-p", + str(env_dir), + ], check=True, capture_output=True, text=True, From 7ab58880301bf355963a1be565d9ac2454c55b3b Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:42:10 -0500 Subject: [PATCH 13/14] change uninstall to uninstalled --- src/diffpy/cmi/packsmanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diffpy/cmi/packsmanager.py b/src/diffpy/cmi/packsmanager.py index ab8ed98..4c9d08e 100644 --- a/src/diffpy/cmi/packsmanager.py +++ b/src/diffpy/cmi/packsmanager.py @@ -350,18 +350,18 @@ def install_pack(self, identifier: str | Path) -> None: def print_info(self) -> None: """Print information about available packs and examples.""" - uninstall_packs = [] + uninstalled_packs = [] installed_packs = [] for pack in self.available_packs(): if self.check_pack(pack): installed_packs.append(pack) else: - uninstall_packs.append(pack) + uninstalled_packs.append(pack) print("Installed Packs:") for pack in installed_packs: print(f" {pack}") print("\nAvailable Packs to Install:") - for pack in uninstall_packs: + for pack in uninstalled_packs: print(f" {pack}") print("\nExamples:") examples_dict = self.available_examples() From d7b0a8e80457352ffbf2109fd61abd736b9b8b08 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Tue, 4 Nov 2025 12:57:15 -0500 Subject: [PATCH 14/14] fix capitalization --- tests/test_packsmanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_packsmanager.py b/tests/test_packsmanager.py index f6b8985..10bf5ab 100644 --- a/tests/test_packsmanager.py +++ b/tests/test_packsmanager.py @@ -379,7 +379,7 @@ def test_print_info(packs_to_install, expected, example_cases, capsys): text=True, ) for pack in packs_to_install: - req_file = req_dir / f"{pack.lower()}.txt" + req_file = req_dir / f"{pack}.txt" subprocess.run( [ "conda",