Esempio n. 1
0
    def test_Expression_variables(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        pvars: AnyOp = lambda e: p.parse(e).variables

        self.assertCaseEqual(pvars, [
            Case(('x * (y * atan(1))', ), {}, ('x', 'y')),
            Case(('pow(x, y)', ), {}, ('x', 'y')),
            Case(("PI", ), {}, tuple()),
            Case(("PI ", ), {}, tuple()),
            Case(("E ", ), {}, tuple()),
            Case((" E", ), {}, tuple()),
            Case(("E", ), {}, tuple()),
            Case(("E+1", ), {}, tuple()),
            Case(("E/1", ), {}, tuple()),
            Case(("sin(PI)+E", ), {}, tuple()),
            Case(('Pie', ), {}, ('Pie', )),
            Case(('PIe', ), {}, ('PIe', )),
            Case(('Eval', ), {}, ('Eval', )),
            Case(('Eval1', ), {}, ('Eval1', )),
            Case(('EPI', ), {}, ('EPI', )),
            Case(('PIE', ), {}, ('PIE', )),
            Case(('Engage', ), {}, ('Engage', )),
            Case(('Engage * PIE', ), {}, ('Engage', 'PIE')),
            Case(('Engage_', ), {}, ('Engage_', )),
            Case(('Engage1', ), {}, ('Engage1', )),
            Case(('E1', ), {}, ('E1', )),
            Case(('PI2', ), {}, ('PI2', )),
            Case(('(E1 + PI)', ), {}, ('E1', )),
            Case(('E1_', ), {}, ('E1_', )),
            Case(('E_', ), {}, ('E_', ))
        ])
Esempio n. 2
0
    def test_PyBuiltin_types(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Number Types
        self.assertCaseEqual(peval, [
            Case(('bool(x)', 1), {}, True),
            Case(('complex(x)', 1), {}, 1 + 0j),
            Case(('float(x)', 1), {}, 1.),
            Case(('int(x)', 1.), {}, 1.)
        ])

        # Builtin Container Types
        self.assertCaseEqual(peval, [
            Case(('bytearray(x)', 1), {}, bytearray(b'\x00')),
            Case(('bytearray(x, e)', 'x', 'utf8'), {}, bytearray(b'x')),
            Case(('bytes(x)', 1), {}, b'\x00'),
            Case(('bytes(x, e)', 'x', 'utf8'), {}, b'x'),
            Case(('dict(s)', [(1, 1)]), {}, {1: 1}),
            Case(('frozenset(l)', [1, 2]), {}, frozenset([1, 2])),
            Case(('list(a)', (1, 2, 3)), {}, [1, 2, 3]),
            Case(('list(memoryview(x))', b'x'), {}, [120]),
            Case(('str(o)', list()), {}, '[]'),
            Case(('set(l)', [1, 2, 3]), {}, {1, 2, 3}),
            Case(('tuple(l)', [1, 2, 3]), {}, (1, 2, 3))
        ])

        # Further Builtin Types
        # Note: object and type are tested within test_PyBuiltin_oop()
        self.assertCaseEqual(peval, [Case(('slice(n)', 3), {}, slice(3))])
Esempio n. 3
0
    def test_PyOperators_logical(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Boolean OR
        with self.subTest(symbol='or'):
            self.assertCaseEqual(peval, [
                Case(('x or y', True, False), {}, True),
                Case(('x or y', False, True), {}, True),
                Case(('x or y', False, False), {}, False),
                Case(('x or y', True, True), {}, True)
            ])

        # Boolean AND
        with self.subTest(symbol='and'):
            self.assertCaseEqual(peval, [
                Case(('x and y', True, False), {}, False),
                Case(('x and y', False, True), {}, False),
                Case(('x and y', False, False), {}, False),
                Case(('x and y', True, True), {}, True)
            ])

        # Boolean NOT
        with self.subTest(symbol='not'):
            self.assertCaseEqual(peval, [
                Case(('not(x)', True), {}, False),
                Case(('not(x)', False), {}, True)
            ])
Esempio n. 4
0
    def test_Expression_eval(self) -> None:

        p = parser.Parser(vocabulary=PyExprEval())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        self.assertCaseEqual(peval, [
            Case(("Ee1", 2), {}, 2),
            Case(("Ee1 + 1", 1), {}, 2),
            Case(('2^x', 3), {}, 8.),
            Case(('2 - 3^x', 4), {}, -79.),
            Case(('-2 - 3^x', 4), {}, -83.),
            Case(('-3^x', 4), {}, -81.),
            Case(('(-3)^x', 4), {}, 81.),
            Case(('2*x + y', 4, 1), {}, 9),
            Case(("'x' == 'x'", ), {}, True),
            Case(("(a + b) == c", 1, 2, 3), {}, True),
            Case(("(a + b) != c", 1, 2, 3), {}, False),
            Case(("x || y", 'hi ', 'u'), {}, 'hi u'),
            Case(("'x' || 'y'", ), {}, 'xy'),
            Case(("concat('hi', ' ', 'u')", ), {}, 'hi u'),
            Case(('if(a>b, 5, 6)', 8, 3), {}, 5),
            Case(('if(a, b, c)', None, 1, 3), {}, 3),
            Case(('a, 3', [1, 2]), {}, [[1, 2], 3]),
            Case((".1", ), {}, .1),
            Case((".5^3", ), {}, .125),
            Case(("16^.5", ), {}, 4.),
            Case(("8300*.8", ), {}, 6640.),
            Case(('"abc"*2', 2), {}, 'abcabc'),
            Case(("a^2-b^2==(a+b)*(a-b)", 12, 4), {}, True),
            Case(("a^2-b^2+1==(a+b)*(a-b)", 5, 2), {}, False),
            Case(("concat('a\n','\n','\rb')=='a\n\n\rb'", ), {}, True),
            Case(("a==''", ''), {}, True)
        ])

        self.assertRaises(ValueError, peval, '..5')
Esempio n. 5
0
    def test_Expression_to_string(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        pstr: AnyOp = lambda e: str(p.parse(e))

        self.assertCaseEqual(pstr, [
            Case(("'a'=='b'", ), {}, "'a' == 'b'"),
            Case(("func(a,1.51,'ok')", ), {}, "func(a, 1.51, 'ok')")
        ])
Esempio n. 6
0
    def test_PyOperators_bitwise(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Bitwise Inversion
        with self.subTest(symbol='~'):
            self.assertCaseEqual(peval, [
                Case(('~x', 0), {}, -1),
                Case(('~x', -1), {}, 0),
                Case(('~x', 1), {}, -2),
                Case(('~x', -2), {}, 1),
                Case(('~(~x)', 3), {}, 3)
            ])

        # Bitwise Right Shift
        with self.subTest(symbol='>>'):
            self.assertCaseEqual(peval, [
                Case(('x >> y', 1, 1), {}, 0),
                Case(('x >> y', 2, 2), {}, 0),
                Case(('x >> y', 1, 2), {}, 0),
                Case(('x >> y', 2, 1), {}, 1)
            ])

        # Bitwise Left Shift
        with self.subTest(symbol='>>'):
            self.assertCaseEqual(peval, [
                Case(('x << y', 1, 1), {}, 2),
                Case(('x << y', 2, 2), {}, 8),
                Case(('x << y', 1, 2), {}, 4),
                Case(('x << y', 2, 1), {}, 4)
            ])

        # Bitwise AND
        with self.subTest(symbol='&'):
            self.assertCaseEqual(peval, [
                Case(('x & y', 2, 2), {}, 2),
                Case(('x & y', 2, 3), {}, 2),
                Case(('x & y', 1, 3), {}, 1),
                Case(('x & y', 1, 2), {}, 0)
            ])

        # Bitwise XOR
        with self.subTest(symbol='^'):
            self.assertCaseEqual(peval, [
                Case(('x ^ y', 2, 2), {}, 0),
                Case(('x ^ y', 2, 3), {}, 1),
                Case(('x ^ y', 1, 3), {}, 2),
                Case(('x ^ y', 1, 2), {}, 3)
            ])

        # Bitwise OR
        with self.subTest(symbol='|'):
            self.assertCaseEqual(peval, [
                Case(('x | y', 2, 2), {}, 2),
                Case(('x | y', 2, 3), {}, 3),
                Case(('x | y', 1, 3), {}, 3),
                Case(('x | y', 1, 2), {}, 3)
            ])
Esempio n. 7
0
    def test_Expression_subst(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        peval: AnyOp = lambda e, v, w, *args: p.parse(e).subst(v, w).eval(*args
                                                                          )

        self.assertCaseEqual(peval, [
            Case(('2*x + 1', 'x', '4*x', 3), {}, 25),
            Case(('a + 1', 'a', 'b', 3), {}, 4)
        ])
Esempio n. 8
0
    def test_PyOperators(self) -> None:
        # The individual operators are tested within seperate tests. Here the
        # operator associativity and precedence is tested.
        # Note: The Precedence is not required to be tested between different
        # operators of same precedence, like comparison operators. In this case
        # the operators are always evaluated from left to right.
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Logical Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x and not(y)', 1, 0), {}, True),
                Case(('not(x and y)', 1, 0), {}, True),
                Case(('x or y and z', 1, 0, 0), {}, True),
                Case(('(x or y) and z', 1, 0, 0), {}, False)
            ])

        # Bitwise Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x | (~y)', 1, 0), {}, -1),
                Case(('~(x | y)', 1, 0), {}, -2),
                Case(('x | y ^ z', 1, 0, 3), {}, 3),
                Case(('(x | y) ^ z', 1, 0, 3), {}, 2),
                Case(('x ^ y ^ z', 1, 0, 3), {}, 2),
                Case(('x ^ y & z', 3, 1, 0), {}, 3),
                Case(('(x ^ y) & z', 3, 1, 0), {}, 0),
                Case(('x & y >> z', 2, 4, 1), {}, 2),
                Case(('(x & y) >> z', 2, 4, 1), {}, 0)
            ])

        # Arithmetic Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x + (-y)', 1, 1), {}, 0),
                Case(('-(x + y)', 1, 1), {}, -2),
                Case(('x + y * z', 1, 0, 0), {}, 1),
                Case(('(x + y) * z', 1, 0, 0), {}, 0),
                Case(('x * y ** z', 2, 2, 2), {}, 8),
                Case(('(x * y) ** z', 2, 2, 2), {}, 16)
            ])

        # Comparison Operators
        # The Precedence is not required to be tested between different
        # comparison operators, since it is always evaluated from left to right

        # Mixed Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x and y | z', 0, 2, 3), {}, 0),
                Case(('(x and y) | z', 0, 2, 3), {}, 3),
                Case(('x << y + z', 1, 2, 3), {}, 32),
                Case(('(x << y) + z', 1, 2, 3), {}, 7)
            ])
