def test_cannot_add_qualifiers_without_runner_in_stack(self): rs = RunnerStack(None) with pytest.raises(err.VinoError) as exc_info: assert len(rs) == 0 rs.add_qualifiers([0, 1]) error = exc_info.value assert 'without specifying a processor' in str(error).lower()
def test_if_first_qfier_None_but_not_single_will_call_add_qualifiers( s, tags, mocker): processor = (tags[0], None, 3) rs = RunnerStack(None) mk_add_qf = mocker.patch.object(rs, 'add_qualifiers') rs.add(processor) mk_add_qf.assert_called_once_with(None, 3)
def test_by_default_new_rs_has_same_ctx_as_original(s, tags): my_context = {'a': 'b'} processors = tuple((t, None) for t in tags) rs = RunnerStack(my_context, *processors) nrs1 = rs.copy() nrs2 = rs.copy(None) assert rs.context is nrs1.context is nrs2.context
def test_can_override_context_for_new_rs(s, tags): context1 = {'a': 'b'} context2 = {'b': 'a'} processors = tuple((t, None) for t in tags) rs = RunnerStack(context1, *processors) nrs = rs.copy(context2) assert nrs.context is context2
def test_overriding_context_for_new_rs_does_not_change_original(s, tags): context1 = {'a': 'b'} context2 = {'b': 'a'} processors = tuple((t, None) for t in tags) rs = RunnerStack(context1, *processors) nrs = rs.copy(context2) assert rs.context is context1
def test_init_method_takes_context_as_first_param(self): with pytest.raises(TypeError) as exc_info: rs = RunnerStack() assert ("missing 1 required positional argument: 'context'" in str(exc_info.value)) rs = RunnerStack(None) assert rs.context is None context = "bla" rs = RunnerStack(context) assert rs.context is context
def test_successive_qualifier_applications_merges_qualifiers(self, tags): processors = ((t, None) for t in tags) c = ctx.Context(qualifier_stack_cls=quals.ItemQualifierStack) rs = RunnerStack(c) rs.add(*processors) rs.add_qualifiers([0, 1]) qstack = rs[-1]['qualifiers'] qualifiers = qstack.qualifiers assert qualifiers['indices'] == {0, 1} rs.add_qualifiers([1, 3, 8]) assert qualifiers['indices'] == {0, 1, 3, 8} rs.add_qualifiers(9, 5, 0, 1) assert qualifiers['indices'] == {0, 1, 3, 8, 9, 5}
def test_interrupts_validation_if_interrupt_flag_set_on_error(s, mocker): def failing_processor(value, context): e = err.ValidationError("I'll fail you, no matter what", interrupt_validation=True) raise e #mk = mocker.MagicMock() # probably better to declare some specs mk = mocker.MagicMock(spec=['run']) processors = tuple((t, None) for t in (failing_processor, mk)) rs = RunnerStack(None, *processors) try: value = rs.run('some contents') except err.ValidationErrorStack as e: assert not mk.run.called
def test_error_stack_given_final_value_if_no_interruption(s, tags): # tags are : bold, italic, and underline in that order def failing_processor(value, context): e = err.ValidationError("I'll fail you, no matter what", interrupt_validation=False) raise e processors = list((t, None) for t in tags) processors[1:1] = [[failing_processor, None]] # inserting at position 1 rs = RunnerStack(None, *processors) with pytest.raises(err.ValidationErrorStack) as e: value = rs.run('some contents') assert e.value.data == '<u><i><b>' + 'some contents' + '</b></i></u>'
def test_run_assigns_failing_value_to_error_after_validation(s, tags): # tags are : bold, italic, and underline in that order def failing_processor(value, context): e = err.ValidationError("I'll fail you, no matter what", interrupt_validation=True) raise e processors = list((t, None) for t in tags) processors[1:1] = [(failing_processor, None) ] # inserting at position 1 rs = RunnerStack(None, *processors) try: value = rs.run('some contents') except err.ValidationErrorStack as e: assert e[0].data == '<b>' + 'some contents' + '</b>'
def test_calls_next_runner_if_interrupt_flag_not_set_on_error(s, mocker): def failing_processor(value, context): e = err.ValidationError("I'll fail you, no matter what", interrupt_validation=False) raise e # we either need to specify spec to restrict the mock's public api # or test for `mock.run.called` #mk = mocker.MagicMock() # probably better to declare some specs mk = mocker.MagicMock(spec=['run', 'vino_init']) mk.vino_init.return_value = mk processors = tuple((t, None) for t in [failing_processor, mk]) rs = RunnerStack(None, *processors) try: value = rs.run('some contents') except err.ValidationErrorStack as e: assert mk.run.called
def test_cannot_add_qualifier_without_context(self, tags): processors = ((t, None) for t in tags) rs = RunnerStack(None) rs.add(*processors) with pytest.raises(err.VinoError) as exc_info: rs.add_qualifiers([0, 1]) error = exc_info.value assert 'must be given a context' in str(error).lower()
def test_can_add_qualifiers_if_context_has_QStack_class(self, tags): processors = ((t, None) for t in tags) c = ctx.Context() c = ctx.Context(qualifier_stack_cls=quals.ItemQualifierStack) rs = RunnerStack(c) rs.add(*processors) rs.add_qualifiers([0, 1]) qstack = rs[-1]['qualifiers'] qualifiers = qstack.qualifiers assert qualifiers['indices'] == {0, 1}
def test_cannot_add_qualifier_if_context_has_no_QStack_class(self, tags): processors = ((t, None) for t in tags) c = ctx.Context(qualifier_stack_cls=quals.ItemQualifierStack) rs = RunnerStack(c) rs.add(*processors) c.qualifier_stack_cls = None with pytest.raises(err.VinoError) as exc_info: rs.add_qualifiers([0, 1]) error = exc_info.value assert ('qualifierstack constructor must be specified' in str(error).lower())
def test_cannot_add_qualifiers_if_runner_has_qualifiers_set_to_False( self, tags): processors = ((t, None) for t in tags) c = ctx.Context() c._qualifier_stack_constructor = quals.ItemQualifierStack rs = RunnerStack(c) rs.add(*processors) rs[-1]['qualifiers'] = False with pytest.raises(err.VinoError) as exc_info: rs.add_qualifiers([0, 1]) error = exc_info.value assert 'does not accept qualifiers' in str(error).lower()
def test_single_qfier_set_to_False_sets_runner_qfiers_to_False(s, tags): processors = [[t, None] for t in tags] processors[1][1] = False rs = RunnerStack(None) rs.add(*processors) assert rs[1]['qualifiers'] is False
def test_if_single_qfier_is_None_no_qfiers_created(s, tags): processors = ((t, None) for t in tags) rs = RunnerStack(None) rs.add(*processors) for r in rs: assert r['qualifiers'] is None
def test_copied_rs_has_same_constructor_than_original(s, tags): processors = tuple((t, None) for t in tags) rs = RunnerStack(None, *processors) nrs = rs.copy() assert rs.__class__ is nrs.__class__
def test_copied_rs_has_same_runners_than_original(s, tags): processors = tuple((t, None) for t in tags) rs = RunnerStack(None, *processors) nrs = rs.copy() for i, r in enumerate(rs): assert r is nrs[i]
def test_copy_returns_different_runner_stack(s): rs = RunnerStack(None) nrs = rs.copy() assert rs is not nrs
def test_returns_number_of_runners_on_len(s, processors): length = len(processors) stack = RunnerStack(None, *processors) assert len(stack) == length
def test_can_add_processors_without_qualifiers(self, tags): processors = ((t, None) for t in tags) c = ctx.Context() rs = RunnerStack(c) rs.add(*processors) assert len(rs) == 3
def test_can_add_processors_without_context(self, tags): processors = ((t, None) for t in tags) rs = RunnerStack(None) rs.add(*processors) assert len(rs) == 3
def test_executes_runners_in_fifo(s, tags): # tags are : bold, italic, and underline in that order processors = ((t, None) for t in tags) rs = RunnerStack(None, *processors) post_process = '<u><i><b>' + 'some contents' + '</b></i></u>' assert rs.run('some contents') == post_process
def test_run_method_returns_value(s, randstr): context = None processor = (lambda v, c: v), None rs = RunnerStack(context, processor) assert rs.run(randstr) == randstr
def test_items_are_Runners(s, tags): processors = ((t, None) for t in tags) rs = RunnerStack(None) rs.add(*processors) for r in rs: assert isinstance(r['runner'], Runner)
def test_can_add_processors_in_tuple(self, tags): processors = ((t, None) for t in tags) rs = RunnerStack(None) rs.add(*processors) assert len(rs) == len(tags)
def test_cannot_add_processor_as_single_item(self, tags): rs = RunnerStack(None) with pytest.raises(err.VinoError) as exc_info: rs.add(*tags) error = exc_info.value assert 'must be specified in tuples' in str(error).lower()
def test_can_set_context_to_None_for_new_rs_by_specifying_False(s, tags): context1 = {'a': 'b'} processors = tuple((t, None) for t in tags) rs = RunnerStack(context1, *processors) nrs = rs.copy(False) assert nrs.context is None
def test_is_indexable(s, processors): length = len(processors) stack = RunnerStack(None, *processors) for i in range(length): assert stack[i]