Example #1
0
def test_cmdstep_runstep_cmd_is_dict_save_true_shell_false_formatting():
    """Dict command with save false and shell false with formatting."""
    context = Context({
        'k1': 'blah',
        'k2': True,
        'cmd': {
            'run': '{k1} -{k1}1 --{k1}2',
            'save': '{k2}'
        }
    })
    with patch_logger('blahname', logging.DEBUG) as mock_logger_debug:
        obj = CmdStep('blahname', context)

    assert obj.is_save
    assert obj.logger.name == 'blahname'
    assert obj.context == Context({
        'k1': 'blah',
        'k2': True,
        'cmd': {
            'run': '{k1} -{k1}1 --{k1}2',
            'save': '{k2}'
        }
    })
    assert obj.cmd_text == 'blah -blah1 --blah2'
    mock_logger_debug.assert_called_once_with(
        'Processing command string: {k1} -{k1}1 --{k1}2')

    with patch('subprocess.run') as mock_run:
        mock_run.return_value = subprocess.CompletedProcess(
            None, 0, 'std', 'err')
        with patch_logger('blahname', logging.ERROR) as mock_logger_error:
            obj.run_step(is_shell=False)

    mock_logger_error.assert_called_once_with('stderr: err')

    # blah is in a list because shell == false
    mock_run.assert_called_once_with(
        ['blah', '-blah1', '--blah2'],
        cwd=None,
        shell=False,
        # capture_output=True,
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE,
        # text=True,
        universal_newlines=True)

    assert context['cmdOut']['returncode'] == 0
    assert context['cmdOut']['stdout'] == 'std'
    assert context['cmdOut']['stderr'] == 'err'
Example #2
0
def test_cmdstep_runstep_cmd_is_string_formatting_shell_false():
    """Str command is always not is_save and works with formatting."""
    with patch_logger('blahname', logging.DEBUG) as mock_logger_debug:
        obj = CmdStep('blahname',
                      Context({
                          'k1': 'blah',
                          'cmd': '{k1} -{k1}1 --{k1}2'
                      }))

    assert not obj.is_save
    assert obj.cwd is None
    assert obj.logger.name == 'blahname'
    assert obj.context == Context({'k1': 'blah', 'cmd': '{k1} -{k1}1 --{k1}2'})
    assert obj.cmd_text == 'blah -blah1 --blah2'
    mock_logger_debug.assert_called_once_with(
        'Processing command string: {k1} -{k1}1 --{k1}2')

    with patch('subprocess.run') as mock_run:
        obj.run_step(is_shell=False)

    # blah is in a list because shell == false
    mock_run.assert_called_once_with(['blah', '-blah1', '--blah2'],
                                     cwd=None,
                                     shell=False,
                                     check=True)
Example #3
0
def test_cmdstep_runstep_cmd_is_string_formatting_shell_false_sic():
    """Command process special tag directive."""
    with patch_logger('blahname', logging.DEBUG) as mock_logger_debug:
        obj = CmdStep(
            'blahname',
            Context({
                'k1': 'blah',
                'cmd': SicString('{k1} -{k1}1 --{k1}2')
            }))

    assert not obj.is_save
    assert obj.cwd is None
    assert obj.logger.name == 'blahname'
    assert obj.context == Context({
        'k1': 'blah',
        'cmd': SicString('{k1} -{k1}1 --{k1}2')
    })
    assert obj.cmd_text == '{k1} -{k1}1 --{k1}2'
    mock_logger_debug.assert_called_once_with(
        'Processing command string: {k1} -{k1}1 --{k1}2')

    with patch('subprocess.run') as mock_run:
        obj.run_step(is_shell=False)

    # blah is in a list because shell == false
    mock_run.assert_called_once_with(['{k1}', '-{k1}1', '--{k1}2'],
                                     cwd=None,
                                     shell=False,
                                     check=True)
