]> crepu.dev Git - config.git/blame - djavu-asus/emacs/elpa/elpy-20230803.1455/elpy/tests/test_jedibackend.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpa / elpy-20230803.1455 / elpy / tests / test_jedibackend.py
CommitLineData
53e6db90
DC
1"""Tests for the elpy.jedibackend module."""
2
3import sys
4import unittest
5
6import jedi
7try:
8 from unittest import mock
9except ImportError:
10 import mock
11import re
12
13from elpy import jedibackend
14from elpy import rpc
15from elpy.tests import compat
16from elpy.tests.support import BackendTestCase
17from elpy.tests.support import RPCGetCompletionsTests
18from elpy.tests.support import RPCGetCompletionDocstringTests
19from elpy.tests.support import RPCGetCompletionLocationTests
20from elpy.tests.support import RPCGetDocstringTests
21from elpy.tests.support import RPCGetOnelineDocstringTests
22from elpy.tests.support import RPCGetDefinitionTests
23from elpy.tests.support import RPCGetCalltipTests
24from elpy.tests.support import RPCGetUsagesTests
25from elpy.tests.support import RPCGetNamesTests
26from elpy.tests.support import RPCGetRenameDiffTests
27from elpy.tests.support import RPCGetExtractFunctionDiffTests
28from elpy.tests.support import RPCGetExtractVariableDiffTests
29from elpy.tests.support import RPCGetInlineDiffTests
30from elpy.tests.support import RPCGetAssignmentTests
31
32
33class 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
40class TestInit(JediBackendTestCase):
41 def test_should_have_jedi_as_name(self):
42 self.assertEqual(self.backend.name, "jedi")
43
44
45class TestRPCGetCompletions(RPCGetCompletionsTests,
46 JediBackendTestCase):
47 BUILTINS = ['object', 'oct', 'open', 'ord', 'OSError', 'OverflowError']
48
49
50class TestRPCGetAssignment(RPCGetAssignmentTests,
51 JediBackendTestCase):
52 pass
53
54
55class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
56 JediBackendTestCase):
57 pass
58
59
60class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
61 JediBackendTestCase):
62 pass
63
64
65class 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
92class 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
137class 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
159class TestRPCGetRenameDiff(RPCGetRenameDiffTests,
160 JediBackendTestCase):
161 pass
162
163
164class TestRPCGetExtractFunctionDiff(RPCGetExtractFunctionDiffTests,
165 JediBackendTestCase):
166 pass
167
168
169class TestRPCGetExtractVariableDiff(RPCGetExtractVariableDiffTests,
170 JediBackendTestCase):
171 pass
172
173
174class TestRPCGetInlineDiff(RPCGetInlineDiffTests,
175 JediBackendTestCase):
176 pass
177
178
179class 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
222class 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
233class TestRPCGetNames(RPCGetNamesTests,
234 JediBackendTestCase):
235 pass
236
237
238class 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
252class 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
276class 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)