k now... emacs>vim

This commit is contained in:
TuDatTr
2017-12-19 22:52:42 +01:00
parent d701704955
commit df3a90ee6b
1500 changed files with 44508 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
"""Unit tests for elpy."""
try:
import unittest2
import sys
sys.modules['unittest'] = unittest2
except:
pass

View File

@@ -0,0 +1,18 @@
"""Python 2/3 compatibility definitions.
These are used by the rest of Elpy to keep compatibility definitions
in one place.
"""
import sys
if sys.version_info >= (3, 0):
PYTHON3 = True
import builtins
from io import StringIO
else:
PYTHON3 = False
import __builtin__ as builtins # noqa
from StringIO import StringIO # noqa

View File

@@ -0,0 +1,950 @@
# 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):
# Bug in Rope: rope#80
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):
# Bug in Rope: rope#81 and rope#82
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):
# Bug in Rope: rope#83
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):
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)
self.assertEqual([cand['suffix'] for cand in completions],
["me"])
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"
@unittest.skipIf(sys.version_info >= (3, 0),
"Bug in Jedi 0.9.0")
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)
@unittest.skipIf(sys.version_info >= (3, 0),
"Bug in Jedi 0.9.0")
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)
@unittest.skipIf(sys.version_info >= (3, 0),
"Bug in Jedi 0.9.0")
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 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

View File

@@ -0,0 +1,20 @@
# coding: utf-8
"""Tests for the elpy.autopep8 module"""
import unittest
from elpy import auto_pep8
from elpy.tests.support import BackendTestCase
class Autopep8TestCase(BackendTestCase):
def setUp(self):
if not auto_pep8.autopep8:
raise unittest.SkipTest
def test_fix_code(self):
code_block = 'x= 123\n'
new_block = auto_pep8.fix_code(code_block)
self.assertEqual(new_block, 'x = 123\n')

View File

@@ -0,0 +1,73 @@
# coding: utf-8
"""Tests for the elpy.impmagic module"""
import re
import sys
import unittest
from elpy import impmagic
from elpy.tests.support import BackendTestCase
TEST_SOURCE = '''# test file
import time
import logging
os.getcwd()
time.sleep(1)
'''
@unittest.skipIf(sys.version_info >= (3, 5), "importmagic fails in 3.5")
class ImportMagicTestCase(BackendTestCase):
def setUp(self):
if not impmagic.importmagic:
raise unittest.SkipTest
self.importmagic = impmagic.ImportMagic()
super(ImportMagicTestCase, self).setUp()
def build_index(self):
self.project_file('mymod.py', 'class AnUncommonName:\n pass\n')
self.importmagic.build_index(self.project_root,
custom_path=[self.project_root],
blacklist_re=re.compile('^$'))
self.importmagic._thread.join()
def test_get_symbols(self):
self.build_index()
candidates = self.importmagic.get_import_symbols('AnUncommonName')
self.assertEqual(candidates, ['from mymod import AnUncommonName'])
candidates = self.importmagic.get_import_symbols('mymod')
self.assertEqual(candidates, ['import mymod'])
def test_add_import(self):
self.build_index()
start, end, newblock = self.importmagic.add_import(
TEST_SOURCE, 'from mymod import AnUncommonName')
self.assertEqual(start, 2)
self.assertEqual(end, 5)
self.assertEqual(newblock.strip(),
'import logging\n'
'import time\n'
'from mymod import AnUncommonName')
start, end, newblock = self.importmagic.add_import(
TEST_SOURCE, 'import mymod')
self.assertEqual(start, 2)
self.assertEqual(end, 5)
self.assertEqual(newblock.strip(),
'import logging\nimport mymod\nimport time')
def test_get_unresolved_symbols(self):
self.build_index()
symbols = self.importmagic.get_unresolved_symbols('x = a + b\ny = c.d')
self.assertEqual(sorted(symbols), ['a', 'b', 'c.d'])
def test_remove_unreferenced_imports(self):
self.build_index()
start, end, newblock = \
self.importmagic.remove_unreferenced_imports(TEST_SOURCE)
self.assertEqual(start, 2)
self.assertEqual(end, 5)
self.assertEqual(newblock.strip(), 'import time')

View File

