|
|
- # coding: utf-8
-
- """Support classes and functions for the elpy test code.
-
- Elpy uses a bit of a peculiar test setup to avoid redundancy. For the
- tests of the two backends, we provide generic test cases for generic
- tests and for specific callback tests.
-
- These mixins can be included in the actual test classes. We can't add
- these tests to a BackendTestCase subclass directly because the test
- discovery would find them there and try to run them, which would fail.
-
- """
-
- import os
- import shutil
- import sys
- import tempfile
- import unittest
-
- from elpy.tests import compat
-
-
- class BackendTestCase(unittest.TestCase):
- """Base class for backend tests.
-
- This class sets up a project root directory and provides an easy
- way to create files within the project root.
-
- """
-
- def setUp(self):
- """Create the project root and make sure it gets cleaned up."""
- super(BackendTestCase, self).setUp()
- self.project_root = tempfile.mkdtemp(prefix="elpy-test")
- self.addCleanup(shutil.rmtree, self.project_root, True)
-
- def project_file(self, relname, contents):
- """Create a file named relname within the project root.
-
- Write contents into that file.
-
- """
- full_name = os.path.join(self.project_root, relname)
- try:
- os.makedirs(os.path.dirname(full_name))
- except OSError:
- pass
- if compat.PYTHON3:
- fobj = open(full_name, "w", encoding="utf-8")
- else:
- fobj = open(full_name, "w")
- with fobj as f:
- f.write(contents)
- return full_name
-
-
- class GenericRPCTests(object):
- """Generic RPC test methods.
-
- This is a mixin to add tests that should be run for all RPC
- methods that follow the generic (filename, source, offset) calling
- conventions.
-
- """
- METHOD = None
-
- def rpc(self, filename, source, offset):
- method = getattr(self.backend, self.METHOD)
- return method(filename, source, offset)
-
- def test_should_not_fail_on_inexisting_file(self):
- filename = self.project_root + "/doesnotexist.py"
- self.rpc(filename, "", 0)
-
- def test_should_not_fail_on_empty_file(self):
- filename = self.project_file("test.py", "")
- self.rpc(filename, "", 0)
-
- def test_should_not_fail_if_file_is_none(self):
- self.rpc(None, "", 0)
-
- def test_should_not_fail_for_module_syntax_errors(self):
- source, offset = source_and_offset(
- "class Foo(object):\n"
- " def bar(self):\n"
- " foo(_|_"
- " bar("
- "\n"
- " def a(self):\n"
- " pass\n"
- "\n"
- " def b(self):\n"
- " pass\n"
- "\n"
- " def b(self):\n"
- " pass\n"
- "\n"
- " def b(self):\n"
- " pass\n"
- "\n"
- " def b(self):\n"
- " pass\n"
- "\n"
- " def b(self):\n"
- " pass\n"
- )
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_bad_indentation(self):
- source, offset = source_and_offset(
- "def foo():\n"
- " print(23)_|_\n"
- " print(17)\n")
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- # @unittest.skipIf((3, 3) <= sys.version_info < (3, 4),
- # "Bug in jedi for Python 3.3")
- def test_should_not_fail_for_relative_import(self):
- source, offset = source_and_offset(
- "from .. import foo_|_"
- )
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_on_keyword(self):
- source, offset = source_and_offset(
- "_|_try:\n"
- " pass\n"
- "except:\n"
- " pass\n")
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_with_bad_encoding(self):
- source, offset = source_and_offset(
- u'# coding: utf-8X_|_\n'
- )
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_with_form_feed_characters(self):
- # Bug in Jedi: jedi#424
- source, offset = source_and_offset(
- "\f\n"
- "class Test(object):_|_\n"
- " pass"
- )
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_dictionaries_in_weird_places(self):
- # Bug in Jedi: jedi#417
- source, offset = source_and_offset(
- "import json\n"
- "\n"
- "def foo():\n"
- " json.loads(_|_\n"
- "\n"
- " json.load.return_value = {'foo': [],\n"
- " 'bar': True}\n"
- "\n"
- " c = Foo()\n"
- )
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_break_with_binary_characters_in_docstring(self):
- # Bug in Jedi: jedi#427
- template = '''\
- class Foo(object):
- def __init__(self):
- """
- COMMUNITY instance that this conversion belongs to.
- DISPERSY_VERSION is the dispersy conversion identifier (on the wire version; must be one byte).
- COMMUNIY_VERSION is the community conversion identifier (on the wire version; must be one byte).
-
- COMMUNIY_VERSION may not be '\\x00' or '\\xff'. '\\x00' is used by the DefaultConversion until
- a proper conversion instance can be made for the Community. '\\xff' is reserved for when
- more than one byte is needed as a version indicator.
- """
- pass
-
-
- x = Foo()
- x._|_
- '''
- source, offset = source_and_offset(template)
- filename = self.project_file("test.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_def_without_name(self):
- # Bug jedi#429
- source, offset = source_and_offset(
- "def_|_():\n"
- " if True:\n"
- " return True\n"
- " else:\n"
- " return False\n"
- )
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_on_lambda(self):
- # Bug #272 / jedi#431, jedi#572
- source, offset = source_and_offset(
- "map(lambda_|_"
- )
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_on_literals(self):
- # Bug #314, #344 / jedi#466
- source = u'lit = u"""\\\n# -*- coding: utf-8 -*-\n"""\n'
- offset = 0
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_with_args_as_args(self):
- # Bug #347 in rope_py3k
- source, offset = source_and_offset(
- "def my_function(*args):\n"
- " ret_|_"
- )
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_unicode_chars_in_string(self):
- # Bug #358 / jedi#482
- source = '''\
- # coding: utf-8
-
- logging.info(u"Saving «{}»...".format(title))
- requests.get(u"https://web.archive.org/save/{}".format(url))
- '''
- offset = 57
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_bad_escape_sequence(self):
- # Bug #360 / jedi#485
- source = r"v = '\x'"
- offset = 8
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_coding_declarations_in_strings(self):
- # Bug #314 / jedi#465 / python#22221
- source = u'lit = """\\\n# -*- coding: utf-8 -*-\n"""'
- offset = 8
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_if_root_vanishes(self):
- # Bug #353
- source, offset = source_and_offset(
- "import foo\n"
- "foo._|_"
- )
- filename = self.project_file("project.py", source)
- shutil.rmtree(self.project_root)
-
- self.rpc(filename, source, offset)
-
- # For some reason, this breaks a lot of other tests. Couldn't
- # figure out why.
- #
- # def test_should_not_fail_for_sys_path(self):
- # # Bug #365 / jedi#486
- # source, offset = source_and_offset(
- # "import sys\n"
- # "\n"
- # "sys.path.index(_|_\n"
- # )
- # filename = self.project_file("project.py", source)
- #
- # self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_key_error(self):
- # Bug #561, #564, #570, #588, #593, #599 / jedi#572, jedi#579,
- # jedi#590
- source, offset = source_and_offset(
- "map(lambda_|_"
- )
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_for_badly_defined_global_variable(self):
- # Bug #519 / jedi#610
- source, offset = source_and_offset(
- """\
- def funct1():
- global global_dict_var
- global_dict_var = dict()
-
- def funct2():
- global global_dict_var
- q = global_dict_var.copy_|_()
- print(q)""")
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
- def test_should_not_fail_with_mergednamesdict(self):
- # Bug #563 / jedi#589
- source, offset = source_and_offset(
- u'from email import message_|_'
- )
- filename = self.project_file("project.py", source)
-
- self.rpc(filename, source, offset)
-
-
- class RPCGetCompletionsTests(GenericRPCTests):
- METHOD = "rpc_get_completions"
-
- def test_should_complete_builtin(self):
- source, offset = source_and_offset("o_|_")
-
- expected = self.BUILTINS
- actual = [cand['name'] for cand in
- self.backend.rpc_get_completions("test.py",
- source, offset)]
-
- for candidate in expected:
- self.assertIn(candidate, actual)
-
- if sys.version_info >= (3, 5) or sys.version_info < (3, 0):
- JSON_COMPLETIONS = ["SONDecoder", "SONEncoder", "SONDecodeError"]
- else:
- JSON_COMPLETIONS = ["SONDecoder", "SONEncoder"]
-
- def test_should_complete_imports(self):
- source, offset = source_and_offset("import json\n"
- "json.J_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- self.assertEqual(
- sorted([cand['suffix'] for cand in completions]),
- sorted(self.JSON_COMPLETIONS))
-
- def test_should_complete_top_level_modules_for_import(self):
- source, offset = source_and_offset("import multi_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- if compat.PYTHON3:
- expected = ["processing"]
- else:
- expected = ["file", "processing"]
- self.assertEqual(sorted([cand['suffix'] for cand in completions]),
- sorted(expected))
-
- def test_should_complete_packages_for_import(self):
- source, offset = source_and_offset("import email.mi_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- if sys.version_info < (3, 0):
- compl = [u'me', u'METext']
- else:
- compl = ['me']
- self.assertEqual([cand['suffix'] for cand in completions],
- compl)
-
- def test_should_not_complete_for_import(self):
- source, offset = source_and_offset("import foo.Conf_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- self.assertEqual([cand['suffix'] for cand in completions],
- [])
-
- # @unittest.skipIf((3, 3) <= sys.version_info < (3, 4),
- # "Bug in jedi for Python 3.3")
- def test_should_not_fail_for_short_module(self):
- source, offset = source_and_offset("from .. import foo_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- self.assertIsNotNone(completions)
-
- def test_should_complete_sys(self):
- source, offset = source_and_offset("import sys\nsys._|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- self.assertIn('path', [cand['suffix'] for cand in completions])
-
- def test_should_find_with_trailing_text(self):
- source, offset = source_and_offset(
- "import threading\nthreading.T_|_mumble mumble")
-
- expected = ["Thread", "ThreadError", "Timer"]
- actual = [cand['name'] for cand in
- self.backend.rpc_get_completions("test.py", source, offset)]
-
- for candidate in expected:
- self.assertIn(candidate, actual)
-
- def test_should_find_completion_different_package(self):
- # See issue #74
- self.project_file("project/__init__.py", "")
- source1 = ("class Add:\n"
- " def add(self, a, b):\n"
- " return a + b\n")
- self.project_file("project/add.py", source1)
- source2, offset = source_and_offset(
- "from project.add import Add\n"
- "class Calculator:\n"
- " def add(self, a, b):\n"
- " c = Add()\n"
- " c.ad_|_\n")
- file2 = self.project_file("project/calculator.py", source2)
- proposals = self.backend.rpc_get_completions(file2,
- source2,
- offset)
- self.assertEqual(["add"],
- [proposal["name"] for proposal in proposals])
-
-
- class RPCGetCompletionDocstringTests(object):
- def test_should_return_docstring(self):
- source, offset = source_and_offset("import json\n"
- "json.JSONEnc_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- completions.sort(key=lambda p: p["name"])
- prop = completions[0]
- self.assertEqual(prop["name"], "JSONEncoder")
-
- docs = self.backend.rpc_get_completion_docstring("JSONEncoder")
-
- self.assertIn("Extensible JSON", docs)
-
- def test_should_return_none_if_unknown(self):
- docs = self.backend.rpc_get_completion_docstring("Foo")
-
- self.assertIsNone(docs)
-
-
- class RPCGetCompletionLocationTests(object):
- def test_should_return_location(self):
- source, offset = source_and_offset("donaudampfschiff = 1\n"
- "donau_|_")
- filename = self.project_file("test.py", source)
- completions = self.backend.rpc_get_completions(filename,
- source,
- offset)
- prop = completions[0]
- self.assertEqual(prop["name"], "donaudampfschiff")
-
- loc = self.backend.rpc_get_completion_location("donaudampfschiff")
-
- self.assertEqual((filename, 1), loc)
-
- def test_should_return_none_if_unknown(self):
- docs = self.backend.rpc_get_completion_location("Foo")
-
- self.assertIsNone(docs)
-
-
- class RPCGetDefinitionTests(GenericRPCTests):
- METHOD = "rpc_get_definition"
-
- def test_should_return_definition_location_same_file(self):
- source, offset = source_and_offset("import threading\n"
- "def test_function(a, b):\n"
- " return a + b\n"
- "\n"
- "test_func_|_tion(\n")
- filename = self.project_file("test.py", source)
-
- location = self.backend.rpc_get_definition(filename,
- source,
- offset)
-
- self.assertEqual(location[0], filename)
- # On def or on the function name
- self.assertIn(location[1], (17, 21))
-
- def test_should_return_location_in_same_file_if_not_saved(self):
- source, offset = source_and_offset(
- "import threading\n"
- "\n"
- "\n"
- "def other_function():\n"
- " test_f_|_unction(1, 2)\n"
- "\n"
- "\n"
- "def test_function(a, b):\n"
- " return a + b\n")
- filename = self.project_file("test.py", "")
-
- location = self.backend.rpc_get_definition(filename,
- source,
- offset)
-
- self.assertEqual(location[0], filename)
- # def or function name
- self.assertIn(location[1], (67, 71))
-
- def test_should_return_location_in_different_file(self):
- source1 = ("def test_function(a, b):\n"
- " return a + b\n")
- file1 = self.project_file("test1.py", source1)
- source2, offset = source_and_offset("from test1 import test_function\n"
- "test_funct_|_ion(1, 2)\n")
- file2 = self.project_file("test2.py", source2)
-
- definition = self.backend.rpc_get_definition(file2,
- source2,
- offset)
-
- self.assertEqual(definition[0], file1)
- # Either on the def or on the function name
- self.assertIn(definition[1], (0, 4))
-
- def test_should_return_none_if_location_not_found(self):
- source, offset = source_and_offset("test_f_|_unction()\n")
- filename = self.project_file("test.py", source)
-
- definition = self.backend.rpc_get_definition(filename,
- source,
- offset)
-
- self.assertIsNone(definition)
-
- def test_should_return_none_if_outside_of_symbol(self):
- source, offset = source_and_offset("test_function(_|_)\n")
- filename = self.project_file("test.py", source)
-
- definition = self.backend.rpc_get_definition(filename,
- source,
- offset)
-
- self.assertIsNone(definition)
-
- def test_should_return_definition_location_different_package(self):
- # See issue #74
- self.project_file("project/__init__.py", "")
- source1 = ("class Add:\n"
- " def add(self, a, b):\n"
- " return a + b\n")
- file1 = self.project_file("project/add.py", source1)
- source2, offset = source_and_offset(
- "from project.add import Add\n"
- "class Calculator:\n"
- " def add(self, a, b):\n"
- " return Add_|_().add(a, b)\n")
- file2 = self.project_file("project/calculator.py", source2)
-
- location = self.backend.rpc_get_definition(file2,
- source2,
- offset)
-
- self.assertEqual(location[0], file1)
- # class or class name
- self.assertIn(location[1], (0, 6))
-
- def test_should_find_variable_definition(self):
- source, offset = source_and_offset("SOME_VALUE = 1\n"
- "\n"
- "variable = _|_SOME_VALUE\n")
- filename = self.project_file("test.py", source)
- self.assertEqual(self.backend.rpc_get_definition(filename,
- source,
- offset),
- (filename, 0))
-
-
- class RPCGetAssignmentTests(GenericRPCTests):
- METHOD = "rpc_get_assignment"
-
- def test_should_return_assignment_location_same_file(self):
- source, offset = source_and_offset("import threading\n"
- "class TestClass(object):\n"
- " def __init__(self, a, b):\n"
- " self.a = a\n"
- " self.b = b\n"
- "\n"
- "testclass = TestClass(2, 4)"
- "\n"
- "testcl_|_ass(\n")
- filename = self.project_file("test.py", source)
-
- location = self.backend.rpc_get_assignment(filename,
- source,
- offset)
-
- self.assertEqual(location[0], filename)
- # On def or on the function name
- self.assertEqual(location[1], 111)
-
- def test_should_return_location_in_same_file_if_not_saved(self):
- source, offset = source_and_offset("import threading\n"
- "class TestClass(object):\n"
- " def __init__(self, a, b):\n"
- " self.a = a\n"
- " self.b = b\n"
- "\n"
- "testclass = TestClass(2, 4)"
- "\n"
- "testcl_|_ass(\n")
- filename = self.project_file("test.py", "")
-
- location = self.backend.rpc_get_assignment(filename,
- source,
- offset)
-
- self.assertEqual(location[0], filename)
- # def or function name
- self.assertEqual(location[1], 111)
-
- def test_should_return_location_in_different_file(self):
- source1 = ("class TestClass(object):\n"
- " def __init__(self, a, b):\n"
- " self.a = a\n"
- " self.b = b\n"
- "testclass = TestClass(3, 5)\n")
- file1 = self.project_file("test1.py", source1)
- source2, offset = source_and_offset("from test1 import testclass\n"
- "testcl_|_ass.a\n")
- file2 = self.project_file("test2.py", source2)
- # First jump goes to import statement
- assignment = self.backend.rpc_get_assignment(file2,
- source2,
- offset)
- # Second jump goes to test1 file
- self.assertEqual(assignment[0], file2)
- assignment = self.backend.rpc_get_assignment(file2,
- source2,
- assignment[1])
-
- self.assertEqual(assignment[0], file1)
- self.assertEqual(assignment[1], 93)
-
- def test_should_return_none_if_location_not_found(self):
- source, offset = source_and_offset("test_f_|_unction()\n")
- filename = self.project_file("test.py", source)
-
- assignment = self.backend.rpc_get_assignment(filename,
- source,
- offset)
-
- self.assertIsNone(assignment)
-
- def test_should_return_none_if_outside_of_symbol(self):
- source, offset = source_and_offset("testcl(_|_)ass\n")
- filename = self.project_file("test.py", source)
-
- assignment = self.backend.rpc_get_assignment(filename,
- source,
- offset)
-
- self.assertIsNone(assignment)
-
- def test_should_find_variable_assignment(self):
- source, offset = source_and_offset("SOME_VALUE = 1\n"
- "\n"
- "variable = _|_SOME_VALUE\n")
- filename = self.project_file("test.py", source)
- self.assertEqual(self.backend.rpc_get_assignment(filename,
- source,
- offset),
- (filename, 0))
-
-
- class RPCGetCalltipTests(GenericRPCTests):
- METHOD = "rpc_get_calltip"
-
- def test_should_get_calltip(self):
- source, offset = source_and_offset(
- "import threading\nthreading.Thread(_|_")
- filename = self.project_file("test.py", source)
- calltip = self.backend.rpc_get_calltip(filename,
- source,
- offset)
-
- expected = self.THREAD_CALLTIP
-
- self.assertEqual(calltip, expected)
-
- def test_should_get_calltip_even_after_parens(self):
- source, offset = source_and_offset(
- "import threading\nthreading.Thread(foo()_|_")
- filename = self.project_file("test.py", source)
-
- actual = self.backend.rpc_get_calltip(filename,
- source,
- offset)
-
- self.assertEqual(self.THREAD_CALLTIP, actual)
-
- def test_should_get_calltip_at_closing_paren(self):
- source, offset = source_and_offset(
- "import threading\nthreading.Thread(_|_)")
- filename = self.project_file("test.py", source)
-
- actual = self.backend.rpc_get_calltip(filename,
- source,
- offset)
-
- self.assertEqual(self.THREAD_CALLTIP, actual)
-
- def test_should_not_missing_attribute_get_definition(self):
- # Bug #627 / jedi#573
- source, offset = source_and_offset(
- "import threading\nthreading.Thread(_|_)")
- filename = self.project_file("test.py", source)
-
- self.backend.rpc_get_calltip(filename, source, offset)
-
- def test_should_return_none_for_bad_identifier(self):
- source, offset = source_and_offset(
- "froblgoo(_|_")
- filename = self.project_file("test.py", source)
- calltip = self.backend.rpc_get_calltip(filename,
- source,
- offset)
- self.assertIsNone(calltip)
-
- def test_should_remove_self_argument(self):
- source, offset = source_and_offset(
- "d = dict()\n"
- "d.keys(_|_")
- filename = self.project_file("test.py", source)
-
- actual = self.backend.rpc_get_calltip(filename,
- source,
- offset)
-
- self.assertEqual(self.KEYS_CALLTIP, actual)
-
- def test_should_remove_package_prefix(self):
- source, offset = source_and_offset(
- "import decimal\n"
- "d = decimal.Decimal('1.5')\n"
- "d.radix(_|_")
- filename = self.project_file("test.py", source)
-
- actual = self.backend.rpc_get_calltip(filename,
- source,
- offset)
-
- self.assertEqual(self.RADIX_CALLTIP, actual)
-
- def test_should_return_none_outside_of_all(self):
- filename = self.project_file("test.py", "")
- source, offset = source_and_offset("import thr_|_eading\n")
- calltip = self.backend.rpc_get_calltip(filename,
- source, offset)
- self.assertIsNone(calltip)
-
- def test_should_find_calltip_different_package(self):
- # See issue #74
- self.project_file("project/__init__.py", "")
- source1 = ("class Add:\n"
- " def add(self, a, b):\n"
- " return a + b\n")
- self.project_file("project/add.py", source1)
- source2, offset = source_and_offset(
- "from project.add import Add\n"
- "class Calculator:\n"
- " def add(self, a, b):\n"
- " c = Add()\n"
- " c.add(_|_\n")
- file2 = self.project_file("project/calculator.py", source2)
-
- actual = self.backend.rpc_get_calltip(file2,
- source2,
- offset)
-
- self.assertEqual(self.ADD_CALLTIP, actual)
-
-
- class RPCGetDocstringTests(GenericRPCTests):
- METHOD = "rpc_get_docstring"
-
- def check_docstring(self, docstring):
-
- def first_line(s):
- return s[:s.index("\n")]
-
- self.assertEqual(first_line(docstring),
- self.JSON_LOADS_DOCSTRING)
-
- def test_should_get_docstring(self):
- source, offset = source_and_offset(
- "import json\njson.loads_|_(")
- filename = self.project_file("test.py", source)
- docstring = self.backend.rpc_get_docstring(filename,
- source,
- offset)
- self.check_docstring(docstring)
-
- def test_should_return_none_for_bad_identifier(self):
- source, offset = source_and_offset(
- "froblgoo_|_(\n")
- filename = self.project_file("test.py", source)
- docstring = self.backend.rpc_get_docstring(filename,
- source,
- offset)
- self.assertIsNone(docstring)
-
-
- class RPCGetOnelineDocstringTests(GenericRPCTests):
- METHOD = "rpc_get_oneline_docstring"
-
- def check_docstring(self, docstring):
-
- self.assertEqual(docstring['doc'],
- self.JSON_LOADS_DOCSTRING)
-
- def check_module_docstring(self, docstring):
-
- self.assertEqual(docstring['doc'],
- self.JSON_DOCSTRING)
-
- def test_should_get_oneline_docstring(self):
- source, offset = source_and_offset(
- "import json\njson.loads_|_(")
- filename = self.project_file("test.py", source)
- docstring = self.backend.rpc_get_oneline_docstring(filename,
- source,
- offset)
- self.check_docstring(docstring)
-
- def test_should_get_oneline_docstring_for_modules(self):
- source, offset = source_and_offset(
- "import json_|_\njson.loads(")
- filename = self.project_file("test.py", source)
- docstring = self.backend.rpc_get_oneline_docstring(filename,
- source,
- offset)
- self.check_module_docstring(docstring)
-
- def test_should_return_none_for_bad_identifier(self):
- source, offset = source_and_offset(
- "froblgoo_|_(\n")
- filename = self.project_file("test.py", source)
- docstring = self.backend.rpc_get_oneline_docstring(filename,
- source,
- offset)
- self.assertIsNone(docstring)
-
-
- class RPCGetNamesTests(GenericRPCTests):
- METHOD = "rpc_get_names"
-
- def test_shouldreturn_names_in_same_file(self):
- filename = self.project_file("test.py", "")
- source, offset = source_and_offset(
- "def foo(x, y):\n"
- " return x + y\n"
- "c = _|_foo(5, 2)\n")
-
- names = self.backend.rpc_get_names(filename,
- source,
- offset)
-
- self.assertEqual(names,
- [{'name': 'foo',
- 'filename': filename,
- 'offset': 4},
- {'name': 'x',
- 'filename': filename,
- 'offset': 8},
- {'name': 'y',
- 'filename': filename,
- 'offset': 11},
- {'name': 'x',
- 'filename': filename,
- 'offset': 26},
- {'name': 'y',
- 'filename': filename,
- 'offset': 30},
- {'name': 'c',
- 'filename': filename,
- 'offset': 32},
- {'name': 'foo',
- 'filename': filename,
- 'offset': 36}])
-
- def test_should_not_fail_without_symbol(self):
- filename = self.project_file("test.py", "")
-
- names = self.backend.rpc_get_names(filename,
- "",
- 0)
-
- self.assertEqual(names, [])
-
-
- class RPCGetUsagesTests(GenericRPCTests):
- METHOD = "rpc_get_usages"
-
- def test_should_return_uses_in_same_file(self):
- filename = self.project_file("test.py", "")
- source, offset = source_and_offset(
- "def foo(x):\n"
- " return _|_x + x\n")
-
- usages = self.backend.rpc_get_usages(filename,
- source,
- offset)
-
- self.assertEqual(usages,
- [{'name': 'x',
- 'offset': 8,
- 'filename': filename},
- {'name': 'x',
- 'filename': filename,
- 'offset': 23},
- {'name': u'x',
- 'filename': filename,
- 'offset': 27}])
-
- def test_should_return_uses_in_other_file(self):
- file1 = self.project_file("file1.py", "")
- file2 = self.project_file("file2.py", "\n\n\n\n\nx = 5")
- source, offset = source_and_offset(
- "import file2\n"
- "file2._|_x\n")
-
- usages = self.backend.rpc_get_usages(file1,
- source,
- offset)
-
- self.assertEqual(usages,
- [{'name': 'x',
- 'filename': file1,
- 'offset': 19},
- {'name': 'x',
- 'filename': file2,
- 'offset': 5}])
-
- def test_should_not_fail_without_symbol(self):
- filename = self.project_file("file.py", "")
-
- usages = self.backend.rpc_get_usages(filename,
- "",
- 0)
-
- self.assertEqual(usages, [])
-
-
- def source_and_offset(source):
- """Return a source and offset from a source description.
-
- >>> source_and_offset("hello, _|_world")
- ("hello, world", 7)
- >>> source_and_offset("_|_hello, world")
- ("hello, world", 0)
- >>> source_and_offset("hello, world_|_")
- ("hello, world", 12)
- """
- offset = source.index("_|_")
- return source[:offset] + source[offset + 3:], offset
|