Example #4
0
def test_pype_set_groups(mock_run_pipeline):
    """Input pype use_parent_context True."""
    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': 'argument here',
            'useParentContext': True,
            'skipParse': True,
            'raiseError': True,
            'loader': 'test loader',
            'groups': 'testgroup',
            'success': 'successgroup',
            'failure': 'failuregroup'
        }
    })
    with patch_logger('pypyr.steps.pype', logging.INFO) as mock_logger_info:
        pype.run_step(context)

    mock_run_pipeline.assert_called_once_with(
        pipeline_name='pipe name',
        pipeline_context_input='argument here',
        context=context,
        parse_input=False,
        loader='test loader',
        groups=['testgroup'],
        success_group='successgroup',
        failure_group='failuregroup')

    assert mock_logger_info.mock_calls == [
        call('pyping pipe name, using parent context.'),
        call('pyped pipe name.')
    ]
Example #5
0
def test_pype_use_parent_context_no_swallow(mock_run_pipeline):
    """Input pype without swallowing error in child pipeline."""
    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': 'argument here',
            'useParentContext': True,
            'skipParse': True,
            'raiseError': True
        }
    })

    with patch_logger('pypyr.steps.pype', logging.ERROR) as mock_logger_error:
        with pytest.raises(RuntimeError) as err_info:
            pype.run_step(context)

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

    mock_run_pipeline.assert_called_once_with(
        pipeline_name='pipe name',
        pipeline_context_input='argument here',
        context=context,
        parse_input=False,
        loader=None,
        groups=None,
        success_group=None,
        failure_group=None)

    mock_logger_error.assert_called_once_with(
        'Something went wrong pyping pipe name. RuntimeError: whoops')
Example #6
0
def test_pathcheck_list_none():
    """Multiple paths ok with none returning match."""
    context = Context({
        'ok1': 'ov1',
        'pathCheck': ['./{ok1}/x', './arb/{ok1}', '{ok1}/arb/z']})

    with patch_logger(
            'pypyr.steps.pathcheck', logging.INFO
    ) as mock_logger_info:
        pathchecker.run_step(context)

    mock_logger_info.assert_called_once_with('checked 3 path(s) and found 0')

    assert context, "context shouldn't be None"
    assert len(context) == 3, "context should have 3 items"
    assert context['ok1'] == 'ov1'
    assert context['pathCheck'] == ['./{ok1}/x', './arb/{ok1}', '{ok1}/arb/z']
    assert context["pathCheckOut"] == {
        './{ok1}/x': {
            'exists': False,
            'count': 0,
            'found': []
        },
        './arb/{ok1}': {
            'exists': False,
            'count': 0,
            'found': []
        },
        '{ok1}/arb/z': {
            'exists': False,
            'count': 0,
            'found': []
        },
    }
Example #7
0
def assert_pipeline_raises(pipeline_name,
                           expected_error,
                           expected_error_msg,
                           expected_notify_output,
                           context_arg=None):
    """Assert pipeline fails with expected NOTIFY output.

    Will fail if pipeline does NOT raise expected_error.

    Args:
        pipeline_name: str. Name of pipeline to run. Relative to ./tests/
        expected_error: type. Expected exception type.
        expected_error_msg: str. Expected exception msg.
        expected_notify_output: list of str. Entirety of strings expected in
                                the NOTIFY level output during pipeline run.
        context_arg: str. Context argument input.
    """
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        with pytest.raises(expected_error) as actual_err:
            pypyr.pipelinerunner.main(pipeline_name=pipeline_name,
                                      pipeline_context_input=context_arg,
                                      working_dir=working_dir)

    if expected_error_msg:
        assert str(actual_err.value) == expected_error_msg

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]
Example #8
0
def test_glob_list(mock_glob):
    """Multiple paths ok."""
    context = Context({
        'ok1': 'ov1',
        'glob': ['./arb/x', './arb/y', './arb/z']})

    mock_glob.return_value = [
        './f1.1',
        './f2.1',
        './f2.2',
        './f2.3',
    ]

    with patch_logger('pypyr.steps.glob', logging.INFO) as mock_logger_info:
        glob_step.run_step(context)

    mock_logger_info.assert_called_once_with(
        'glob checked 3 globs and saved 4 paths to globOut')

    assert context, "context shouldn't be None"
    assert len(context) == 3, "context should have 3 items"
    assert context['ok1'] == 'ov1'
    assert context['glob'] == ['./arb/x', './arb/y', './arb/z']
    assert context["globOut"] == [
        './f1.1',
        './f2.1',
        './f2.2',
        './f2.3',
    ]

    mock_glob.assert_called_once_with(
        ['./arb/x', './arb/y', './arb/z'])
