From 0815f8fe6a71694fb7cfac9144341ae967bd73ec Mon Sep 17 00:00:00 2001 From: "r.jaepel" <r.jaepel@fz-juelich.de> Date: Thu, 17 Aug 2023 18:01:56 +0200 Subject: [PATCH] add tests for current use-cases --- .gitignore | 3 +- modsimdata/utils.py | 161 +------------------------------------- tests/__init__.py | 0 tests/test_git_adapter.py | 139 ++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 160 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/test_git_adapter.py diff --git a/.gitignore b/.gitignore index 0ec68de..50c03c9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ build *.egg-info results -__pycache__ \ No newline at end of file +__pycache__ +tests/test_repo \ No newline at end of file diff --git a/modsimdata/utils.py b/modsimdata/utils.py index 6d493be..cf509df 100644 --- a/modsimdata/utils.py +++ b/modsimdata/utils.py @@ -272,10 +272,10 @@ class ProjectRepo(BaseRepo): previous_branch = self.output_repo.active_branch.name self.output_repo.git.checkout(branch_name) - source_filepath = os.path.join(self._output_folder, file_path) + source_filepath = os.path.join(self.output_repo.working_dir, file_path) # target_folder = os.path.join(self._output_folder + "_cached", branch_name) - target_folder = os.path.join(self._output_folder, "cached", branch_name) + target_folder = os.path.join(self.output_repo.working_dir, "cached", branch_name) os.makedirs(target_folder, exist_ok=True) target_filepath = os.path.join(target_folder, file_path) @@ -414,7 +414,6 @@ def is_tool(name): """Check whether `name` is on PATH and marked as executable.""" from shutil import which - return which(name) is not None @@ -471,159 +470,3 @@ def initialize_git_repo(path_to_repo: str, output_repo_name: (str | bool) = "out repo.git.commit("-m", "initial commit") os.chdir(starting_directory) - return - - -def example_generate_results_array(seed=None): - import numpy as np - - if seed is not None: - np.random.seed(seed) - - results_array = np.random.random((500, 3)) - np.savetxt(os.path.join("output", "result.csv"), results_array, delimiter=",") - return results_array - - -def example_generate_results_figures(input_array): - import matplotlib.pyplot as plt - import numpy as np - - plt.figure() - plt.scatter(np.arange(0, 500), input_array[:, 0], alpha=0.5) - plt.scatter(np.arange(0, 500), input_array[:, 1], alpha=0.5) - plt.scatter(np.arange(0, 500), input_array[:, 2], alpha=0.5) - plt.savefig(os.path.join("output", "fig.png")) - plt.savefig(os.path.join("output", "fig.jpg"), dpi=1000) - plt.savefig(os.path.join("output", f"fig_{np.random.randint(265)}_{random.randint(0, 1000)}.png")) - - -def alter_code(): - # Add changes to the project code - random_number = random.randint(0, 265) - # random_number = 42 - with open("random_number.txt", "a") as file: - file.write(str(random_number)) - return random_number - - -def example_usage(): - """ Pretend this is a python file """ - - home_dir = os.path.expanduser("~") - os.chdir(os.path.join(home_dir, 'ModSimData')) - - random_number = alter_code() - - project_repo = ProjectRepo(".") - project_repo.commit(message="fixed super important bug", update_packages=False) - - with project_repo.track_results(results_commit_message="Add figures and array"): - # Generate data - print("Generating results output") - results_array = example_generate_results_array(seed=random_number) - example_generate_results_figures(results_array) - - -def example_write_array(): - """ Pretend this is a python file """ - - home_dir = os.path.expanduser("~") - os.chdir(os.path.join(home_dir, 'ModSimData')) - - # Add changes to the project code - random_number = random.randint(0, 265) - # random_number = 42 - with open(f"random_number_{random_number}.txt", "a") as file: - file.write(str(random_number)) - - project_repo = ProjectRepo(".") - project_repo.commit("add code that writes an array to file", update_packages=False) - - with project_repo.track_results(results_commit_message="Add array"): - example_generate_results_array() - - branch_name = str(project_repo.output_repo.active_branch) - return branch_name - - -def example_load(branch_name): - """ Pretend this is a python file """ - import numpy as np - """ move into home directory """ - - home_dir = os.path.expanduser("~") - os.chdir(os.path.join(home_dir, 'ModSimData')) - - # Add changes to the project code - random_number = random.randint(0, 265) - # random_number = 42 - with open(f"random_number_{random_number}.txt", "a") as file: - file.write(str(random_number)) - - project_repo = ProjectRepo(".") - project_repo.commit("add code that creates figures based on an array", update_packages=False) - - with project_repo.track_results(results_commit_message="Add figures"): - cached_array_path = project_repo.cache_previous_results(branch_name=branch_name, - file_path="result.csv") - previous_array = np.loadtxt(cached_array_path, delimiter=",") - - # with project_repo.load_previous_result_file(branch_name=branch_name, - # file_path="result.csv") as file_handle: - # pass - example_generate_results_figures(previous_array) - - branch_name = str(project_repo.output_repo.active_branch) - return branch_name - - -def example_load_large(branch_name1, branch_name2): - """ Pretend this is a python file """ - import numpy as np - """ move into home directory """ - - home_dir = os.path.expanduser("~") - os.chdir(os.path.join(home_dir, 'ModSimData')) - - # Add changes to the project code - random_number = random.randint(0, 265) - # random_number = 42 - with open(f"random_number_{random_number}.txt", "a") as file: - file.write(str(random_number)) - - project_repo = ProjectRepo(".") - project_repo.commit("add code that creates figures based on an array", update_packages=False) - - with project_repo.track_results(results_commit_message="Add figures"): - # cached_fig_path = project_repo.cache_previous_results(branch_name=branch_name2, - # file_path="fig.jpg") - cached_array_path = project_repo.cache_previous_results(branch_name=branch_name1, - file_path="result.csv") - previous_array = np.loadtxt(cached_array_path, delimiter=",") - - example_generate_results_figures(previous_array) - - branch_name = str(project_repo.output_repo.active_branch) - return branch_name - - -def example_two_step_process(): - branch_name = example_write_array() - branch_name2 = example_load(branch_name) - example_load_large(branch_name, branch_name2) - - -def create_example_repo(): - os.chdir(os.path.expanduser("~")) - - """ initialize Project directory """ - if not os.path.exists("ModSimData"): - initialize_git_repo("ModSimData") - - -if __name__ == '__main__': - # pass - create_example_repo() - example_usage() - example_two_step_process() diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_git_adapter.py b/tests/test_git_adapter.py new file mode 100644 index 0000000..7272313 --- /dev/null +++ b/tests/test_git_adapter.py @@ -0,0 +1,139 @@ +import os.path +import shutil +import stat +import random + +import pytest +import git +import numpy as np + +from modsimdata import initialize_git_repo, ProjectRepo + + +@pytest.fixture(scope="module") +def path_to_repo(): + # a "fixture" serves up shared, ready variables to test functions that should use the fixture as a kwarg + return "test_repo" + + +# @pytest.fixture(scope="module", autouse=True) +# def my_fixture(path_to_repo): +# print('INITIALIZATION') +# if os.path.exists(path_to_repo): +# remove_dir(path_to_repo) +# yield "this is just here because something must yield" +# print("TEAR DOWN") +# remove_dir(path_to_repo) + + +def remove_dir(path_to_dir): + def remove_readonly(func, path, exc_info): + "Clear the readonly bit and reattempt the removal" + # ERROR_ACCESS_DENIED = 5 + if func not in (os.unlink, os.rmdir) or exc_info[1].winerror != 5: + raise exc_info[1] + os.chmod(path, stat.S_IWRITE) + func(path) + + shutil.rmtree(path_to_dir, onerror=remove_readonly) + + +def modify_code(path_to_repo): + # Add changes to the project code + random_number = random.randint(0, 265) + filepath = os.path.join(path_to_repo, f"print_random_number.py") + with open(filepath, "w") as file: + file.write(f"print({random_number})\n") + + +def count_commit_number(repo): + commit_log = repo.git.log("--oneline").split("\n") + current_commit_number = len(commit_log) + return current_commit_number + + +def example_generate_results_array(path_to_repo, output_folder): + results_array = np.random.random((500, 3)) + np.savetxt(os.path.join(path_to_repo, output_folder, "result.csv"), + results_array, + delimiter=",") + return results_array + + +def try_initialize_git_repo(path_to_repo): + def try_init_gitpython_repo(repo_path): + os.path.exists(repo_path) + git.Repo(repo_path) + return True + + if os.path.exists(path_to_repo): + remove_dir(path_to_repo) + + initialize_git_repo(path_to_repo=path_to_repo) + + assert try_init_gitpython_repo(path_to_repo) + assert try_init_gitpython_repo(os.path.join(path_to_repo, "output")) + + +def try_commit_code(path_to_repo): + repo = ProjectRepo(path_to_repo) + current_commit_number = count_commit_number(repo) + + modify_code(path_to_repo) + repo.commit("add code to print random number", update_packages=False) + + updated_commit_number = count_commit_number(repo) + assert current_commit_number + 1 == updated_commit_number + + +def try_commit_code_without_code_changes(path_to_repo): + repo = ProjectRepo(path_to_repo) + current_commit_number = count_commit_number(repo) + repo.commit("This commit will not be made") + updated_commit_number = count_commit_number(repo) + assert current_commit_number == updated_commit_number + + +def try_commit_results_data(path_to_repo): + repo = ProjectRepo(path_to_repo) + current_commit_number = count_commit_number(repo.output_repo) + with repo.track_results(results_commit_message="Add array"): + example_generate_results_array(path_to_repo, output_folder=repo._output_folder) + updated_commit_number = count_commit_number(repo.output_repo) + assert current_commit_number + 1 == updated_commit_number + return str(repo.output_repo.active_branch) + + +def try_commit_results_with_uncommitted_code_changes(path_to_repo): + repo = ProjectRepo(path_to_repo) + modify_code(path_to_repo) + with pytest.raises(Exception): + with repo.track_results(results_commit_message="Add array"): + example_generate_results_array(path_to_repo, output_folder=repo._output_folder) + repo.commit("add code to print random number", update_packages=False) + + +def try_load_previous_result(path_to_repo, branch_name): + repo = ProjectRepo(path_to_repo) + with repo.track_results(results_commit_message="Load array and extend"): + cached_array_path = repo.cache_previous_results(branch_name=branch_name, + file_path="result.csv") + previous_array = np.loadtxt(cached_array_path, delimiter=",") + extended_array = np.concatenate([previous_array, previous_array]) + extended_array_file_path = os.path.join(path_to_repo, repo._output_folder, "extended_result.csv") + np.savetxt(extended_array_file_path, + extended_array, + delimiter=",") + assert os.path.exists(cached_array_path) + assert os.path.exists(extended_array_file_path) + + +def test_cadet_rdm(path_to_repo): + # because these depend on one-another and there is no native support afaik for sequential tests + # these tests are called sequentially here as try_ functions. + try_initialize_git_repo(path_to_repo) + try_commit_code(path_to_repo) + try_commit_code_without_code_changes(path_to_repo) + results_branch_name = try_commit_results_data(path_to_repo) + try_commit_results_with_uncommitted_code_changes(path_to_repo) + try_load_previous_result(path_to_repo, results_branch_name) -- GitLab