»Core Development>Code coverage>Lib/idlelib/idle_test/test_hyperparser.py

Python code coverage for Lib/idlelib/idle_test/test_hyperparser.py

#countcontent
1n/a"""Unittest for idlelib.hyperparser.py."""
2n/aimport unittest
3n/afrom test.support import requires
4n/afrom tkinter import Tk, Text
5n/afrom idlelib.editor import EditorWindow
6n/afrom idlelib.hyperparser import HyperParser
7n/a
8n/aclass DummyEditwin:
9n/a def __init__(self, text):
10n/a self.text = text
11n/a self.indentwidth = 8
12n/a self.tabwidth = 8
13n/a self.context_use_ps1 = True
14n/a self.num_context_lines = 50, 500, 1000
15n/a
16n/a _build_char_in_string_func = EditorWindow._build_char_in_string_func
17n/a is_char_in_string = EditorWindow.is_char_in_string
18n/a
19n/a
20n/aclass HyperParserTest(unittest.TestCase):
21n/a code = (
22n/a '"""This is a module docstring"""\n'
23n/a '# this line is a comment\n'
24n/a 'x = "this is a string"\n'
25n/a "y = 'this is also a string'\n"
26n/a 'l = [i for i in range(10)]\n'
27n/a 'm = [py*py for # comment\n'
28n/a ' py in l]\n'
29n/a 'x.__len__\n'
30n/a "z = ((r'asdf')+('a')))\n"
31n/a '[x for x in\n'
32n/a 'for = False\n'
33n/a 'cliché = "this is a string with unicode, what a cliché"'
34n/a )
35n/a
36n/a @classmethod
37n/a def setUpClass(cls):
38n/a requires('gui')
39n/a cls.root = Tk()
40n/a cls.root.withdraw()
41n/a cls.text = Text(cls.root)
42n/a cls.editwin = DummyEditwin(cls.text)
43n/a
44n/a @classmethod
45n/a def tearDownClass(cls):
46n/a del cls.text, cls.editwin
47n/a cls.root.destroy()
48n/a del cls.root
49n/a
50n/a def setUp(self):
51n/a self.text.insert('insert', self.code)
52n/a
53n/a def tearDown(self):
54n/a self.text.delete('1.0', 'end')
55n/a self.editwin.context_use_ps1 = True
56n/a
57n/a def get_parser(self, index):
58n/a """
59n/a Return a parser object with index at 'index'
60n/a """
61n/a return HyperParser(self.editwin, index)
62n/a
63n/a def test_init(self):
64n/a """
65n/a test corner cases in the init method
66n/a """
67n/a with self.assertRaises(ValueError) as ve:
68n/a self.text.tag_add('console', '1.0', '1.end')
69n/a p = self.get_parser('1.5')
70n/a self.assertIn('precedes', str(ve.exception))
71n/a
72n/a # test without ps1
73n/a self.editwin.context_use_ps1 = False
74n/a
75n/a # number of lines lesser than 50
76n/a p = self.get_parser('end')
77n/a self.assertEqual(p.rawtext, self.text.get('1.0', 'end'))
78n/a
79n/a # number of lines greater than 50
80n/a self.text.insert('end', self.text.get('1.0', 'end')*4)
81n/a p = self.get_parser('54.5')
82n/a
83n/a def test_is_in_string(self):
84n/a get = self.get_parser
85n/a
86n/a p = get('1.0')
87n/a self.assertFalse(p.is_in_string())
88n/a p = get('1.4')
89n/a self.assertTrue(p.is_in_string())
90n/a p = get('2.3')
91n/a self.assertFalse(p.is_in_string())
92n/a p = get('3.3')
93n/a self.assertFalse(p.is_in_string())
94n/a p = get('3.7')
95n/a self.assertTrue(p.is_in_string())
96n/a p = get('4.6')
97n/a self.assertTrue(p.is_in_string())
98n/a p = get('12.54')
99n/a self.assertTrue(p.is_in_string())
100n/a
101n/a def test_is_in_code(self):
102n/a get = self.get_parser
103n/a
104n/a p = get('1.0')
105n/a self.assertTrue(p.is_in_code())
106n/a p = get('1.1')
107n/a self.assertFalse(p.is_in_code())
108n/a p = get('2.5')
109n/a self.assertFalse(p.is_in_code())
110n/a p = get('3.4')
111n/a self.assertTrue(p.is_in_code())
112n/a p = get('3.6')
113n/a self.assertFalse(p.is_in_code())
114n/a p = get('4.14')
115n/a self.assertFalse(p.is_in_code())
116n/a
117n/a def test_get_surrounding_bracket(self):
118n/a get = self.get_parser
119n/a
120n/a def without_mustclose(parser):
121n/a # a utility function to get surrounding bracket
122n/a # with mustclose=False
123n/a return parser.get_surrounding_brackets(mustclose=False)
124n/a
125n/a def with_mustclose(parser):
126n/a # a utility function to get surrounding bracket
127n/a # with mustclose=True
128n/a return parser.get_surrounding_brackets(mustclose=True)
129n/a
130n/a p = get('3.2')
131n/a self.assertIsNone(with_mustclose(p))
132n/a self.assertIsNone(without_mustclose(p))
133n/a
134n/a p = get('5.6')
135n/a self.assertTupleEqual(without_mustclose(p), ('5.4', '5.25'))
136n/a self.assertTupleEqual(without_mustclose(p), with_mustclose(p))
137n/a
138n/a p = get('5.23')
139n/a self.assertTupleEqual(without_mustclose(p), ('5.21', '5.24'))
140n/a self.assertTupleEqual(without_mustclose(p), with_mustclose(p))
141n/a
142n/a p = get('6.15')
143n/a self.assertTupleEqual(without_mustclose(p), ('6.4', '6.end'))
144n/a self.assertIsNone(with_mustclose(p))
145n/a
146n/a p = get('9.end')
147n/a self.assertIsNone(with_mustclose(p))
148n/a self.assertIsNone(without_mustclose(p))
149n/a
150n/a def test_get_expression(self):
151n/a get = self.get_parser
152n/a
153n/a p = get('4.2')
154n/a self.assertEqual(p.get_expression(), 'y ')
155n/a
156n/a p = get('4.7')
157n/a with self.assertRaises(ValueError) as ve:
158n/a p.get_expression()
159n/a self.assertIn('is inside a code', str(ve.exception))
160n/a
161n/a p = get('5.25')
162n/a self.assertEqual(p.get_expression(), 'range(10)')
163n/a
164n/a p = get('6.7')
165n/a self.assertEqual(p.get_expression(), 'py')
166n/a
167n/a p = get('6.8')
168n/a self.assertEqual(p.get_expression(), '')
169n/a
170n/a p = get('7.9')
171n/a self.assertEqual(p.get_expression(), 'py')
172n/a
173n/a p = get('8.end')
174n/a self.assertEqual(p.get_expression(), 'x.__len__')
175n/a
176n/a p = get('9.13')
177n/a self.assertEqual(p.get_expression(), "r'asdf'")
178n/a
179n/a p = get('9.17')
180n/a with self.assertRaises(ValueError) as ve:
181n/a p.get_expression()
182n/a self.assertIn('is inside a code', str(ve.exception))
183n/a
184n/a p = get('10.0')
185n/a self.assertEqual(p.get_expression(), '')
186n/a
187n/a p = get('10.6')
188n/a self.assertEqual(p.get_expression(), '')
189n/a
190n/a p = get('10.11')
191n/a self.assertEqual(p.get_expression(), '')
192n/a
193n/a p = get('11.3')
194n/a self.assertEqual(p.get_expression(), '')
195n/a
196n/a p = get('11.11')
197n/a self.assertEqual(p.get_expression(), 'False')
198n/a
199n/a p = get('12.6')
200n/a self.assertEqual(p.get_expression(), 'cliché')
201n/a
202n/a def test_eat_identifier(self):
203n/a def is_valid_id(candidate):
204n/a result = HyperParser._eat_identifier(candidate, 0, len(candidate))
205n/a if result == len(candidate):
206n/a return True
207n/a elif result == 0:
208n/a return False
209n/a else:
210n/a err_msg = "Unexpected result: {} (expected 0 or {}".format(
211n/a result, len(candidate)
212n/a )
213n/a raise Exception(err_msg)
214n/a
215n/a # invalid first character which is valid elsewhere in an identifier
216n/a self.assertFalse(is_valid_id('2notid'))
217n/a
218n/a # ASCII-only valid identifiers
219n/a self.assertTrue(is_valid_id('valid_id'))
220n/a self.assertTrue(is_valid_id('_valid_id'))
221n/a self.assertTrue(is_valid_id('valid_id_'))
222n/a self.assertTrue(is_valid_id('_2valid_id'))
223n/a
224n/a # keywords which should be "eaten"
225n/a self.assertTrue(is_valid_id('True'))
226n/a self.assertTrue(is_valid_id('False'))
227n/a self.assertTrue(is_valid_id('None'))
228n/a
229n/a # keywords which should not be "eaten"
230n/a self.assertFalse(is_valid_id('for'))
231n/a self.assertFalse(is_valid_id('import'))
232n/a self.assertFalse(is_valid_id('return'))
233n/a
234n/a # valid unicode identifiers
235n/a self.assertTrue(is_valid_id('cliche'))
236n/a self.assertTrue(is_valid_id('cliché'))
237n/a self.assertTrue(is_valid_id('aÙ¢'))
238n/a
239n/a # invalid unicode identifiers
240n/a self.assertFalse(is_valid_id('2a'))
241n/a self.assertFalse(is_valid_id('Ù¢a'))
242n/a self.assertFalse(is_valid_id('a²'))
243n/a
244n/a # valid identifier after "punctuation"
245n/a self.assertEqual(HyperParser._eat_identifier('+ var', 0, 5), len('var'))
246n/a self.assertEqual(HyperParser._eat_identifier('+var', 0, 4), len('var'))
247n/a self.assertEqual(HyperParser._eat_identifier('.var', 0, 4), len('var'))
248n/a
249n/a # invalid identifiers
250n/a self.assertFalse(is_valid_id('+'))
251n/a self.assertFalse(is_valid_id(' '))
252n/a self.assertFalse(is_valid_id(':'))
253n/a self.assertFalse(is_valid_id('?'))
254n/a self.assertFalse(is_valid_id('^'))
255n/a self.assertFalse(is_valid_id('\\'))
256n/a self.assertFalse(is_valid_id('"'))
257n/a self.assertFalse(is_valid_id('"a string"'))
258n/a
259n/a def test_eat_identifier_various_lengths(self):
260n/a eat_id = HyperParser._eat_identifier
261n/a
262n/a for length in range(1, 21):
263n/a self.assertEqual(eat_id('a' * length, 0, length), length)
264n/a self.assertEqual(eat_id('é' * length, 0, length), length)
265n/a self.assertEqual(eat_id('a' + '2' * (length - 1), 0, length), length)
266n/a self.assertEqual(eat_id('é' + '2' * (length - 1), 0, length), length)
267n/a self.assertEqual(eat_id('é' + 'a' * (length - 1), 0, length), length)
268n/a self.assertEqual(eat_id('é' * (length - 1) + 'a', 0, length), length)
269n/a self.assertEqual(eat_id('+' * length, 0, length), 0)
270n/a self.assertEqual(eat_id('2' + 'a' * (length - 1), 0, length), 0)
271n/a self.assertEqual(eat_id('2' + 'é' * (length - 1), 0, length), 0)
272n/a
273n/aif __name__ == '__main__':
274n/a unittest.main(verbosity=2)