Exemplo n.º 1
0
    def test_is_balanced(self):
        # Tests that balanced_reduce returns the object as a balanced tree
        class CombinedNode:
            def __init__(self, a, b):
                self.a = a
                self.b = b

            def __repr__(self):
                return '(%s %s)' % (self.a, self.b)

        self.assertEqual(
            repr(
                balanced_reduce(CombinedNode,
                                ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'])),
            '(((A B) (C D)) ((E F) (G H)))'
            # Note: functools.reduce will return '(((((((A B) C) D) E) F) G) H)'
        )
Exemplo n.º 2
0
    def test_is_balanced(self):
        # Tests that balanced_reduce returns the object as a balanced tree
        class CombinedNode:
            def __init__(self, a, b):
                self.a = a
                self.b = b

            def __repr__(self):
                return "(%s %s)" % (self.a, self.b)

        self.assertEqual(
            repr(
                balanced_reduce(CombinedNode,
                                ["A", "B", "C", "D", "E", "F", "G", "H"])),
            "(((A B) (C D)) ((E F) (G H)))"
            # Note: functools.reduce will return '(((((((A B) C) D) E) F) G) H)'
        )
Exemplo n.º 3
0
    def test_iterator_usage(self):
        class SequenceClass:
            def __init__(self, n):
                self.n = n

            def __getitem__(self, i):
                if 0 <= i < self.n:
                    return i
                else:
                    raise IndexError

        from operator import add
        self.assertEqual(balanced_reduce(add, SequenceClass(5)), 10)
        self.assertEqual(balanced_reduce(add, SequenceClass(5), 42), 52)
        self.assertRaises(TypeError, balanced_reduce, add, SequenceClass(0))
        self.assertEqual(balanced_reduce(add, SequenceClass(0), 42), 42)
        self.assertEqual(balanced_reduce(add, SequenceClass(1)), 0)
        self.assertEqual(balanced_reduce(add, SequenceClass(1), 42), 42)

        d = {"one": 1, "two": 2, "three": 3}
        self.assertEqual(balanced_reduce(add, d), "".join(d.keys()))
Exemplo n.º 4
0
    def test_reduce(self):
        class Squares:
            def __init__(self, max):
                self.max = max
                self.sofar = []

            def __len__(self):
                return len(self.sofar)

            def __getitem__(self, i):
                if not 0 <= i < self.max:
                    raise IndexError
                n = len(self.sofar)
                while n <= i:
                    self.sofar.append(n * n)
                    n += 1
                return self.sofar[i]

        def add(x, y):
            return x + y

        self.assertEqual(balanced_reduce(add, ['a', 'b', 'c'], ''), 'abc')
        self.assertEqual(
            balanced_reduce(add, [['a', 'c'], [], ['d', 'w']], []),
            ['a', 'c', 'd', 'w'])
        self.assertEqual(balanced_reduce(lambda x, y: x * y, range(2, 8), 1),
                         5040)
        self.assertEqual(balanced_reduce(lambda x, y: x * y, range(2, 21), 1),
                         2432902008176640000)
        self.assertEqual(balanced_reduce(add, Squares(10)), 285)
        self.assertEqual(balanced_reduce(add, Squares(10), 0), 285)
        self.assertEqual(balanced_reduce(add, Squares(0), 0), 0)
        self.assertRaises(TypeError, balanced_reduce)
        self.assertRaises(TypeError, balanced_reduce, 42, 42)
        self.assertRaises(TypeError, balanced_reduce, 42, 42, 42)
        self.assertEqual(balanced_reduce(42, "1"),
                         "1")  # func is never called with one item
        self.assertEqual(balanced_reduce(42, "", "1"),
                         "1")  # func is never called with one item
        self.assertRaises(TypeError, balanced_reduce, 42, (42, 42))
        self.assertRaises(
            TypeError, balanced_reduce, add,
            [])  # arg 2 must not be empty sequence with no initial value
        self.assertRaises(TypeError, balanced_reduce, add, "")
        self.assertRaises(TypeError, balanced_reduce, add, ())
        self.assertRaises(TypeError, balanced_reduce, add, object())

        class TestFailingIter:
            def __iter__(self):
                raise RuntimeError

        self.assertRaises(RuntimeError, balanced_reduce, add,
                          TestFailingIter())

        self.assertEqual(balanced_reduce(add, [], None), None)
        self.assertEqual(balanced_reduce(add, [], 42), 42)

        class BadSeq:
            def __getitem__(self, index):
                raise ValueError

        self.assertRaises(ValueError, balanced_reduce, 42, BadSeq())
Exemplo n.º 5
0
    def build_search_query_content(self, query, invert=False):
        if isinstance(query, PlainText):
            terms = query.query_string.split()
            if not terms:
                return None

            last_term = terms.pop()

            lexemes = Lexeme(last_term,
                             invert=invert,
                             prefix=self.LAST_TERM_IS_PREFIX)
            for term in terms:
                new_lexeme = Lexeme(term, invert=invert)

                if query.operator == "and":
                    lexemes &= new_lexeme
                else:
                    lexemes |= new_lexeme

            return SearchQuery(lexemes)

        elif isinstance(query, Phrase):
            return SearchQuery(query.query_string, search_type="phrase")

        elif isinstance(query, Boost):
            # Not supported
            msg = "The Boost query is not supported by the MySQL search backend."
            warnings.warn(msg, RuntimeWarning)

            return self.build_search_query_content(query.subquery,
                                                   invert=invert)

        elif isinstance(query, Not):
            return self.build_search_query_content(query.subquery,
                                                   invert=not invert)

        elif isinstance(query, (And, Or)):
            # If this part of the query is inverted, we swap the operator and
            # pass down the inversion state to the child queries.
            # This works thanks to De Morgan's law.
            #
            # For example, the following query:
            #
            #   Not(And(Term("A"), Term("B")))
            #
            # Is equivalent to:
            #
            #   Or(Not(Term("A")), Not(Term("B")))
            #
            # It's simpler to code it this way as we only need to store the
            # invert status of the terms rather than all the operators.

            subquery_lexemes = [
                self.build_search_query_content(subquery, invert=invert)
                for subquery in query.subqueries
            ]

            is_and = isinstance(query, And)

            if invert:
                is_and = not is_and

            if is_and:
                return balanced_reduce(lambda a, b: a & b, subquery_lexemes)
            else:
                return balanced_reduce(lambda a, b: a | b, subquery_lexemes)

        raise NotImplementedError(
            "`%s` is not supported by the MySQL search backend." %
            query.__class__.__name__)