def test_load_and_run_pipeline_steps_error_raises(
        mocked_get_work_dir,
        mocked_set_work_dir,
        mocked_get_pipe_def,
        mocked_get_parsed_context,
        mocked_steps_runner):
    """run_pipeline raises error if steps group fails."""
    pipeline_cache.clear()
    pypeloader_cache.clear()
    # First time it runs is steps - give a KeyNotInContextError.
    mocked_steps_runner.return_value.run_step_groups.side_effect = (
        KeyNotInContextError)

    with pytest.raises(KeyNotInContextError):
        pypyr.pipelinerunner.load_and_run_pipeline(
            pipeline_name='arb pipe',
            pipeline_context_input='arb context input')

    mocked_set_work_dir.assert_not_called()

    mocked_get_pipe_def.assert_called_once_with(pipeline_name='arb pipe',
                                                working_dir='arb/dir')
    mocked_get_parsed_context.assert_called_once_with(
        pipeline='pipe def',
        context_in_args='arb context input')

    mocked_steps_runner.return_value.run_step_groups.assert_called_once_with(
        groups=['steps'],
        success_group='on_success',
        failure_group='on_failure'
    )
    mocked_steps_runner.assert_called_once_with(pipeline_definition='pipe def',
                                                context={})
def test_load_and_run_pipeline_with_failure_group_specified(
        mocked_get_work_dir,
        mocked_set_work_dir,
        mocked_get_pipe_def,
        mocked_get_parsed_context,
        mocked_steps_runner):
    """Pass run_pipeline with specified failure group."""
    pipeline_cache.clear()
    pypeloader_cache.clear()
    existing_context = Context({'2': 'original', '3': 'new'})
    existing_context.working_dir = 'from/context'

    pypyr.pipelinerunner.load_and_run_pipeline(
        pipeline_name='arb pipe',
        pipeline_context_input='arb context input',
        context=existing_context,
        failure_group='arb1')

    assert existing_context.working_dir == 'from/context'
    mocked_set_work_dir.assert_not_called()
    mocked_get_pipe_def.assert_called_once_with(pipeline_name='arb pipe',
                                                working_dir='from/context')
    mocked_get_parsed_context.assert_called_once_with(
        pipeline='pipe def',
        context_in_args='arb context input')

    mocked_steps_runner.return_value.run_step_groups.assert_called_once_with(
        groups=['steps'],
        success_group=None,
        failure_group='arb1'
    )
    mocked_steps_runner.assert_called_once_with(pipeline_definition='pipe def',
                                                context={'1': 'context 1',
                                                         '2': 'context2',
                                                         '3': 'new'})
def test_load_and_run_pipeline_pass_skip_parse_context(
        mocked_get_work_dir,
        mocked_set_work_dir,
        mocked_get_pipe_def,
        mocked_get_parsed_context,
        mocked_steps_runner):
    """run_pipeline passes correct params to all methods."""
    pipeline_cache.clear()
    pypeloader_cache.clear()
    pypyr.pipelinerunner.load_and_run_pipeline(
        pipeline_name='arb pipe',
        parse_input=False)

    mocked_set_work_dir.assert_not_called()
    mocked_get_pipe_def.assert_called_once_with(pipeline_name='arb pipe',
                                                working_dir='arb/dir')
    mocked_get_parsed_context.assert_not_called()

    mocked_steps_runner.assert_called_once_with(pipeline_definition='pipe def',
                                                context={})
    # No called steps, just on_failure since err on parse context already
    sr = mocked_steps_runner.return_value
    sr.run_step_groups.assert_called_once_with(groups=['steps'],
                                               success_group='on_success',
                                               failure_group='on_failure')
    sr.run_failure_step_group.assert_not_called()
def test_load_and_run_pipeline_parse_context_error(
        mocked_get_work_dir,
        mocked_set_work_dir,
        mocked_get_pipe_def,
        mocked_get_parsed_context,
        mocked_steps_runner):
    """run_pipeline on_failure with empty Context if context parse fails."""
    pipeline_cache.clear()
    pypeloader_cache.clear()
    mocked_get_parsed_context.side_effect = ContextError

    with pytest.raises(ContextError):
        pypyr.pipelinerunner.load_and_run_pipeline(
            pipeline_name='arb pipe',
            pipeline_context_input='arb context input')

    mocked_set_work_dir.assert_not_called()
    mocked_get_pipe_def.assert_called_once_with(pipeline_name='arb pipe',
                                                working_dir='arb/dir')
    mocked_get_parsed_context.assert_called_once_with(
        pipeline='pipe def',
        context_in_args='arb context input')

    mocked_steps_runner.assert_called_once_with(pipeline_definition='pipe def',
                                                context=Context())
    # No called steps, just on_failure since err on parse context already
    sr = mocked_steps_runner.return_value
    sr.run_step_groups.assert_not_called()
    sr.run_failure_step_group.assert_called_once_with('on_failure')