@@ -0,0 +1,317 @@
"""Tests for the elpy.jedibackend module."""
import sys
import unittest
import jedi
import mock
from elpy import jedibackend
from elpy import rpc
from elpy.tests import compat
from elpy.tests.support import BackendTestCase
from elpy.tests.support import RPCGetCompletionsTests
from elpy.tests.support import RPCGetCompletionDocstringTests
from elpy.tests.support import RPCGetCompletionLocationTests
from elpy.tests.support import RPCGetDocstringTests
from elpy.tests.support import RPCGetDefinitionTests
from elpy.tests.support import RPCGetAssignmentTests
from elpy.tests.support import RPCGetCalltipTests
from elpy.tests.support import RPCGetUsagesTests
from elpy.tests.support import RPCGetNamesTests
class JediBackendTestCase(BackendTestCase):
def setUp(self):
super(JediBackendTestCase, self).setUp()
self.backend = jedibackend.JediBackend(self.project_root)
class TestInit(JediBackendTestCase):
def test_should_have_jedi_as_name(self):
self.assertEqual(self.backend.name, "jedi")
class TestRPCGetCompletions(RPCGetCompletionsTests,
JediBackendTestCase):
BUILTINS = ['object', 'oct', 'open', 'ord', 'OSError', 'OverflowError']
class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
JediBackendTestCase):
pass
class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
JediBackendTestCase):
pass
class TestRPCGetDocstring(RPCGetDocstringTests,
JediBackendTestCase):
JSON_LOADS_DOCSTRING = (
'loads(s, encoding=None, cls=None, '
'object_hook=None, parse_float=None,'
)
def check_docstring(self, docstring):
lines = docstring.splitlines()
self.assertEqual(lines[0], 'Documentation for json.loads:')
self.assertEqual(lines[2], self.JSON_LOADS_DOCSTRING)
@mock.patch("elpy.jedibackend.run_with_debug")
def test_should_not_return_empty_docstring(self, run_with_debug):
location = mock.MagicMock()
location.full_name = "testthing"
location.docstring.return_value = ""
run_with_debug.return_value = [location]
filename = self.project_file("test.py", "print")
docstring = self.backend.rpc_get_docstring(filename, "print", 0)
self.assertIsNone(docstring)
class TestRPCGetDefinition(RPCGetDefinitionTests,
JediBackendTestCase):
@mock.patch("jedi.Script")
def test_should_not_fail_if_module_path_is_none(self, Script):
"""Do not fail if loc.module_path is None.
This can happen under some circumstances I am unsure about.
See #537 for the issue that reported this.
"""
locations = [
mock.Mock(module_path=None)
]
script = Script.return_value
script.goto_definitions.return_value = locations
script.goto_assignments.return_value = locations
location = self.rpc("", "", 0)
self.assertIsNone(location)
class TestRPCGetAssignment(RPCGetAssignmentTests,
JediBackendTestCase):
@mock.patch("jedi.Script")
def test_should_not_fail_if_module_path_is_none(self, Script):
"""Do not fail if loc.module_path is None.
"""
locations = [
mock.Mock(module_path=None)
]
script = Script.return_value
script.goto_assignments.return_value = locations
script.goto_assignments.return_value = locations
location = self.rpc("", "", 0)
self.assertIsNone(location)
class TestRPCGetCalltip(RPCGetCalltipTests,
JediBackendTestCase):
KEYS_CALLTIP = {'index': 0,
'params': ['param '],
'name': u'keys'}
RADIX_CALLTIP = {'index': None,
'params': [],
'name': u'radix'}
ADD_CALLTIP = {'index': 0,
'params': [u'param a', u'param b'],
'name': u'add'}
if compat.PYTHON3:
THREAD_CALLTIP = {"name": "Thread",
"params": ["group=None",
"target=None",
"name=None",
"args=()",
"kwargs=None",
"daemon=None"],
"index": 0}
else:
THREAD_CALLTIP = {"name": "Thread",
"params": ["param group=None",
"param target=None",
"param name=None",
"param args=()",
"param kwargs=None",
"param verbose=None"],
"index": 0}
def test_should_not_fail_with_get_subscope_by_name(self):
# Bug #677 / jedi#628
source = (
u"my_lambda = lambda x: x+1\n"
u"my_lambda(1)"
)
filename = self.project_file("project.py", source)
offset = 37
sigs = self.backend.rpc_get_calltip(filename, source, offset)
sigs["index"]
class TestRPCGetUsages(RPCGetUsagesTests,
JediBackendTestCase):
def test_should_not_fail_for_missing_module(self):
# This causes use.module_path to be None
source = "import sys\n\nsys.path.\n" # insert()"
offset = 21
filename = self.project_file("project.py", source)
self.rpc(filename, source, offset)
class TestRPCGetNames(RPCGetNamesTests,
JediBackendTestCase):
pass
class TestPosToLinecol(unittest.TestCase):
def test_should_handle_beginning_of_string(self):
self.assertEqual(jedibackend.pos_to_linecol("foo", 0),
(1, 0))
def test_should_handle_end_of_line(self):
self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 9),
(3, 1))
def test_should_handle_end_of_string(self):
self.assertEqual(jedibackend.pos_to_linecol("foo\nbar\nbaz\nqux", 14),
(4, 2))
class TestLinecolToPos(unittest.TestCase):
def test_should_handle_beginning_of_string(self):
self.assertEqual(jedibackend.linecol_to_pos("foo", 1, 0),
0)
def test_should_handle_end_of_string(self):
self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
3, 1),
9)
def test_should_return_offset(self):
self.assertEqual(jedibackend.linecol_to_pos("foo\nbar\nbaz\nqux",
4, 2),
14)
def test_should_fail_for_line_past_text(self):
self.assertRaises(ValueError,
jedibackend.linecol_to_pos, "foo\n", 3, 1)
def test_should_fail_for_column_past_text(self):
self.assertRaises(ValueError,
jedibackend.linecol_to_pos, "foo\n", 1, 10)
class TestRunWithDebug(unittest.TestCase):
@mock.patch('jedi.Script')
def test_should_call_method(self, Script):
Script.return_value.test_method.return_value = "test-result"
result = jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
Script.assert_called_with(1, 2, arg=3)
self.assertEqual(result, 'test-result')
@mock.patch('jedi.Script')
def test_should_re_raise(self, Script):
Script.side_effect = RuntimeError
with self.assertRaises(RuntimeError):
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3,
re_raise=(RuntimeError,))
@mock.patch('jedi.Script')
@mock.patch('jedi.set_debug_function')
def test_should_keep_debug_info(self, set_debug_function, Script):
Script.side_effect = RuntimeError
try:
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
except rpc.Fault as e:
self.assertGreaterEqual(e.code, 400)
self.assertIsNotNone(e.data)
self.assertIn("traceback", e.data)
jedi_debug_info = e.data["jedi_debug_info"]
self.assertIsNotNone(jedi_debug_info)
self.assertEqual(jedi_debug_info["script_args"],
"1, 2, arg=3")
self.assertEqual(jedi_debug_info["source"], None)
self.assertEqual(jedi_debug_info["method"], "test_method")
self.assertEqual(jedi_debug_info["debug_info"], [])
else:
self.fail("Fault not thrown")
@mock.patch('jedi.Script')
@mock.patch('jedi.set_debug_function')
def test_should_keep_error_text(self, set_debug_function, Script):
Script.side_effect = RuntimeError
try:
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)
except rpc.Fault as e:
self.assertEqual(str(e), str(RuntimeError()))
self.assertEqual(e.message, str(RuntimeError()))
else:
self.fail("Fault not thrown")
@mock.patch('jedi.Script')
@mock.patch('jedi.set_debug_function')
def test_should_handle_source_special(self, set_debug_function, Script):
Script.side_effect = RuntimeError
try:
jedibackend.run_with_debug(jedi, 'test_method', source="foo")
except rpc.Fault as e:
self.assertEqual(e.data["jedi_debug_info"]["script_args"],
"source=source")
self.assertEqual(e.data["jedi_debug_info"]["source"], "foo")
else:
self.fail("Fault not thrown")
@mock.patch('jedi.Script')
@mock.patch('jedi.set_debug_function')
def test_should_set_debug_info(self, set_debug_function, Script):
the_debug_function = [None]
def my_set_debug_function(debug_function, **kwargs):
the_debug_function[0] = debug_function
def my_script(*args, **kwargs):
the_debug_function[0](jedi.debug.NOTICE, "Notice")
the_debug_function[0](jedi.debug.WARNING, "Warning")
the_debug_function[0]("other", "Other")
raise RuntimeError
set_debug_function.side_effect = my_set_debug_function
Script.return_value.test_method = my_script
try:
jedibackend.run_with_debug(jedi, 'test_method', source="foo")
except rpc.Fault as e:
self.assertEqual(e.data["jedi_debug_info"]["debug_info"],
["[N] Notice",
"[W] Warning",
"[?] Other"])
else:
self.fail("Fault not thrown")
@mock.patch('jedi.set_debug_function')
@mock.patch('jedi.Script')
def test_should_not_fail_with_bad_data(self, Script, set_debug_function):
import jedi.debug
def set_debug(function, speed=True):
if function is not None:
function(jedi.debug.NOTICE, u"\xab")
set_debug_function.side_effect = set_debug
Script.return_value.test_method.side_effect = Exception
with self.assertRaises(rpc.Fault):
jedibackend.run_with_debug(jedi, 'test_method', 1, 2, arg=3)

View File

