]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpa/elpy-20230803.1455/elpy/tests/test_jedibackend.py
4ea99cfbe2595241bb606e09a25c5ac5e7df981e
[config.git] / djavu-asus / emacs / elpa / elpy-20230803.1455 / elpy / tests / test_jedibackend.py
1 """Tests for the elpy.jedibackend module."""
2
3 import sys
4 import unittest
5
6 import jedi
7 try:
8 from unittest import mock
9 except ImportError:
10 import mock
11 import re
12
13 from elpy import jedibackend
14 from elpy import rpc
15 from elpy.tests import compat
16 from elpy.tests.support import BackendTestCase
17 from elpy.tests.support import RPCGetCompletionsTests
18 from elpy.tests.support import RPCGetCompletionDocstringTests
19 from elpy.tests.support import RPCGetCompletionLocationTests
20 from elpy.tests.support import RPCGetDocstringTests
21 from elpy.tests.support import RPCGetOnelineDocstringTests
22 from elpy.tests.support import RPCGetDefinitionTests
23 from elpy.tests.support import RPCGetCalltipTests
24 from elpy.tests.support import RPCGetUsagesTests
25 from elpy.tests.support import RPCGetNamesTests
26 from elpy.tests.support import RPCGetRenameDiffTests
27 from elpy.tests.support import RPCGetExtractFunctionDiffTests
28 from elpy.tests.support import RPCGetExtractVariableDiffTests
29 from elpy.tests.support import RPCGetInlineDiffTests
30 from elpy.tests.support import RPCGetAssignmentTests
31
32
33 class JediBackendTestCase(BackendTestCase):
34 def setUp(self):
35 super(JediBackendTestCase, self).setUp()
36 env = jedi.get_default_environment().path
37 self.backend = jedibackend.JediBackend(self.project_root, env)
38
39
40 class TestInit(JediBackendTestCase):
41 def test_should_have_jedi_as_name(self):
42 self.assertEqual(self.backend.name, "jedi")
43
44
45 class TestRPCGetCompletions(RPCGetCompletionsTests,
46 JediBackendTestCase):
47 BUILTINS = ['object', 'oct', 'open', 'ord', 'OSError', 'OverflowError']
48
49
50 class TestRPCGetAssignment(RPCGetAssignmentTests,
51 JediBackendTestCase):
52 pass
53
54
55 class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
56 JediBackendTestCase):
57 pass
58
59
60 class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
61 JediBackendTestCase):
62 pass
63
64
65 class TestRPCGetDocstring(RPCGetDocstringTests,
66 JediBackendTestCase):
67
68 def __init__(self, *args, **kwargs):
69 super(TestRPCGetDocstring, self).__init__(*args, **kwargs)
70 self.JSON_LOADS_REGEX = (
71 r'loads\(s.*, cls.*, object_hook.*, parse_float.*, '
72 r'parse_int.*, .*\)'
73 )
74
75 def check_docstring(self, docstring):
76 lines = docstring.splitlines()
77 self.assertEqual(lines[0], 'Documentation for json.loads:')
78 match = re.match(self.JSON_LOADS_REGEX, lines[2])
79 self.assertIsNotNone(match)
80
81 @mock.patch("elpy.jedibackend.run_with_debug")
82 def test_should_not_return_empty_docstring(self, run_with_debug):
83 location = mock.MagicMock()
84 location.full_name = "testthing"
85 location.docstring.return_value = ""
86 run_with_debug.return_value = [location]
87 filename = self.project_file("test.py", "print")
88 docstring = self.backend.rpc_get_docstring(filename, "print", 0)
89 self.assertIsNone(docstring)
90
91
92 class TestRPCGetOnelineDocstring(RPCGetOnelineDocstringTests,
93 JediBackendTestCase):
94
95 def __init__(self, *args, **kwargs):
96 super(TestRPCGetOnelineDocstring, self).__init__(*args, **kwargs)
97 if sys.version_info >= (3, 6):
98 self.JSON_LOADS_DOCSTRING = (
99 'Deserialize ``s`` (a ``str``, ``bytes`` or'
100 ' ``bytearray`` instance containing a JSON'
101 ' document) to a Python object.'
102 )
103 self.JSON_DOCSTRING = (
104 "JSON (JavaScript Object Notation) <http://json.org>"
105 " is a subset of JavaScript syntax (ECMA-262"
106 " 3rd edition) used as a lightweight data interchange format.")
107 elif sys.version_info >= (3, 0):
108 self.JSON_LOADS_DOCSTRING = (
109 'Deserialize ``s`` (a ``str`` instance '
110 'containing a JSON document) to a Python object.'
111 )
112 self.JSON_DOCSTRING = (
113 "JSON (JavaScript Object Notation) <http://json.org>"
114 " is a subset of JavaScript syntax (ECMA-262"
115 " 3rd edition) used as a lightweight data interchange format.")
116 else:
117 self.JSON_LOADS_DOCSTRING = (
118 'Deserialize ``s`` (a ``str`` or ``unicode`` '
119 'instance containing a JSON document) to a Python object.'
120 )
121 self.JSON_DOCSTRING = (
122 "JSON (JavaScript Object Notation) <http://json.org>"
123 " is a subset of JavaScript syntax (ECMA-262"
124 " 3rd edition) used as a lightweight data interchange format.")
125
126 @mock.patch("elpy.jedibackend.run_with_debug")
127 def test_should_not_return_empty_docstring(self, run_with_debug):
128 location = mock.MagicMock()
129 location.full_name = "testthing"
130 location.docstring.return_value = ""
131 run_with_debug.return_value = [location]
132 filename = self.project_file("test.py", "print")
133 docstring = self.backend.rpc_get_oneline_docstring(filename, "print", 0)
134 self.assertIsNone(docstring)
135
136
137 class TestRPCGetDefinition(RPCGetDefinitionTests,
138 JediBackendTestCase):
139 @mock.patch("jedi.Script")
140 def test_should_not_fail_if_module_path_is_none(self, Script):
141 """Do not fail if loc.module_path is None.
142
143 This can happen under some circumstances I am unsure about.
144 See #537 for the issue that reported this.
145
146 """
147 locations = [
148 mock.Mock(module_path=None)
149 ]
150 script = Script.return_value
151 script.goto_definitions.return_value = locations
152 script.goto_assignments.return_value = locations
153
154 location = self.rpc("", "", 0)
155
156 self.assertIsNone(location)
157
158
159 class TestRPCGetRenameDiff(RPCGetRenameDiffTests,
160 JediBackendTestCase):
161 pass
162
163
164 class TestRPCGetExtractFunctionDiff(RPCGetExtractFunctionDiffTests,
165 JediBackendTestCase):
166 pass
167
168
169 class TestRPCGetExtractVariableDiff(RPCGetExtractVariableDiffTests,
170 JediBackendTestCase):
171 pass
172
173
174 class TestRPCGetInlineDiff(RPCGetInlineDiffTests,
175 JediBackendTestCase):
176 pass
177
178
179 class TestRPCGetCalltip(RPCGetCalltipTests,
180 JediBackendTestCase):
181 KEYS_CALLTIP = {'index': None,
182 'params': [],
183 'name': u'keys'}
184 RADIX_CALLTIP = {'index': None,
185 'params': [],
186 'name': u'radix'}
187 ADD_CALLTIP = {'index': 0,
188 'params': [u'a', u'b'],
189 'name': u'add'}
190 if compat.PYTHON3:
191 THREAD_CALLTIP = {'name': 'Thread',
192 'index': 0,
193 'params': ['group: None=...',
194 'target: Optional[Callable[..., Any]]=...',
195 'name: Optional[str]=...',
196 'args: Iterable[Any]=...',
197 'kwargs: Mapping[str, Any]=...',
198 'daemon: Optional[bool]=...']}
199
200 else:
201 THREAD_CALLTIP = {'index': 0,
202 'name': u'Thread',
203 'params': [u'group: None=...',
204 u'target: Optional[Callable[..., Any]]=...',
205 u'name: Optional[str]=...',
206 u'args: Iterable[Any]=...',
207 u'kwargs: Mapping[str, Any]=...']}
208
209 def test_should_not_fail_with_get_subscope_by_name(self):
210 # Bug #677 / jedi#628
211 source = (
212 u"my_lambda = lambda x: x+1\n"
213 u"my_lambda(1)"
214 )
215 filename = self.project_file("project.py", source)
216 offset = 37
217
218 sigs = self.backend.rpc_get_calltip(filename, source, offset)
219 sigs["index"]
220
221
222 class TestRPCGetUsages(RPCGetUsagesTests,
223 JediBackendTestCase):
224 def test_should_not_fail_for_missing_module(self):
225 # This causes use.module_path to be None
226 source = "import sys\n\nsys.path.\n" # insert()"
227 offset = 21
228 filename = self.project_file("project.py", source)
229
230 self.rpc(filename, source, offset)
231
232
233 class TestRPCGetNames(RPCGetNamesTests,
234 JediBackendTestCase):
235 pass
236
237
238 class TestPosToLinecol(unittest.TestCase):
239 def test_should_handle_beginning_of_string(self):
240 self.assertEqual(jedibackend.pos_to_linecol("foo", 0),
241 (1, 0))
242
243 def test_should_handle_end_of_line(self):
244 self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 9),
245 (3, 1))
246
247 def test_should_handle_end_of_string(self):
248 self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 14),
249 (4, 2))
250
251
252 class TestLinecolToPos(unittest.TestCase):
253 def test_should_handle_beginning_of_string(self):
254 self.assertEqual(jedibackend.linecol_to_pos("foo", 1, 0),
255 0)
256
257 def test_should_handle_end_of_string(self):
258 self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
259 3, 1),
260 9)
261
262 def test_should_return_offset(self):
263 self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
264 4, 2),
265 14)
266
267 def test_should_fail_for_line_past_text(self):
268 self.assertRaises(ValueError,
269 jedibackend.linecol_to_pos, "foo\n", 3, 1)
270
271 def test_should_fail_for_column_past_text(self):
272 self.assertRaises(ValueError,
273 jedibackend.linecol_to_pos, "foo\n", 1, 10)
274
275
276 class TestRunWithDebug(unittest.TestCase):
277 @mock.patch('jedi.Script')
278 def test_should_call_method(self, Script):
279 Script.return_value.test_method.return_value = "test-result"
280
281 result = jedibackend.run_with_debug(jedi, 'test_method', {}, 1, 2,
282 arg=3)
283
284 Script.assert_called_with(1, 2, arg=3)
285 self.assertEqual(result, 'test-result')
286
287 @mock.patch('jedi.Script')
288 def test_should_re_raise(self, Script):
289 Script.side_effect = RuntimeError
290
291 with self.assertRaises(RuntimeError):
292 jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3,
293 re_raise=(RuntimeError,))
294
295 @mock.patch('jedi.Script')
296 @mock.patch('jedi.set_debug_function')
297 def test_should_keep_debug_info(self, set_debug_function, Script):
298 Script.side_effect = RuntimeError
299
300 try:
301 jedibackend.run_with_debug(jedi, 'test_method', {}, 1, 2, arg=3)
302 except rpc.Fault as e:
303 self.assertGreaterEqual(e.code, 400)
304 self.assertIsNotNone(e.data)
305 self.assertIn("traceback", e.data)
306 jedi_debug_info = e.data["jedi_debug_info"]
307 self.assertIsNotNone(jedi_debug_info)
308 self.assertEqual(jedi_debug_info["script_args"],
309 "1, 2, arg=3")
310 self.assertEqual(jedi_debug_info["source"], None)
311 self.assertEqual(jedi_debug_info["method"], "test_method")
312 self.assertEqual(jedi_debug_info["debug_info"], [])
313 else:
314 self.fail("Fault not thrown")
315
316 @mock.patch('jedi.Script')
317 @mock.patch('jedi.set_debug_function')
318 def test_should_keep_error_text(self, set_debug_function, Script):
319 Script.side_effect = RuntimeError
320
321 try:
322 jedibackend.run_with_debug(jedi, 'test_method', {}, 1, 2, arg=3)
323 except rpc.Fault as e:
324 self.assertEqual(str(e), str(RuntimeError()))
325 self.assertEqual(e.message, str(RuntimeError()))
326 else:
327 self.fail("Fault not thrown")
328
329 @mock.patch('jedi.Script')
330 @mock.patch('jedi.set_debug_function')
331 def test_should_handle_source_special(self, set_debug_function, Script):
332 Script.side_effect = RuntimeError
333
334 try:
335 jedibackend.run_with_debug(jedi, 'test_method', source="foo")
336 except rpc.Fault as e:
337 self.assertEqual(e.data["jedi_debug_info"]["script_args"],
338 "source=source")
339 self.assertEqual(e.data["jedi_debug_info"]["source"], "foo")
340 else:
341 self.fail("Fault not thrown")
342
343 @mock.patch('jedi.Script')
344 @mock.patch('jedi.set_debug_function')
345 def test_should_set_debug_info(self, set_debug_function, Script):
346 the_debug_function = [None]
347
348 def my_set_debug_function(debug_function, **kwargs):
349 the_debug_function[0] = debug_function
350
351 def my_script(*args, **kwargs):
352 the_debug_function[0](jedi.debug.NOTICE, "Notice")
353 the_debug_function[0](jedi.debug.WARNING, "Warning")
354 the_debug_function[0]("other", "Other")
355 raise RuntimeError
356
357 set_debug_function.side_effect = my_set_debug_function
358 Script.return_value.test_method = my_script
359
360 try:
361 jedibackend.run_with_debug(jedi, 'test_method', source="foo")
362 except rpc.Fault as e:
363 self.assertEqual(e.data["jedi_debug_info"]["debug_info"],
364 ["[N] Notice",
365 "[W] Warning",
366 "[?] Other"])
367 else:
368 self.fail("Fault not thrown")
369
370 @mock.patch('jedi.set_debug_function')
371 @mock.patch('jedi.Script')
372 def test_should_not_fail_with_bad_data(self, Script, set_debug_function):
373 import jedi.debug
374
375 def set_debug(function, speed=True):
376 if function is not None:
377 function(jedi.debug.NOTICE, u"\xab")
378
379 set_debug_function.side_effect = set_debug
380 Script.return_value.test_method.side_effect = Exception
381
382 with self.assertRaises(rpc.Fault):
383 jedibackend.run_with_debug(jedi, 'test_method', {}, 1, 2, arg=3)