def test_main_with_context_pass(mocked_get_mocked_work_dir,
                                mocked_set_work_dir, mocked_run_pipeline,
                                mocked_set_up_notify):
    """Main with context initializes and runs pipelines."""
    pipeline_cache.clear()
    out = pypyr.pipelinerunner.main_with_context(
        pipeline_name='arb pipe',
        dict_in={'arb': 'context input'},
        working_dir='arb/dir',
        groups=['g'],
        success_group='sg',
        failure_group='fg',
        loader='arb loader')

    assert out == Context({'arb': 'context input'})
    assert type(out) is Context
    assert out.pipeline_name == 'arb pipe'
    assert out.working_dir == 'arb/dir'

    mocked_set_up_notify.assert_not_called()
    mocked_set_work_dir.assert_called_once_with('arb/dir')
    mocked_run_pipeline.assert_called_once_with(pipeline_name='arb pipe',
                                                pipeline_context_input=None,
                                                context=out,
                                                parse_input=False,
                                                loader='arb loader',
                                                groups=['g'],
                                                success_group='sg',
                                                failure_group='fg')
def test_load_and_run_pipeline_pass(mocked_get_work_dir,
                                    mocked_set_work_dir,
                                    mocked_get_pipe_def,
                                    mocked_get_parsed_context,
                                    mocked_steps_runner):
    """On run_pipeline pass correct params to all methods."""
    pipeline_cache.clear()
    pypeloader_cache.clear()
    with patch('pypyr.context.Context') as mock_context:
        mock_context.return_value = Context()
        pypyr.pipelinerunner.load_and_run_pipeline(
            pipeline_name='arb pipe',
            pipeline_context_input='arb context input')

    mocked_set_work_dir.assert_not_called()
    mocked_get_pipe_def.assert_called_once_with(pipeline_name='arb pipe',
                                                working_dir='arb/dir')
    mocked_get_parsed_context.assert_called_once_with(
        pipeline='pipe def',
        context_in_args='arb context input')

    # assure that freshly created context instance does have working dir set
    assert mock_context.return_value.working_dir == 'arb/dir'

    mocked_steps_runner.assert_called_once_with(pipeline_definition='pipe def',
                                                context={'a': 'b'})
    # No called steps, just on_failure since err on parse context already
    sr = mocked_steps_runner.return_value
    sr.run_step_groups.assert_called_once_with(groups=['steps'],
                                               success_group='on_success',
                                               failure_group='on_failure')
    sr.run_failure_step_group.assert_not_called()
def test_arbitrary_loader_module_not_found():
    """Raise when loader not found."""
    with pytest.raises(PyModuleNotFoundError):
        pipeline_cache.clear()
        pypyr.moduleloader.set_working_directory('arb/dir')
        pypyr.pipelinerunner.load_and_run_pipeline(
            pipeline_name='arb pipe',
            pipeline_context_input='arb context input',
            loader='not_found_loader')
def test_main_with_minimal(mocked_get_mocked_work_dir, mocked_set_work_dir,
                           mocked_run_pipeline):
    """Main initializes and runs pipelines with minimal input."""
    pipeline_cache.clear()
    pypyr.pipelinerunner.main(pipeline_name='arb pipe')

    mocked_set_work_dir.assert_called_once_with(None)
    mocked_run_pipeline.assert_called_once_with(pipeline_name='arb pipe',
                                                pipeline_context_input=None,
                                                context=None,
                                                parse_input=True,
                                                loader=None,
                                                groups=None,
                                                success_group=None,
                                                failure_group=None)
