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

# | count | content |
---|---|---|

1 | n/a | """Unittest for idlelib.hyperparser.py.""" |

2 | n/a | import unittest |

3 | n/a | from test.support import requires |

4 | n/a | from tkinter import Tk, Text |

5 | n/a | from idlelib.editor import EditorWindow |

6 | n/a | from idlelib.hyperparser import HyperParser |

7 | n/a | |

8 | n/a | class DummyEditwin: |

9 | n/a | def __init__(self, text): |

10 | n/a | self.text = text |

11 | n/a | self.indentwidth = 8 |

12 | n/a | self.tabwidth = 8 |

13 | n/a | self.context_use_ps1 = True |

14 | n/a | self.num_context_lines = 50, 500, 1000 |

15 | n/a | |

16 | n/a | _build_char_in_string_func = EditorWindow._build_char_in_string_func |

17 | n/a | is_char_in_string = EditorWindow.is_char_in_string |

18 | n/a | |

19 | n/a | |

20 | n/a | class HyperParserTest(unittest.TestCase): |

21 | n/a | code = ( |

22 | n/a | '"""This is a module docstring"""\n' |

23 | n/a | '# this line is a comment\n' |

24 | n/a | 'x = "this is a string"\n' |

25 | n/a | "y = 'this is also a string'\n" |

26 | n/a | 'l = [i for i in range(10)]\n' |

27 | n/a | 'm = [py*py for # comment\n' |

28 | n/a | ' py in l]\n' |

29 | n/a | 'x.__len__\n' |

30 | n/a | "z = ((r'asdf')+('a')))\n" |

31 | n/a | '[x for x in\n' |

32 | n/a | 'for = False\n' |

33 | n/a | 'clichÃ© = "this is a string with unicode, what a clichÃ©"' |

34 | n/a | ) |

35 | n/a | |

36 | n/a | @classmethod |

37 | n/a | def setUpClass(cls): |

38 | n/a | requires('gui') |

39 | n/a | cls.root = Tk() |

40 | n/a | cls.root.withdraw() |

41 | n/a | cls.text = Text(cls.root) |

42 | n/a | cls.editwin = DummyEditwin(cls.text) |

43 | n/a | |

44 | n/a | @classmethod |

45 | n/a | def tearDownClass(cls): |

46 | n/a | del cls.text, cls.editwin |

47 | n/a | cls.root.destroy() |

48 | n/a | del cls.root |

49 | n/a | |

50 | n/a | def setUp(self): |

51 | n/a | self.text.insert('insert', self.code) |

52 | n/a | |

53 | n/a | def tearDown(self): |

54 | n/a | self.text.delete('1.0', 'end') |

55 | n/a | self.editwin.context_use_ps1 = True |

56 | n/a | |

57 | n/a | def get_parser(self, index): |

58 | n/a | """ |

59 | n/a | Return a parser object with index at 'index' |

60 | n/a | """ |

61 | n/a | return HyperParser(self.editwin, index) |

62 | n/a | |

63 | n/a | def test_init(self): |

64 | n/a | """ |

65 | n/a | test corner cases in the init method |

66 | n/a | """ |

67 | n/a | with self.assertRaises(ValueError) as ve: |

68 | n/a | self.text.tag_add('console', '1.0', '1.end') |

69 | n/a | p = self.get_parser('1.5') |

70 | n/a | self.assertIn('precedes', str(ve.exception)) |

71 | n/a | |

72 | n/a | # test without ps1 |

73 | n/a | self.editwin.context_use_ps1 = False |

74 | n/a | |

75 | n/a | # number of lines lesser than 50 |

76 | n/a | p = self.get_parser('end') |

77 | n/a | self.assertEqual(p.rawtext, self.text.get('1.0', 'end')) |

78 | n/a | |

79 | n/a | # number of lines greater than 50 |

80 | n/a | self.text.insert('end', self.text.get('1.0', 'end')*4) |

81 | n/a | p = self.get_parser('54.5') |

82 | n/a | |

83 | n/a | def test_is_in_string(self): |

84 | n/a | get = self.get_parser |

85 | n/a | |

86 | n/a | p = get('1.0') |

87 | n/a | self.assertFalse(p.is_in_string()) |

88 | n/a | p = get('1.4') |

89 | n/a | self.assertTrue(p.is_in_string()) |

90 | n/a | p = get('2.3') |

91 | n/a | self.assertFalse(p.is_in_string()) |

92 | n/a | p = get('3.3') |

93 | n/a | self.assertFalse(p.is_in_string()) |

94 | n/a | p = get('3.7') |

95 | n/a | self.assertTrue(p.is_in_string()) |

96 | n/a | p = get('4.6') |

97 | n/a | self.assertTrue(p.is_in_string()) |

98 | n/a | p = get('12.54') |

99 | n/a | self.assertTrue(p.is_in_string()) |

