From 8fce0139dc37648bb7db96c2a341d9ccd05ccb95 Mon Sep 17 00:00:00 2001
From: TANIGUCHI Takaki <takaki@debian.org>
Date: Sat, 30 May 2020 13:54:50 +0900
Subject: [PATCH] New upstream version 0.10.0

---
 PKG-INFO                      |  15 +-
 README.rst                    |  10 +
 bin/jp.py                     |   2 +-
 jmespath.egg-info/PKG-INFO    |  15 +-
 jmespath.egg-info/SOURCES.txt |   5 +-
 jmespath/__init__.py          |  13 +-
 jmespath/parser.py            |   2 +-
 setup.py                      |  14 +-
 tests/__init__.py             |  40 ----
 tests/test_compliance.py      | 109 ----------
 tests/test_parser.py          | 368 ----------------------------------
 11 files changed, 64 insertions(+), 529 deletions(-)
 delete mode 100644 tests/__init__.py
 delete mode 100644 tests/test_compliance.py
 delete mode 100644 tests/test_parser.py

diff --git a/PKG-INFO b/PKG-INFO
index 8e567b4..6432a30 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: jmespath
-Version: 0.9.5
+Version: 0.10.0
 Summary: JSON Matching Expressions
 Home-page: https://github.com/jmespath/jmespath.py
 Author: James Saryerwinnie
@@ -55,6 +55,16 @@ Description: JMESPath
         The expression: ``foo.*.name`` will return ["one", "two"].
         
         
+        Installation
+        ============
+        
+        You can install JMESPath from pypi with:
+        
+        .. code:: bash
+        
+            pip install jmespath
+        
+        
         API
         ===
         
@@ -236,3 +246,4 @@ Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
diff --git a/README.rst b/README.rst
index 3e972da..530709e 100644
--- a/README.rst
+++ b/README.rst
@@ -47,6 +47,16 @@ The ``*`` can also be used for hash types::
 The expression: ``foo.*.name`` will return ["one", "two"].
 
 
+Installation
+============
+
+You can install JMESPath from pypi with:
+
+.. code:: bash
+
+    pip install jmespath
+
+
 API
 ===
 
diff --git a/bin/jp.py b/bin/jp.py
index 91b5ca9..6384876 100755
--- a/bin/jp.py
+++ b/bin/jp.py
@@ -34,7 +34,7 @@ def main():
         data = json.loads(data)
     try:
         sys.stdout.write(json.dumps(
-            jmespath.search(expression, data), indent=4))
+            jmespath.search(expression, data), indent=4, ensure_ascii=False))
         sys.stdout.write('\n')
     except exceptions.ArityError as e:
         sys.stderr.write("invalid-arity: %s\n" % e)
diff --git a/jmespath.egg-info/PKG-INFO b/jmespath.egg-info/PKG-INFO
index 8e567b4..6432a30 100644
--- a/jmespath.egg-info/PKG-INFO
+++ b/jmespath.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: jmespath
-Version: 0.9.5
+Version: 0.10.0
 Summary: JSON Matching Expressions
 Home-page: https://github.com/jmespath/jmespath.py
 Author: James Saryerwinnie
@@ -55,6 +55,16 @@ Description: JMESPath
         The expression: ``foo.*.name`` will return ["one", "two"].
         
         
+        Installation
+        ============
+        
+        You can install JMESPath from pypi with:
+        
+        .. code:: bash
+        
+            pip install jmespath
+        
+        
         API
         ===
         
@@ -236,3 +246,4 @@ Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
diff --git a/jmespath.egg-info/SOURCES.txt b/jmespath.egg-info/SOURCES.txt
index 24375d4..ef526cc 100644
--- a/jmespath.egg-info/SOURCES.txt
+++ b/jmespath.egg-info/SOURCES.txt
@@ -15,7 +15,4 @@ jmespath/visitor.py
 jmespath.egg-info/PKG-INFO
 jmespath.egg-info/SOURCES.txt
 jmespath.egg-info/dependency_links.txt