def test_main_fail(mocked_work_dir, mocked_run_pipeline):
    """Main raise unhandled error on pipeline failure."""
    pipeline_cache.clear()
    with pytest.raises(ContextError) as err_info:
        pypyr.pipelinerunner.main(pipeline_name='arb pipe',
                                  pipeline_context_input='arb context input',
                                  working_dir='arb/dir')

    assert str(err_info.value) == "arb"

    mocked_work_dir.assert_called_once_with('arb/dir')
    mocked_run_pipeline.assert_called_once_with(
        pipeline_name='arb pipe',
        pipeline_context_input='arb context input',
        groups=None,
        success_group=None,
        failure_group=None)
def test_main_with_context_minimal(mocked_get_mocked_work_dir,
                                   mocked_set_work_dir, mocked_run_pipeline):
    """Main with context with minimal args."""
    pipeline_cache.clear()
    out = pypyr.pipelinerunner.main_with_context(pipeline_name='arb pipe')

    assert out == Context()
    assert type(out) is Context
    assert out.pipeline_name == 'arb pipe'
    assert out.working_dir == 'arb/dir'

    mocked_set_work_dir.assert_called_once_with(None)
    mocked_run_pipeline.assert_called_once_with(pipeline_name='arb pipe',
                                                pipeline_context_input=None,
                                                context=out,
                                                parse_input=False,
                                                loader=None,
                                                groups=None,
                                                success_group=None,
                                                failure_group=None)
def test_main_pass(mocked_get_mocked_work_dir,
                   mocked_set_work_dir,
                   mocked_run_pipeline,
                   mocked_set_up_notify):
    """Main initializes and runs pipelines."""
    pipeline_cache.clear()
    pypyr.pipelinerunner.main(pipeline_name='arb pipe',
                              pipeline_context_input='arb context input',
                              working_dir='arb/dir',
                              groups=['g'],
                              success_group='sg',
                              failure_group='fg')

    mocked_set_up_notify.assert_called_once()
    mocked_set_work_dir.assert_called_once_with('arb/dir')
    mocked_run_pipeline.assert_called_once_with(
        pipeline_name='arb pipe',
        pipeline_context_input='arb context input',
        groups=['g'],
        success_group='sg',
        failure_group='fg')
def test_empty_loader_set_up_to_default(mock_get_pipeline_definition,
                                        mock_run_pipeline):
    """Default loader should be pypyr.pypeloaders.fileloader."""
    pypyr.moduleloader.set_working_directory('arb/dir')
    pipeline_cache.clear()
    pypeloader_cache.clear()
    pypyr.pipelinerunner.load_and_run_pipeline(
        pipeline_name='arb pipe',
        pipeline_context_input='arb context input',
    )

    mock_get_pipeline_definition.assert_called_once_with(
        pipeline_name='arb pipe', working_dir=Path('arb/dir'))
    mock_run_pipeline.assert_called_once_with(
        context={},
        parse_input=True,
        pipeline='pipe def',
        pipeline_context_input='arb context input',
        groups=None,
        success_group=None,
        failure_group=None)
def test_main_with_context_fail(mocked_get_work_dir, mocked_work_dir,
                                mocked_run_pipeline):
    """Main with context raise unhandled error on pipeline failure."""
    pipeline_cache.clear()
    with pytest.raises(ContextError) as err_info:
        pypyr.pipelinerunner.main_with_context(
            pipeline_name='arb pipe',
            dict_in={'arb': 'context input'},
            working_dir='arb/dir')

    assert str(err_info.value) == "arb"

    mocked_work_dir.assert_called_once_with('arb/dir')
    mocked_run_pipeline.assert_called_once_with(pipeline_name='arb pipe',
                                                pipeline_context_input=None,
                                                context=Context(
                                                    {'arb': 'context input'}),
                                                parse_input=False,
                                                loader=None,
                                                groups=None,
                                                success_group=None,
                                                failure_group=None)
def test_arb_loader(mock_run_pipeline):
    """Test loader set up."""
    pypyr.moduleloader.set_working_directory('tests')
    pipeline_cache.clear()
    pypyr.pipelinerunner.load_and_run_pipeline(
        pipeline_name='arb pipe',
        pipeline_context_input='arb context input',
        loader='arbpack.arbloader',
        groups=None,
        success_group=None,
        failure_group=None
    )

    mock_run_pipeline.assert_called_once_with(
        context={},
        parse_input=True,
        pipeline={'pipeline_name': 'arb pipe',
                  'working_dir': 'tests'},
        pipeline_context_input='arb context input',
        groups=None,
        success_group=None,
        failure_group=None
    )