class YamlTest(TestCase): def yaml_func(self, context, args): context.setdefault('args', {}).update(args) def setUp(self): self.step_set = StepSet() self.yaml_step = YamlFuncStep(self.yaml_func) self.step_set.add_step(self.yaml_step) def test_yaml_step(self): steps = self.step_set.parse('foo: bar\nbar: baz') expected = [({'foo': 'bar', 'bar': 'baz'}, self.yaml_step)] self.assertEqual(steps, expected) def test_multiple_yaml_steps(self): steps = self.step_set.parse('foo: bar\n...\nbar: baz\n...') expected = [({ 'foo': 'bar' }, self.yaml_step), ({ 'bar': 'baz' }, self.yaml_step)] self.assertEqual(steps, expected) context = self.step_set.run('foo: bar\n...\nbar: baz\n...') expected = {'foo': 'bar', 'bar': 'baz'} self.assertEqual(context.args, expected) def test_mixed_steps(self): re_step = RegexStep('%hello%') self.step_set.add_step(re_step) steps = self.step_set.parse('foo: bar\n...\n%hello%') expected = [({'foo': 'bar'}, self.yaml_step), ({}, re_step)] self.assertEqual(steps, expected)
class YamlTest(TestCase): def yaml_func(self, context, args): context.setdefault('args', {}).update(args) def setUp(self): self.step_set = StepSet() self.yaml_step = YamlFuncStep(self.yaml_func) self.step_set.add_step(self.yaml_step) def test_yaml_step(self): steps = self.step_set.parse('foo: bar\nbar: baz') expected = [({'foo': 'bar', 'bar': 'baz'}, self.yaml_step)] self.assertEqual(steps, expected) def test_multiple_yaml_steps(self): steps = self.step_set.parse('foo: bar\n...\nbar: baz\n...') expected = [({'foo': 'bar'}, self.yaml_step), ({'bar': 'baz'}, self.yaml_step)] self.assertEqual(steps, expected) context = self.step_set.run('foo: bar\n...\nbar: baz\n...') expected = { 'foo': 'bar', 'bar': 'baz' } self.assertEqual(context.args, expected) def test_mixed_steps(self): re_step = RegexStep('%hello%') self.step_set.add_step(re_step) steps = self.step_set.parse('foo: bar\n...\n%hello%') expected = [ ({'foo': 'bar'}, self.yaml_step), ({}, re_step) ] self.assertEqual(steps, expected)
class CompositeTest(TestCase): def setUp(self): self.step_set = StepSet() def set_x_to_y(context, args): context[args.x] = args.y self.set_step = RegexFuncStep('set (?P<x>.+) to (?P<y>.+)', set_x_to_y) self.step_set.add_step(self.set_step) def test_predicate_step(self): def if_func(context, args): return context[args.x] == args.y if_step = RegexFuncStep('if (?P<x>.+) is (?P<y>.+) then', if_func) def set_from_yaml(context, args): context.update(args) set_from_yaml_step = YamlFuncStep(set_from_yaml) pred_step = PredicateStep(if_step, set_from_yaml_step) self.step_set.add_step(pred_step) rule = """\ set foo to bar if foo is blah then a: 2 b: nope if foo is bar then c: 42 d: yep """ steps = self.step_set.parse(rule) expected = [ ({1: 'foo', 2: 'bar', 'x': 'foo', 'y': 'bar'}, self.set_step), ({1: 'foo', 2: 'blah', 'x': 'foo', 'y': 'blah', 'a': 2, 'b': 'nope'}, pred_step), ({1: 'foo', 2: 'bar', 'x': 'foo', 'y': 'bar', 'c': 42, 'd': 'yep'}, pred_step) ] self.assertEqual(steps, expected) context = self.step_set.run(rule) expected = { 'foo': 'bar', 'c': 42, 'd': 'yep', 1: 'foo', 2: 'bar', 'x': 'foo', 'y': 'bar', 'last_return': None } self.assertEqual(context, expected) def test_recursive_parse_conditional(self): def if_func(context, args): return context.get(args[1]) == args[2] if_step = RegexFuncStep( r'\s*if (.+) is (\w+) ', if_func, multiline=True) def set_from_yaml(context, args): context.setdefault('args', {}).update( {k: v for k, v in args.items() if isinstance(k, str)}) set_from_yaml_step = CompositeStep(PrefixStep('then set:'), YamlFuncStep(set_from_yaml)) self.step_set.add_step(PredicateStep(if_step)) self.step_set.add_step(set_from_yaml_step) rule = """ if a is b then set: x: blah y: 42 set a to b if a is b then set: foo: x bar: 0 """ context = self.step_set.run(rule) self.assertEqual(context.args, {'foo': 'x', 'bar': 0}) def test_yaml_prefix(self): def yaml_func(context, args): context.setdefault('args', {}).update(args) yaml_step = YamlFuncStep(yaml_func) prefix_step = PrefixStep('YAML!') prefixed_yaml_step = CompositeStep(prefix_step, yaml_step) self.step_set.add_step(prefixed_yaml_step) rule = """YAML! a: foo b: bar """ expected = {'a': 'foo', 'b': 'bar'} context = self.step_set.run(rule) self.assertEqual(context.args, expected) def test_loop_step(self): self.step_set.add_step(LoopStep('For each thing ', 'things')) @RegexFuncStep.make('increment') def increment(context, args): context[context.it] = context.get(context.it, 0) + 1 self.step_set.add_step(increment) rule = "For each thing increment" self.step_set.run(rule, context=Context(things=[]))
class CallingTest(TestCase): def setUp(self): self.step_set = StepSet() def test_run_plaintext(self): def set_foo(context, args): self.assertEqual(args, {}) context.foo = 'bar' return 'the middle' def set_bar(context, args): self.assertEqual(args, {}) self.assertEqual(context.last_return, 'the middle') context.bar = 'baz' return 'the end' self.step_set.add_step(RFS('Set foo', set_foo)) self.step_set.add_step(RFS('Set bar', set_bar)) context = self.step_set.run('Set foo\nSet bar') self.assertEqual(context.foo, 'bar') self.assertEqual(context.last_return, 'the end') def test_run_with_args(self): def set_x_to_y(context, args): context[args.x] = args.y def add_x_to_y(context, args): context.sum = int(context[args.x]) + int(context[args.y]) def x_should_equal_y(context, args): self.assertEqual(str(context[args.x]), args.y) self.step_set.add_step(RFS('Set (?P<x>.*) to (?P<y>.*)', set_x_to_y)) self.step_set.add_step(RFS('Add (?P<x>.*) to (?P<y>.*)', add_x_to_y)) self.step_set.add_step( RFS('(?P<x>.*) should equal (?P<y>.*)', x_should_equal_y)) self.step_set.run( dedent("""\ Set a to 1 Set b to 3 Add a to b sum should equal 4 Set c to 38 Add sum to c sum should equal 42""")) def test_run_multiline(self): def message(context, args): msg = re.sub(r'\s+', ' ', args.msg) messages = context.setdefault('messages', []) messages.append(msg) return msg step_re = r'([ /t]*)Message:\s*(?P<msg>.*(\n\1[ \t]+.+)*)' self.step_set.add_step(RFS(step_re, message, multiline=True)) lines = dedent("""\ Message: Hey there. This message is lots of lines long. Message: This is also a longer message. """) context = self.step_set.run(lines) self.assertEqual(context.messages, [ 'Hey there. This message is lots of lines long.', 'This is also a longer message.' ])
class ParsingTest(TestCase): def setUp(self): self.step_set = StepSet() _ok = lambda ctx, args: True def test_plain_text_step(self): step = RegexFuncStep("I'm a step!", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("I'm a step!") expected = [({}, step)] self.assertEqual(parsed, expected) def test_failed_plain_text_step(self): step = RegexFuncStep("I'm a step!", self._ok) self.step_set.add_step(step) self.assertRaises(UnmatchedStepError, self.step_set.parse, "I don't match") def test_plain_text_step_suffix_content(self): step = RegexFuncStep("I'm a step", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("I'm a step plus more") expected = [({'suffix_content': ' plus more'}, step)] self.assertEqual(parsed, expected) def test_plain_text_step_prefix_suffix_content(self): step = RegexFuncStep("I'm a step", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("Hey I'm a step plus") expected = [({'prefix_content': 'Hey ', 'suffix_content': ' plus'}, step)] self.assertEqual(parsed, expected) def test_regex_nocaptures(self): step = RegexFuncStep('^strictly this$', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('strictly this') expected = [({}, step)] self.assertEqual(parsed, expected) def test_regex_extra_fail(self): step = RegexFuncStep('^strictly this$', self._ok) self.step_set.add_step(step) self.assertRaises(UnmatchedStepError, self.step_set.parse, 'strictly this plus more') self.assertRaises(UnmatchedStepError, self.step_set.parse, 'prefix and strictly this') def test_regex_captures(self): step = RegexFuncStep('one (?P<two>.*) three (?P<four>.*)', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('one 2 three 4\none hey three there') expected = [ ({'two': '2', 'four': '4', 1: '2', 2: '4'}, step), ({'two': 'hey', 'four': 'there', 1: 'hey', 2: 'there'}, step) ] self.assertEqual(parsed, expected) def test_regex_numeric_captures(self): step = RegexFuncStep('one (.*) three (.*)', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('one 2 three 4\none hey three there') expected = [ ({1: '2', 2: '4'}, step), ({1: 'hey', 2: 'there'}, step) ] self.assertEqual(parsed, expected) def test_multiline(self): step = RegexFuncStep('this: (.*)\nand this: (.*)', self._ok, multiline=True) self.step_set.add_step(step) parsed = self.step_set.parse('this: first\nand this: second') expected = [({1: 'first', 2: 'second'}, step)] self.assertEqual(parsed, expected)
class CallingTest(TestCase): def setUp(self): self.step_set = StepSet() def test_run_plaintext(self): def set_foo(context, args): self.assertEqual(args, {}) context.foo = 'bar' return 'the middle' def set_bar(context, args): self.assertEqual(args, {}) self.assertEqual(context.last_return, 'the middle') context.bar = 'baz' return 'the end' self.step_set.add_step(RFS('Set foo', set_foo)) self.step_set.add_step(RFS('Set bar', set_bar)) context = self.step_set.run('Set foo\nSet bar') self.assertEqual(context.foo, 'bar') self.assertEqual(context.last_return, 'the end') def test_run_with_args(self): def set_x_to_y(context, args): context[args.x] = args.y def add_x_to_y(context, args): context.sum = int(context[args.x]) + int(context[args.y]) def x_should_equal_y(context, args): self.assertEqual(str(context[args.x]), args.y) self.step_set.add_step(RFS('Set (?P<x>.*) to (?P<y>.*)', set_x_to_y)) self.step_set.add_step(RFS('Add (?P<x>.*) to (?P<y>.*)', add_x_to_y)) self.step_set.add_step(RFS('(?P<x>.*) should equal (?P<y>.*)', x_should_equal_y)) self.step_set.run(dedent("""\ Set a to 1 Set b to 3 Add a to b sum should equal 4 Set c to 38 Add sum to c sum should equal 42""")) def test_run_multiline(self): def message(context, args): msg = re.sub(r'\s+', ' ', args.msg) messages = context.setdefault('messages', []) messages.append(msg) return msg step_re = r'([ /t]*)Message:\s*(?P<msg>.*(\n\1[ \t]+.+)*)' self.step_set.add_step(RFS(step_re, message, multiline=True)) lines = dedent("""\ Message: Hey there. This message is lots of lines long. Message: This is also a longer message. """) context = self.step_set.run(lines) self.assertEqual(context.messages, ['Hey there. This message is lots of lines long.', 'This is also a longer message.'])
class ParsingTest(TestCase): def setUp(self): self.step_set = StepSet() _ok = lambda ctx, args: True def test_plain_text_step(self): step = RegexFuncStep("I'm a step!", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("I'm a step!") expected = [({}, step)] self.assertEqual(parsed, expected) def test_failed_plain_text_step(self): step = RegexFuncStep("I'm a step!", self._ok) self.step_set.add_step(step) self.assertRaises(UnmatchedStepError, self.step_set.parse, "I don't match") def test_plain_text_step_suffix_content(self): step = RegexFuncStep("I'm a step", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("I'm a step plus more") expected = [({'suffix_content': ' plus more'}, step)] self.assertEqual(parsed, expected) def test_plain_text_step_prefix_suffix_content(self): step = RegexFuncStep("I'm a step", self._ok) self.step_set.add_step(step) parsed = self.step_set.parse("Hey I'm a step plus") expected = [({ 'prefix_content': 'Hey ', 'suffix_content': ' plus' }, step)] self.assertEqual(parsed, expected) def test_regex_nocaptures(self): step = RegexFuncStep('^strictly this$', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('strictly this') expected = [({}, step)] self.assertEqual(parsed, expected) def test_regex_extra_fail(self): step = RegexFuncStep('^strictly this$', self._ok) self.step_set.add_step(step) self.assertRaises(UnmatchedStepError, self.step_set.parse, 'strictly this plus more') self.assertRaises(UnmatchedStepError, self.step_set.parse, 'prefix and strictly this') def test_regex_captures(self): step = RegexFuncStep('one (?P<two>.*) three (?P<four>.*)', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('one 2 three 4\none hey three there') expected = [({ 'two': '2', 'four': '4', 1: '2', 2: '4' }, step), ({ 'two': 'hey', 'four': 'there', 1: 'hey', 2: 'there' }, step)] self.assertEqual(parsed, expected) def test_regex_numeric_captures(self): step = RegexFuncStep('one (.*) three (.*)', self._ok) self.step_set.add_step(step) parsed = self.step_set.parse('one 2 three 4\none hey three there') expected = [({1: '2', 2: '4'}, step), ({1: 'hey', 2: 'there'}, step)] self.assertEqual(parsed, expected) def test_multiline(self): step = RegexFuncStep('this: (.*)\nand this: (.*)', self._ok, multiline=True) self.step_set.add_step(step) parsed = self.step_set.parse('this: first\nand this: second') expected = [({1: 'first', 2: 'second'}, step)] self.assertEqual(parsed, expected)