@@ -0,0 +1,88 @@
import os
import unittest
import shutil
import sys
import tempfile
import mock
import elpy.pydocutils
class TestGetPydocCompletions(unittest.TestCase):
def test_should_return_top_level_modules(self):
modules = elpy.pydocutils.get_pydoc_completions("")
self.assertIn('sys', modules)
self.assertIn('json', modules)
def test_should_return_submodules(self):
modules = elpy.pydocutils.get_pydoc_completions("elpy")
self.assertIn("elpy.rpc", modules)
self.assertIn("elpy.server", modules)
modules = elpy.pydocutils.get_pydoc_completions("os")
self.assertIn("os.path", modules)
def test_should_find_objects_in_module(self):
self.assertIn("elpy.tests.test_pydocutils.TestGetPydocCompletions",
elpy.pydocutils.get_pydoc_completions
("elpy.tests.test_pydocutils"))
def test_should_find_attributes_of_objects(self):
attribs = elpy.pydocutils.get_pydoc_completions(
"elpy.tests.test_pydocutils.TestGetPydocCompletions")
self.assertIn("elpy.tests.test_pydocutils.TestGetPydocCompletions."
"test_should_find_attributes_of_objects",
attribs)
def test_should_return_none_for_inexisting_module(self):
self.assertEqual([],
elpy.pydocutils.get_pydoc_completions
("does_not_exist"))
def test_should_work_for_unicode_strings(self):
self.assertIsNotNone(elpy.pydocutils.get_pydoc_completions
(u"sys"))
def test_should_find_partial_completions(self):
self.assertIn("multiprocessing",
elpy.pydocutils.get_pydoc_completions
("multiprocess"))
self.assertIn("multiprocessing.util",
elpy.pydocutils.get_pydoc_completions
("multiprocessing.ut"))
def test_should_ignore_trailing_dot(self):
self.assertIn("elpy.pydocutils",
elpy.pydocutils.get_pydoc_completions
("elpy."))
class TestGetModules(unittest.TestCase):
def test_should_return_top_level_modules(self):
modules = elpy.pydocutils.get_modules()
self.assertIn('sys', modules)
self.assertIn('json', modules)
def test_should_return_submodules(self):
modules = elpy.pydocutils.get_modules("elpy")
self.assertIn("rpc", modules)
self.assertIn("server", modules)
@mock.patch.object(elpy.pydocutils, 'safeimport')
def test_should_catch_import_errors(self, safeimport):
def raise_function(message):
raise elpy.pydocutils.ErrorDuringImport(message,
(None, None, None))
safeimport.side_effect = raise_function
self.assertEqual([], elpy.pydocutils.get_modules("foo.bar"))
def test_should_not_fail_for_permission_denied(self):
tmpdir = tempfile.mkdtemp(prefix="test-elpy-get-modules-")
sys.path.append(tmpdir)
os.chmod(tmpdir, 0o000)
try:
elpy.pydocutils.get_modules()
finally:
os.chmod(tmpdir, 0o755)
shutil.rmtree(tmpdir)
sys.path.remove(tmpdir)

View File