100 | n/a | |

101 | n/a | def test_is_in_code(self): |

102 | n/a | get = self.get_parser |

103 | n/a | |

104 | n/a | p = get('1.0') |

105 | n/a | self.assertTrue(p.is_in_code()) |

106 | n/a | p = get('1.1') |

107 | n/a | self.assertFalse(p.is_in_code()) |

108 | n/a | p = get('2.5') |

109 | n/a | self.assertFalse(p.is_in_code()) |

110 | n/a | p = get('3.4') |

111 | n/a | self.assertTrue(p.is_in_code()) |

112 | n/a | p = get('3.6') |

113 | n/a | self.assertFalse(p.is_in_code()) |

114 | n/a | p = get('4.14') |

115 | n/a | self.assertFalse(p.is_in_code()) |

116 | n/a | |

117 | n/a | def test_get_surrounding_bracket(self): |

118 | n/a | get = self.get_parser |

119 | n/a | |

120 | n/a | def without_mustclose(parser): |

121 | n/a | # a utility function to get surrounding bracket |

122 | n/a | # with mustclose=False |

123 | n/a | return parser.get_surrounding_brackets(mustclose=False) |

124 | n/a | |

125 | n/a | def with_mustclose(parser): |

126 | n/a | # a utility function to get surrounding bracket |

127 | n/a | # with mustclose=True |

128 | n/a | return parser.get_surrounding_brackets(mustclose=True) |

129 | n/a | |

130 | n/a | p = get('3.2') |

131 | n/a | self.assertIsNone(with_mustclose(p)) |

132 | n/a | self.assertIsNone(without_mustclose(p)) |

133 | n/a | |

134 | n/a | p = get('5.6') |

135 | n/a | self.assertTupleEqual(without_mustclose(p), ('5.4', '5.25')) |

136 | n/a | self.assertTupleEqual(without_mustclose(p), with_mustclose(p)) |

137 | n/a | |

138 | n/a | p = get('5.23') |

139 | n/a | self.assertTupleEqual(without_mustclose(p), ('5.21', '5.24')) |

140 | n/a | self.assertTupleEqual(without_mustclose(p), with_mustclose(p)) |

141 | n/a | |

142 | n/a | p = get('6.15') |

143 | n/a | self.assertTupleEqual(without_mustclose(p), ('6.4', '6.end')) |

144 | n/a | self.assertIsNone(with_mustclose(p)) |

145 | n/a | |

146 | n/a | p = get('9.end') |

147 | n/a | self.assertIsNone(with_mustclose(p)) |

148 | n/a | self.assertIsNone(without_mustclose(p)) |

149 | n/a | |

150 | n/a | def test_get_expression(self): |

151 | n/a | get = self.get_parser |

152 | n/a | |

153 | n/a | p = get('4.2') |

154 | n/a | self.assertEqual(p.get_expression(), 'y ') |

155 | n/a | |

156 | n/a | p = get('4.7') |

157 | n/a | with self.assertRaises(ValueError) as ve: |

158 | n/a | p.get_expression() |

159 | n/a | self.assertIn('is inside a code', str(ve.exception)) |

160 | n/a | |

161 | n/a | p = get('5.25') |

162 | n/a | self.assertEqual(p.get_expression(), 'range(10)') |

163 | n/a | |

164 | n/a | p = get('6.7') |

165 | n/a | self.assertEqual(p.get_expression(), 'py') |

166 | n/a | |

167 | n/a | p = get('6.8') |

168 | n/a | self.assertEqual(p.get_expression(), '') |

169 | n/a | |

170 | n/a | p = get('7.9') |

171 | n/a | self.assertEqual(p.get_expression(), 'py') |

172 | n/a | |

173 | n/a | p = get('8.end') |

174 | n/a | self.assertEqual(p.get_expression(), 'x.__len__') |

175 | n/a | |

176 | n/a | p = get('9.13') |

177 | n/a | self.assertEqual(p.get_expression(), "r'asdf'") |

178 | n/a | |

179 | n/a | p = get('9.17') |

180 | n/a | with self.assertRaises(ValueError) as ve: |

181 | n/a | p.get_expression() |

182 | n/a | self.assertIn('is inside a code', str(ve.exception)) |

183 | n/a | |

184 | n/a | p = get('10.0') |

185 | n/a | self.assertEqual(p.get_expression(), '') |

186 | n/a | |

187 | n/a | p = get('10.6') |

188 | n/a | self.assertEqual(p.get_expression(), '') |

189 | n/a | |

190 | n/a | p = get('10.11') |

191 | n/a | self.assertEqual(p.get_expression(), '') |

192 | n/a | |

193 | n/a | p = get('11.3') |

194 | n/a | self.assertEqual(p.get_expression(), '') |

195 | n/a | |

196 | n/a | p = get('11.11') |