-jmespath.egg-info/top_level.txt
-tests/__init__.py
-tests/test_compliance.py
-tests/test_parser.py
\ No newline at end of file
+jmespath.egg-info/top_level.txt
\ No newline at end of file
diff --git a/jmespath/__init__.py b/jmespath/__init__.py
index f8f514b..99482db 100644
--- a/jmespath/__init__.py
+++ b/jmespath/__init__.py
@@ -1,7 +1,18 @@
+import warnings
+import sys
 from jmespath import parser
 from jmespath.visitor import Options
 
-__version__ = '0.9.5'
+__version__ = '0.10.0'
+
+
+if sys.version_info[:2] <= (2, 6) or ((3, 0) <= sys.version_info[:2] <= (3, 3)):
+    python_ver = '.'.join(str(x) for x in sys.version_info[:3])
+
+    warnings.warn(
+        'You are using Python {0}, which will no longer be supported in '
+        'version 0.11.0'.format(python_ver),
+        DeprecationWarning)
 
 
 def compile(expression):
diff --git a/jmespath/parser.py b/jmespath/parser.py
index 4d5ba38..eeac38f 100644
--- a/jmespath/parser.py
+++ b/jmespath/parser.py
@@ -490,7 +490,7 @@ class Parser(object):
 
     def _free_cache_entries(self):
         for key in random.sample(self._CACHE.keys(), int(self._MAX_SIZE / 2)):
-            del self._CACHE[key]
+            self._CACHE.pop(key, None)
 
     @classmethod
     def purge(cls):
diff --git a/setup.py b/setup.py
index e7f0e95..3337d51 100644
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,24 @@
 #!/usr/bin/env python
 
 import io
+import sys
+import warnings
 
 from setuptools import setup, find_packages
 
 
