From d3c21497c5f9a3658658f37165ffa8e1f436e9fe Mon Sep 17 00:00:00 2001 From: ptmcg Date: Sat, 6 Feb 2016 20:04:48 +0000 Subject: Add support for pickling ParseResults with protocols 2 and higher (default protocol in Py3 is 3) git-svn-id: svn://svn.code.sf.net/p/pyparsing/code/trunk@318 9bf210a0-9d2d-494c-87cf-cfb32e7dff7b --- src/CHANGES | 7 +++++++ src/pyparsing.py | 7 ++++++- src/unitTests.py | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/CHANGES b/src/CHANGES index ff211a2..4fe0eda 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -13,6 +13,13 @@ Version 2.0.8 - most recently to Michael Cohen, who sent in a proposed patch, and got me to finally tackle this problem. +- Added compatibility for pickle protocols 2-4 when pickling ParseResults. + In Python 2.x, protocol 0 was the default, and protocol 2 did not work. + In Python 3.x, protocol 3 is the default, so explicitly naming + protocol 0 or 1 was required to pickle ParseResults. With this release, + all protocols 0-4 are supported. Thanks for reporting this on StackOverflow, + Arne Wolframm, and for providing a nice simple test case! + - Added expression names for many internal and builtin expressions, to reduce name and error message overhead during parsing. diff --git a/src/pyparsing.py b/src/pyparsing.py index f1f19c8..eaa99b3 100644 --- a/src/pyparsing.py +++ b/src/pyparsing.py @@ -58,7 +58,7 @@ The pyparsing module handles some of the problems that are typically vexing when """ __version__ = "2.0.8" -__versionTime__ = "23 Jan 2016 01:33" +__versionTime__ = "6 Feb 2016 13:47" __author__ = "Paul McGuire " import string @@ -282,6 +282,8 @@ class ParseResults(object): self.__name = None self.__parent = None self.__accumNames = {} + self.__asList = asList + self.__modal = modal if isinstance(toklist, list): self.__toklist = toklist[:] elif isinstance(toklist, _generatorType): @@ -688,6 +690,9 @@ class ParseResults(object): else: self.__parent = None + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + def __dir__(self): return (dir(type(self)) + list(self.keys())) diff --git a/src/unitTests.py b/src/unitTests.py index cf840eb..f38606b 100644 --- a/src/unitTests.py +++ b/src/unitTests.py @@ -1283,6 +1283,11 @@ class OperatorPrecedenceGrammarTest4(ParseTestCase): print_(results) assert str(results) == expected, "failed to match expected results, got '%s'" % str(results) print_() + +class Greeting(): + def __init__(self, toks): + self.salutation = toks[0] + self.greetee = toks[1] class ParseResultsPickleTest(ParseTestCase): @@ -1295,9 +1300,7 @@ class ParseResultsPickleTest(ParseTestCase): print_(result.dump()) print_() - # TODO - add support for protocols >= 2 - #~ for protocol in range(pickle.HIGHEST_PROTOCOL+1): - for protocol in range(2): + for protocol in range(pickle.HIGHEST_PROTOCOL+1): print_("Test pickle dump protocol", protocol) try: pickleString = pickle.dumps(result, protocol) @@ -1311,6 +1314,35 @@ class ParseResultsPickleTest(ParseTestCase): assert result.dump() == newresult.dump(), "Error pickling ParseResults object (protocol=%d)" % protocol print_() + import pyparsing as pp + import pickle + + + word = pp.Word(pp.alphas+"'.") + salutation = pp.OneOrMore(word) + comma = pp.Literal(",") + greetee = pp.OneOrMore(word) + endpunc = pp.oneOf("! ?") + greeting = salutation + pp.Suppress(comma) + greetee + pp.Suppress(endpunc) + greeting.setParseAction(Greeting) + + string = 'Good morning, Miss Crabtree!' + + result = greeting.parseString(string) + + for protocol in range(pickle.HIGHEST_PROTOCOL+1): + print_("Test pickle dump protocol", protocol) + pkl = "pickle_test_protocol_%d.pkl" % protocol + try: + pickleString = pickle.dumps(result, protocol) + except Exception as e: + print_("dumps exception:", e) + newresult = ParseResults([]) + else: + newresult = pickle.loads(pickleString) + print_(newresult.dump()) + + class ParseResultsWithNamedTupleTest(ParseTestCase): def runTest(self): @@ -2627,7 +2659,7 @@ if console: testRunner = TextTestRunner() testRunner.run( makeTestSuite() ) - #~ testclass = TrimArityExceptionMaskingTest + #~ testclass = ParseResultsPickleTest #~ if lp is None: #~ testRunner.run( makeTestSuiteTemp(testclass) ) #~ else: -- cgit v1.2.1