"""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): pass 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"])