Esempio n. 9
0
    def test_PyBuiltin_constants(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Constants
        self.assertCaseEqual(peval, [
            Case(('True', ), {}, True),
            Case(('False', ), {}, False),
            Case(('None', ), {}, None),
            Case(('Ellipsis', ), {}, Ellipsis)
        ])
Esempio n. 10
0
    def test_PyBuiltin_conversion(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Conversion
        self.assertCaseEqual(peval, [
            Case(('ascii(x)', 1), {}, '1'),
            Case(('bin(x)', 1), {}, '0b1'),
            Case(('chr(x)', 65), {}, 'A'),
            Case(('format(x)', 'A'), {}, 'A'),
            Case(('hex(x)', 1), {}, '0x1'),
            Case(('oct(x)', 1), {}, '0o1'),
            Case(('ord(x)', 'A'), {}, 65)
        ])
Esempio n. 11
0
    def test_PyBuiltin_math(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Simple mathematical functions
        self.assertCaseEqual(peval, [
            Case(('abs(x)', -1), {}, 1),
            Case(('divmod(a, b)', 2, 1), {}, (2, 0)),
            Case(('max(l)', [1, 2, 3]), {}, 3),
            Case(('min(l)', [1, 2, 3]), {}, 1),
            Case(('pow(x, y)', 2, 2), {}, 4),
            Case(('round(x)', .6), {}, 1),
            Case(('sum(l)', [1, 2, 3]), {}, 6)
        ])
Esempio n. 12
0
    def test_Vocabulary(self) -> None:
        voc = parser.PyOperators()
        self.assertEqual(voc.search(type=parser.FUNCTION), {})

        mean: AnyOp = lambda s: sum(s) / len(s)
        voc.add(parser.Symbol(parser.FUNCTION, 'mean', mean))
        self.assertIn('mean', voc.search(type=parser.FUNCTION, builtin=False))
        self.assertNotIn('mean', voc.search(type=parser.FUNCTION,
                                            builtin=True))

        p = parser.Parser(vocabulary=voc)
        self.assertEqual(p.parse('mean(s)').variables, ('s', ))
        self.assertEqual(p.parse('mean(s)').symbols, ('mean', 's'))
        self.assertEqual(p.parse('mean(s)').eval([1, 2, 3]), 2)
Esempio n. 13
0
    def test_PyBuiltin_runtime(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Runtime Evaluation and Meta Programming
        # TODO: Untested functions: breakpoint(), help(), input(), print()
        self.assertCaseEqual(peval, [
            Case(('bool(compile(a, b, c))', '1', '1', 'eval'), {}, True),
            Case(('eval(e)', 'True'), {}, True),
            Case(('exec(e)', 'True'), {}, None),
            Case(('bool(globals())', ), {}, True),
            Case(('id(x)', None), {}, id(None)),
            Case(('bool(locals())', ), {}, True)
        ])
Esempio n. 14
0
    def test_PyBuiltin_functional(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Functional Programming and Iterator functions
        self.assertCaseEqual(peval, [
            Case(('all(l)', [1, 1, 0]), {}, False),
            Case(('any(l)', [1, 1, 0]), {}, True),
            Case(('list(enumerate(l))', [1, 2]), {}, [(0, 1), (1, 2)]),
            Case(('list(filter(None, l))', []), {}, []),
            Case(('list(iter(l))', [1, 2, 3]), {}, [1, 2, 3]),
            Case(('list(map(f, l))', bool, [0]), {}, [False]),
            Case(('next(iter(l))', [1, 2, 3]), {}, 1),
            Case(('list(range(n))', 3), {}, [0, 1, 2]),
            Case(('sorted(l)', [3, 2, 1]), {}, [1, 2, 3]),
            Case(('list(zip(l, l))', range(2)), {}, [(0, 0), (1, 1)])
        ])
Esempio n. 15
0
    def test_Expression_simplify(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        psubs: AnyOp = lambda e, d, *args: p.parse(e).simplify(d).eval(*args)
        pvars: AnyOp = lambda e, d: p.parse(e).simplify(d).variables

        # expr = p.parse('x * (y * atan(1))').simplify({'y': 4})
        # self.assertIn('x*3.141592', expr.to_string())

        self.assertCaseEqual(psubs, [
            Case(("x / ((x + y))", {}, 1, 1), {}, .5),
            Case(('x * (y * 1)', {
                'y': 4
            }, 2), {}, 8)
        ])

        self.assertCaseEqual(
            pvars, [Case(('x * (y * atan(1))', {
                'y': 4
            }), {}, ('x', ))])
Esempio n. 16
0
    def test_PyOperators_matrix_product(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Matrix Product
        with self.subTest(symbol='@'):
            N = np.matrix([(0, 0), (0, 0)])  # Zero Matrix
            I = np.matrix([(1, 0), (0, 1)])  # Identity Matrix
            C = np.matrix([(0, 1), (1, 0)])  # Row Exchange Matrix
            X = np.matrix([(1, 0), (0, 0)])  # Projection to 'x' Component
            Y = np.matrix([(0, 0), (0, 1)])  # Projection to 'y' Component

            self.assertCaseEqual(peval, [
                Case(('X @ Y', I, I), {}, I),
                Case(('X @ Y', I, X), {}, X),
                Case(('X @ Y', Y, I), {}, Y),
                Case(('X @ Y', N, I), {}, N),
                Case(('X @ Y', X, N), {}, N),
                Case(('X @ Y', C, C), {}, I),
                Case(('X @ Y', X, Y), {}, N)
            ])
Esempio n. 17
0
    def test_PyBuiltin_oop(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Types for Object Oriented Programming
        self.assertCaseEqual(peval, [
            Case(('isinstance(object(), c)', object), {}, True),
            Case(('type(o)', object), {}, type)
        ])

        # Builtin functions for Object and Class Tree Organisation
        self.assertCaseEqual(peval, [
            Case(('isinstance(a, b)', 1, int), {}, True),
            Case(('issubclass(a, b)', int, int), {}, True)
        ])

        # Builtin functions for Attribute Organisation
        self.assertCaseEqual(peval, [
            Case(('delattr(o, a)', mock.Mock(), 'a'), {}, None),
            Case(('dir(o)', object), {}, dir(object)),
            Case(('getattr(o, a)', 1j, 'imag'), {}, 1.),
            Case(('hasattr(o, a)', 1j, 'imag'), {}, True),
            Case(('setattr(o, a, v)', mock.Mock(), 'a', 0), {}, None)
        ])

        # Builtin functions for special Methods
        self.assertCaseEqual(peval, [
            Case(('bool(classmethod(o))', object), {}, True),
            Case(("hasattr(property(), 'getter')", ), {}, True),
            Case(("hasattr(staticmethod(f), '__func__')", list), {}, True)
        ])

        # Builtin functions for special Attributes
        self.assertCaseEqual(peval, [
            Case(('callable(o)', object), {}, True),
            Case(('hash(o)', 1), {}, 1),
            Case(('len(o)', [1, 2, 3]), {}, 3),
            Case(('repr(o)', 'x'), {}, "'x'"),
            Case(('sorted(vars(o))', type), {}, sorted(vars(type)))
        ])
Esempio n. 18
0
    def test_Parser_symbols(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        psyms: AnyOp = lambda e: p.parse(e).symbols

        self.assertCaseEqual(psyms,
                             [Case(('pow(x,y)', ), {}, ('pow', 'x', 'y'))])
Esempio n. 19
0
    def test_PyOperators_comparison(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Equality
        with self.subTest(symbol='=='):
            self.assertCaseEqual(peval, [
                Case(('x == y', 1, 1), {}, True),
                Case(('x == y', 1, 2), {}, False),
                Case(('x == y', 'a', 'a'), {}, True),
                Case(('x == y', 'a', 'b'), {}, False)
            ])

        # Inequality
        with self.subTest(symbol='!='):
            self.assertCaseEqual(peval, [
                Case(('x != y', 1, 1), {}, False),
                Case(('x != y', 1, 2), {}, True),
                Case(('x != y', 'a', 'a'), {}, False),
                Case(('x != y', 'a', 'b'), {}, True)
            ])

        # Greater
        with self.subTest(symbol='>'):
            self.assertCaseEqual(peval, [
                Case(('x > y', 1, 1), {}, False),
                Case(('x > y', 2, 1), {}, True),
                Case(('x > y', 'a', 'a'), {}, False),
                Case(('x > y', 'b', 'a'), {}, True)
            ])

        # Greater or Equal
        with self.subTest(symbol='>='):
            self.assertCaseEqual(peval, [
                Case(('x >= y', 1, 2), {}, False),
                Case(('x >= y', 1, 1), {}, True),
                Case(('x >= y', 'a', 'b'), {}, False),
                Case(('x >= y', 'a', 'a'), {}, True)
            ])

        # Lower
        with self.subTest(symbol='<'):
            self.assertCaseEqual(peval, [
                Case(('x < y', 1, 1), {}, False),
                Case(('x < y', 1, 2), {}, True),
                Case(('x < y', 'a', 'a'), {}, False),
                Case(('x < y', 'a', 'b'), {}, True)
            ])

        # Lower or Equal
        with self.subTest(symbol='<='):
            self.assertCaseEqual(peval, [
                Case(('x <= y', 2, 1), {}, False),
                Case(('x <= y', 1, 1), {}, True),
                Case(('x <= y', 'b', 'a'), {}, False),
                Case(('x <= y', 'a', 'a'), {}, True)
            ])

        # Identity
        with self.subTest(symbol='is'):
            self.assertCaseEqual(peval, [
                Case(('x is y', True, True), {}, True),
                Case(('x is y', True, False), {}, False)
            ])

        # Containment
        with self.subTest(symbol='in'):
            self.assertCaseEqual(peval, [
                Case(('x in y', 'a', 'a'), {}, True),
                Case(('x in y', 'a', 'b'), {}, False),
                Case(('x in y', 'a', 'ba'), {}, True),
                Case(('x in y', 'ab', 'ba'), {}, False)
            ])
Esempio n. 20
0
    def test_PyOperators_arithmetic(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Unary Plus
        with self.subTest(symbol='+'):
            self.assertCaseEqual(peval, [
                Case(('+x', 1), {}, 1),
                Case(('+x', -1), {}, -1),
                Case(('+(+x)', 1), {}, 1),
                Case(('+(+x)', -1), {}, -1)
            ])

        # Negation
        with self.subTest(symbol='-'):
            self.assertCaseEqual(peval, [
                Case(('-x', 1), {}, -1),
                Case(('-x', -1), {}, 1),
                Case(('-(-x)', 1), {}, 1),
                Case(('-(-x)', -1), {}, -1)
            ])

        # Exponentiation
        with self.subTest(symbol='**'):
            self.assertCaseEqual(peval, [
                Case(('x ** y', 1, 1), {}, 1),
                Case(('x ** y', 1., 1), {}, 1.),
                Case(('x ** y', 4, .5), {}, 2.),
                Case(('x ** y', 2, 2.), {}, 4.)
            ])

        # Division
        with self.subTest(symbol='/'):
            self.assertCaseEqual(peval, [
                Case(('x / y', 1, 1), {}, 1.),
                Case(('x / y', 2, 1), {}, 2.),
                Case(('x / y', 1, .2), {}, 5.),
                Case(('x / y', 1, 2), {}, .5)
            ])

        # Floor Division
        with self.subTest(symbol='//'):
            self.assertCaseEqual(peval, [
                Case(('x // y', 1, 1), {}, 1),
                Case(('x // y', 2, 1), {}, 2),
                Case(('x // y', 1, .2), {}, 4),
                Case(('x // y', 1, 2), {}, 0)
            ])

        # Remainder
        with self.subTest(symbol='%'):
            self.assertCaseEqual(peval, [
                Case(('x % y', 2, 3), {}, 2),
                Case(('x % y', 3, 2), {}, 1),
                Case(('x % y', 2, 1), {}, 0),
                Case(('x % y', .1, .5), {}, .1)
            ])

        # Multiplication
        with self.subTest(symbol='*'):
            self.assertCaseEqual(peval, [
                Case(('x * y', -1, -1), {}, 1),
                Case(('x * y', 2, .5), {}, 1),
                Case(('x * y', 2, 2), {}, 4),
                Case(('x * y', -.5, .5), {}, -.25)
            ])

        # Addition
        with self.subTest(symbol='+'):
            self.assertCaseEqual(peval, [
                Case(('x + y', 0, 1), {}, 1),
                Case(('x + y', -1, 1), {}, 0),
                Case(('x + y', 2, 2), {}, 4),
                Case(('x + y', .5, .5), {}, 1)
            ])

        # Subtraction
        with self.subTest(symbol='-'):
            self.assertCaseEqual(peval, [
                Case(('x - y', 0, 1), {}, -1),
                Case(('x - y', -1, 1), {}, -2),
                Case(('x - y', 2, 2), {}, 0),
                Case(('x - y', .5, .5), {}, 0)
            ])