@@ -0,0 +1,545 @@
import unittest
import tempfile
import shutil
import os
import mock
import sys
from elpy import refactor
from textwrap import dedent
class RefactorTestCase(unittest.TestCase):
def setUp(self):
self.project_root = tempfile.mkdtemp(prefix="test-refactor-root")
self.addCleanup(shutil.rmtree, self.project_root,
ignore_errors=True)
def create_file(self, name, contents=""):
filename = os.path.join(self.project_root, name)
contents = dedent(contents)
offset = contents.find("_|_")
if offset > -1:
contents = contents[:offset] + contents[offset + 3:]
with open(filename, "w") as f:
f.write(contents)
return filename, offset
def assertSourceEqual(self, first, second, msg=None):
"""Fail if the two objects are unequal, ignoring indentation."""
self.assertEqual(dedent(first), dedent(second), msg=msg)
class TestGetRefactorOptions(RefactorTestCase):
def test_should_only_return_importsmodule_if_not_on_symbol(self):
filename, offset = self.create_file("foo.py",
"""\
import foo
_|_""")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset)
self.assertTrue(all(opt['category'] in ('Imports',
'Module')
for opt in options))
filename, offset = self.create_file("foo.py",
"""\
_|_
import foo""")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset)
self.assertTrue(all(opt['category'] in ('Imports',
'Module')
for opt in options))
def test_should_return_all_if_on_symbol(self):
filename, offset = self.create_file("foo.py",
"import _|_foo")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset)
self.assertTrue(all(opt['category'] in ('Imports',
'Method',
'Module',
'Symbol')
for opt in options))
def test_should_return_only_region_if_endoffset(self):
filename, offset = self.create_file("foo.py",
"import foo")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset, 5)
self.assertTrue(all(opt['category'] == 'Region'
for opt in options))
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
def test_should_treat_from_import_special(self):
filename, offset = self.create_file("foo.py",
"""\
import foo
_|_""")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset)
self.assertFalse(any(opt['name'] == "refactor_froms_to_imports"
for opt in options))
filename, offset = self.create_file("foo.py",
"imp_|_ort foo")
ref = refactor.Refactor(self.project_root, filename)
options = ref.get_refactor_options(offset)
self.assertTrue(any(opt['name'] == "refactor_froms_to_imports"
for opt in options))
class TestGetChanges(RefactorTestCase):
def test_should_fail_if_method_is_not_refactoring(self):
filename, offset = self.create_file("foo.py")
ref = refactor.Refactor(self.project_root, filename)
self.assertRaises(ValueError, ref.get_changes, "bad_name")
def test_should_return_method_results(self):
filename, offset = self.create_file("foo.py")
ref = refactor.Refactor(self.project_root, filename)
with mock.patch.object(ref, 'refactor_extract_method') as test:
test.return_value = "Meep!"
self.assertEqual(ref.get_changes("refactor_extract_method",
1, 2),
"Meep!")
test.assert_called_with(1, 2)
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestIsOnSymbol(RefactorTestCase):
def test_should_find_symbol(self):
filename, offset = self.create_file("test.py", "__B_|_AR = 100")
r = refactor.Refactor(self.project_root, filename)
self.assertTrue(r._is_on_symbol(offset))
# Issue #111
def test_should_find_symbol_with_underscores(self):
filename, offset = self.create_file("test.py", "_|___BAR = 100")
r = refactor.Refactor(self.project_root, filename)
self.assertTrue(r._is_on_symbol(offset))
def test_should_not_find_weird_places(self):
filename, offset = self.create_file("test.py", "hello = _|_ 1 + 1")
r = refactor.Refactor(self.project_root, filename)
self.assertFalse(r._is_on_symbol(offset))
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestFromsToImports(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"""\
_|_from datetime import datetime
d = datetime(2013, 4, 7)
""")
ref = refactor.Refactor(self.project_root, filename)
(change,) = ref.get_changes("refactor_froms_to_imports", offset)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], filename)
self.assertSourceEqual(change['contents'],
"""\
import datetime
d = datetime.datetime(2013, 4, 7)
""")
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestOrganizeImports(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"""\
import unittest, base64
import datetime, json
obj = json.dumps(23)
unittest.TestCase()
""")
ref = refactor.Refactor(self.project_root, filename)
(change,) = ref.get_changes("refactor_organize_imports")
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], filename)
self.assertSourceEqual(change['contents'],
"""\
import json
import unittest
obj = json.dumps(23)
unittest.TestCase()
""")
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestModuleToPackage(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"_|_import os\n")
ref = refactor.Refactor(self.project_root, filename)
changes = ref.refactor_module_to_package()
a, b, c = changes
# Not sure why the a change is there. It's a CHANGE that
# changes nothing...
self.assertEqual(a['diff'], '')
self.assertEqual(b['action'], 'create')
self.assertEqual(b['type'], 'directory')
self.assertEqual(b['path'], os.path.join(self.project_root, "foo"))
self.assertEqual(c['action'], 'move')
self.assertEqual(c['type'], 'file')
self.assertEqual(c['source'], os.path.join(self.project_root,
"foo.py"))
self.assertEqual(c['destination'], os.path.join(self.project_root,
"foo/__init__.py"))
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestRenameAtPoint(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"""\
class Foo(object):
def _|_foo(self):
return 5
def bar(self):
return self.foo()
""")
file2, offset2 = self.create_file(
"bar.py",
"""\
import foo
x = foo.Foo()
x.foo()""")
ref = refactor.Refactor(self.project_root, filename)
first, second = ref.refactor_rename_at_point(offset, "frob",
in_hierarchy=False,
docs=False)
if first['file'] == filename:
a, b = first, second
else:
a, b = second, first
self.assertEqual(a['action'], 'change')
self.assertEqual(a['file'], filename)
self.assertSourceEqual(a['contents'],
"""\
class Foo(object):
def frob(self):
return 5
def bar(self):
return self.frob()
""")
self.assertEqual(b['action'], 'change')
self.assertEqual(b['file'], file2)
self.assertSourceEqual(b['contents'],
"""\
import foo
x = foo.Foo()
x.frob()""")
def test_should_refactor_in_hierarchy(self):
filename, offset = self.create_file(
"foo.py",
"""\
class Foo(object):
def _|_foo(self):
return 5
def bar(self):
return self.foo()
class Bar(Foo):
def foo(self):
return 42
class Baz(object):
def foo(self):
return 42
""")
file2, offset2 = self.create_file(
"bar.py",
"""\
import foo
x, y, z = foo.Foo(), foo.Bar(), foo.Baz()
x.foo()
y.foo()
z.foo()""")
ref = refactor.Refactor(self.project_root, filename)
first, second = ref.refactor_rename_at_point(offset, "frob",
in_hierarchy=True,
docs=False)
if first['file'] == filename:
a, b = first, second
else:
a, b = second, first
self.assertEqual(a['action'], 'change')
self.assertEqual(a['file'], filename)
self.assertSourceEqual(a['contents'],
"""\
class Foo(object):
def frob(self):
return 5
def bar(self):
return self.frob()
class Bar(Foo):
def frob(self):
return 42
class Baz(object):
def foo(self):
return 42
""")
self.assertEqual(b['action'], 'change')
self.assertEqual(b['file'], file2)
self.assertSourceEqual(b['contents'],
"""\
import foo
x, y, z = foo.Foo(), foo.Bar(), foo.Baz()
x.frob()
y.frob()
z.foo()""")
def test_should_refactor_in_docstrings(self):
filename, offset = self.create_file(
"foo.py",
"""\
class Foo(object):
"Frobnicate the foo"
def _|_foo(self):
return 5
print("I'm an unrelated foo")
""")
ref = refactor.Refactor(self.project_root, filename)
(change,) = ref.refactor_rename_at_point(offset, "frob",
in_hierarchy=False,
docs=True)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], filename)
self.assertSourceEqual(change['contents'],
"""\
class Foo(object):
"Frobnicate the frob"
def frob(self):
return 5
print("I'm an unrelated foo")
""")
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestRenameCurrentModule(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"_|_import os\n")
file2, offset = self.create_file(
"bar.py",
"""\
_|_import foo
foo.os
""")
dest = os.path.join(self.project_root, "frob.py")
ref = refactor.Refactor(self.project_root, filename)
a, b = ref.refactor_rename_current_module("frob")
self.assertEqual(a['action'], 'change')
self.assertEqual(a['file'], file2)
self.assertEqual(a['contents'],
"import frob\n"
"frob.os\n")
self.assertEqual(b['action'], 'move')
self.assertEqual(b['type'], 'file')
self.assertEqual(b['source'], filename)
self.assertEqual(b['destination'], dest)
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestMoveModule(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"_|_import os\n")
file2, offset = self.create_file(
"bar.py",
"""\
_|_import foo
foo.os
""")
dest = os.path.join(self.project_root, "frob")
os.mkdir(dest)
with open(os.path.join(dest, "__init__.py"), "w") as f:
f.write("")
ref = refactor.Refactor(self.project_root, filename)
a, b = ref.refactor_move_module(dest)
self.assertEqual(a['action'], 'change')
self.assertEqual(a['file'], file2)
self.assertSourceEqual(a['contents'],
"""\
import frob.foo
frob.foo.os
""")
self.assertEqual(b['action'], 'move')
self.assertEqual(b['type'], 'file')
self.assertEqual(b['source'], filename)
self.assertEqual(b['destination'],
os.path.join(dest, "foo.py"))
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestCreateInline(RefactorTestCase):
def setUp(self):
super(TestCreateInline, self).setUp()
self.filename, self.offset = self.create_file(
"foo.py",
"""\
def add(a, b):
return a + b
x = _|_add(2, 3)
y = add(17, 4)
""")
def test_should_refactor_single_occurrenc(self):
ref = refactor.Refactor(self.project_root, self.filename)
(change,) = ref.refactor_create_inline(self.offset, True)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], self.filename)
self.assertSourceEqual(change['contents'],
"""\
def add(a, b):
return a + b
x = 2 + 3
y = add(17, 4)
""")
def test_should_refactor_all_occurrencs(self):
ref = refactor.Refactor(self.project_root, self.filename)
(change,) = ref.refactor_create_inline(self.offset, False)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], self.filename)
self.assertSourceEqual(change['contents'],
"""\
x = 2 + 3
y = 17 + 4
""")
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestExtractMethod(RefactorTestCase):
def setUp(self):
super(TestExtractMethod, self).setUp()
self.filename, self.offset = self.create_file(
"foo.py",
"""\
class Foo(object):
def spaghetti(self, a, b):
_|_x = a + 5
y = b + 23
return y
""")
@unittest.skipIf(sys.version_info >= (3, 5), "Python 3.5 not supported")
def test_should_refactor_local(self):
ref = refactor.Refactor(self.project_root, self.filename)
(change,) = ref.refactor_extract_method(self.offset, 104,
"calc", False)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], self.filename)
expected = """\
class Foo(object):
def spaghetti(self, a, b):
return self.calc(a, b)
def calc(self, a, b):
x = a + 5
y = b + 23
return y
"""
expected2 = expected.replace("return self.calc(a, b)",
"return self.calc(b, a)")
expected2 = expected2.replace("def calc(self, a, b)",
"def calc(self, b, a)")
# This is silly, but it's what we got.
if change['contents'] == dedent(expected2):
self.assertSourceEqual(change['contents'], expected2)
else:
self.assertSourceEqual(change['contents'], expected)
@unittest.skipIf(sys.version_info >= (3, 5), "Python 3.5 not supported")
def test_should_refactor_global(self):
ref = refactor.Refactor(self.project_root, self.filename)
(change,) = ref.refactor_extract_method(self.offset, 104,
"calc", True)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], self.filename)
expected = """\
class Foo(object):
def spaghetti(self, a, b):
return calc(a, b)
def calc(a, b):
x = a + 5
y = b + 23
return y
"""
expected2 = expected.replace("return calc(a, b)",
"return calc(b, a)")
expected2 = expected2.replace("def calc(a, b)",
"def calc(b, a)")
if change['contents'] == dedent(expected2):
self.assertSourceEqual(change['contents'], expected2)
else:
self.assertSourceEqual(change['contents'], expected)
@unittest.skipIf(not refactor.ROPE_AVAILABLE, "Requires Rope")
class TestUseFunction(RefactorTestCase):
def test_should_refactor(self):
filename, offset = self.create_file(
"foo.py",
"""\
def _|_add_and_multiply(a, b, c):
temp = a + b
return temp * c
f = 1 + 2
g = f * 3
""")
ref = refactor.Refactor(self.project_root, filename)
(change,) = ref.refactor_use_function(offset)
self.assertEqual(change['action'], 'change')
self.assertEqual(change['file'], filename)
self.assertSourceEqual(change['contents'],
"""\
def add_and_multiply(a, b, c):
temp = a + b
return temp * c
g = add_and_multiply(1, 2, 3)
""")