Example #9
0
def test_pathcheck_single_not_found(mock_glob):
    """Single path ok on not found."""
    context = Context({'ok1': 'ov1', 'pathCheck': './arb/x'})

    mock_glob.return_value = []

    with patch_logger('pypyr.steps.pathcheck',
                      logging.INFO) as mock_logger_info:
        pathchecker.run_step(context)

    mock_logger_info.assert_called_once_with('checked 1 path(s) and found 0')

    assert context, "context shouldn't be None"
    assert len(context) == 3, "context should have 3 items"
    assert context['ok1'] == 'ov1'
    assert context['pathCheck'] == './arb/x'
    assert context["pathCheckOut"] == {
        './arb/x': {
            'exists': False,
            'count': 0,
            'found': []
        }
    }

    mock_glob.assert_called_once_with('./arb/x')
Example #10
0
def test_objectrewriter_in_to_out_no_out_str(temp_file_creator):
    """Object Rewriter in place edit with str object."""
    representer = ArbRepresenter()
    rewriter = filesystem.ObjectRewriter(get_arb_formatted, representer)

    path_in = temp_file_creator()
    path_in.write_text('yyy')

    with patch_logger('pypyr.utils.filesystem',
                      logging.DEBUG) as mock_logger_debug:
        rewriter.in_to_out(str(path_in), None)

    assert representer.load_payload == 'yyy'
    assert representer.load_call_count == 1
    assert representer.dump_payload == 'XyyyX'
    assert representer.dump_call_count == 1

    assert mock_logger_debug.mock_calls == [
        call(f"opening source file: {path_in}"),
        call("opening temp file for writing..."),
        call(f"moving temp file to: {path_in}")
    ]

    assert path_in.is_file()
    assert path_in.read_text() == 'XyyyX'
Example #11
0
def test_cache_multiple_items_get_hit_closures():
    """Cache with multiple items work."""
    cache = Cache()

    def closure(x, y):
        def inner():
            return x + y
        return inner

    with patch_logger('pypyr.cache', logging.DEBUG) as mock_logger_debug:
        obj1 = cache.get('one', closure(2, 3))
        obj2 = cache.get('two', closure(4, 5))
        obj3 = cache.get('three', closure(6, 7))
        obj4 = cache.get('one', closure(8, 9))

    assert obj1 == 5
    assert obj2 == 9
    assert obj3 == 13
    assert obj4 == 5

    assert mock_logger_debug.mock_calls == [
        call("one not found in cache. . . creating"),
        call("two not found in cache. . . creating"),
        call("three not found in cache. . . creating"),
        call("one loading from cache")]
def test_pipeline_runner_main_with_context_with_failure_handled():
    """Run main with context with failure argument as expected."""
    expected_notify_output = ['sg3', 'on_failure']
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        out = pipelinerunner.main_with_context(
            pipeline_name='tests/pipelines/api/main-all',
            groups=['sg3'],
            failure_group='on_failure')

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]
    assert out.pipeline_name == 'tests/pipelines/api/main-all'
    assert out.working_dir == Path.cwd()

    assert len(out) == 2
    assert out['py'] == "raise ValueError('err from sg3')"

    assert len(out['runErrors']) == 1
    out_run_error = out['runErrors'][0]
    assert out_run_error
    assert out_run_error['col'] == 5
    assert out_run_error['customError'] == {}
    assert out_run_error['description'] == 'err from sg3'
    assert repr(out_run_error['exception']) == repr(ValueError('err from sg3'))
    assert out_run_error['line'] == 50
    assert out_run_error['name'] == 'ValueError'
    assert out_run_error['step'] == 'pypyr.steps.py'
    assert out_run_error['swallowed'] is False

    # somewhat arbitrary check if behaves like Context()
    with pytest.raises(KeyNotInContextError) as err:
        out.assert_key_has_value('set_in_pipe', 'arbcaller')

    assert str(err.value) == ("context['set_in_pipe'] doesn't exist. It must "
                              "exist for arbcaller.")
