|
| 1 | +from pathlib import Path |
| 2 | + |
1 | 3 | import pytest |
2 | 4 |
|
3 | | -from diffpy.cmi import cli |
| 5 | +from diffpy.cmi.cli import copy_examples |
4 | 6 | from diffpy.cmi.packsmanager import PacksManager |
5 | 7 |
|
6 | | - |
7 | | -def safe_get_examples(nonempty_packs, pack, n=None): |
8 | | - """Return up to n examples if available.""" |
9 | | - exs = nonempty_packs.get(pack, []) |
10 | | - if not exs: |
11 | | - return [] |
12 | | - return exs if n is None else exs[:n] |
13 | | - |
14 | | - |
15 | | -def select_examples_subset(examples_dict, copy_type): |
16 | | - """Select subset of examples depending on scenario. |
17 | | -
|
18 | | - Handles edge cases where some packs may be empty. |
19 | | - """ |
20 | | - subset = {} |
21 | | - if not examples_dict: |
22 | | - return {} |
23 | | - nonempty_packs = {k: v for k, v in examples_dict.items() if v} |
24 | | - if not nonempty_packs: |
25 | | - return {} |
26 | | - packs = list(nonempty_packs.keys()) |
27 | | - if copy_type == "one_example": |
28 | | - pack = packs[0] |
29 | | - exs = safe_get_examples(nonempty_packs, pack, 1) |
30 | | - if exs: |
31 | | - subset[pack] = exs |
32 | | - elif copy_type == "multiple_examples_same_pack": |
33 | | - pack = packs[0] |
34 | | - exs = safe_get_examples(nonempty_packs, pack, 2) |
35 | | - if exs: |
36 | | - subset[pack] = exs |
37 | | - elif copy_type == "multiple_examples_diff_packs": |
38 | | - for pack in packs[:2]: |
39 | | - exs = safe_get_examples(nonempty_packs, pack, 1) |
40 | | - if exs: |
41 | | - subset[pack] = exs |
42 | | - elif copy_type == "pack_all_examples": |
43 | | - pack = packs[0] |
44 | | - exs = safe_get_examples(nonempty_packs, pack) |
45 | | - if exs: |
46 | | - subset[pack] = exs |
47 | | - elif copy_type == "multi_packs_all_examples": |
48 | | - for pack in packs[:2]: |
49 | | - exs = safe_get_examples(nonempty_packs, pack) |
50 | | - if exs: |
51 | | - subset[pack] = exs |
52 | | - elif copy_type == "combo_packs_and_examples": |
53 | | - first_pack = packs[0] |
54 | | - exs_first = safe_get_examples(nonempty_packs, first_pack, 1) |
55 | | - if exs_first: |
56 | | - subset[first_pack] = exs_first |
57 | | - if len(packs) > 1: |
58 | | - second_pack = packs[1] |
59 | | - exs_second = safe_get_examples(nonempty_packs, second_pack) |
60 | | - if exs_second: |
61 | | - subset[second_pack] = exs_second |
62 | | - elif copy_type == "all_packs_all_examples": |
63 | | - subset = nonempty_packs |
64 | | - else: |
65 | | - raise ValueError(f"Unknown copy_type: {copy_type}") |
66 | | - return subset |
67 | | - |
68 | | - |
69 | | -def verify_copied_files(subset, target_dir, case_dir): |
70 | | - """Verify that all example files were copied correctly.""" |
71 | | - if not subset: |
72 | | - if target_dir: |
73 | | - assert not any(target_dir.iterdir()) |
74 | | - else: |
75 | | - pass |
76 | | - return |
77 | | - dest = target_dir or case_dir |
78 | | - assert dest.exists() |
79 | | - for pack, examples in subset.items(): |
80 | | - for example_name, example_path in examples: |
81 | | - for ex_file in example_path.rglob("*.py"): |
82 | | - rel = ex_file.relative_to(example_path.parent.parent) |
83 | | - dest_file = dest / rel |
84 | | - assert dest_file.exists(), f"{dest_file} missing" |
85 | | - |
86 | | - |
87 | 8 | # Test copy_examples for various structural cases and copy scenarios. |
88 | | -# In total, 5 structural cases x 14 copy scenarios = 70 tests. |
| 9 | +# In total, 5 structural cases x 6 copy scenarios + 2 path scenarios = 32 tests |
89 | 10 | # The copy scenarios are: |
90 | | -# 1a) copy one example to cwd |
91 | | -# 1b) copy one example to a target dir |
92 | | -# 2a) copy multiple examples from same pack to cwd |
93 | | -# 2b) copy multiple examples from same pack to a target dir |
94 | | -# 3a) copy multiple examples from different packs to cwd |
95 | | -# 3b) copy multiple examples from different packs to a target dir |
96 | | -# 4a) copy all examples from a pack to cwd |
97 | | -# 4b) copy all examples from a pack to a target dir |
98 | | -# 5a) copy all examples from multiple packs to cwd |
99 | | -# 5b) copy all examples from multiple packs to target dir |
100 | | -# 6a) copy a combination of packs and examples to cwd |
101 | | -# 6b) copy a combination of packs and examples to target |
102 | | -# 7a) copy all examples from all packs to cwd |
103 | | -# 7b) copy all examples from all packs to a target dir |
| 11 | +# a) copy to cwd |
| 12 | +# b) copy to target dir |
104 | 13 |
|
105 | | -copy_scenarios = [ |
106 | | - ("one_example", "cwd"), |
107 | | - ("one_example", "target"), |
108 | | - ("multiple_examples_same_pack", "cwd"), |
109 | | - ("multiple_examples_same_pack", "target"), |
110 | | - ("multiple_examples_diff_packs", "cwd"), |
111 | | - ("multiple_examples_diff_packs", "target"), |
112 | | - ("pack_all_examples", "cwd"), |
113 | | - ("pack_all_examples", "target"), |
114 | | - ("multi_packs_all_examples", "cwd"), |
115 | | - ("multi_packs_all_examples", "target"), |
116 | | - ("combo_packs_and_examples", "cwd"), |
117 | | - ("combo_packs_and_examples", "target"), |
118 | | - ("all_packs_all_examples", "cwd"), |
119 | | - ("all_packs_all_examples", "target"), |
| 14 | +# 1) copy one example |
| 15 | +# 2) copy list of examples from same pack |
| 16 | +# 3) copy list of examples from different packs |
| 17 | +# 4) copy all examples from a pack |
| 18 | +# 5) copy all examples from list of packs |
| 19 | +# 6) copy all examples from all packs |
| 20 | + |
| 21 | +# Case params: List of tuples |
| 22 | +# input: str - name of the test case directory |
| 23 | +# user_inputs: List[List[str]] - Possible user inputs for the given case |
| 24 | +# expected: List[List[Path]] - The expected paths that should be copied for |
| 25 | +# each user input |
| 26 | +case_params = [ |
| 27 | + ( |
| 28 | + "case1", # empty pack |
| 29 | + [ |
| 30 | + ["empty_pack"], # 4) all examples from a pack (but pack is empty) |
| 31 | + ["all"], # 6) all examples from all packs (but pack is empty) |
| 32 | + ], |
| 33 | + [ |
| 34 | + [], |
| 35 | + [], |
| 36 | + ], |
| 37 | + ), |
| 38 | + ( |
| 39 | + "case2", # one pack with multiple examples |
| 40 | + [ |
| 41 | + ["ex1"], # 1) single example |
| 42 | + ["ex1", "ex2"], # 2) multiple examples from same pack |
| 43 | + ["full_pack"], # 4) all examples from a pack |
| 44 | + ["all"], # 6) all examples from all packs |
| 45 | + ], |
| 46 | + [ |
| 47 | + [Path("full_pack/ex1/solution/diffpy-cmi/script1.py")], |
| 48 | + [ |
| 49 | + Path("full_pack/ex1/solution/diffpy-cmi/script1.py"), |
| 50 | + Path("full_pack/ex2/random/path/script1.py"), |
| 51 | + Path("full_pack/ex2/random/path/script2.py"), |
| 52 | + ], |
| 53 | + [ |
| 54 | + Path("full_pack/ex1/solution/diffpy-cmi/script1.py"), |
| 55 | + Path("full_pack/ex2/random/path/script1.py"), |
| 56 | + Path("full_pack/ex2/random/path/script2.py"), |
| 57 | + ], |
| 58 | + [ |
| 59 | + Path("full_pack/ex1/solution/diffpy-cmi/script1.py"), |
| 60 | + Path("full_pack/ex2/random/path/script1.py"), |
| 61 | + Path("full_pack/ex2/random/path/script2.py"), |
| 62 | + ], |
| 63 | + ], |
| 64 | + ), |
| 65 | + ( |
| 66 | + "case3", # multiple packs with multiple examples |
| 67 | + [ |
| 68 | + ["ex1"], # 1) single example from packA |
| 69 | + ["ex1", "ex2"], # 2) list of examples from same pack |
| 70 | + ["ex2", "ex3"], # 3) list of examples from different packs |
| 71 | + ["packA"], # 4) all examples from a pack |
| 72 | + ["packA", "packB"], # 5) all examples from multiple packs |
| 73 | + ["all"], # 6) all examples from all packs |
| 74 | + ], |
| 75 | + [ |
| 76 | + [Path("packA/ex1/script1.py")], |
| 77 | + [ |
| 78 | + Path("packA/ex1/script1.py"), |
| 79 | + Path("packA/ex2/solutions/script2.py"), |
| 80 | + ], |
| 81 | + [ |
| 82 | + Path("packA/ex2/solutions/script2.py"), |
| 83 | + Path("packB/ex3/more/random/path/script3.py"), |
| 84 | + Path("packB/ex3/more/random/path/script4.py"), |
| 85 | + ], |
| 86 | + [ |
| 87 | + Path("packA/ex1/script1.py"), |
| 88 | + Path("packA/ex2/solutions/script2.py"), |
| 89 | + ], |
| 90 | + [ |
| 91 | + Path("packA/ex1/script1.py"), |
| 92 | + Path("packA/ex2/solutions/script2.py"), |
| 93 | + Path("packB/ex3/more/random/path/script3.py"), |
| 94 | + Path("packB/ex3/more/random/path/script4.py"), |
| 95 | + ], |
| 96 | + [ |
| 97 | + Path("packA/ex1/script1.py"), |
| 98 | + Path("packA/ex2/solutions/script2.py"), |
| 99 | + Path("packB/ex3/more/random/path/script3.py"), |
| 100 | + Path("packB/ex3/more/random/path/script4.py"), |
| 101 | + ], |
| 102 | + ], |
| 103 | + ), |
| 104 | + ( |
| 105 | + "case4", # no packs (empty examples directory) |
| 106 | + [ |
| 107 | + ["all"], # 6) all examples from all packs (but examples exist) |
| 108 | + ], |
| 109 | + [ |
| 110 | + [], |
| 111 | + ], |
| 112 | + ), |
| 113 | + ( |
| 114 | + "case5", # multiple packs containing examples with the same name |
| 115 | + [ |
| 116 | + ["ex1"], # 1) single example (ambiguous, should get both) |
| 117 | + [ |
| 118 | + "ex1", |
| 119 | + "ex1", |
| 120 | + ], # 3) list of ex from diff packs (ambiguous, should get both) |
| 121 | + ["packA"], # 4) all examples from a pack |
| 122 | + ["packA", "packB"], # 5) all examples from a list of packs |
| 123 | + ["all"], # 6) all examples from all packs |
| 124 | + ], |
| 125 | + [ |
| 126 | + [ |
| 127 | + Path("packA/ex1/path1/script1.py"), |
| 128 | + Path("packB/ex1/path2/script2.py"), |
| 129 | + ], |
| 130 | + [ |
| 131 | + Path("packA/ex1/path1/script1.py"), |
| 132 | + Path("packB/ex1/path2/script2.py"), |
| 133 | + ], |
| 134 | + [Path("packA/ex1/path1/script1.py")], |
| 135 | + [ |
| 136 | + Path("packA/ex1/path1/script1.py"), |
| 137 | + Path("packB/ex1/path2/script2.py"), |
| 138 | + ], |
| 139 | + [ |
| 140 | + Path("packA/ex1/path1/script1.py"), |
| 141 | + Path("packA/ex1/path2/script2.py"), |
| 142 | + ], |
| 143 | + ], |
| 144 | + ), |
120 | 145 | ] |
121 | 146 |
|
122 | 147 |
|
123 | | -@pytest.mark.parametrize( |
124 | | - "case_name", |
125 | | - ["case1", "case2", "case3", "case4", "case5"], |
126 | | -) |
127 | | -@pytest.mark.parametrize( |
128 | | - "copy_type, target_type", |
129 | | - copy_scenarios, |
130 | | -) |
131 | | -def test_copy_examples( |
132 | | - case_name, copy_type, target_type, example_cases, tmp_path |
133 | | -): |
134 | | - """Test copy_examples for all structural and copy scenarios.""" |
135 | | - case_dir = example_cases / case_name |
| 148 | +@pytest.mark.parametrize("target", ["cwd", "target"]) |
| 149 | +@pytest.mark.parametrize("input,user_inputs,expected", case_params) |
| 150 | +def test_copy_examples(input, expected, user_inputs, target, example_cases): |
| 151 | + case_dir = example_cases / input |
136 | 152 | pm = PacksManager(root_path=case_dir) |
137 | 153 | examples_dict = pm.available_examples() |
138 | | - target_dir = None if target_type == "cwd" else tmp_path / "target" |
139 | | - if target_dir: |
140 | | - target_dir.mkdir(parents=True, exist_ok=True) |
141 | | - subset = select_examples_subset(examples_dict, copy_type) |
142 | | - cli.copy_examples(subset, target_dir=target_dir) |
143 | | - verify_copied_files(subset, target_dir, case_dir) |
| 154 | + if target == "target": |
| 155 | + target_dir = case_dir / "target_dir" |
| 156 | + else: |
| 157 | + target_dir = case_dir |
| 158 | + target_dir.mkdir(parents=True, exist_ok=True) |
| 159 | + for command in user_inputs: |
| 160 | + copy_examples(examples_dict, user_input=command, target_dir=target_dir) |
| 161 | + for exp_paths in expected: |
| 162 | + for path in exp_paths: |
| 163 | + dest_file = target_dir / path |
| 164 | + assert dest_file.exists(), f"{dest_file} missing" |
0 commit comments