View File

@@ -0,0 +1,205 @@
"""Tests for elpy.ropebackend."""
import os
import shutil
import sys
import tempfile
import mock
from elpy import ropebackend
from elpy import rpc
from elpy.tests import compat
from elpy.tests.support import BackendTestCase
from elpy.tests.support import RPCGetCompletionsTests
from elpy.tests.support import RPCGetCompletionDocstringTests
from elpy.tests.support import RPCGetCompletionLocationTests
from elpy.tests.support import RPCGetDefinitionTests
from elpy.tests.support import RPCGetCalltipTests
from elpy.tests.support import RPCGetDocstringTests
class RopeBackendTestCase(BackendTestCase):
def setUp(self):
super(RopeBackendTestCase, self).setUp()
self.backend = ropebackend.RopeBackend(self.project_root)
class ShouldCallValidateTest(object):
def test_should_call_validate(self):
with mock.patch.object(self.backend, 'validate') as validate:
self.rpc(None, "", 0)
self.assertTrue(validate.called)
class TestInit(RopeBackendTestCase):
def test_should_have_rope_as_name(self):
self.assertEqual(self.backend.name, "rope")
def test_should_patch_project_files(self):
self.project_file("foo.txt", "")
self.project_file("baddir/file.py", "")
self.backend.project.validate()
actual = [f.real_path for f in
self.backend.project.file_list.get_files()]
self.assertEqual([os.path.join(self.project_root, "foo.txt")],
actual)
def test_should_fail_for_inexisting_project_root(self):
with self.assertRaises(rpc.Fault):
ropebackend.RopeBackend("/does/not/exist/")
class TestValidate(RopeBackendTestCase):
def test_should_call_validate_after_timeout(self):
with mock.patch("time.time") as t:
t.return_value = 10
self.backend.validate()
with mock.patch.object(self.backend, 'project') as project:
t.return_value = 10 + ropebackend.VALIDATE_EVERY_SECONDS + 1
self.backend.validate()
self.assertTrue(project.validate.called)
def test_should_not_call_validate_before_timeout(self):
with mock.patch("time.time") as t:
t.return_value = 10
self.backend.validate()
with mock.patch.object(self.backend, 'project') as project:
t.return_value = 10 + ropebackend.VALIDATE_EVERY_SECONDS - 1
self.backend.validate()
self.assertFalse(project.validate.called)
def test_should_not_fail_if_root_vanishes(self):
# Bug #353
tmpdir = tempfile.mkdtemp(prefix="elpy-test-validate-")
try:
backend = ropebackend.RopeBackend(tmpdir)
finally:
shutil.rmtree(tmpdir)
backend.validate()
class TestRPCGetCompletions(RPCGetCompletionsTests,
RopeBackendTestCase):
BUILTINS = ["object", "oct", "open", "or", "ord"]
class TestRPCGetCompletionDocstring(RPCGetCompletionDocstringTests,
RopeBackendTestCase):
pass
class TestRPCGetCompletionLocation(RPCGetCompletionLocationTests,
RopeBackendTestCase):
pass
class TestRPCGetDefinition(RPCGetDefinitionTests,
ShouldCallValidateTest,
RopeBackendTestCase):
pass
class TestRPCGetCalltip(RPCGetCalltipTests,
ShouldCallValidateTest,
RopeBackendTestCase):
ADD_CALLTIP = 'Add.add(a, b)'
RADIX_CALLTIP = "Decimal.radix()"
if compat.PYTHON3:
THREAD_CALLTIP = (
"threading.Thread(group=None, target=None, "
"name=None, args=(), kwargs=None, daemon=None, *)"
)
KEYS_CALLTIP = "builtins.keys()"
else:
THREAD_CALLTIP = (
"threading.Thread(group=None, target=None, "
"name=None, args=(), kwargs=None, verbose=None)"
)
KEYS_CALLTIP = "__builtin__.keys()"
class TestRPCGetDocstring(RPCGetDocstringTests,
ShouldCallValidateTest,
RopeBackendTestCase):
if sys.version_info < (2, 7):
JSON_LOADS_DOCSTRING = (
'loads(s, encoding=None, cls=None, object_hook=None, '
'parse_float=None, parse_int=None, parse_constant=None, '
'**kw):'
)
else:
JSON_LOADS_DOCSTRING = (
'loads(s, encoding=None, cls=None, object_hook=None, '
'parse_float=None, parse_int=None, parse_constant=None, '
'object_pairs_hook=None, **kw):'
)
class TestGetPythonProjectFiles(RopeBackendTestCase):
def test(self):
self.project_file("foo.txt", "")
self.project_file("gooddir/__init__.py", "")
self.project_file("gooddir/file.py", "")
self.project_file("baddir/file.py", "")
expected = set(os.path.join(self.project_root, name)
for name in ["foo.txt", "gooddir/__init__.py",
"gooddir/file.py"])
project = self.backend.project
actual = set(resource.real_path
for resource
in ropebackend.get_python_project_files(project))
self.assertEqual(expected, actual)
class TestPatchProjectFiles(RopeBackendTestCase):
def test(self):
self.project_file("foo.txt", "")
self.project_file("gooddir/__init__.py", "")
self.project_file("gooddir/file.py", "")
self.project_file("baddir/file.py", "")
expected = set(os.path.join(self.project_root, name)
for name in ["foo.txt", "gooddir/__init__.py",
"gooddir/file.py"])
actual = set(resource.real_path
for resource
in self.backend.project.get_files())
self.assertEqual(expected, actual)
class TestCallRope(RopeBackendTestCase):
def test_should_return_value(self):
func = mock.MagicMock()
func.return_value = 23
actual = self.backend.call_rope(
func, "foo.py", "", 0
)
self.assertEqual(23, actual)
def test_should_raise_fault_with_data_on_exception(self):
func = mock.MagicMock()
func.side_effect = RuntimeError("Stuff!")
func.__module__ = "rope.test"
func.__name__ = "test_function"
try:
self.backend.call_rope(
func, "foo.py", "", 0
)
except rpc.Fault as e:
self.assertEqual(500, e.code)
self.assertEqual("Stuff!", e.message)
self.assertIn("traceback", e.data)
self.assertIn("rope_debug_info", e.data)
self.assertEqual("rope.test.test_function",
e.data["rope_debug_info"]["function_name"])