197 | n/a | self.assertEqual(p.get_expression(), 'False') |

198 | n/a | |

199 | n/a | p = get('12.6') |

200 | n/a | self.assertEqual(p.get_expression(), 'clichÃ©') |

201 | n/a | |

202 | n/a | def test_eat_identifier(self): |

203 | n/a | def is_valid_id(candidate): |

204 | n/a | result = HyperParser._eat_identifier(candidate, 0, len(candidate)) |

205 | n/a | if result == len(candidate): |

206 | n/a | return True |

207 | n/a | elif result == 0: |

208 | n/a | return False |

209 | n/a | else: |

210 | n/a | err_msg = "Unexpected result: {} (expected 0 or {}".format( |

211 | n/a | result, len(candidate) |

212 | n/a | ) |

213 | n/a | raise Exception(err_msg) |

214 | n/a | |

215 | n/a | # invalid first character which is valid elsewhere in an identifier |

216 | n/a | self.assertFalse(is_valid_id('2notid')) |

217 | n/a | |

218 | n/a | # ASCII-only valid identifiers |

219 | n/a | self.assertTrue(is_valid_id('valid_id')) |

220 | n/a | self.assertTrue(is_valid_id('_valid_id')) |

221 | n/a | self.assertTrue(is_valid_id('valid_id_')) |

222 | n/a | self.assertTrue(is_valid_id('_2valid_id')) |

223 | n/a | |

224 | n/a | # keywords which should be "eaten" |

225 | n/a | self.assertTrue(is_valid_id('True')) |

226 | n/a | self.assertTrue(is_valid_id('False')) |

227 | n/a | self.assertTrue(is_valid_id('None')) |

228 | n/a | |

229 | n/a | # keywords which should not be "eaten" |

230 | n/a | self.assertFalse(is_valid_id('for')) |

231 | n/a | self.assertFalse(is_valid_id('import')) |

232 | n/a | self.assertFalse(is_valid_id('return')) |

233 | n/a | |

234 | n/a | # valid unicode identifiers |

235 | n/a | self.assertTrue(is_valid_id('cliche')) |

236 | n/a | self.assertTrue(is_valid_id('clichÃ©')) |

237 | n/a | self.assertTrue(is_valid_id('aÙ¢')) |

238 | n/a | |

239 | n/a | # invalid unicode identifiers |

240 | n/a | self.assertFalse(is_valid_id('2a')) |

241 | n/a | self.assertFalse(is_valid_id('Ù¢a')) |

242 | n/a | self.assertFalse(is_valid_id('aÂ²')) |

243 | n/a | |

244 | n/a | # valid identifier after "punctuation" |

245 | n/a | self.assertEqual(HyperParser._eat_identifier('+ var', 0, 5), len('var')) |

246 | n/a | self.assertEqual(HyperParser._eat_identifier('+var', 0, 4), len('var')) |

247 | n/a | self.assertEqual(HyperParser._eat_identifier('.var', 0, 4), len('var')) |

248 | n/a | |

249 | n/a | # invalid identifiers |

250 | n/a | self.assertFalse(is_valid_id('+')) |

251 | n/a | self.assertFalse(is_valid_id(' ')) |

252 | n/a | self.assertFalse(is_valid_id(':')) |

253 | n/a | self.assertFalse(is_valid_id('?')) |

254 | n/a | self.assertFalse(is_valid_id('^')) |

255 | n/a | self.assertFalse(is_valid_id('\\')) |

256 | n/a | self.assertFalse(is_valid_id('"')) |

257 | n/a | self.assertFalse(is_valid_id('"a string"')) |

258 | n/a | |

259 | n/a | def test_eat_identifier_various_lengths(self): |

260 | n/a | eat_id = HyperParser._eat_identifier |

261 | n/a | |

262 | n/a | for length in range(1, 21): |

263 | n/a | self.assertEqual(eat_id('a' * length, 0, length), length) |

264 | n/a | self.assertEqual(eat_id('Ã©' * length, 0, length), length) |

265 | n/a | self.assertEqual(eat_id('a' + '2' * (length - 1), 0, length), length) |

266 | n/a | self.assertEqual(eat_id('Ã©' + '2' * (length - 1), 0, length), length) |

267 | n/a | self.assertEqual(eat_id('Ã©' + 'a' * (length - 1), 0, length), length) |

268 | n/a | self.assertEqual(eat_id('Ã©' * (length - 1) + 'a', 0, length), length) |

269 | n/a | self.assertEqual(eat_id('+' * length, 0, length), 0) |

270 | n/a | self.assertEqual(eat_id('2' + 'a' * (length - 1), 0, length), 0) |

271 | n/a | self.assertEqual(eat_id('2' + 'Ã©' * (length - 1), 0, length), 0) |

272 | n/a | |

273 | n/a | if __name__ == '__main__': |

274 | n/a | unittest.main(verbosity=2) |