diff options
author | Matt Carmody <33763384+mattcarmody@users.noreply.github.com> | 2020-03-23 02:52:01 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-22 21:52:01 -0500 |
commit | db302309628c9aa4604092cd1642d708399d3e3a (patch) | |
tree | 51d491733ecf9610d4b58dfd882f862dd6f14eec /tests/test_unit.py | |
parent | 541159939d8679e3f0550f4f3f756c3a6a805432 (diff) | |
download | pyparsing-git-db302309628c9aa4604092cd1642d708399d3e3a.tar.gz |
New unit tests (#192)
* Add tests for matchPreviousLiteral - question in comments
* Bug fix - matchPreviousLiteral
One line fix for scanString of matchPreviousLiteral with mulitple
return tokens.
Test still needs to be refactored.
* Demo 3 issues in matchPreviousLiteral and matchPreviousExpr
* Correct mistakes and demonstrate potential matchPreviousExpr issue
* Add nestedExpr unit tests
* Add makeXMLTags unit test
* Add unit tests for oneOf with empty list and int input
Diffstat (limited to 'tests/test_unit.py')
-rw-r--r-- | tests/test_unit.py | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/tests/test_unit.py b/tests/test_unit.py index 39d10fa..e1986a9 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -1812,6 +1812,131 @@ class Test2_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase): "Failed repeater for test: {}, matching {}".format(tst, str(seq)), ) + def testRepeater2(self): + """test matchPreviousLiteral with empty repeater""" + + if ParserElement._packratEnabled: + print("skipping this test, not compatible with packratting") + return + + first = pp.Optional(pp.Word("abcdef").setName("words1")) + bridge = pp.Word(pp.nums).setName("number") + second = pp.matchPreviousLiteral(first).setName("repeat(word1Literal)") + + seq = first + bridge + second + + expected = True + found = False + tst = "12" + for tokens, start, end in seq.scanString(tst): + print(tokens) + found = True + if not found: + print("No literal match in", tst) + self.assertEqual( + expected, + found, + "Failed repeater for test: {}, matching {}".format(tst, str(seq)), + ) + + def testRepeater3(self): + """test matchPreviousLiteral with multiple repeater tokens""" + + if ParserElement._packratEnabled: + print("skipping this test, not compatible with packratting") + return + + first = pp.Word("a") + pp.Word("d") + bridge = pp.Word(pp.nums).setName("number") + second = pp.matchPreviousLiteral(first).setResultsName("second") + + seq = first + bridge + second + + expected = True + found = False + tst = "aaaddd12aaaddd" + + result = seq.parseString(tst) + print(result.dump()) + if result[0] == result[3] and result[1] == result[4]: + found = True + if not found: + print("No literal match in", tst) + self.assertEqual( + expected, + found, + "Failed repeater for test: {}, matching {}".format(tst, str(seq)), + ) + + def testRepeater4(self): + """test matchPreviousExpr with multiple repeater tokens""" + + if ParserElement._packratEnabled: + print("skipping this test, not compatible with packratting") + return + + first = pp.Group(pp.Word(pp.alphas) + pp.Word(pp.alphas))("first") + bridge = pp.Word(pp.nums) + + # no matching is used - this is just here for a sanity check + #second = pp.Group(pp.Word(pp.alphas) + pp.Word(pp.alphas))("second") + #second = pp.Group(pp.Word(pp.alphas) + pp.Word(pp.alphas)).setResultsName("second") + + # ISSUE: when matchPreviousExpr returns multiple tokens the matching tokens are nested an extra level deep. + # This behavior is not seen with a single return token (see testRepeater5 directly below.) + second = pp.matchPreviousExpr(first)("second") + + expr = first + bridge + second + + tst = "aaa ddd 12 aaa ddd" + + expected = True + found = False + + res = expr.parseString(tst) + print(res.dump()) + + # TODO: improve this hacky condition + if res["first"][0] == res["second"][0] and res["first"][1] == res["second"][1]: + found = True + if not found: + print("No literal match in", tst) + self.assertEqual( + expected, + found, + "Failed repeater for test: {}, matching {}".format(tst, str(expr)), + ) + + def testRepeater5(self): + """a simplified testRepeater4 to examine matchPreviousExpr with a single repeater token""" + + if ParserElement._packratEnabled: + print("skipping this test, not compatible with packratting") + return + + first = pp.Word(pp.alphas)("first") + bridge = pp.Word(pp.nums) + second = pp.matchPreviousExpr(first)("second") + + expr = first + bridge + second + + expected = True + found = False + tst = "aaa 12 aaa" + + res = expr.parseString(tst) + print(res.dump()) + + if res["first"] == res["second"]: + found = True + if not found: + print("No literal match in", tst) + self.assertEqual( + expected, + found, + "Failed repeater for test: {}, matching {}".format(tst, str(expr)), + ) + def testRecursiveCombine(self): from pyparsing import Forward, Word, alphas, nums, Optional, Combine @@ -3497,6 +3622,51 @@ class Test2_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase): verbose=True, ) + def testNestedExpressions2(self): + """test nestedExpr with conditions that explore other paths + + identical opener and closer + opener and/or closer of type other than string or iterable + multi-character opener and/or closer + single character opener and closer with ignoreExpr=None + multi-character opener and/or closer with ignoreExpr=None + """ + + name = pp.Word(pp.alphanums + "_") + + # identical opener and closer + with self.assertRaises(ValueError, msg="matching opener and closer should raise error"): + expr = name + pp.nestedExpr(opener="{", closer="{") + + # opener and/or closer of type other than string or iterable + with self.assertRaises(ValueError, msg="opener and closer as ints should raise error"): + expr = name + pp.nestedExpr(opener=12, closer=18) + + # multi-character opener and/or closer + tstMulti = "aName {{ outer {{ 'inner with opener {{ and closer }} in quoted string' }} }}" + expr = name + pp.nestedExpr(opener="{{", closer="}}") + result = expr.parseString(tstMulti) + expected = ['aName', ['outer', ["'inner with opener {{ and closer }} in quoted string'"]]] + print(result.dump()) + self.assertParseResultsEquals(result, expected, msg="issue with multi-character opener and closer") + + # single character opener and closer with ignoreExpr=None + tst = "aName { outer { 'inner with opener { and closer } in quoted string' }} }}" + expr = name + pp.nestedExpr(opener="{", closer="}", ignoreExpr=None) + singleCharResult = expr.parseString(tst) + print(singleCharResult.dump()) + + # multi-character opener and/or closer with ignoreExpr=None + expr = name + pp.nestedExpr(opener="{{", closer="}}", ignoreExpr=None) + multiCharResult = expr.parseString(tstMulti) + print(multiCharResult.dump()) + + self.assertParseResultsEquals( + singleCharResult, + multiCharResult.asList(), + msg="using different openers and closers shouldn't affect resulting ParseResults", + ) + def testWordExclude(self): from pyparsing import Word, printables @@ -5332,6 +5502,16 @@ class Test2_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase): }, ) + def testMakeXMLTags(self): + """test helper function makeXMLTags in simple use case""" + + body, bodyEnd = pp.makeXMLTags("body") + tst = "<body>Hello</body>" + expr = body + pp.Word(pp.alphas)("contents") + bodyEnd + result = expr.parseString(tst) + print(result.dump()) + self.assertParseResultsEquals(result, ['body', False, 'Hello', '</body>'], msg="issue using makeXMLTags") + def testFollowedBy(self): expr = pp.Word(pp.alphas)("item") + pp.FollowedBy(ppc.integer("qty")) @@ -6420,6 +6600,22 @@ class Test2_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase): "still have infinite loop in oneOf with duplicate symbols (set input)" ) + def testOneOfWithEmptyList(self): + """test oneOf helper function with an empty list as input""" + + tst = [] + result = pp.oneOf(tst) + + expected = True + found = isinstance(result, pp.NoMatch) + self.assertEqual(expected, found) + + def testOneOfWithUnexpectedInput(self): + """test oneOf with an input that isn't a string or iterable""" + + with self.assertWarns(SyntaxWarning, msg="failed to warn use of integer for oneOf"): + expr = pp.oneOf(6) + def testMatchFirstIteratesOverAllChoices(self): # test MatchFirst bugfix print("verify MatchFirst iterates properly") |