[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/bassdeveloper/bpython/embed/bpython/test/test_simpleeval.py [Back]  [Original]

# -*- coding: utf-8 -*-

import ast
import numbers

from bpython.simpleeval import (simple_eval,
                                evaluate_current_expression,
                                EvaluationError)
from bpython.test import unittest


class TestSimpleEval(unittest.TestCase):
    def assertMatchesStdlib(self, expr):
        self.assertEqual(ast.literal_eval(expr), simple_eval(expr))

    def test_matches_stdlib(self):
        """Should match the stdlib literal_eval if no names or indexing"""
        self.assertMatchesStdlib("[1]")
        self.assertMatchesStdlib("{(1,): [2,3,{}]}")

    def test_indexing(self):
        """Literals can be indexed into"""
        self.assertEqual(simple_eval('[1,2][0]'), 1)
        self.assertEqual(simple_eval('a', {'a': 1}), 1)

    def test_name_lookup(self):
        """Names can be lookup up in a namespace"""
        self.assertEqual(simple_eval('a', {'a': 1}), 1)
        self.assertEqual(simple_eval('map'), map)
        self.assertEqual(simple_eval('a[b]', {'a': {'c': 1}, 'b': 'c'}), 1)

    def test_allow_name_lookup(self):
        """Names can be lookup up in a namespace"""
        self.assertEqual(simple_eval('a', {'a': 1}), 1)

    def test_lookup_on_suspicious_types(self):
        class FakeDict(object):
            pass

        with self.assertRaises(ValueError):
            simple_eval('a[1]', {'a': FakeDict()})

        class TrickyDict(dict):
            def __getitem__(self, index):
                self.fail("doing key lookup isn't safe")

        with self.assertRaises(ValueError):
            simple_eval('a[1]', {'a': TrickyDict()})

        class SchrodingersDict(dict):
            def __getattribute__(inner_self, attr):
                self.fail("doing attribute lookup might have side effects")

        with self.assertRaises(ValueError):
            simple_eval('a[1]', {'a': SchrodingersDict()})

        class SchrodingersCatsDict(dict):
            def __getattr__(inner_self, attr):
                self.fail("doing attribute lookup might have side effects")

        with self.assertRaises(ValueError):
            simple_eval('a[1]', {'a': SchrodingersDict()})

    def test_operators_on_suspicious_types(self):
        class Spam(numbers.Number):
            def __add__(inner_self, other):
                self.fail("doing attribute lookup might have side effects")

        with self.assertRaises(ValueError):
            simple_eval('a + 1', {'a': Spam()})

    def test_operators_on_numbers(self):
        self.assertEqual(simple_eval('-2'), -2)
        self.assertEqual(simple_eval('1 + 1'), 2)
        self.assertEqual(simple_eval('a - 2', {'a': 1}), -1)
        with self.assertRaises(ValueError):
            simple_eval('2 * 3')
        with self.assertRaises(ValueError):
            simple_eval('2 ** 3')

    def test_function_calls_raise(self):
        with self.assertRaises(ValueError):
            simple_eval('1()')

    def test_nonexistant_names_raise(self):
        with self.assertRaises(EvaluationError):
            simple_eval('a')


class TestEvaluateCurrentExpression(unittest.TestCase):

    def assertEvaled(self, line, value, ns=None):
        assert line.count('|') == 1
        cursor_offset = line.find('|')
        line = line.replace('|', '')
        self.assertEqual(evaluate_current_expression(cursor_offset, line, ns),
                         value)

    def assertCannotEval(self, line, ns=None):
        assert line.count('|') == 1
        cursor_offset = line.find('|')
        line = line.replace('|', '')
        with self.assertRaises(EvaluationError):
            evaluate_current_expression(cursor_offset, line, ns)

    def test_simple(self):
        self.assertEvaled('[1].a|bc', [1])
        self.assertEvaled('[1].abc|', [1])
        self.assertEvaled('[1].|abc', [1])
        self.assertEvaled('[1]. |abc', [1])
        self.assertEvaled('[1] .|abc', [1])
        self.assertCannotEval('[1].abc |', [1])
        self.assertCannotEval('[1]. abc |', [1])
        self.assertCannotEval('[2][1].a|bc', [1])

    def test_nonsense(self):
        self.assertEvaled('!@#$ [1].a|bc', [1])
        self.assertEvaled('--- [2][0].a|bc', 2)
        self.assertCannotEval('"asdf".centered()[1].a|bc')
        self.assertEvaled('"asdf"[1].a|bc', 's')

    def test_with_namespace(self):
        self.assertEvaled('a[1].a|bc', 'd', {'a': 'adsf'})
        self.assertCannotEval('a[1].a|bc', {})

if __name__ == '__main__':
    unittest.main()

Web Proxy Viewer  |  New URL  |  Original Page