Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve "Create Script to Snapshot Compadre into Trilinos" #176

Merged
merged 3 commits into from
Apr 20, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 262 additions & 0 deletions scripts/snapshot_into_trilinos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#!/usr/bin/env python3
"""
Create a snapshot from the Compadre repository containing this script into the
Trilinos repository pointed to, omitting the kokkos, kokkos-kernels, python,
and scripts directories.

Note: This will assert that both repositories are in a clean state.

Warning: This will clean out any locally-ignored files in Compadre (e.g.,
ignored via .git/info/exclude) to avoid copying them over and then
committing them to Trilinos. Be sure you don't have any ignored files in
Compadre that you want to keep before running this script.

To test this script to ensure that it's working correctly, simply use

pytest snapshot_into_trilinos.py
"""
import os
import pytest
import sys




def parse_arguments(argv):
"""
Parse the command line arguments to the script.

Parameters:
argv (list): The command line arguments to be parsed.

Returns:
dict: A mapping from the options to their values.
"""
import argparse, textwrap
width = 79
description = __doc__
description = ("[ Snapshot Compadre Into Trilinos ]".center(width, "-") +
"\n" + description)
examples = """
Show what's going to happen without actually doing the snapshot::

./snapshot_into_trilinos.py \\
--trilinos-dir /path/to/Trilinos \\
--dry-run

Actually do the snapshot::

./snapshot_into_trilinos.py \\
--trilinos-dir /path/to/Trilinos
"""
examples = textwrap.dedent(examples)
examples = "[ Examples ]".center(width, "-") + "\n\n" + examples
parser = argparse.ArgumentParser(
description=description,
epilog=examples,
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("-t", "--trilinos-dir", dest="trilinos_dir",
action="store", required=True, default=None,
help="The path (relative or absolute) to the root of "
"the Trilinos repository you wish to snapshot "
"Compadre into.")
parser.add_argument("-d", "--dry-run", dest="dry_run", action="store_true",
default=False, help="Show what will happen, but don't "
"actually do it.")
return parser.parse_args(argv)



def test_parse_arguments():
"""
Test that the :func:`parse_arguments` function works as intended.
"""
options = parse_arguments("--trilinos-dir /path/to/Trilinos --dry-run".
split())
assert (options.trilinos_dir == "/path/to/Trilinos" and
options.dry_run == True)
options = parse_arguments("-t /path/to/Trilinos -d".split())
assert (options.trilinos_dir == "/path/to/Trilinos" and
options.dry_run == True)
options = parse_arguments("-t /some/other/dir".split())
assert (options.trilinos_dir == "/some/other/dir" and
options.dry_run == False)



def check_trilinos_dir_is_root(trilinos_dir):
"""
Check to ensure the Trilinos directory specified is indeed the root of the
Trilinos repository by ensuring it contains a ``ProjectName.cmake`` that
specifies Trilinos as the project name.
"""
import re
try:
with open(os.path.join(trilinos_dir, "ProjectName.cmake"), "r") as f:
data = f.read().lower()
if not re.search(r"set\s*\(\s*project_name\s+trilinos\s*\)", data):
sys.exit(f"Error: {trilinos_dir}/ProjectName.cmake does not "
"set the project name to Trilinos. Make sure you "
"point to the root of the Trilinos repository.")
except FileNotFoundError:
sys.exit(f"Error: {trilinos_dir} does not contain a "
"ProjectName.cmake. Make sure you point to the root of the "
"Trilinos repository.")



def test_check_trilinos_dir_is_root(tmpdir):
"""
Test that the :func:`check_trilinos_dir_is_root` function works as
intended.
"""
# Ensure the check fails if trilinos_dir doesn't contain ProjectName.cmake.
trilinos_dir = tmpdir.mkdir("trilinos_dir")
with pytest.raises(SystemExit):
check_trilinos_dir_is_root(trilinos_dir)

# Ensure the check fails if ProjectName.cmake doesn't set the project name
# to Trilinos.
file_to_check = trilinos_dir.join("ProjectName.cmake")
file_to_check.write("Doesn't set PROJECT_NAME to Trilinos")
with pytest.raises(SystemExit):
check_trilinos_dir_is_root(trilinos_dir)

# Ensure the check passes if ProjectName.cmake does set the project name to
# Trilinos.
file_to_check.write("SET(PROJECT_NAME Trilinos)")
check_trilinos_dir_is_root(trilinos_dir)



def create_directory_variables(trilinos_dir, verbose=False):
"""
Use the given path to Trilinos to create a handful of other variables
pointing to:
* The python_utils directory, so we can import the SnapshotDir utility.
* The Compadre repository containing this script.
* The location to where Compadre will be shapshotted.

Parameters:
trilinos_dir (str): The path to Trilinos given on the command line.
verbose (bool): Whether or not to print out details.

Returns:
tuple: The original Compadre directory, and the location to be
snapshotted to.
"""
trilinos_dir = os.path.abspath(trilinos_dir)
python_utils_dir = os.path.join(trilinos_dir, "cmake/tribits/python_utils")
sys.path.append(python_utils_dir)
script_dir = os.path.dirname(os.path.realpath(__file__))
compadre_orig_dir = os.path.abspath(os.path.join(script_dir, ".."))
compadre_dest_dir = os.path.join(trilinos_dir, "packages/compadre")
if verbose:
print(f"Trilinos repository root: {trilinos_dir}\n"
f"Using snapshot-dir.py from: {python_utils_dir}\n"
f"Snapshotting Compadre from: {compadre_orig_dir}\n"
f" into: {compadre_dest_dir}")
return (compadre_orig_dir, compadre_dest_dir)



def test_create_directory_variables(capfd):
"""
Test that the :func:`create_directory_variables` function works as
intended.
"""
trilinos_dir = "/path/to/Trilinos"
compadre_dir = os.path.abspath(os.path.join(os.path.dirname(
os.path.realpath(__file__)), ".."))
(orig_dir, dest_dir) = create_directory_variables(trilinos_dir)
assert (orig_dir == compadre_dir and
dest_dir == "/path/to/Trilinos/packages/compadre" and
os.path.join(trilinos_dir, "cmake/tribits/python_utils") in
sys.path)
out, err = capfd.readouterr()
assert out == ""
create_directory_variables(trilinos_dir, verbose=True)
out, err = capfd.readouterr()
expected = (f"Trilinos repository root: {trilinos_dir}\n"
f"Using snapshot-dir.py from: {trilinos_dir}/cmake/tribits/"
"python_utils\n"
f"Snapshotting Compadre from: {compadre_dir}\n"
f" into: {trilinos_dir}/packages/"
"compadre\n")
assert out == expected



def create_snapshot_dir_args(orig_dir, dest_dir, dry_run=False):
"""
Create the arguments to pass to the SnapshotDir utility from TriBITS.

Parameters:
orig_dir (str): The path to the Compadre repository to be snapshotted.
dest_dir (str): The path to where Compadre will be snapshotted.
dry_run (bool): Whether or not to show what will happen without
actually doing it.

Returns:
list: The arguments to be passed to the utility.
"""
args = (f"--orig-dir {orig_dir}/ "
f"--dest-dir {dest_dir}/ "
"--exclude kokkos kokkos-kernels python scripts cmake/bob.cmake "
"cmake/detect_trilinos_opts.cmake "
"examples/Python_3D_Convergence.py.in "
"--clean-ignored-files-orig-dir")
if dry_run:
args += " --show-defaults"
return args.split(" ")



def test_create_snapshot_dir_args():
"""
Test that the :func:`create_snapshot_dir_args` function works as intended.
"""
orig = "from_here"
dest = "to_there"
args = create_snapshot_dir_args(orig, dest)
expected = (f"--orig-dir {orig}/ --dest-dir {dest}/ --exclude kokkos "
"kokkos-kernels python scripts cmake/bob.cmake "
"cmake/detect_trilinos_opts.cmake "
"examples/Python_3D_Convergence.py.in "
"--clean-ignored-files-orig-dir")
assert args == expected.split()
args = create_snapshot_dir_args(orig, dest, dry_run=True)
expected += " --show-defaults"
assert args == expected.split()



def snapshot(snapshot_dir_args):
"""
Perform the snapshot using the SnapshotDir utility from TriBITS.

Parameters:
shapshot_dir_args (str): The arguments to pass to SnapshotDir.

Returns:
bool: Whether or not the snapshot was successful.

Note:
The SnapshotDir utility is already unit tested within TriBITS, so
there's no need for an additional test here.
"""
import SnapshotDir
return SnapshotDir.snapshotDirMainDriver(snapshot_dir_args)



if __name__ == "__main__":
options = parse_arguments(sys.argv[1:])
check_trilinos_dir_is_root(options.trilinos_dir)
(orig_dir, dest_dir) = create_directory_variables(options.trilinos_dir,
options.dry_run)
success = snapshot(create_snapshot_dir_args(orig_dir, dest_dir,
options.dry_run))
return_code = 0 if success else 1
sys.exit(return_code)