Example #13
0
def test_contextdefault_pass_different_types_with_log():
    """Input contextdefault success case with substitutions of non strings."""
    context = Context({
        'k1': 33,
        'k2': 123.45,
        'k3': False,
        'defaults': {
            'kint': '{k1}',
            'kfloat': '{k2}',
            'kbool': '{k3}'
        }
    })

    with patch_logger('pypyr.steps.default', logging.INFO) as mock_logger_info:
        pypyr.steps.default.run_step(context)

    mock_logger_info.assert_called_once_with('set 3 context item defaults.')

    assert context['kint'] == 33
    assert context['k1'] == 33
    assert context['kfloat'] == 123.45
    assert context['k2'] == 123.45
    assert not context['kbool']
    assert isinstance(context['kbool'], bool)
    assert not context['k3']
Example #14
0
def test_pype_use_parent_context_swallow_stop_error(mock_run_pipeline):
    """Input pype doesn't swallow stop error in child pipeline."""
    mock_run_pipeline.side_effect = mocked_run_pipeline_with_stop
    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': 'argument here',
            'useParentContext': True,
            'skipParse': True,
            'raiseError': False
        }
    })

    context.pipeline_name = 'og pipe name'

    with patch_logger('pypyr.steps.pype', logging.ERROR) as mock_logger_error:
        with pytest.raises(Stop) as err_info:
            pype.run_step(context)

        assert isinstance(err_info.value, Stop)

    assert context.pipeline_name == 'og pipe name'

    mock_run_pipeline.assert_called_once_with(
        pipeline_name='pipe name',
        pipeline_context_input=['argument', 'here'],
        context=context,
        parse_input=False,
        loader=None,
        groups=None,
        success_group=None,
        failure_group=None)

    mock_logger_error.assert_not_called()
Example #15
0
def test_pype_use_parent_context(mock_run_pipeline):
    """Input pype use_parent_context True."""
    mock_run_pipeline.side_effect = mocked_run_pipeline

    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': 'argument here',
            'useParentContext': True,
            'skipParse': True,
            'raiseError': True,
            'loader': 'test loader'
        }
    })
    context.pipeline_name = 'og pipe name'

    with patch_logger('pypyr.steps.pype', logging.INFO) as mock_logger_info:
        pype.run_step(context)

    mock_run_pipeline.assert_called_once_with(
        pipeline_name='pipe name',
        pipeline_context_input=['argument', 'here'],
        context=context,
        parse_input=False,
        loader='test loader',
        groups=None,
        success_group=None,
        failure_group=None)

    assert context.pipeline_name == 'og pipe name'

    assert mock_logger_info.mock_calls == [
        call('pyping pipe name, using parent context.'),
        call('pyped pipe name.')
    ]
Example #16
0
def test_pype_no_pipe_arg(mock_run_pipeline):
    """Input pype use_parent_context False."""
    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': None,
            'useParentContext': False,
            'skipParse': False,
            'raiseError': True,
        }
    })

    context.working_dir = 'arb/dir'

    with patch_logger('pypyr.steps.pype', logging.INFO) as mock_logger_info:
        pype.run_step(context)

    mock_run_pipeline.assert_called_once_with(pipeline_name='pipe name',
                                              pipeline_context_input=None,
                                              context={},
                                              parse_input=True,
                                              loader=None,
                                              groups=None,
                                              success_group=None,
                                              failure_group=None)

    assert mock_logger_info.mock_calls == [
        call('pyping pipe name, without parent context.'),
        call('pyped pipe name.')
    ]
