Skip to content

Commit 09f65c1

Browse files
authored
Merge pull request #176 from jmgate/175-create-script-to-snapshot-compadre-into-trilinos
Resolve "Create Script to Snapshot Compadre into Trilinos"
2 parents fab3550 + 684ccbd commit 09f65c1

File tree

1 file changed

+262
-0
lines changed

1 file changed

+262
-0
lines changed

scripts/snapshot_into_trilinos.py

+262
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Create a snapshot from the Compadre repository containing this script into the
4+
Trilinos repository pointed to, omitting the kokkos, kokkos-kernels, python,
5+
and scripts directories.
6+
7+
Note: This will assert that both repositories are in a clean state.
8+
9+
Warning: This will clean out any locally-ignored files in Compadre (e.g.,
10+
ignored via .git/info/exclude) to avoid copying them over and then
11+
committing them to Trilinos. Be sure you don't have any ignored files in
12+
Compadre that you want to keep before running this script.
13+
14+
To test this script to ensure that it's working correctly, simply use
15+
16+
pytest snapshot_into_trilinos.py
17+
"""
18+
import os
19+
import pytest
20+
import sys
21+
22+
23+
24+
25+
def parse_arguments(argv):
26+
"""
27+
Parse the command line arguments to the script.
28+
29+
Parameters:
30+
argv (list): The command line arguments to be parsed.
31+
32+
Returns:
33+
dict: A mapping from the options to their values.
34+
"""
35+
import argparse, textwrap
36+
width = 79
37+
description = __doc__
38+
description = ("[ Snapshot Compadre Into Trilinos ]".center(width, "-") +
39+
"\n" + description)
40+
examples = """
41+
Show what's going to happen without actually doing the snapshot::
42+
43+
./snapshot_into_trilinos.py \\
44+
--trilinos-dir /path/to/Trilinos \\
45+
--dry-run
46+
47+
Actually do the snapshot::
48+
49+
./snapshot_into_trilinos.py \\
50+
--trilinos-dir /path/to/Trilinos
51+
"""
52+
examples = textwrap.dedent(examples)
53+
examples = "[ Examples ]".center(width, "-") + "\n\n" + examples
54+
parser = argparse.ArgumentParser(
55+
description=description,
56+
epilog=examples,
57+
formatter_class=argparse.RawDescriptionHelpFormatter
58+
)
59+
parser.add_argument("-t", "--trilinos-dir", dest="trilinos_dir",
60+
action="store", required=True, default=None,
61+
help="The path (relative or absolute) to the root of "
62+
"the Trilinos repository you wish to snapshot "
63+
"Compadre into.")
64+
parser.add_argument("-d", "--dry-run", dest="dry_run", action="store_true",
65+
default=False, help="Show what will happen, but don't "
66+
"actually do it.")
67+
return parser.parse_args(argv)
68+
69+
70+
71+
def test_parse_arguments():
72+
"""
73+
Test that the :func:`parse_arguments` function works as intended.
74+
"""
75+
options = parse_arguments("--trilinos-dir /path/to/Trilinos --dry-run".
76+
split())
77+
assert (options.trilinos_dir == "/path/to/Trilinos" and
78+
options.dry_run == True)
79+
options = parse_arguments("-t /path/to/Trilinos -d".split())
80+
assert (options.trilinos_dir == "/path/to/Trilinos" and
81+
options.dry_run == True)
82+
options = parse_arguments("-t /some/other/dir".split())
83+
assert (options.trilinos_dir == "/some/other/dir" and
84+
options.dry_run == False)
85+
86+
87+
88+
def check_trilinos_dir_is_root(trilinos_dir):
89+
"""
90+
Check to ensure the Trilinos directory specified is indeed the root of the
91+
Trilinos repository by ensuring it contains a ``ProjectName.cmake`` that
92+
specifies Trilinos as the project name.
93+
"""
94+
import re
95+
try:
96+
with open(os.path.join(trilinos_dir, "ProjectName.cmake"), "r") as f:
97+
data = f.read().lower()
98+
if not re.search(r"set\s*\(\s*project_name\s+trilinos\s*\)", data):
99+
sys.exit(f"Error: {trilinos_dir}/ProjectName.cmake does not "
100+
"set the project name to Trilinos. Make sure you "
101+
"point to the root of the Trilinos repository.")
102+
except FileNotFoundError:
103+
sys.exit(f"Error: {trilinos_dir} does not contain a "
104+
"ProjectName.cmake. Make sure you point to the root of the "
105+
"Trilinos repository.")
106+
107+
108+
109+
def test_check_trilinos_dir_is_root(tmpdir):
110+
"""
111+
Test that the :func:`check_trilinos_dir_is_root` function works as
112+
intended.
113+
"""
114+
# Ensure the check fails if trilinos_dir doesn't contain ProjectName.cmake.
115+
trilinos_dir = tmpdir.mkdir("trilinos_dir")
116+
with pytest.raises(SystemExit):
117+
check_trilinos_dir_is_root(trilinos_dir)
118+
119+
# Ensure the check fails if ProjectName.cmake doesn't set the project name
120+
# to Trilinos.
121+
file_to_check = trilinos_dir.join("ProjectName.cmake")
122+
file_to_check.write("Doesn't set PROJECT_NAME to Trilinos")
123+
with pytest.raises(SystemExit):
124+
check_trilinos_dir_is_root(trilinos_dir)
125+
126+
# Ensure the check passes if ProjectName.cmake does set the project name to
127+
# Trilinos.
128+
file_to_check.write("SET(PROJECT_NAME Trilinos)")
129+
check_trilinos_dir_is_root(trilinos_dir)
130+
131+
132+
133+
def create_directory_variables(trilinos_dir, verbose=False):
134+
"""
135+
Use the given path to Trilinos to create a handful of other variables
136+
pointing to:
137+
* The python_utils directory, so we can import the SnapshotDir utility.
138+
* The Compadre repository containing this script.
139+
* The location to where Compadre will be shapshotted.
140+
141+
Parameters:
142+
trilinos_dir (str): The path to Trilinos given on the command line.
143+
verbose (bool): Whether or not to print out details.
144+
145+
Returns:
146+
tuple: The original Compadre directory, and the location to be
147+
snapshotted to.
148+
"""
149+
trilinos_dir = os.path.abspath(trilinos_dir)
150+
python_utils_dir = os.path.join(trilinos_dir, "cmake/tribits/python_utils")
151+
sys.path.append(python_utils_dir)
152+
script_dir = os.path.dirname(os.path.realpath(__file__))
153+
compadre_orig_dir = os.path.abspath(os.path.join(script_dir, ".."))
154+
compadre_dest_dir = os.path.join(trilinos_dir, "packages/compadre")
155+
if verbose:
156+
print(f"Trilinos repository root: {trilinos_dir}\n"
157+
f"Using snapshot-dir.py from: {python_utils_dir}\n"
158+
f"Snapshotting Compadre from: {compadre_orig_dir}\n"
159+
f" into: {compadre_dest_dir}")
160+
return (compadre_orig_dir, compadre_dest_dir)
161+
162+
163+
164+
def test_create_directory_variables(capfd):
165+
"""
166+
Test that the :func:`create_directory_variables` function works as
167+
intended.
168+
"""
169+
trilinos_dir = "/path/to/Trilinos"
170+
compadre_dir = os.path.abspath(os.path.join(os.path.dirname(
171+
os.path.realpath(__file__)), ".."))
172+
(orig_dir, dest_dir) = create_directory_variables(trilinos_dir)
173+
assert (orig_dir == compadre_dir and
174+
dest_dir == "/path/to/Trilinos/packages/compadre" and
175+
os.path.join(trilinos_dir, "cmake/tribits/python_utils") in
176+
sys.path)
177+
out, err = capfd.readouterr()
178+
assert out == ""
179+
create_directory_variables(trilinos_dir, verbose=True)
180+
out, err = capfd.readouterr()
181+
expected = (f"Trilinos repository root: {trilinos_dir}\n"
182+
f"Using snapshot-dir.py from: {trilinos_dir}/cmake/tribits/"
183+
"python_utils\n"
184+
f"Snapshotting Compadre from: {compadre_dir}\n"
185+
f" into: {trilinos_dir}/packages/"
186+
"compadre\n")
187+
assert out == expected
188+
189+
190+
191+
def create_snapshot_dir_args(orig_dir, dest_dir, dry_run=False):
192+
"""
193+
Create the arguments to pass to the SnapshotDir utility from TriBITS.
194+
195+
Parameters:
196+
orig_dir (str): The path to the Compadre repository to be snapshotted.
197+
dest_dir (str): The path to where Compadre will be snapshotted.
198+
dry_run (bool): Whether or not to show what will happen without
199+
actually doing it.
200+
201+
Returns:
202+
list: The arguments to be passed to the utility.
203+
"""
204+
args = (f"--orig-dir {orig_dir}/ "
205+
f"--dest-dir {dest_dir}/ "
206+
"--exclude kokkos kokkos-kernels python scripts cmake/bob.cmake "
207+
"cmake/detect_trilinos_opts.cmake "
208+
"examples/Python_3D_Convergence.py.in "
209+
"--clean-ignored-files-orig-dir")
210+
if dry_run:
211+
args += " --show-defaults"
212+
return args.split(" ")
213+
214+
215+
216+
def test_create_snapshot_dir_args():
217+
"""
218+
Test that the :func:`create_snapshot_dir_args` function works as intended.
219+
"""
220+
orig = "from_here"
221+
dest = "to_there"
222+
args = create_snapshot_dir_args(orig, dest)
223+
expected = (f"--orig-dir {orig}/ --dest-dir {dest}/ --exclude kokkos "
224+
"kokkos-kernels python scripts cmake/bob.cmake "
225+
"cmake/detect_trilinos_opts.cmake "
226+
"examples/Python_3D_Convergence.py.in "
227+
"--clean-ignored-files-orig-dir")
228+
assert args == expected.split()
229+
args = create_snapshot_dir_args(orig, dest, dry_run=True)
230+
expected += " --show-defaults"
231+
assert args == expected.split()
232+
233+
234+
235+
def snapshot(snapshot_dir_args):
236+
"""
237+
Perform the snapshot using the SnapshotDir utility from TriBITS.
238+
239+
Parameters:
240+
shapshot_dir_args (str): The arguments to pass to SnapshotDir.
241+
242+
Returns:
243+
bool: Whether or not the snapshot was successful.
244+
245+
Note:
246+
The SnapshotDir utility is already unit tested within TriBITS, so
247+
there's no need for an additional test here.
248+
"""
249+
import SnapshotDir
250+
return SnapshotDir.snapshotDirMainDriver(snapshot_dir_args)
251+
252+
253+
254+
if __name__ == "__main__":
255+
options = parse_arguments(sys.argv[1:])
256+
check_trilinos_dir_is_root(options.trilinos_dir)
257+
(orig_dir, dest_dir) = create_directory_variables(options.trilinos_dir,
258+
options.dry_run)
259+
success = snapshot(create_snapshot_dir_args(orig_dir, dest_dir,
260+
options.dry_run))
261+
return_code = 0 if success else 1
262+
sys.exit(return_code)

0 commit comments

Comments
 (0)