diff --git a/chi_pet/chi_run.py b/chi_pet/chi_run.py index d5abf04..7ca4eef 100644 --- a/chi_pet/chi_run.py +++ b/chi_pet/chi_run.py @@ -12,10 +12,36 @@ ''' +def run_args(workdir, state, args): + current_dir = Path.cwd() + try: + action = state + '-ing' + action_file = Path('.' + action) + print("Started {} sim using args {}".format(action, args)) + sys.stdout.flush() + if workdir.exists(): + os.chdir(workdir) + action_file.touch() # Keeps track of current pipeline state + status = run(args) + if status.returncode: + print(f"Run failed: State {state} did not succeed.") + action_file.unlink() # Remove once completed successfully + return status.returncode + else: + print( + f"Run failed: could not find work directory {workdir} to do action {state}.") + return 1 + except: + print(f"Run failed: State {state} did not succeed.") + return 1 + finally: + os.chdir(current_dir) + + class ChiRun(object): def __init__(self, opts): self._opts = opts - self._arg_dict = opts.args_dict + self._args_dict = opts.args_dict self._states = opts.states def run(self): @@ -23,14 +49,13 @@ def run(self): """ - # TODO Add option to see if sim_action file exists and only run those states. for run_state, vals in self._args_dict.items(): args = [str(a) for a in vals] sim_state = Path('sim.{}'.format(run_state)) # If sim action file exists then run the state if run_state in self._states: - if self.run_args(self._workdir, run_state, args): + if run_args(self._opts.workdir, run_state, args): (self._opts.workdir / '.error').touch() elif sim_state.exists(): sim_state.unlink() @@ -38,25 +63,6 @@ def run(self): def get_run_states(self): return self._states - @classmethod - def run_args(workdir, state, args): - action = state + '-ing' - action_file = Path('.' + action) - print("Started {} sim using args {}".format(action, args)) - sys.stdout.flush() - if workdir.exists(): - os.chdir(workdir) - action_file.touch() # Keeps track of current pipeline state - status = run(args) - if status.returncode: - print(f"Run failed: State {state} did not succeed.") - action_file.unlink() # Remove once completed successfully - return status.returncode - else: - print( - f"Run failed: could not find work directory {workdir} to do action {state}.") - return 1 - if __name__ == '__main__': opts = parse_chi_options() diff --git a/tests/mhelpers.py b/tests/mhelpers.py index d6ca815..7dde29d 100644 --- a/tests/mhelpers.py +++ b/tests/mhelpers.py @@ -23,7 +23,8 @@ MOCK_ARGS_FILE_DICT = {'stage1': ['arg1', 'arg2', 'arg3'], 'stage2': ['arg4', 'arg5', 'arg6']} -MOCK_SHELL_ARGS_FILE_DICT = {'touch': ['touch', 'mock_command.txt']} +MOCK_SHELL_ARGS_FILE_DICT = {'touch1': ['touch', 'mock_output1.txt'], + 'touch2': ['touch', 'mock_output2.txt'], } MOCK_PARAM_DICT_PATH = 'mock_param.yaml' MOCK_CHI_PARAM_DICT_PATH = 'mock_param_chi_param.yaml' @@ -33,7 +34,7 @@ def clean_mocks(): """Clean up mock directories and files before testing to make sure we are working from a clean slate. """ - for mpath in Path('.').glob('tests/mock*'): + for mpath in Path.cwd().glob('tests/mock*'): if mpath.is_file(): mpath.unlink() elif mpath.is_dir(): @@ -90,11 +91,6 @@ def mock_leaf_dir(): with yaml_param_path.open('w') as ypp: yaml.dump(MOCK_PARAM_DICT, ypp) - args_file_path = chi_leaf_path / 'mock_args.yaml' - with args_file_path.open('w') as aff: - yaml.dump(MOCK_ARGS_FILE_DICT, aff) - yield args_file_path - yield chi_leaf_path @@ -134,8 +130,6 @@ def mock_run_opts(): def opts(x): return None opts.command = 'run' opts.use_sim_states = 'False' - opts.replace = 'False' - opts.non_yaml = [] opts.args_dict = MOCK_ARGS_FILE_DICT opts.states = list(opts.args_dict.keys()) yield opts diff --git a/tests/test_chi_run.py b/tests/test_chi_run.py index f7f097c..cdd4b4d 100644 --- a/tests/test_chi_run.py +++ b/tests/test_chi_run.py @@ -15,14 +15,39 @@ def test_chi_run_states(mock_run_opts): assert crun.get_run_states() == mock_run_opts.states -def test_chi_run_with_touch(mock_run_opts): +def test_chi_run_touch(mock_leaf_dir, mock_run_opts): """Test chi_run.""" + mock_leaf_path = mock_leaf_dir + # Create and modify run optoins + mock_run_opts.args_dict = MOCK_SHELL_ARGS_FILE_DICT + mock_run_opts.states = mock_run_opts.args_dict.keys() + mock_run_opts.workdir = mock_leaf_path + # Make a ChiRun object crun = ChiRun(mock_run_opts) + # Run the pipeline + crun.run() + + # Make sure action is carried out + assert (mock_leaf_path / 'mock_output1.txt').exists() + assert (mock_leaf_path / 'mock_output2.txt').exists() - assert crun.get_run_states() == mock_run_opts.states +def test_chi_run_only_one_touch(mock_leaf_dir, mock_run_opts): + """Test chi_run.""" + mock_leaf_path = mock_leaf_dir + # Create and modify run optoins + mock_run_opts.args_dict = MOCK_SHELL_ARGS_FILE_DICT + mock_run_opts.states = ['touch1'] + mock_run_opts.workdir = mock_leaf_path + + # Make a ChiRun object + crun = ChiRun(mock_run_opts) # Run the pipeline + crun.run() + # Make sure action is carried out + assert (mock_leaf_path / 'mock_output1.txt').exists() + assert not (mock_leaf_path / 'mock_output2.txt').exists() -# TODO NEXT TEST add tests for chi_run.py +# TODO NEXT TEST test run args to make sure it always returns you to the right directory