Example #17
0
def test_objectrewriter_in_to_out_same_path(temp_file_creator):
    """Object Rewriter in place edit with path object."""
    representer = ArbRepresenter()
    rewriter = filesystem.ObjectRewriter(get_arb_formatted, representer)

    path_in = temp_file_creator()
    path_in.write_text('yyy')

    str_out = os.path.relpath(path_in)

    with patch_logger('pypyr.utils.filesystem',
                      logging.DEBUG) as mock_logger_debug:
        rewriter.in_to_out(path_in, str_out)

    assert representer.load_payload == 'yyy'
    assert representer.load_call_count == 1
    assert representer.dump_payload == 'XyyyX'
    assert representer.dump_call_count == 1

    assert mock_logger_debug.mock_calls == [
        call("in path and out path are the same file. writing to temp "
             "file and then replacing in path with the temp file."),
        call(f"opening source file: {path_in}"),
        call("opening temp file for writing..."),
        call(f"moving temp file to: {path_in}")
    ]

    assert path_in.is_file()
    assert path_in.read_text() == 'XyyyX'
Example #18
0
def test_init_package():
    """Import pypyr runs one off initialization code."""
    import logging
    with patch_logger(__name__, logging.NOTIFY) as mock_log:
        logging.getLogger(__name__).notify("arb")

    assert mock_log.mock_calls == [call('arb')]
Example #19
0
def test_cache_clear():
    """Cache should clear on clear()."""
    cache = Cache()

    def closure(x, y):
        def inner():
            return x + y
        return inner

    with patch_logger('pypyr.cache', logging.DEBUG) as mock_logger_debug:
        obj1 = cache.get('one', closure(2, 3))
        obj2 = cache.get('two', closure(4, 5))
        obj3 = cache.get('one', closure(6, 7))

    cache.clear()
    assert len(cache._cache) == 0
    assert obj1 == 5
    assert obj2 == 9
    assert obj3 == 5

    assert mock_logger_debug.mock_calls == [
        call("one not found in cache. . . creating"),
        call("two not found in cache. . . creating"),
        call("one loading from cache")]

    obj1 = cache.get('one', closure(2, 3))
    obj2 = cache.get('two', closure(4, 5))
    obj3 = cache.get('one', closure(6, 7))

    assert len(cache._cache) == 2
    assert obj1 == 5
    assert obj2 == 9
    assert obj3 == 5
Example #20
0
def test_objectrewriter_in_to_out_path(temp_dir, temp_file_creator):
    """Object Rewriter writes single in to out path object."""
    representer = ArbRepresenter()
    rewriter = filesystem.ObjectRewriter(get_arb_formatted, representer)

    path_in = temp_file_creator()
    path_in.write_text('yyy')
    path_out = temp_dir.joinpath('sub', 'filename')

    with patch_logger('pypyr.utils.filesystem',
                      logging.DEBUG) as mock_logger_debug:
        rewriter.in_to_out(path_in, path_out)

    assert representer.load_payload == 'yyy'
    assert representer.load_call_count == 1
    assert representer.dump_payload == 'XyyyX'
    assert representer.dump_call_count == 1

    assert mock_logger_debug.mock_calls == [
        call(f"opening source file: {path_in}"),
        call(f"opening destination file for writing: {path_out}")
    ]

    assert path_in.is_file()
    assert path_in.read_text() == 'yyy'
    assert path_out.is_file()
    assert path_out.read_text() == 'XyyyX'
Example #21
0
def test_filerewriter_files_in_to_out_dir_slash_create(temp_dir,
                                                       temp_file_creator):
    """Files in to out when out dir shown by / creates dir."""
    rewriter = ArbRewriter("formatter")

    file1 = temp_file_creator()
    file2 = temp_file_creator()

    in_path = temp_dir.joinpath("*")
    out = str(temp_dir.joinpath('sub')) + os.sep

    with patch_logger('pypyr.utils.filesystem',
                      logging.INFO) as mock_logger_info:
        rewriter.files_in_to_out(in_path, out)

    assert mock_logger_info.mock_calls == [
        call(f"read {in_path}, formatted and wrote 2 file(s) to {out}")
    ]

    path_out = Path(out)
    # out/sub exists
    assert path_out.is_dir()
    rewriter.assert_in_to_out_call_count(2)
    # outfile created with same name as in-file in out/sub dir
    rewriter.assert_in_to_out_call_path(file1, path_out.joinpath(file1.name))
    rewriter.assert_in_to_out_call_path(file2, path_out.joinpath(file2.name))