+if sys.version_info[:2] <= (2, 6) or ((3, 0) <= sys.version_info[:2] <= (3, 3)):
+    python_ver = '.'.join(str(x) for x in sys.version_info[:3])
+
+    warnings.warn(
+        'You are using Python {0}, which will no longer be supported in '
+        'version 0.11.0'.format(python_ver),
+        DeprecationWarning)
+
+
 setup(
     name='jmespath',
-    version='0.9.5',
+    version='0.10.0',
     description='JSON Matching Expressions',
     long_description=io.open('README.rst', encoding='utf-8').read(),
     author='James Saryerwinnie',
@@ -16,6 +27,7 @@ setup(
     scripts=['bin/jp.py'],
     packages=find_packages(exclude=['tests']),
     license='MIT',
+    python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*',
     classifiers=[
         'Development Status :: 5 - Production/Stable',
         'Intended Audience :: Developers',
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index d86946c..0000000
--- a/tests/__init__.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import sys
-from jmespath import ast
-
-
-# The unittest module got a significant overhaul
-# in 2.7, so if we're in 2.6 we can use the backported
-# version unittest2.
-if sys.version_info[:2] == (2, 6):
-    import unittest2 as unittest
-    import simplejson as json
-    from ordereddict import OrderedDict
-else:
-    import unittest
-    import json
-    from collections import OrderedDict
-
-
-# Helper method used to create an s-expression
-# of the AST to make unit test assertions easier.
-# You get a nice string diff on assert failures.
-def as_s_expression(node):
-    parts = []
-    _as_s_expression(node, parts)
-    return ''.join(parts)
-
-
-def _as_s_expression(node, parts):
-    parts.append("(%s" % (node.__class__.__name__.lower()))
-    if isinstance(node, ast.Field):
-        parts.append(" %s" % node.name)
-    elif isinstance(node, ast.FunctionExpression):
-        parts.append(" %s" % node.name)
-    elif isinstance(node, ast.KeyValPair):
-        parts.append(" %s" % node.key_name)
-    for child in node.children:
-        parts.append(" ")
-        _as_s_expression(child, parts)
-    parts.append(")")
-
-
diff --git a/tests/test_compliance.py b/tests/test_compliance.py
deleted file mode 100644
index 3cc8cdb..0000000
--- a/tests/test_compliance.py
+++ /dev/null
@@ -1,109 +0,0 @@
-import os
-from pprint import pformat
-from tests import OrderedDict
-from tests import json
-
-from nose.tools import assert_equal
-
-from jmespath.visitor import Options
-
-
-TEST_DIR = os.path.dirname(os.path.abspath(__file__))
-COMPLIANCE_DIR = os.path.join(TEST_DIR, 'compliance')
-LEGACY_DIR = os.path.join(TEST_DIR, 'legacy')
-NOT_SPECIFIED = object()
-OPTIONS = Options(dict_cls=OrderedDict)
-
-
-def test_compliance():
-    for full_path in _walk_files():
-        if full_path.endswith('.json'):
-            for given, test_type, test_data in load_cases(full_path):
-                t = test_data
-                # Benchmark tests aren't run as part of the normal
-                # test suite, so we only care about 'result' and
-                # 'error' test_types.
-                if test_type == 'result':
-                    yield (_test_expression, given, t['expression'],
-                           t['result'], os.path.basename(full_path))
-                elif test_type == 'error':
-                    yield (_test_error_expression, given, t['expression'],
-                           t['error'], os.path.basename(full_path))
-
-
-def _walk_files():
-    # Check for a shortcut when running the tests interactively.
-    # If a JMESPATH_TEST is defined, that file is used as the
-    # only test to run.  Useful when doing feature development.
-    single_file = os.environ.get('JMESPATH_TEST')
-    if single_file is not None:
-        yield os.path.abspath(single_file)
-    else:
-        for root, dirnames, filenames in os.walk(TEST_DIR):
-            for filename in filenames:
-                yield os.path.join(root, filename)
-        for root, dirnames, filenames in os.walk(LEGACY_DIR):
-            for filename in filenames:
-                yield os.path.join(root, filename)
-
-
-def load_cases(full_path):
-    all_test_data = json.load(open(full_path), object_pairs_hook=OrderedDict)
-    for test_data in all_test_data:
-        given = test_data['given']
-        for case in test_data['cases']:
-            if 'result' in case:
-                test_type = 'result'
-            elif 'error' in case:
-                test_type = 'error'
-            elif 'bench' in case:
-                test_type = 'bench'
-            else:
-                raise RuntimeError("Unknown test type: %s" % json.dumps(case))
-            yield (given, test_type, case)
-
-
-def _test_expression(given, expression, expected, filename):
-    import jmespath.parser
-    try:
-        parsed = jmespath.compile(expression)
-    except ValueError as e:
-        raise AssertionError(
-            'jmespath expression failed to compile: "%s", error: %s"' %
-            (expression, e))
-    actual = parsed.search(given, options=OPTIONS)
-    expected_repr = json.dumps(expected, indent=4)
-    actual_repr = json.dumps(actual, indent=4)
-    error_msg = ("\n\n  (%s) The expression '%s' was suppose to give:\n%s\n"
-                 "Instead it matched:\n%s\nparsed as:\n%s\ngiven:\n%s" % (
-                     filename, expression, expected_repr,
-                     actual_repr, pformat(parsed.parsed),
-                     json.dumps(given, indent=4)))
-    error_msg = error_msg.replace(r'\n', '\n')
-    assert_equal(actual, expected, error_msg)
-
-
-def _test_error_expression(given, expression, error, filename):
-    import jmespath.parser
-    if error not in ('syntax', 'invalid-type',
-                     'unknown-function', 'invalid-arity', 'invalid-value'):
-        raise RuntimeError("Unknown error type '%s'" % error)
-    try:
-        parsed = jmespath.compile(expression)
-        parsed.search(given)
-    except ValueError:
-        # Test passes, it raised a parse error as expected.
-        pass
-    except Exception as e:
-        # Failure because an unexpected exception was raised.
-        error_msg = ("\n\n  (%s) The expression '%s' was suppose to be a "
-                     "syntax error, but it raised an unexpected error:\n\n%s" % (
-                         filename, expression, e))
-        error_msg = error_msg.replace(r'\n', '\n')
-        raise AssertionError(error_msg)
-    else:
-        error_msg = ("\n\n  (%s) The expression '%s' was suppose to be a "
-                     "syntax error, but it successfully parsed as:\n\n%s" % (
-                         filename, expression, pformat(parsed.parsed)))
-        error_msg = error_msg.replace(r'\n', '\n')
-        raise AssertionError(error_msg)
diff --git a/tests/test_parser.py b/tests/test_parser.py
deleted file mode 100644
index 9d6f43f..0000000
--- a/tests/test_parser.py
+++ /dev/null
@@ -1,368 +0,0 @@
-#!/usr/bin/env python
-
-import re
-from tests import unittest, OrderedDict
-
-from jmespath import parser
-from jmespath import visitor
-from jmespath import ast
-from jmespath import exceptions
-
-
-class TestParser(unittest.TestCase):
-    def setUp(self):
-        self.parser = parser.Parser()
-
-    def assert_parsed_ast(self, expression, expected_ast):
-        parsed = self.parser.parse(expression)
-        self.assertEqual(parsed.parsed, expected_ast)
-
-    def test_parse_empty_string_raises_exception(self):
-        with self.assertRaises(exceptions.EmptyExpressionError):
-            self.parser.parse('')
-
-    def test_field(self):
-        self.assert_parsed_ast('foo', ast.field('foo'))
-
-    def test_dot_syntax(self):
-        self.assert_parsed_ast('foo.bar',
-                               ast.subexpression([ast.field('foo'),
-                                                  ast.field('bar')]))
-
-    def test_multiple_dots(self):
-        parsed = self.parser.parse('foo.bar.baz')
-        self.assertEqual(
-            parsed.search({'foo': {'bar': {'baz': 'correct'}}}), 'correct')
-
-    def test_index(self):
-        parsed = self.parser.parse('foo[1]')
-        self.assertEqual(
-            parsed.search({'foo': ['zero', 'one', 'two']}),
-            'one')
-
-    def test_quoted_subexpression(self):
-        self.assert_parsed_ast('"foo"."bar"',
-                               ast.subexpression([
-                                   ast.field('foo'),
-                                   ast.field('bar')]))
-
-    def test_wildcard(self):
-        parsed = self.parser.parse('foo[*]')
-        self.assertEqual(
-            parsed.search({'foo': ['zero', 'one', 'two']}),
-            ['zero', 'one', 'two'])
-
-    def test_wildcard_with_children(self):
-        parsed = self.parser.parse('foo[*].bar')
-        self.assertEqual(
-            parsed.search({'foo': [{'bar': 'one'}, {'bar': 'two'}]}),
-            ['one', 'two'])
-
-    def test_or_expression(self):
-        parsed = self.parser.parse('foo || bar')
-        self.assertEqual(parsed.search({'foo': 'foo'}), 'foo')
-        self.assertEqual(parsed.search({'bar': 'bar'}), 'bar')
-        self.assertEqual(parsed.search({'foo': 'foo', 'bar': 'bar'}), 'foo')
-        self.assertEqual(parsed.search({'bad': 'bad'}), None)
-
-    def test_complex_or_expression(self):
-        parsed = self.parser.parse('foo.foo || foo.bar')
-        self.assertEqual(parsed.search({'foo': {'foo': 'foo'}}), 'foo')
-        self.assertEqual(parsed.search({'foo': {'bar': 'bar'}}), 'bar')
-        self.assertEqual(parsed.search({'foo': {'baz': 'baz'}}), None)
-
-    def test_or_repr(self):
-        self.assert_parsed_ast('foo || bar', ast.or_expression(ast.field('foo'),
-                                                               ast.field('bar')))
-
-    def test_unicode_literals_escaped(self):
-        self.assert_parsed_ast(r'`"\u2713"`', ast.literal(u'\u2713'))
-
-    def test_multiselect(self):
-        parsed = self.parser.parse('foo.{bar: bar,baz: baz}')
-        self.assertEqual(
-            parsed.search({'foo': {'bar': 'bar', 'baz': 'baz', 'qux': 'qux'}}),
-            {'bar': 'bar', 'baz': 'baz'})
-
-    def test_multiselect_subexpressions(self):
-        parsed = self.parser.parse('foo.{"bar.baz": bar.baz, qux: qux}')
-        self.assertEqual(
-            parsed.search({'foo': {'bar': {'baz': 'CORRECT'}, 'qux': 'qux'}}),
-            {'bar.baz': 'CORRECT', 'qux': 'qux'})
-
-    def test_multiselect_with_all_quoted_keys(self):
-        parsed = self.parser.parse('foo.{"bar": bar.baz, "qux": qux}')
-        result = parsed.search({'foo': {'bar': {'baz': 'CORRECT'}, 'qux': 'qux'}})
-        self.assertEqual(result, {"bar": "CORRECT", "qux": "qux"})
-
-    def test_function_call_with_and_statement(self):
-        self.assert_parsed_ast(
-            'f(@ && @)',
-            {'children': [{'children': [{'children': [], 'type': 'current'},
-                                        {'children': [], 'type': 'current'}],
-                           'type': 'and_expression'}],
-             'type': 'function_expression',
-             'value': 'f'})
-
-
-class TestErrorMessages(unittest.TestCase):
-
-    def setUp(self):
-        self.parser = parser.Parser()
-
-    def assert_error_message(self, expression, error_message,
-                             exception=exceptions.ParseError):
-        try:
-            self.parser.parse(expression)
-        except exception as e:
-            self.assertEqual(error_message, str(e))
-            return
-        except Exception as e:
-            self.fail(
-                "Unexpected error raised (%s: %s) for bad expression: %s" %
-                (e.__class__.__name__, e, expression))
-        else:
-            self.fail(
-                "ParseError not raised for bad expression: %s" % expression)
-
-    def test_bad_parse(self):
-        with self.assertRaises(exceptions.ParseError):
-            self.parser.parse('foo]baz')
-
-    def test_bad_parse_error_message(self):
-        error_message = (
-            'Unexpected token: ]: Parse error at column 3, '
-            'token "]" (RBRACKET), for expression:\n'
-            '"foo]baz"\n'
-            '    ^')
-        self.assert_error_message('foo]baz', error_message)
-
-    def test_bad_parse_error_message_with_multiselect(self):
-        error_message = (
-            'Invalid jmespath expression: Incomplete expression:\n'
-            '"foo.{bar: baz,bar: bar"\n'
-            '                       ^')
-        self.assert_error_message('foo.{bar: baz,bar: bar', error_message)
-
-    def test_incomplete_expression_with_missing_paren(self):
-        error_message = (
-            'Invalid jmespath expression: Incomplete expression:\n'
-            '"length(@,"\n'
-            '          ^')
-        self.assert_error_message('length(@,', error_message)
-
-    def test_bad_lexer_values(self):
-        error_message = (
-            'Bad jmespath expression: '
-            'Unclosed " delimiter:\n'
-            'foo."bar\n'
-            '    ^')
-        self.assert_error_message('foo."bar', error_message,
-                                  exception=exceptions.LexerError)
-
-    def test_bad_unicode_string(self):
-        # This error message is straight from the JSON parser
-        # and pypy has a slightly different error message,
-        # so we're not using assert_error_message.
-        error_message = re.compile(
-            r'Bad jmespath expression: '
-            r'Invalid \\uXXXX escape.*\\uAZ12', re.DOTALL)
-        with self.assertRaisesRegexp(exceptions.LexerError, error_message):
-            self.parser.parse(r'"\uAZ12"')
-
-
-class TestParserWildcards(unittest.TestCase):
-    def setUp(self):
-        self.parser = parser.Parser()
-        self.data = {
-            'foo': [
-                {'bar': [{'baz': 'one'}, {'baz': 'two'}]},
-                {'bar': [{'baz': 'three'}, {'baz': 'four'}, {'baz': 'five'}]},
-            ]
-        }
-
-    def test_multiple_index_wildcards(self):
-        parsed = self.parser.parse('foo[*].bar[*].baz')
-        self.assertEqual(parsed.search(self.data),
-                         [['one', 'two'], ['three', 'four', 'five']])
-
-    def test_wildcard_mix_with_indices(self):
-        parsed = self.parser.parse('foo[*].bar[0].baz')
-        self.assertEqual(parsed.search(self.data),
-                         ['one', 'three'])
-
-    def test_wildcard_mix_last(self):
-        parsed = self.parser.parse('foo[0].bar[*].baz')
-        self.assertEqual(parsed.search(self.data),
-                         ['one', 'two'])
-
-    def test_indices_out_of_bounds(self):
-        parsed = self.parser.parse('foo[*].bar[2].baz')
-        self.assertEqual(parsed.search(self.data),
-                         ['five'])
-
-    def test_root_indices(self):
-        parsed = self.parser.parse('[0]')
-        self.assertEqual(parsed.search(['one', 'two']), 'one')
-
-    def test_root_wildcard(self):
-        parsed = self.parser.parse('*.foo')
-        data = {'top1': {'foo': 'bar'}, 'top2': {'foo': 'baz'},
-                'top3': {'notfoo': 'notfoo'}}
-        # Sorted is being used because the order of the keys are not
-        # required to be in any specific order.
-        self.assertEqual(sorted(parsed.search(data)), sorted(['bar', 'baz']))
-        self.assertEqual(sorted(self.parser.parse('*.notfoo').search(data)),
-                         sorted(['notfoo']))
-
-    def test_only_wildcard(self):
-        parsed = self.parser.parse('*')
-        data = {'foo': 'a', 'bar': 'b', 'baz': 'c'}
-        self.assertEqual(sorted(parsed.search(data)), sorted(['a', 'b', 'c']))
-
-    def test_escape_sequences(self):
-        self.assertEqual(self.parser.parse(r'"foo\tbar"').search(
-            {'foo\tbar': 'baz'}), 'baz')
-        self.assertEqual(self.parser.parse(r'"foo\nbar"').search(
-            {'foo\nbar': 'baz'}), 'baz')
-        self.assertEqual(self.parser.parse(r'"foo\bbar"').search(
-            {'foo\bbar': 'baz'}), 'baz')
-        self.assertEqual(self.parser.parse(r'"foo\fbar"').search(
-            {'foo\fbar': 'baz'}), 'baz')
-        self.assertEqual(self.parser.parse(r'"foo\rbar"').search(
-            {'foo\rbar': 'baz'}), 'baz')
-
-    def test_consecutive_escape_sequences(self):
-        parsed = self.parser.parse(r'"foo\\nbar"')
-        self.assertEqual(parsed.search({'foo\\nbar': 'baz'}), 'baz')
-
-        parsed = self.parser.parse(r'"foo\n\t\rbar"')
-        self.assertEqual(parsed.search({'foo\n\t\rbar': 'baz'}), 'baz')
-
-    def test_escape_sequence_at_end_of_string_not_allowed(self):
-        with self.assertRaises(ValueError):
-            self.parser.parse('foobar\\')
-
-    def test_wildcard_with_multiselect(self):
-        parsed = self.parser.parse('foo.*.{a: a, b: b}')
-        data = {
-            'foo': {
-                'one': {
-                    'a': {'c': 'CORRECT', 'd': 'other'},
-                    'b': {'c': 'ALSOCORRECT', 'd': 'other'},
-                },
-                'two': {
-                    'a': {'c': 'CORRECT', 'd': 'other'},
-                    'c': {'c': 'WRONG', 'd': 'other'},
-                },
-            }
-        }
-        match = parsed.search(data)
-        self.assertEqual(len(match), 2)
-        self.assertIn('a', match[0])
-        self.assertIn('b', match[0])
-        self.assertIn('a', match[1])
-        self.assertIn('b', match[1])
-
-
-class TestMergedLists(unittest.TestCase):
-    def setUp(self):
-        self.parser = parser.Parser()
-        self.data = {
-            "foo": [
-                [["one", "two"], ["three", "four"]],
-                [["five", "six"], ["seven", "eight"]],
-                [["nine"], ["ten"]]
-            ]
-        }
-
-    def test_merge_with_indices(self):
-        parsed = self.parser.parse('foo[][0]')
-        match = parsed.search(self.data)
-        self.assertEqual(match, ["one", "three", "five", "seven",
-                                 "nine", "ten"])
-
-    def test_trailing_merged_operator(self):
-        parsed = self.parser.parse('foo[]')
-        match = parsed.search(self.data)
-        self.assertEqual(
-            match,
-            [["one", "two"], ["three", "four"],
-             ["five", "six"], ["seven", "eight"],
-             ["nine"], ["ten"]])
-
-
-class TestParserCaching(unittest.TestCase):
-    def test_compile_lots_of_expressions(self):
-        # We have to be careful here because this is an implementation detail
-        # that should be abstracted from the user, but we need to make sure we
-        # exercise the code and that it doesn't blow up.
-        p = parser.Parser()
-        compiled = []
-        compiled2 = []
-        for i in range(parser.Parser._MAX_SIZE + 1):
-            compiled.append(p.parse('foo%s' % i))
-        # Rerun the test and half of these entries should be from the
-        # cache but they should still be equal to compiled.
-        for i in range(parser.Parser._MAX_SIZE + 1):
-            compiled2.append(p.parse('foo%s' % i))
-        self.assertEqual(len(compiled), len(compiled2))
-        self.assertEqual(
-            [expr.parsed for expr in compiled],
-            [expr.parsed for expr in compiled2])
-
-    def test_cache_purge(self):
-        p = parser.Parser()
-        first = p.parse('foo')
-        cached = p.parse('foo')
-        p.purge()
-        second = p.parse('foo')
-        self.assertEqual(first.parsed,
-                         second.parsed)
-        self.assertEqual(first.parsed,
-                         cached.parsed)
-
-
-class TestParserAddsExpressionAttribute(unittest.TestCase):
-    def test_expression_available_from_parser(self):
-        p = parser.Parser()
-        parsed = p.parse('foo.bar')
-        self.assertEqual(parsed.expression, 'foo.bar')
-
-
-class TestParsedResultAddsOptions(unittest.TestCase):
-    def test_can_have_ordered_dict(self):
-        p = parser.Parser()
-        parsed = p.parse('{a: a, b: b, c: c}')
-        options = visitor.Options(dict_cls=OrderedDict)
-        result = parsed.search(
-            {"c": "c", "b": "b", "a": "a"}, options=options)
-        # The order should be 'a', 'b' because we're using an
-        # OrderedDict
-        self.assertEqual(list(result), ['a', 'b', 'c'])
-
-
-class TestRenderGraphvizFile(unittest.TestCase):
-    def test_dot_file_rendered(self):
-        p = parser.Parser()
-        result = p.parse('foo')
-        dot_contents = result._render_dot_file()
-        self.assertEqual(dot_contents,
-                         'digraph AST {\nfield1 [label="field(foo)"]\n}')
-
-    def test_dot_file_subexpr(self):
-        p = parser.Parser()
-        result = p.parse('foo.bar')
-        dot_contents = result._render_dot_file()
-        self.assertEqual(
-            dot_contents,
-            'digraph AST {\n'
-            'subexpression1 [label="subexpression()"]\n'
-            '  subexpression1 -> field2\n'
-            'field2 [label="field(foo)"]\n'
-            '  subexpression1 -> field3\n'
-            'field3 [label="field(bar)"]\n}')
-
-
-if __name__ == '__main__':
-    unittest.main()
-- 
GitLab