summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul McGuire <ptmcg@austin.rr.com>2019-09-06 22:50:28 -0500
committerPaul McGuire <ptmcg@austin.rr.com>2019-09-06 22:50:28 -0500
commit76d9748718eb3fbf16b2e352fd524ae123dd9f47 (patch)
treeab27d33e31acf51c9d56db0699032df6eca0f78b
parent87016995f05a0b4927eef22f767a349d85e6afd2 (diff)
downloadpyparsing-git-76d9748718eb3fbf16b2e352fd524ae123dd9f47.tar.gz
First take on unittest integration methods and classes
-rw-r--r--CHANGES3
-rw-r--r--pyparsing.py106
-rw-r--r--simple_unit_tests.py24
-rw-r--r--unitTests.py373
4 files changed, 307 insertions, 199 deletions
diff --git a/CHANGES b/CHANGES
index 26ac8ff..126a375 100644
--- a/CHANGES
+++ b/CHANGES
@@ -73,6 +73,9 @@ Version 3.0.0a1
pp.__diag__.enable_all_warnings()
+- New namespace, assert methods and classes added to support writing unit tests.
+ (MORE TBD)
+
- Fixed handling of ParseSyntaxExceptions raised as part of Each
expressions, when sub-expressions contain '-' backtrack
suppression. As part of resolution to a question posted by John
diff --git a/pyparsing.py b/pyparsing.py
index e47aa54..0e41493 100644
--- a/pyparsing.py
+++ b/pyparsing.py
@@ -96,7 +96,7 @@ classes inherit from. Use the docstrings for examples of how to:
"""
__version__ = "3.0.0a1"
-__versionTime__ = "02 Sep 2019 16:36 UTC"
+__versionTime__ = "07 Sep 2019 03:49 UTC"
__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>"
import string
@@ -114,8 +114,9 @@ from datetime import datetime
from operator import itemgetter, attrgetter
import itertools
from functools import wraps
-
from itertools import filterfalse
+from contextlib import contextmanager
+import unittest
try:
from _thread import RLock
@@ -6704,6 +6705,102 @@ pyparsing_unicode.ไทย = pyparsing_unicode.Thai
pyparsing_unicode.देवनागरी = pyparsing_unicode.Devanagari
+class pyparsing_test:
+ """
+ namespace class for classes useful in writing unit tests
+ """
+ class ParseTestContext:
+ def __init__(self):
+ self._save_context = {}
+
+ def __enter__(self):
+ self._save_context['default_whitespace'] = ParserElement.DEFAULT_WHITE_CHARS
+ self._save_context['default_keyword_chars'] = Keyword.DEFAULT_KEYWORD_CHARS
+ self._save_context['literal_string_class'] = ParserElement._literalStringClass
+ self._save_context['packrat_enabled'] = ParserElement._packratEnabled
+ return self
+
+ def __exit__(self, *args):
+ # reset pyparsing global state
+ if ParserElement.DEFAULT_WHITE_CHARS != self._save_context['default_whitespace']:
+ ParserElement.setDefaultWhitespaceChars(self._save_context['default_whitespace'])
+ Keyword.DEFAULT_KEYWORD_CHARS = self._save_context['default_keyword_chars']
+ ParserElement.inlineLiteralsUsing(self._save_context['literal_string_class'])
+ for diagname in __diag__._all_names:
+ __diag__.disable(diagname)
+ ParserElement._packratEnabled = self._save_context['packrat_enabled']
+
+
+ class ParseResultsAsserts(unittest.TestCase):
+
+ def assertParseResultsEquals(self, result, expected_list=None, expected_dict=None, msg=None):
+ """
+ Unit test assertion to compare a ParseResults object with an optional expected_list,
+ and compare any defined results names with an optional expected_dict.
+ :param result:
+ :param expected_list:
+ :param expected_dict:
+ :param msg:
+ :return:
+ """
+ if expected_list is not None:
+ self.assertEqual(expected_list, result.asList(), msg=msg)
+ if expected_dict is not None:
+ self.assertEqual(expected_dict, result.asDict(), msg=msg)
+
+ def assertRunTestResults(self, run_tests_report, expected_parse_results=None, msg=None):
+ """
+ Unit test assertion to evaluate output of ParserElement.runTests(). If a list of
+ list-dict tuples is given as the expected_parse_results argument, then these are zipped
+ with the report tuples returned by runTests and evaluated using assertParseResultsEquals.
+ Finally, asserts that the overall runTests() success value is True.
+
+ :param run_tests_report: tuple(bool, [tuple(str, ParseResults or Exception)]) returned from runTests
+ :param expected_parse_results (optional): [tuple(str, list, dict, Exception)]
+ :param msg:
+ :return: None
+ """
+ run_test_success, run_test_results = run_tests_report
+
+ if expected_parse_results is not None:
+ merged = [(*rpt, expected) for rpt, expected in zip(run_test_results, expected_parse_results)]
+ for test_string, result, expected in merged:
+ # expected should be a tuple containing a list and/or a dict or an exception,
+ # and optional failure message string
+ # an empty tuple will skip any result validation
+ fail_msg = next((exp for exp in expected if isinstance(exp, str)), None)
+ expected_exception = next((exp for exp in expected
+ if isinstance(exp, type) and issubclass(exp, Exception)), None)
+ if expected_exception is not None:
+ with self.assertRaises(expected_exception=expected_exception, msg=fail_msg or msg):
+ if isinstance(result, Exception):
+ raise result
+ else:
+ expected_list = next((exp for exp in expected if isinstance(exp, list)), None)
+ expected_dict = next((exp for exp in expected if isinstance(exp, dict)), None)
+ if (expected_list, expected_dict) != (None, None):
+ self.assertParseResultsEquals(result,
+ expected_list=expected_list, expected_dict=expected_dict,
+ msg=fail_msg or msg)
+ else:
+ # warning here maybe?
+ print("no validation for {!r}".format(test_string))
+
+ # do this last, in case some specific test results can be reported instead
+ self.assertTrue(run_test_success, msg=msg if msg is not None else "failed runTests")
+
+ @contextmanager
+ def assertRaisesParseException(self, exc_type=ParseException, msg=None):
+ with self.assertRaises(exc_type, msg=msg):
+ yield
+
+
+# build list of built-in expressions, for future reference if a global default value
+# gets updated
+_builtin_exprs = [v for v in itertools.chain(vars().values(), vars(pyparsing_common).values())
+ if isinstance(v, ParserElement)]
+
+
if __name__ == "__main__":
selectToken = CaselessLiteral("select")
@@ -6774,8 +6871,3 @@ if __name__ == "__main__":
pyparsing_common.uuid.runTests("""
12345678-1234-5678-1234-567812345678
""")
-
-# build list of built-in expressions, for future reference if a global default value
-# gets updated
-_builtin_exprs = [v for v in itertools.chain(vars().values(), vars(pyparsing_common).values())
- if isinstance(v, ParserElement)]
diff --git a/simple_unit_tests.py b/simple_unit_tests.py
index 6fdab44..f0493cf 100644
--- a/simple_unit_tests.py
+++ b/simple_unit_tests.py
@@ -11,6 +11,7 @@ import unittest
import pyparsing as pp
from collections import namedtuple
from datetime import datetime
+ppt = pp.pyparsing_test
# Test spec data class for specifying simple pyparsing test cases
PpTestSpec = namedtuple("PpTestSpec", "desc expr text parse_fn "
@@ -18,7 +19,7 @@ PpTestSpec = namedtuple("PpTestSpec", "desc expr text parse_fn "
PpTestSpec.__new__.__defaults__ = ('', pp.Empty(), '', 'parseString', None, None, None)
-class PyparsingExpressionTestCase(unittest.TestCase):
+class PyparsingExpressionTestCase(ppt.ParseResultsAsserts, unittest.TestCase):
"""
Base pyparsing testing class to parse various pyparsing expressions against
given text strings. Subclasses must define a class attribute 'tests' which
@@ -50,10 +51,9 @@ class PyparsingExpressionTestCase(unittest.TestCase):
if test_spec.parse_fn == 'parseString':
print(result.dump())
# compare results against given list and/or dict
- if test_spec.expected_list is not None:
- self.assertEqual(result.asList(), test_spec.expected_list)
- if test_spec.expected_dict is not None:
- self.assertEqual(result.asDict(), test_spec.expected_dict)
+ self.assertParseResultsEquals(result,
+ expected_list=test_spec.expected_list,
+ expected_dict=test_spec.expected_dict)
elif test_spec.parse_fn == 'transformString':
print(result)
# compare results against given list and/or dict
@@ -66,13 +66,13 @@ class PyparsingExpressionTestCase(unittest.TestCase):
self.assertEqual([result], test_spec.expected_list)
else:
# expect fail
- try:
- parsefn(test_spec.text)
- except Exception as exc:
- print(pp.ParseException.explain(exc))
- self.assertEqual(exc.loc, test_spec.expected_fail_locn)
- else:
- self.assertTrue(False, "failed to raise expected exception")
+ with self.assertRaisesParseException():
+ try:
+ parsefn(test_spec.text)
+ except Exception as exc:
+ print(pp.ParseException.explain(exc))
+ self.assertEqual(exc.loc, test_spec.expected_fail_locn)
+ raise
# =========== TEST DEFINITIONS START HERE ==============
diff --git a/unitTests.py b/unitTests.py
index 1bf584c..fb39e08 100644
--- a/unitTests.py
+++ b/unitTests.py
@@ -11,6 +11,7 @@ from unittest import TestCase, TestSuite, TextTestRunner
import datetime
from pyparsing import ParseException
import pyparsing as pp
+ppt = pp.pyparsing_test
import sys
from io import StringIO
@@ -60,7 +61,7 @@ class resetting(object):
BUFFER_OUTPUT = True
-class ParseTestCase(TestCase):
+class ParseTestCase(ppt.ParseResultsAsserts, TestCase):
def __init__(self):
super().__init__(methodName='_runTest')
@@ -75,7 +76,8 @@ class ParseTestCase(TestCase):
sys.stdout = buffered_stdout
sys.stderr = buffered_stdout
print(">>>> Starting test", str(self))
- self.runTest()
+ with ppt.ParseTestContext():
+ self.runTest()
finally:
print("<<<< End of test", str(self))
@@ -525,7 +527,7 @@ class ParseCommaSeparatedValuesTest(ParseTestCase):
for line, tests in zip(testData, testVals):
print("Parsing: %r ->" % line, end=' ')
results = ppc.comma_separated_list.parseString(line)
- print(results.asList())
+ print(results)
for t in tests:
if not(len(results) > t[0] and results[t[0]] == t[1]):
print("$$$", results.dump())
@@ -991,19 +993,13 @@ class ParseExpressionResultsAccumulateTest(ParseTestCase):
list_of_num=delimitedList(hexnum | num | name, ",")
tokens = list_of_num.parseString('1, 0x2, 3, 0x4, aaa')
- for k, llen, lst in (("base10", 2, ['1', '3']),
- ("hex", 2, ['0x2', '0x4']),
- ("word", 1, ['aaa'])):
- print(k, tokens[k])
- self.assertEqual(len(tokens[k]), llen, "Wrong length for key %s, %s" % (k, str(tokens[k].asList())))
- self.assertEqual(lst, tokens[k].asList(),
- "Incorrect list returned for key %s, %s" % (k, str(tokens[k].asList())))
- self.assertEqual(tokens.base10.asList(), ['1', '3'],
- "Incorrect list for attribute base10, %s" % str(tokens.base10.asList()))
- self.assertEqual(tokens.hex.asList(), ['0x2', '0x4'],
- "Incorrect list for attribute hex, %s" % str(tokens.hex.asList()))
- self.assertEqual(tokens.word.asList(), ['aaa'],
- "Incorrect list for attribute word, %s" % str(tokens.word.asList()))
+ print(tokens.dump())
+ self.assertParseResultsEquals(tokens,
+ expected_list=['1', '0x2', '3', '0x4', 'aaa'],
+ expected_dict={'base10': ['1', '3'],
+ 'hex': ['0x2', '0x4'],
+ 'word': ['aaa']},
+ )
from pyparsing import Literal, Word, nums, Group, Dict, alphas, \
quotedString, oneOf, delimitedList, removeQuotes, alphanums
@@ -1022,10 +1018,11 @@ class ParseExpressionResultsAccumulateTest(ParseTestCase):
test="""Q(x,y,z):-Bloo(x,"Mitsis",y),Foo(y,z,1243),y>28,x<12,x>3"""
queryRes = Query.parseString(test)
- print("pred", queryRes.pred)
- self.assertEqual(queryRes.pred.asList(), [['y', '>', '28'], ['x', '<', '12'], ['x', '>', '3']],
- "Incorrect list for attribute pred, %s" % str(queryRes.pred.asList()))
print(queryRes.dump())
+ self.assertParseResultsEquals(queryRes.pred,
+ expected_list=[['y', '>', '28'], ['x', '<', '12'], ['x', '>', '3']],
+ msg="Incorrect list for attribute pred, %s" % str(queryRes.pred.asList())
+ )
class ReStringRangeTest(ParseTestCase):
def runTest(self):
@@ -1121,14 +1118,12 @@ class SkipToParserTests(ParseTestCase):
num_word = Word(nums, asKeyword=True).setName("int")
def test(expr, test_string, expected_list, expected_dict):
- try:
- result = expr.parseString(test_string)
- except Exception as pe:
- if any(expected is not None for expected in (expected_list, expected_dict)):
- self.assertTrue(False, "{} failed to parse {!r}".format(expr, test_string))
+ if (expected_list, expected_dict) == (None, None):
+ with self.assertRaises(Exception, msg="{} failed to parse {!r}".format(expr, test_string)):
+ expr.parseString(test_string)
else:
- self.assertEqual(result.asList(), expected_list)
- self.assertEqual(result.asDict(), expected_dict)
+ result = expr.parseString(test_string)
+ self.assertParseResultsEquals(result, expected_list=expected_list, expected_dict=expected_dict)
# ellipses for SkipTo
e = ... + Literal("end")
@@ -1248,10 +1243,7 @@ class EllipsisRepetionWithResultsNamesTest(ParseTestCase):
for obs, exp in zip(results, expected):
test, result = obs
exp_list, exp_dict = exp
- self.assertEqual(result.asList(), exp_list,
- "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList()))
- self.assertEqual(result.asDict(), exp_dict,
- "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict()))
+ self.assertParseResultsEquals(result, expected_list=exp_list, expected_dict=exp_dict)
parser = label('label') + val[...]('values')
@@ -1268,10 +1260,7 @@ class EllipsisRepetionWithResultsNamesTest(ParseTestCase):
for obs, exp in zip(results, expected):
test, result = obs
exp_list, exp_dict = exp
- self.assertEqual(result.asList(), exp_list,
- "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList()))
- self.assertEqual(result.asDict(), exp_dict,
- "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict()))
+ self.assertParseResultsEquals(result, expected_list=exp_list, expected_dict=exp_dict)
pt = pp.Group(val('x') + pp.Suppress(',') + val('y'))
parser = label('label') + pt[...]("points")
@@ -1290,10 +1279,7 @@ class EllipsisRepetionWithResultsNamesTest(ParseTestCase):
for obs, exp in zip(results, expected):
test, result = obs
exp_list, exp_dict = exp
- self.assertEqual(result.asList(), exp_list,
- "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList()))
- self.assertEqual(result.asDict(), exp_dict,
- "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict()))
+ self.assertParseResultsEquals(result, expected_list=exp_list, expected_dict=exp_dict)
class CustomQuotesTest(ParseTestCase):
@@ -1386,7 +1372,7 @@ class RepeaterTest(ParseTestCase):
for tst, result in tests:
found = False
for tokens, start, end in seq.scanString(tst):
- print(tokens.asList())
+ print(tokens)
found = True
if not found:
print("No expression match in", tst)
@@ -1413,7 +1399,7 @@ class RepeaterTest(ParseTestCase):
for tst, result in tests:
found = False
for tokens, start, end in compoundSeq.scanString(tst):
- print("match:", tokens.asList())
+ print("match:", tokens)
found = True
break
if not found:
@@ -1433,7 +1419,7 @@ class RepeaterTest(ParseTestCase):
for tst, result in tests:
found = False
for tokens, start, end in eSeq.scanString(tst):
- print(tokens.asList())
+ print(tokens)
found = True
if not found:
print("No match in", tst)
@@ -1446,15 +1432,15 @@ class RecursiveCombineTest(ParseTestCase):
testInput = "myc(114)r(11)dd"
Stream=Forward()
Stream << Optional(Word(alphas)) + Optional("(" + Word(nums) + ")" + Stream)
- expected = Stream.parseString(testInput).asList()
- print(["".join(expected)])
+ expected = [''.join(Stream.parseString(testInput))]
+ print(expected)
Stream=Forward()
Stream << Combine(Optional(Word(alphas)) + Optional("(" + Word(nums) + ")" + Stream))
- testVal = Stream.parseString(testInput).asList()
+ testVal = Stream.parseString(testInput)
print(testVal)
- self.assertEqual("".join(testVal), "".join(expected), "Failed to process Combine with recursive content")
+ self.assertParseResultsEquals(testVal, expected_list=expected)
class InfixNotationGrammarTest1(ParseTestCase):
def runTest(self):
@@ -1502,10 +1488,12 @@ class InfixNotationGrammarTest1(ParseTestCase):
[[1, '+', [2, '*', ['-', [3, '^', 4]], '*', 5], '+', ['-', ['+', ['-', 6]]]]]
[[3, '!', '!']]""".split('\n')
expected = [ast.literal_eval(x.strip()) for x in expected]
- for t, e in zip(test, expected):
- print(t, "->", e, "got", expr.parseString(t).asList())
- self.assertEqual(expr.parseString(t).asList(), e,
- "mismatched results for infixNotation: got %s, expected %s" % (expr.parseString(t).asList(), e))
+ for test_str, exp_list in zip(test, expected):
+ result = expr.parseString(test_str)
+ print(test_str, "->", exp_list, "got", result)
+ self.assertParseResultsEquals(result, expected_list=exp_list,
+ msg="mismatched results for infixNotation: got %s, expected %s" %
+ (result.asList(), exp_list))
class InfixNotationGrammarTest2(ParseTestCase):
def runTest(self):
@@ -1583,8 +1571,10 @@ class InfixNotationGrammarTest2(ParseTestCase):
print("r =", boolVars["r"])
print()
for t in test:
- res = boolExpr.parseString(t)[0]
- print(t, '\n', res, '=', bool(res), '\n')
+ res = boolExpr.parseString(t)
+ print(t, '\n', res[0], '=', bool(res[0]), '\n')
+ expected = eval(t, {}, boolVars)
+ self.assertEquals(expected, bool(res[0]))
class InfixNotationGrammarTest3(ParseTestCase):
@@ -1647,14 +1637,14 @@ class InfixNotationGrammarTest4(ParseTestCase):
f = booleanExpr(word) + pp.StringEnd()
tests = [
- ("bar = foo", "[['bar', '=', 'foo']]"),
- ("bar = foo & baz = fee", "['&', [['bar', '=', 'foo'], ['baz', '=', 'fee']]]"),
+ ("bar = foo", [['bar', '=', 'foo']]),
+ ("bar = foo & baz = fee", ['&', [['bar', '=', 'foo'], ['baz', '=', 'fee']]]),
]
for test, expected in tests:
print(test)
results = f.parseString(test)
print(results)
- self.assertEqual(str(results), expected, "failed to match expected results, got '%s'" % str(results))
+ self.assertParseResultsEquals(results, expected_list=expected)
print()
class InfixNotationGrammarTest5(ParseTestCase):
@@ -1805,8 +1795,9 @@ class ParseResultsWithNamedTupleTest(ParseTestCase):
res = expr.parseString("A")
print(repr(res))
print(res.Achar)
- self.assertEqual(res.Achar, ("A", "Z"),
- "Failed accessing named results containing a tuple, got {0!r}".format(res.Achar))
+ self.assertParseResultsEquals(res, expected_dict={'Achar': ('A', 'Z')},
+ msg="Failed accessing named results containing a tuple, "
+ "got {0!r}".format(res.Achar))
class ParseHTMLTagsTest(ParseTestCase):
@@ -1831,7 +1822,7 @@ class ParseHTMLTagsTest(ParseTestCase):
bodyStart, bodyEnd = pp.makeHTMLTags("BODY")
resIter = iter(results)
for t, s, e in (bodyStart | bodyEnd).scanString(test):
- print(test[s:e], "->", t.asList())
+ print(test[s:e], "->", t)
(expectedType, expectedEmpty, expectedBG, expectedFG) = next(resIter)
print(t.dump())
@@ -1876,11 +1867,6 @@ class UpcaseDowncaseUnicode(ParseTestCase):
kw = pp.Keyword('mykey', caseless=True).setParseAction(ppc.upcaseTokens)('rname')
ret = kw.parseString('mykey')
print(ret.rname)
- self.assertEqual(ret.rname, 'MYKEY', "failed to upcase with named result")
-
- kw = pp.Keyword('mykey', caseless=True).setParseAction(ppc.upcaseTokens)('rname')
- ret = kw.parseString('mykey')
- print(ret.rname)
self.assertEqual(ret.rname, 'MYKEY', "failed to upcase with named result (pyparsing_common)")
kw = pp.Keyword('MYKEY', caseless=True).setParseAction(ppc.downcaseTokens)('rname')
@@ -1966,7 +1952,7 @@ class ParseUsingRegex(ParseTestCase):
self.assertTrue(testMatch(namedGrouping, '"foo bar" baz', True, '"foo bar"'), "Re: (16) failed, expected pass")
ret = namedGrouping.parseString('"zork" blah')
- print(ret.asList())
+ print(ret)
print(list(ret.items()))
print(ret.content)
self.assertEqual(ret.content, 'zork', "named group lookup failed")
@@ -1996,7 +1982,8 @@ class RegexAsTypeTest(ParseTestCase):
result = expr.parseString(test_str)
print(result.dump())
print(expected_group_list)
- self.assertEqual(result.asList(), expected_group_list, "incorrect group list returned by Regex)")
+ self.assertParseResultsEquals(result, expected_list=expected_group_list,
+ msg="incorrect group list returned by Regex)")
print("return as re.match instance")
expr = pp.Regex(r"\w+ (?P<num1>\d+) (?P<num2>\d+) (?P<last_word>\w+)", asMatch=True)
@@ -2084,16 +2071,8 @@ class PrecededByTest(ParseTestCase):
]:
print(expr.searchString(s))
result = sum(expr.searchString(s))
- print(result)
-
- self.assertEqual(result.asList(), expected_list,
- "Erroneous tokens for {0}: expected {1}, got {2}".format(expr,
- expected_list,
- result.asList()))
- self.assertEqual(result.asDict(), expected_dict,
- "Erroneous named results for {0}: expected {1}, got {2}".format(expr,
- expected_dict,
- result.asDict()))
+ print(result.dump())
+ self.assertParseResultsEquals(result, expected_list, expected_dict)
class CountedArrayTest(ParseTestCase):
def runTest(self):
@@ -2106,10 +2085,9 @@ class CountedArrayTest(ParseTestCase):
r = OneOrMore(countedField).parseString(testString)
print(testString)
- print(r.asList())
+ print(r)
- self.assertEqual(r.asList(), [[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]],
- "Failed matching countedArray, got " + str(r.asList()))
+ self.assertParseResultsEquals(r, expected_list=[[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]])
class CountedArrayTest2(ParseTestCase):
# addresses bug raised by Ralf Vosseler
@@ -2124,10 +2102,9 @@ class CountedArrayTest2(ParseTestCase):
dummy = Word("A")
r = OneOrMore(dummy ^ countedField).parseString(testString)
print(testString)
- print(r.asList())
+ print(r)
- self.assertEqual(r.asList(), [[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]],
- "Failed matching countedArray, got " + str(r.asList()))
+ self.assertParseResultsEquals(r, expected_list=[[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]])
class CountedArrayTest3(ParseTestCase):
# test case where counter is not a decimal integer
@@ -2144,10 +2121,9 @@ class CountedArrayTest3(ParseTestCase):
r = OneOrMore(countedField).parseString(testString)
print(testString)
- print(r.asList())
+ print(r)
- self.assertEqual(r.asList(), [[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]],
- "Failed matching countedArray, got " + str(r.asList()))
+ self.assertParseResultsEquals(r, expected_list=[[5, 7], [0, 1, 2, 3, 4, 5], [], [5, 4, 3]])
class LineStartTest(ParseTestCase):
def runTest(self):
@@ -2257,13 +2233,13 @@ class LineAndStringEndTest(ParseTestCase):
for test, expected in tests:
res1 = bnf1.parseString(test)
print(res1, '=?', expected)
- self.assertEqual(res1.asList(), expected,
- "Failed lineEnd/stringEnd test (1): " + repr(test)+ " -> " + str(res1.asList()))
+ self.assertParseResultsEquals(res1, expected_list=expected,
+ msg="Failed lineEnd/stringEnd test (1): " + repr(test)+ " -> " + str(res1))
res2 = bnf2.searchString(test)[0]
- print(res2.asList(), '=?', expected[-1:])
- self.assertEqual(res2.asList(), expected[-1:],
- "Failed lineEnd/stringEnd test (2): " + repr(test)+ " -> " + str(res2.asList()))
+ print(res2, '=?', expected[-1:])
+ self.assertParseResultsEquals(res2, expected_list=expected[-1:],
+ msg="Failed lineEnd/stringEnd test (2): " + repr(test)+ " -> " + str(res2))
res3 = bnf3.parseString(test)
first = res3[0]
@@ -2289,16 +2265,15 @@ class LineAndStringEndTest(ParseTestCase):
]
for i, (src, expected) in enumerate(tests):
print(i, repr(src).replace('\\\\', '\\'), end=' ')
- try:
- res = k.parseString(src, parseAll=True).asList()
- except ParseException as pe:
- res = None
- print(res)
- self.assertEqual(res, expected, "Failed on parseAll=True test %d" % i)
+ if expected is None:
+ with self.assertRaisesParseException():
+ k.parseString(src, parseAll=True)
+ else:
+ res = k.parseString(src, parseAll=True)
+ self.assertParseResultsEquals(res, expected, msg="Failed on parseAll=True test %d" % i)
class VariableParseActionArgsTest(ParseTestCase):
def runTest(self):
-
pa3 = lambda s, l, t: t
pa2 = lambda l, t: t
pa1 = lambda t: t
@@ -2439,8 +2414,9 @@ class VariableParseActionArgsTest(ParseTestCase):
I | J | K | L | M | N | O | P | Q | R | S | U | V | B | T)
testString = "VUTSRQPONMLKJIHGFEDCBA"
res = gg.parseString(testString)
- print(res.asList())
- self.assertEqual(res.asList(), list(testString), "Failed to parse using variable length parse actions")
+ print(res)
+ self.assertParseResultsEquals(res, expected_list=list(testString),
+ msg="Failed to parse using variable length parse actions")
A = Literal("A").setParseAction(ClassAsPA0)
B = Literal("B").setParseAction(ClassAsPA1)
@@ -2457,7 +2433,7 @@ class VariableParseActionArgsTest(ParseTestCase):
"Failed to parse using variable length parse actions "
"using class constructors as parse actions")
-class EnablePackratParsing(ParseTestCase):
+class EnablePackratParsing(TestCase):
def runTest(self):
from pyparsing import ParserElement
ParserElement.enablePackrat()
@@ -3719,12 +3695,26 @@ class TokenMapTest(ParseTestCase):
from pyparsing import tokenMap, Word, hexnums, OneOrMore
parser = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
- success, results = parser.runTests("""
+ success, report = parser.runTests("""
00 11 22 aa FF 0a 0d 1a
- """, printResults=False)
- self.assertTrue(success, "failed to parse hex integers")
- print(results)
- self.assertEqual(results[0][-1].asList(), [0, 17, 34, 170, 255, 10, 13, 26], "tokenMap parse action failed")
+ """)
+ # WAS:
+ # self.assertTrue(success, "failed to parse hex integers")
+ # print(results)
+ # self.assertEqual(results[0][-1].asList(), [0, 17, 34, 170, 255, 10, 13, 26], "tokenMap parse action failed")
+
+ # USING JUST assertParseResultsEquals
+ # results = [rpt[1] for rpt in report]
+ # self.assertParseResultsEquals(results[0], [0, 17, 34, 170, 255, 10, 13, 26],
+ # msg="tokenMap parse action failed")
+
+ # if I hadn't unpacked the return from runTests, I could have just passed it directly,
+ # instead of reconstituting as a tuple
+ self.assertRunTestResults((success, report),
+ [
+ ([0, 17, 34, 170, 255, 10, 13, 26], "tokenMap parse action failed"),
+ ],
+ msg="failed to parse hex integers")
class ParseFileTest(ParseTestCase):
@@ -3860,56 +3850,71 @@ class ParseFatalExceptionTest(ParseTestCase):
from pyparsing import Word, nums, ParseFatalException
- success = False
- try:
+ with self.assertRaisesParseException(exc_type=ParseFatalException,
+ msg="failed to raise ErrorStop exception"):
expr = "ZZZ" - Word(nums)
expr.parseString("ZZZ bad")
- except ParseFatalException as pfe:
- print('ParseFatalException raised correctly')
- success = True
- except Exception as e:
- print(type(e))
- print(e)
- self.assertTrue(success, "bad handling of syntax error")
+ # WAS:
+ # success = False
+ # try:
+ # expr = "ZZZ" - Word(nums)
+ # expr.parseString("ZZZ bad")
+ # except ParseFatalException as pfe:
+ # print('ParseFatalException raised correctly')
+ # success = True
+ # except Exception as e:
+ # print(type(e))
+ # print(e)
+ #
+ # self.assertTrue(success, "bad handling of syntax error")
class InlineLiteralsUsingTest(ParseTestCase):
def runTest(self):
from pyparsing import ParserElement, Suppress, Literal, CaselessLiteral, Word, alphas, oneOf, CaselessKeyword, nums
- with resetting(ParserElement, "_literalStringClass"):
- ParserElement.inlineLiteralsUsing(Suppress)
- wd = Word(alphas)
- result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
- self.assertEqual(len(result), 3, "inlineLiteralsUsing(Suppress) failed!")
-
- ParserElement.inlineLiteralsUsing(Literal)
- result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
- self.assertEqual(len(result), 4, "inlineLiteralsUsing(Literal) failed!")
+ wd = Word(alphas)
- ParserElement.inlineLiteralsUsing(CaselessKeyword)
- result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
- self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
- "inlineLiteralsUsing(CaselessKeyword) failed!")
+ ParserElement.inlineLiteralsUsing(Suppress)
+ result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
+ self.assertEqual(len(result), 3, "inlineLiteralsUsing(Suppress) failed!")
- ParserElement.inlineLiteralsUsing(CaselessLiteral)
- result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
- self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
- "inlineLiteralsUsing(CaselessLiteral) failed!")
+ ParserElement.inlineLiteralsUsing(Literal)
+ result = (wd + ',' + wd + oneOf("! . ?")).parseString("Hello, World!")
+ self.assertEqual(len(result), 4, "inlineLiteralsUsing(Literal) failed!")
- integer = Word(nums)
- ParserElement.inlineLiteralsUsing(Literal)
- date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
- result = date_str.parseString("1999/12/31")
- self.assertEqual(result.asList(), ['1999', '/', '12', '/', '31'], "inlineLiteralsUsing(example 1) failed!")
+ ParserElement.inlineLiteralsUsing(CaselessKeyword)
+ result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
+ # WAS:
+ # self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
+ # "inlineLiteralsUsing(CaselessKeyword) failed!")
+ self.assertParseResultsEquals(result, "SELECT color FROM colors".split(),
+ msg="inlineLiteralsUsing(CaselessKeyword) failed!")
- # change to Suppress
- ParserElement.inlineLiteralsUsing(Suppress)
- date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+ ParserElement.inlineLiteralsUsing(CaselessLiteral)
+ result = ("SELECT" + wd + "FROM" + wd).parseString("select color from colors")
+ # self.assertEqual(result.asList(), "SELECT color FROM colors".split(),
+ # "inlineLiteralsUsing(CaselessLiteral) failed!")
+ self.assertParseResultsEquals(result, "SELECT color FROM colors".split(),
+ msg="inlineLiteralsUsing(CaselessLiteral) failed!")
- result = date_str.parseString("1999/12/31") # -> ['1999', '12', '31']
- self.assertEqual(result.asList(), ['1999', '12', '31'], "inlineLiteralsUsing(example 2) failed!")
+ integer = Word(nums)
+ ParserElement.inlineLiteralsUsing(Literal)
+ date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+ result = date_str.parseString("1999/12/31")
+ # self.assertEqual(result.asList(), ['1999', '/', '12', '/', '31'], "inlineLiteralsUsing(example 1) failed!")
+ self.assertParseResultsEquals(result, expected_list=['1999', '/', '12', '/', '31'],
+ msg="inlineLiteralsUsing(example 1) failed!")
+
+ # change to Suppress
+ ParserElement.inlineLiteralsUsing(Suppress)
+ date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+
+ result = date_str.parseString("1999/12/31") # -> ['1999', '12', '31']
+ # self.assertEqual(result.asList(), ['1999', '12', '31'], "inlineLiteralsUsing(example 2) failed!")
+ self.assertParseResultsEquals(result, expected_list=['1999', '12', '31'],
+ msg="inlineLiteralsUsing(example 2) failed!")
class CloseMatchTest(ParseTestCase):
def runTest(self):
@@ -3945,19 +3950,13 @@ class DefaultKeywordCharsTest(ParseTestCase):
def runTest(self):
import pyparsing as pp
- try:
+ with self.assertRaisesParseException(msg="failed to fail matching keyword using updated keyword chars"):
pp.Keyword("start").parseString("start1000")
- except pp.ParseException:
- pass
- else:
- self.assertTrue(False, "failed to fail on default keyword chars")
try:
pp.Keyword("start", identChars=pp.alphas).parseString("start1000")
except pp.ParseException:
self.assertTrue(False, "failed to match keyword using updated keyword chars")
- else:
- pass
with resetting(pp.Keyword, "DEFAULT_KEYWORD_CHARS"):
pp.Keyword.setDefaultKeywordChars(pp.alphas)
@@ -3965,22 +3964,14 @@ class DefaultKeywordCharsTest(ParseTestCase):
pp.Keyword("start").parseString("start1000")
except pp.ParseException:
self.assertTrue(False, "failed to match keyword using updated keyword chars")
- else:
- pass
- try:
+ with self.assertRaisesParseException(msg="failed to fail matching keyword using updated keyword chars"):
pp.CaselessKeyword("START").parseString("start1000")
- except pp.ParseException:
- pass
- else:
- self.assertTrue(False, "failed to fail on default keyword chars")
try:
pp.CaselessKeyword("START", identChars=pp.alphas).parseString("start1000")
except pp.ParseException:
self.assertTrue(False, "failed to match keyword using updated keyword chars")
- else:
- pass
with resetting(pp.Keyword, "DEFAULT_KEYWORD_CHARS"):
pp.Keyword.setDefaultKeywordChars(pp.alphas)
@@ -3988,8 +3979,6 @@ class DefaultKeywordCharsTest(ParseTestCase):
pp.CaselessKeyword("START").parseString("start1000")
except pp.ParseException:
self.assertTrue(False, "failed to match keyword using updated keyword chars")
- else:
- pass
class ColTest(ParseTestCase):
def runTest(self):
@@ -4053,7 +4042,8 @@ class ParseActionNestingTest(ParseTestCase):
vals.addParseAction(add_total)
results = vals.parseString("244 23 13 2343")
print(results.dump())
- self.assertEqual(results.int_values.asDict(), {}, "noop parse action changed ParseResults structure")
+ self.assertParseResultsEquals(results, expected_dict={'int_values': [244, 23, 13, 2343], 'total': 2623},
+ msg="noop parse action changed ParseResults structure")
name = pp.Word(pp.alphas)('name')
score = pp.Word(pp.nums + '.')('score')
@@ -4107,15 +4097,12 @@ class ParseResultsNamesInGroupWithDictTest(ParseTestCase):
test_string = '"Golden Gate Bridge" 37.819722 -122.478611 height=746 span=4200'
site.runTests(test_string)
- # U = list_num.parseString(test_string)
- # self.assertTrue("LIT_NUM" not in U.LIST.LIST_VALUES, "results name retained as sub in ungrouped named result")
-
a, aEnd = pp.makeHTMLTags('a')
attrs = a.parseString("<a href='blah'>")
print(attrs.dump())
- self.assertEqual(attrs.startA.href, 'blah')
- self.assertEqual(attrs.asDict(), {'startA': {'href': 'blah', 'tag': 'a', 'empty': False},
- 'href': 'blah', 'tag': 'a', 'empty': False})
+ self.assertParseResultsEquals(attrs,
+ expected_dict = {'startA': {'href': 'blah', 'tag': 'a', 'empty': False},
+ 'href': 'blah', 'tag': 'a', 'empty': False})
class FollowedByTest(ParseTestCase):
@@ -4193,8 +4180,10 @@ class UnicodeTests(ParseTestCase):
hello = "Καλημέρα, κόσμε!"
result = greet.parseString(hello)
print(result)
- self.assertTrue(result.asList() == ['Καλημέρα', ',', 'κόσμε', '!'],
- "Failed to parse Greek 'Hello, World!' using pyparsing_unicode.Greek.alphas")
+ self.assertParseResultsEquals(result,
+ expected_list=['Καλημέρα', ',', 'κόσμε', '!'],
+ msg="Failed to parse Greek 'Hello, World!' using "
+ "pyparsing_unicode.Greek.alphas")
# define a custom unicode range using multiple inheritance
class Turkish_set(ppu.Latin1, ppu.LatinA):
@@ -4223,9 +4212,10 @@ class UnicodeTests(ParseTestCase):
nüfus=4279677"""
result = pp.Dict(pp.OneOrMore(pp.Group(key_value))).parseString(sample)
- print(result.asDict())
- self.assertEqual(result.asDict(), {'şehir': 'İzmir', 'ülke': 'Türkiye', 'nüfus': 4279677},
- "Failed to parse Turkish key-value pairs")
+ print(result.dump())
+ self.assertParseResultsEquals(result,
+ expected_dict={'şehir': 'İzmir', 'ülke': 'Türkiye', 'nüfus': 4279677},
+ msg="Failed to parse Turkish key-value pairs")
class IndentedBlockExampleTest(ParseTestCase):
@@ -4508,12 +4498,18 @@ class ParseResultsWithNameMatchFirst(ParseTestCase):
expr_a = pp.Literal('not') + pp.Literal('the') + pp.Literal('bird')
expr_b = pp.Literal('the') + pp.Literal('bird')
expr = (expr_a | expr_b)('rexp')
- expr.runTests("""\
+
+ success, report = expr.runTests("""\
not the bird
the bird
""")
- self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
- self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
+ results = [rpt[1] for rpt in report]
+ self.assertParseResultsEquals(results[0],
+ ['not', 'the', 'bird'],
+ {'rexp': ['not', 'the', 'bird']})
+ self.assertParseResultsEquals(results[1],
+ ['the', 'bird'],
+ {'rexp': ['the', 'bird']})
# test compatibility mode, no longer restoring pre-2.3.1 behavior
with resetting(pp.__compat__, "collect_all_And_tokens"), \
@@ -4525,12 +4521,17 @@ class ParseResultsWithNameMatchFirst(ParseTestCase):
with self.assertWarns(UserWarning, msg="failed to warn of And within alternation"):
expr = (expr_a | expr_b)('rexp')
- expr.runTests("""
+ success, report = expr.runTests("""
not the bird
the bird
""")
- self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
- self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
+ results = [rpt[1] for rpt in report]
+ self.assertParseResultsEquals(results[0],
+ ['not', 'the', 'bird'],
+ {'rexp': ['not', 'the', 'bird']})
+ self.assertParseResultsEquals(results[1],
+ ['the', 'bird'],
+ {'rexp': ['the', 'bird']})
class ParseResultsWithNameOr(ParseTestCase):
@@ -4543,16 +4544,29 @@ class ParseResultsWithNameOr(ParseTestCase):
not the bird
the bird
""")
- self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
- self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
+ result = expr.parseString('not the bird')
+ self.assertParseResultsEquals(result,
+ ['not', 'the', 'bird'],
+ {'rexp': ['not', 'the', 'bird']})
+ result = expr.parseString('the bird')
+ self.assertParseResultsEquals(result,
+ ['the', 'bird'],
+ {'rexp': ['the', 'bird']})
expr = (expr_a | expr_b)('rexp')
expr.runTests("""\
not the bird
the bird
""")
- self.assertEqual(list(expr.parseString('not the bird')['rexp']), 'not the bird'.split())
- self.assertEqual(list(expr.parseString('the bird')['rexp']), 'the bird'.split())
+ result = expr.parseString('not the bird')
+ self.assertParseResultsEquals(result,
+ ['not', 'the', 'bird'],
+ {'rexp':
+ ['not', 'the', 'bird']})
+ result = expr.parseString('the bird')
+ self.assertParseResultsEquals(result,
+ ['the', 'bird'],
+ {'rexp': ['the', 'bird']})
# test compatibility mode, no longer restoring pre-2.3.1 behavior
with resetting(pp.__compat__, "collect_all_And_tokens"), \
@@ -5118,7 +5132,6 @@ def makeTestSuite():
test_case_classes.remove(PyparsingTestInit)
# test_case_classes.remove(ParseASMLTest)
- test_case_classes.remove(EnablePackratParsing)
if IRON_PYTHON_ENV:
test_case_classes.remove(OriginalTextForTest)