def test_pipeline_runner_main_with_context_minimal_with_failure_handled():
    """Run main with context minimal with failure argument as expected."""
    expected_notify_output = ['steps', 'on_success', 'on_failure']
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        out = pipelinerunner.main_with_context(
            pipeline_name='tests/pipelines/api/main-all',
            dict_in={'argList': ['A', 'B', 'C', 'raise on success']})

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]
    assert out.pipeline_name == 'tests/pipelines/api/main-all'
    assert out.working_dir == Path.cwd()

    assert len(out) == 4
    assert out['argList'] == ['A', 'B', 'C', 'raise on success']
    assert out['set_in_pipe'] == 456
    assert out['py'] == "raise ValueError('err from on_success')"

    assert len(out['runErrors']) == 1
    out_run_error = out['runErrors'][0]
    assert out_run_error
    assert out_run_error['col'] == 5
    assert out_run_error['customError'] == {}
    assert out_run_error['description'] == 'err from on_success'
    assert repr(out_run_error['exception']) == repr(
        ValueError('err from on_success'))
    assert out_run_error['line'] == 74
    assert out_run_error['name'] == 'ValueError'
    assert out_run_error['step'] == 'pypyr.steps.py'
    assert out_run_error['swallowed'] is False
    # somewhat arbitrary check if behaves like Context()
    out.assert_key_has_value('set_in_pipe', 'caller')
Example #23
0
def test_pype_use_parent_context_with_swallow(mock_run_pipeline):
    """Input pype swallowing error in child pipeline."""
    mock_run_pipeline.side_effect = mocked_run_pipeline_with_runtime_error
    context = Context({
        'pype': {
            'name': 'pipe name',
            'pipeArg': 'argument here',
            'useParentContext': True,
            'skipParse': True,
            'raiseError': False,
            'loader': 'test loader'
        }
    })

    context.pipeline_name = 'og pipe name'

    with patch_logger('pypyr.steps.pype', logging.ERROR) as mock_logger_error:
        pype.run_step(context)

    assert context.pipeline_name == 'og pipe name'

    mock_run_pipeline.assert_called_once_with(
        pipeline_name='pipe name',
        pipeline_context_input=['argument', 'here'],
        context=context,
        parse_input=False,
        loader='test loader',
        groups=None,
        success_group=None,
        failure_group=None)

    mock_logger_error.assert_called_once_with(
        'Something went wrong pyping pipe name. RuntimeError: whoops')
Example #24
0
def test_cmdstep_runstep_cmd_is_dict_save_true_shell_true_cwd_set():
    """Dict command with save false and shell true with cwd set."""
    context = Context({
        'cmd': {
            'run': 'blah -blah1 --blah2',
            'save': True,
            'cwd': 'pathhere'
        }
    })
    with patch_logger('blahname', logging.DEBUG) as mock_logger_debug:
        obj = CmdStep('blahname', context)

    assert obj.is_save
    assert obj.logger.name == 'blahname'
    assert obj.context == Context({
        'cmd': {
            'run': 'blah -blah1 --blah2',
            'save': True,
            'cwd': 'pathhere'
        }
    })
    assert obj.cmd_text == 'blah -blah1 --blah2'
    mock_logger_debug.assert_called_once_with(
        'Processing command string in dir pathhere: blah -blah1 --blah2')

    with patch('subprocess.run') as mock_run:
        mock_run.return_value = subprocess.CompletedProcess(
            None, 0, 'std', None)
        with patch_logger('blahname', logging.INFO) as mock_logger_info:
            obj.run_step(is_shell=True)

    mock_logger_info.assert_called_once_with('stdout: std')

    # blah is in a list because shell == false
    mock_run.assert_called_once_with(
        'blah -blah1 --blah2',
        cwd='pathhere',
        shell=True,
        # capture_output=True,
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE,
        # text=True,
        universal_newlines=True)

    assert context['cmdOut']['returncode'] == 0
    assert context['cmdOut']['stdout'] == 'std'
    assert context['cmdOut']['stderr'] is None