View File

@@ -0,0 +1,209 @@
"""Tests for elpy.rpc."""
import json
import unittest
import sys
from elpy import rpc
from elpy.tests.compat import StringIO
class TestFault(unittest.TestCase):
def test_should_have_code_and_data(self):
fault = rpc.Fault("Hello", code=250, data="Fnord")
self.assertEqual(str(fault), "Hello")
self.assertEqual(fault.code, 250)
self.assertEqual(fault.data, "Fnord")
def test_should_have_defaults_for_code_and_data(self):
fault = rpc.Fault("Hello")
self.assertEqual(str(fault), "Hello")
self.assertEqual(fault.code, 500)
self.assertIsNone(fault.data)
class TestJSONRPCServer(unittest.TestCase):
def setUp(self):
self.stdin = StringIO()
self.stdout = StringIO()
self.rpc = rpc.JSONRPCServer(self.stdin, self.stdout)
def write(self, s):
self.stdin.seek(0)
self.stdin.truncate()
self.stdout.seek(0)
self.stdout.truncate()
self.stdin.write(s)
self.stdin.seek(0)
def read(self):
value = self.stdout.getvalue()
self.stdin.seek(0)
self.stdin.truncate()
self.stdout.seek(0)
self.stdout.truncate()
return value
class TestInit(TestJSONRPCServer):
def test_should_use_arguments(self):
self.assertEqual(self.rpc.stdin, self.stdin)
self.assertEqual(self.rpc.stdout, self.stdout)
def test_should_default_to_sys(self):
testrpc = rpc.JSONRPCServer()
self.assertEqual(sys.stdin, testrpc.stdin)
self.assertEqual(sys.stdout, testrpc.stdout)
class TestReadJson(TestJSONRPCServer):
def test_should_read_json(self):
objlist = [{'foo': 'bar'},
{'baz': 'qux', 'fnord': 'argl\nbargl'},
"beep\r\nbeep\r\nbeep"]
self.write("".join([(json.dumps(obj) + "\n")
for obj in objlist]))
for obj in objlist:
self.assertEqual(self.rpc.read_json(),
obj)
def test_should_raise_eof_on_eof(self):
self.assertRaises(EOFError, self.rpc.read_json)
def test_should_fail_on_malformed_json(self):
self.write("malformed json\n")
self.assertRaises(ValueError,
self.rpc.read_json)
class TestWriteJson(TestJSONRPCServer):
def test_should_write_json_line(self):
objlist = [{'foo': 'bar'},
{'baz': 'qux', 'fnord': 'argl\nbargl'},
]
for obj in objlist:
self.rpc.write_json(**obj)
self.assertEqual(json.loads(self.read()),
obj)
class TestHandleRequest(TestJSONRPCServer):
def test_should_fail_if_json_does_not_contain_a_method(self):
self.write(json.dumps(dict(params=[],
id=23)))
self.assertRaises(ValueError,
self.rpc.handle_request)
def test_should_call_right_method(self):
self.write(json.dumps(dict(method='foo',
params=[1, 2, 3],
id=23)))
self.rpc.rpc_foo = lambda *params: params
self.rpc.handle_request()
self.assertEqual(json.loads(self.read()),
dict(id=23,
result=[1, 2, 3]))
def test_should_pass_defaults_for_missing_parameters(self):
def test_method(*params):
self.args = params
self.write(json.dumps(dict(method='foo')))
self.rpc.rpc_foo = test_method
self.rpc.handle_request()
self.assertEqual(self.args, ())
self.assertEqual(self.read(), "")
def test_should_return_error_for_missing_method(self):
self.write(json.dumps(dict(method='foo',
id=23)))
self.rpc.handle_request()
result = json.loads(self.read())
self.assertEqual(result["id"], 23)
self.assertEqual(result["error"]["message"],
"Unknown method foo")
def test_should_return_error_for_exception_in_method(self):
def test_method():
raise ValueError("An error was raised")
self.write(json.dumps(dict(method='foo',
id=23)))
self.rpc.rpc_foo = test_method
self.rpc.handle_request()
result = json.loads(self.read())
self.assertEqual(result["id"], 23)
self.assertEqual(result["error"]["message"], "An error was raised")
self.assertIn("traceback", result["error"]["data"])
def test_should_not_include_traceback_for_faults(self):
def test_method():
raise rpc.Fault("This is a fault")
self.write(json.dumps(dict(method="foo",
id=23)))
self.rpc.rpc_foo = test_method
self.rpc.handle_request()
result = json.loads(self.read())
self.assertEqual(result["id"], 23)
self.assertEqual(result["error"]["message"], "This is a fault")
self.assertNotIn("traceback", result["error"])
def test_should_add_data_for_faults(self):
def test_method():
raise rpc.Fault("St. Andreas' Fault",
code=12345, data="Yippieh")
self.write(json.dumps(dict(method="foo", id=23)))
self.rpc.rpc_foo = test_method
self.rpc.handle_request()
result = json.loads(self.read())
self.assertEqual(result["error"]["data"], "Yippieh")
def test_should_call_handle_for_unknown_method(self):
def test_handle(method_name, args):
return "It works"
self.write(json.dumps(dict(method="doesnotexist",
id=23)))
self.rpc.handle = test_handle
self.rpc.handle_request()
self.assertEqual(json.loads(self.read()),
dict(id=23,
result="It works"))
class TestServeForever(TestJSONRPCServer):
def handle_request(self):
self.hr_called += 1
if self.hr_called > 10:
raise self.error()
def setUp(self):
super(TestServeForever, self).setUp()
self.hr_called = 0
self.error = KeyboardInterrupt
self.rpc.handle_request = self.handle_request
def test_should_call_handle_request_repeatedly(self):
self.rpc.serve_forever()
self.assertEqual(self.hr_called, 11)
def test_should_return_on_some_errors(self):
self.error = KeyboardInterrupt
self.rpc.serve_forever()
self.error = EOFError
self.rpc.serve_forever()
self.error = SystemExit
self.rpc.serve_forever()
def test_should_fail_on_most_errors(self):
self.error = RuntimeError
self.assertRaises(RuntimeError,
self.rpc.serve_forever)

View File

@@ -0,0 +1,441 @@
# coding: utf-8
"""Tests for the elpy.server module"""
import os
import tempfile
import unittest
import mock
from elpy import rpc
from elpy import server
from elpy.tests import compat
from elpy.tests.support import BackendTestCase
import elpy.refactor
class ServerTestCase(unittest.TestCase):
def setUp(self):
self.srv = server.ElpyRPCServer()
class BackendCallTestCase(ServerTestCase):
def assert_calls_backend(self, method):
with mock.patch("elpy.server.get_source") as get_source:
with mock.patch.object(self.srv, "backend") as backend:
get_source.return_value = "transformed source"
getattr(self.srv, method)("filename", "source", "offset")
get_source.assert_called_with("source")
getattr(backend, method).assert_called_with(
"filename", "transformed source", "offset"
)
class TestInit(ServerTestCase):
def test_should_not_select_a_backend_by_default(self):
self.assertIsNone(self.srv.backend)
class TestRPCEcho(ServerTestCase):
def test_should_return_arguments(self):
self.assertEqual(("hello", "world"),
self.srv.rpc_echo("hello", "world"))
class TestRPCInit(ServerTestCase):
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_set_project_root(self, RopeBackend, JediBackend):
self.srv.rpc_init({"project_root": "/project/root",
"backend": "rope"})
self.assertEqual("/project/root", self.srv.project_root)
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_initialize_rope(self, RopeBackend, JediBackend):
self.srv.rpc_init({"project_root": "/project/root",
"backend": "rope"})
RopeBackend.assert_called_with("/project/root")
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_initialize_jedi(self, RopeBackend, JediBackend):
self.srv.rpc_init({"project_root": "/project/root",
"backend": "jedi"})
JediBackend.assert_called_with("/project/root")
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_use_rope_if_available_and_requested(
self, RopeBackend, JediBackend):
RopeBackend.return_value.name = "rope"
JediBackend.return_value.name = "jedi"
self.srv.rpc_init({"project_root": "/project/root",
"backend": "rope"})
self.assertEqual("rope", self.srv.backend.name)
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_use_jedi_if_available_and_requested(
self, RopeBackend, JediBackend):
RopeBackend.return_value.name = "rope"
JediBackend.return_value.name = "jedi"
self.srv.rpc_init({"project_root": "/project/root",
"backend": "jedi"})
self.assertEqual("jedi", self.srv.backend.name)
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_use_rope_if_available_and_nothing_requested(
self, RopeBackend, JediBackend):
RopeBackend.return_value.name = "rope"
JediBackend.return_value.name = "jedi"
self.srv.rpc_init({"project_root": "/project/root",
"backend": None})
self.assertEqual("rope", self.srv.backend.name)
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_use_jedi_if_rope_not_available_and_nothing_requested(
self, RopeBackend, JediBackend):
RopeBackend.return_value.name = "rope"
JediBackend.return_value.name = "jedi"
old_rope = server.ropebackend
server.ropebackend = None
try:
self.srv.rpc_init({"project_root": "/project/root",
"backend": None})
finally:
server.ropebackend = old_rope
self.assertEqual("jedi", self.srv.backend.name)
@mock.patch("elpy.jedibackend.JediBackend")
@mock.patch("elpy.ropebackend.RopeBackend")
def test_should_use_none_if_nothing_available(
self, RopeBackend, JediBackend):
RopeBackend.return_value.name = "rope"
JediBackend.return_value.name = "jedi"
old_rope = server.ropebackend
old_jedi = server.jedibackend
server.ropebackend = None
server.jedibackend = None
try:
self.srv.rpc_init({"project_root": "/project/root",
"backend": None})
finally:
server.ropebackend = old_rope
server.jedibackend = old_jedi
self.assertIsNone(self.srv.backend)
class TestRPCGetCalltip(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_calltip")
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_calltip("filname", "source",
"offset"))
class TestRPCGetCompletions(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_completions")
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertEqual([],
self.srv.rpc_get_completions("filname", "source",
"offset"))
def test_should_sort_results(self):
with mock.patch.object(self.srv, 'backend') as backend:
backend.rpc_get_completions.return_value = [
{'name': '_e'},
{'name': '__d'},
{'name': 'c'},
{'name': 'B'},
{'name': 'a'},
]
expected = list(reversed(backend.rpc_get_completions.return_value))
actual = self.srv.rpc_get_completions("filename", "source",
"offset")
self.assertEqual(expected, actual)
def test_should_uniquify_results(self):
with mock.patch.object(self.srv, 'backend') as backend:
backend.rpc_get_completions.return_value = [
{'name': 'a'},
{'name': 'a'},
]
expected = [{'name': 'a'}]
actual = self.srv.rpc_get_completions("filename", "source",
"offset")
self.assertEqual(expected, actual)
class TestRPCGetCompletionDocs(ServerTestCase):
def test_should_call_backend(self):
with mock.patch.object(self.srv, "backend") as backend:
self.srv.rpc_get_completion_docstring("completion")
(backend.rpc_get_completion_docstring
.assert_called_with("completion"))
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_completion_docstring("foo"))
class TestRPCGetCompletionLocation(ServerTestCase):
def test_should_call_backend(self):
with mock.patch.object(self.srv, "backend") as backend:
self.srv.rpc_get_completion_location("completion")
(backend.rpc_get_completion_location
.assert_called_with("completion"))
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_completion_location("foo"))
class TestRPCGetDefinition(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_definition")
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_definition("filname", "source",
"offset"))
class TestRPCGetAssignment(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_assignment")
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_assignment("filname", "source",
"offset"))
class TestRPCGetDocstring(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_docstring")
def test_should_handle_no_backend(self):
self.srv.backend = None
self.assertIsNone(self.srv.rpc_get_docstring("filname", "source",
"offset"))
class TestRPCGetPydocCompletions(ServerTestCase):
@mock.patch.object(server, 'get_pydoc_completions')
def test_should_call_pydoc_completions(self, get_pydoc_completions):
srv = server.ElpyRPCServer()
srv.rpc_get_pydoc_completions()
get_pydoc_completions.assert_called_with(None)
srv.rpc_get_pydoc_completions("foo")
get_pydoc_completions.assert_called_with("foo")
class TestGetPydocDocumentation(ServerTestCase):
@mock.patch("pydoc.render_doc")
def test_should_find_documentation(self, render_doc):
render_doc.return_value = "expected"
actual = self.srv.rpc_get_pydoc_documentation("open")
render_doc.assert_called_with("open",
"Elpy Pydoc Documentation for %s",
False)
self.assertEqual("expected", actual)
def test_should_return_none_for_unknown_module(self):
actual = self.srv.rpc_get_pydoc_documentation("frob.open")
self.assertIsNone(actual)
def test_should_return_valid_unicode(self):
import json
docstring = self.srv.rpc_get_pydoc_documentation("tarfile")
json.dumps(docstring)
class TestRPCGetRefactorOptions(BackendTestCase):
@mock.patch.object(compat.builtins, '__import__')
def test_should_fail_if_rope_is_not_available(self, import_):
import_.side_effect = ImportError
filename = self.project_file("foo.py", "")
srv = server.ElpyRPCServer()
self.assertRaises(ImportError, srv.rpc_get_refactor_options,
filename, 0)
@mock.patch.object(elpy.refactor, 'Refactor')
def test_should_initialize_and_call_refactor_object(self, Refactor):
filename = self.project_file("foo.py", "import foo")
srv = server.ElpyRPCServer()
srv.project_root = self.project_root
srv.rpc_get_refactor_options(filename, 5)
Refactor.assert_called_with(self.project_root, filename)
Refactor.return_value.get_refactor_options.assert_called_with(5, None)
class TestRPCRefactor(BackendTestCase):
@mock.patch.object(compat.builtins, '__import__')
def test_should_fail_if_rope_is_not_available(self, import_):
import_.side_effect = ImportError
filename = self.project_file("foo.py", "")
srv = server.ElpyRPCServer()
self.assertRaises(ImportError, srv.rpc_refactor,
filename, 'foo', ())
@mock.patch.object(elpy.refactor, 'Refactor')
def test_should_initialize_and_call_refactor_object_with_args(
self, Refactor):
filename = self.project_file("foo.py", "import foo")
srv = server.ElpyRPCServer()
srv.project_root = self.project_root
srv.rpc_refactor(filename, 'foo', (1, 2, 3))
Refactor.assert_called_with(self.project_root, filename)
Refactor.return_value.get_changes.assert_called_with('foo', 1, 2, 3)
@mock.patch.object(elpy.refactor, 'Refactor')
def test_should_initialize_and_call_refactor_object_without_args(
self, Refactor):
filename = self.project_file("foo.py", "import foo")
srv = server.ElpyRPCServer()
srv.project_root = self.project_root
srv.rpc_refactor(filename, 'foo', None)
Refactor.assert_called_with(self.project_root, filename)
Refactor.return_value.get_changes.assert_called_with('foo')
class TestRPCGetUsages(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_usages")
def test_should_handle_no_backend(self):
self.srv.backend = None
with self.assertRaises(rpc.Fault):
self.assertIsNone(self.srv.rpc_get_usages("filname", "source",
"offset"))
class TestRPCGetNames(BackendCallTestCase):
def test_should_call_backend(self):
self.assert_calls_backend("rpc_get_names")
def test_should_handle_no_backend(self):
self.srv.backend = None
with self.assertRaises(rpc.Fault):
self.assertIsNone(self.srv.rpc_get_names("filname", "source", 0))
class TestRPCImportMagic(ServerTestCase):
def test_should_call_importmagic(self):
with mock.patch.object(self.srv, "import_magic") as impmagic:
self.srv.rpc_get_import_symbols("filename", "source", "os")
impmagic.get_import_symbols.assert_called_with("os")
self.srv.rpc_add_import("filename", "source", "import os")
impmagic.add_import.assert_called_with("source", "import os")
self.srv.rpc_get_unresolved_symbols("filename", "source")
impmagic.get_unresolved_symbols.assert_called_with("source")
self.srv.rpc_remove_unreferenced_imports("filename", "source")
impmagic.remove_unreferenced_imports.assert_called_with("source")
class TestGetSource(unittest.TestCase):
def test_should_return_string_by_default(self):
self.assertEqual(server.get_source("foo"),
"foo")
def test_should_return_file_contents(self):
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
self.addCleanup(os.remove, filename)
with open(filename, "w") as f:
f.write("file contents")
fileobj = {'filename': filename}
self.assertEqual(server.get_source(fileobj),
"file contents")
def test_should_clean_up_tempfile(self):
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
with open(filename, "w") as f:
f.write("file contents")
fileobj = {'filename': filename,
'delete_after_use': True}
self.assertEqual(server.get_source(fileobj),
"file contents")
self.assertFalse(os.path.exists(filename))
def test_should_support_utf8(self):
fd, filename = tempfile.mkstemp(prefix="elpy-test-")
self.addCleanup(os.remove, filename)
with open(filename, "wb") as f:
f.write(u"möp".encode("utf-8"))
source = server.get_source({'filename': filename})
self.assertEqual(source, u"möp")
class TestPysymbolKey(BackendTestCase):
def keyLess(self, a, b):
self.assertLess(b, a)
self.assertLess(server._pysymbol_key(a),
server._pysymbol_key(b))
def test_should_be_case_insensitive(self):
self.keyLess("bar", "Foo")
def test_should_sort_private_symbols_after_public_symbols(self):
self.keyLess("foo", "_bar")
def test_should_sort_private_symbols_after_dunder_symbols(self):
self.assertLess(server._pysymbol_key("__foo__"),
server._pysymbol_key("_bar"))
def test_should_sort_dunder_symbols_after_public_symbols(self):
self.keyLess("bar", "__foo")
class Autopep8TestCase(ServerTestCase):
def test_rpc_fix_code_should_return_formatted_string(self):
code_block = 'x= 123\n'
new_block = self.srv.rpc_fix_code(code_block)
self.assertEqual(new_block, 'x = 123\n')

View File

@@ -0,0 +1,19 @@
"""Tests for elpy.tests.support. Yep, we test test code."""
import unittest
from elpy.tests.support import source_and_offset
class TestSourceAndOffset(unittest.TestCase):
def test_should_return_source_and_offset(self):
self.assertEqual(source_and_offset("hello, _|_world"),
("hello, world", 7))
def test_should_handle_beginning_of_string(self):
self.assertEqual(source_and_offset("_|_hello, world"),
("hello, world", 0))
def test_should_handle_end_of_string(self):
self.assertEqual(source_and_offset("hello, world_|_"),
("hello, world", 12))

View File

@@ -0,0 +1,32 @@
# coding: utf-8
"""Tests for the elpy.yapf module"""
import unittest
from elpy import yapfutil
from elpy.rpc import Fault
from elpy.tests.support import BackendTestCase
@unittest.skipIf(yapfutil.YAPF_NOT_SUPPORTED,
'yapf not supported for current python version')
class YAPFTestCase(BackendTestCase):
def setUp(self):
if yapfutil.YAPF_NOT_SUPPORTED:
raise unittest.SkipTest
def test_fix_code_should_throw_error_for_invalid_code(self):
src = 'x = '
self.assertRaises(Fault, yapfutil.fix_code, src)
def test_fix_code(self):
testdata = [
('x= 123\n', 'x = 123\n'),
('x=1; \ny=2 \n', 'x = 1\ny = 2\n'),
]
for src, expected in testdata:
self._assert_format(src, expected)
def _assert_format(self, src, expected):
new_block = yapfutil.fix_code(src)
self.assertEqual(new_block, expected)