Example #25
0
def test_echo_echo_me_none_pass():
    """Echo can output None."""
    context = Context({'echoMe': None})
    with patch_logger(
            'pypyr.steps.echo', logging.NOTIFY) as mock_logger_notify:
        pypyr.steps.echo.run_step(context)

    mock_logger_notify.assert_called_once_with(str(None))
Example #26
0
def test_while_until_true_no_max(mock_time_sleep):
    """while_until_true with dynamic invocation, infinite (max is None)."""
    mock = MagicMock()
    mock.side_effect = [
        'test string 1',
        'test string 2',
        'test string 3',
        'test string 4',
        'test string 5',
        'test string 6',
        'test string 7',
        'test string 8',
        'test string 9',
        'test string 10',
        'test string 11',
    ]

    actual_counter = 0

    def decorate_me(counter, arg1, arg2):
        """Test static decorator syntax."""
        assert arg1 == 'v1'
        assert arg2 == 'v2'
        nonlocal actual_counter
        actual_counter += 1
        assert actual_counter == counter
        out = mock(arg1)
        assert out == f'test string {counter}'
        if out == 'test string 11':
            return True
        else:
            return False

    with patch_logger('pypyr.utils.poll', logging.DEBUG) as mock_logger_debug:
        assert (poll.while_until_true(interval=0.01,
                                      max_attempts=None)(decorate_me)('v1',
                                                                      'v2'))
    assert mock_logger_debug.mock_calls == [
        call('started'),
        call('Looping every 0.01 seconds.'),
        call('iteration 1. Still waiting. . .'),
        call('iteration 2. Still waiting. . .'),
        call('iteration 3. Still waiting. . .'),
        call('iteration 4. Still waiting. . .'),
        call('iteration 5. Still waiting. . .'),
        call('iteration 6. Still waiting. . .'),
        call('iteration 7. Still waiting. . .'),
        call('iteration 8. Still waiting. . .'),
        call('iteration 9. Still waiting. . .'),
        call('iteration 10. Still waiting. . .'),
        call('iteration 11. Desired state reached.'),
        call('done')
    ]

    assert mock.call_count == 11
    mock.assert_called_with('v1')
    assert mock_time_sleep.call_count == 10
    mock_time_sleep.assert_called_with(0.01)
Example #27
0
def test_no_inputs():
    """Dump entire context with no input specified."""
    context = Context({'k1': 'v1', 'k2': 'x{k1}x', 'k3': [0, 1, 2]})

    with patch_logger('pypyr.steps.debug', logging.INFO) as mock_logger_info:
        debug.run_step(context)

    assert mock_logger_info.mock_calls == [
        call("\n{'k1': 'v1', 'k2': 'x{k1}x', 'k3': [0, 1, 2]}")]
def test_pipeline_runner_main_minimal_with_failure_handled():
    """Run main minimal with failure argument as expected."""
    expected_notify_output = ['steps', 'on_success', 'on_failure']
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        pipelinerunner.main(
            pipeline_name='tests/pipelines/api/main-all',
            pipeline_context_input=['A', 'B', 'C', 'raise on success'])

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]
def test_pipeline_runner_main_minimal():
    """Run main with minimal arguments as expected."""
    expected_notify_output = ['steps', 'argList==None', 'on_success']

    # working_dir will default to repo root rather than test root
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        pipelinerunner.main('tests/pipelines/api/main-all')

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]
def test_pipeline_runner_main_with_failure_handled():
    """Run main with failure argument as expected."""
    expected_notify_output = ['sg3', 'on_failure']
    with patch_logger('pypyr.steps.echo', logging.NOTIFY) as mock_log:
        pipelinerunner.main(pipeline_name='tests/pipelines/api/main-all',
                            groups=['sg3'],
                            failure_group='on_failure')

    assert mock_log.mock_calls == [call(v) for v in expected_notify_output]