Files
jedi/test/regression.py
2013-03-01 00:23:13 +04:30

428 lines
15 KiB
Python
Executable File

#!/usr/bin/env python
"""
Unit tests to avoid errors of the past. Makes use of Python's ``unittest``
module.
"""
# -*- coding: utf-8 -*-
import unittest
import time
import functools
import itertools
import os
from base import TestBase
import jedi
from jedi._compatibility import is_py25, utf8, unicode
from jedi import api
#jedi.set_debug_function(jedi.debug.print_to_stdout)
class TestRegression(TestBase):
def test_star_import_cache_duration(self):
new = 0.01
old, jedi.settings.star_import_cache_validity = \
jedi.settings.star_import_cache_validity, new
cache = api.cache
cache.star_import_cache = {} # first empty...
# path needs to be not-None (otherwise caching effects are not visible)
jedi.Script('', 1, 0, '').complete()
time.sleep(2 * new)
jedi.Script('', 1, 0, '').complete()
# reset values
jedi.settings.star_import_cache_validity = old
length = len(cache.star_import_cache)
cache.star_import_cache = {}
self.assertEqual(length, 1)
def test_part_parser(self):
""" test the function_definition speedups """
s = '\n' * 100 + 'abs('
pos = 101, 4
self.function_definition(s, pos)
assert self.function_definition(s, pos)
def test_definition_cursor(self):
s = ("class A():\n"
" def _something(self):\n"
" return\n"
" def different_line(self,\n"
" b):\n"
" return\n"
"A._something\n"
"A.different_line"
)
in_name = 2, 9
under_score = 2, 8
cls = 2, 7
should1 = 7, 10
diff_line = 4, 10
should2 = 8, 10
get_def = lambda pos: [d.description for d in self.definition(s, pos)]
in_name = get_def(in_name)
under_score = get_def(under_score)
should1 = get_def(should1)
should2 = get_def(should2)
diff_line = get_def(diff_line)
assert should1 == in_name
assert should1 == under_score
assert should2 == diff_line
self.assertRaises(jedi.NotFoundError, get_def, cls)
def test_keyword_doc(self):
r = list(self.definition("or", (1, 1)))
assert len(r) == 1
if not is_py25:
assert len(r[0].doc) > 100
r = list(self.definition("asfdasfd", (1, 1)))
assert len(r) == 0
def test_operator_doc(self):
r = list(self.definition("a == b", (1, 3)))
assert len(r) == 1
if not is_py25:
assert len(r[0].doc) > 100
def test_function_call_signature(self):
defs = self.definition("""
def f(x, y=1, z='a'):
pass
f""")
doc = defs[0].doc
assert "f(x, y = 1, z = 'a')" in doc
def test_class_call_signature(self):
defs = self.definition("""
class Foo:
def __init__(self, x, y=1, z='a'):
pass
Foo""")
doc = defs[0].doc
assert "Foo(self, x, y = 1, z = 'a')" in doc
def test_definition_at_zero(self):
assert self.definition("a", (1, 1)) == []
s = self.definition("str", (1, 1))
assert len(s) == 1
assert list(s)[0].description == 'class str'
assert self.definition("", (1, 0)) == []
def test_complete_at_zero(self):
s = self.complete("str", (1, 3))
assert len(s) == 1
assert list(s)[0].word == 'str'
s = self.complete("", (1, 0))
assert len(s) > 0
def test_definition_on_import(self):
assert self.definition("import sys_blabla", (1, 8)) == []
assert len(self.definition("import sys", (1, 8))) == 1
def test_complete_on_empty_import(self):
# should just list the files in the directory
assert 10 < len(self.complete("from .", path='')) < 30
assert 10 < len(self.complete("from . import", (1, 5), '')) < 30
assert 10 < len(self.complete("from . import classes",
(1, 5), '')) < 30
assert len(self.complete("import")) == 0
assert len(self.complete("import import", path='')) > 0
# 111
assert self.complete("from datetime import")[0].word == 'import'
assert self.complete("from datetime import ")
def test_function_definition(self):
def check(call_def, name, index):
return call_def and call_def.call_name == name \
and call_def.index == index
# simple
s = "abs(a, str("
s2 = "abs(), "
s3 = "abs()."
# more complicated
s4 = 'abs(zip(), , set,'
s5 = "abs(1,\nif 2:\n def a():"
s6 = "str().center("
s7 = "str().upper().center("
s8 = "str(int[zip("
assert check(self.function_definition(s, (1, 4)), 'abs', 0)
assert check(self.function_definition(s, (1, 6)), 'abs', 1)
assert check(self.function_definition(s, (1, 7)), 'abs', 1)
assert check(self.function_definition(s, (1, 8)), 'abs', 1)
assert check(self.function_definition(s, (1, 11)), 'str', 0)
assert check(self.function_definition(s2, (1, 4)), 'abs', 0)
assert self.function_definition(s2, (1, 5)) is None
assert self.function_definition(s2) is None
assert self.function_definition(s3, (1, 5)) is None
assert self.function_definition(s3) is None
assert self.function_definition(s4, (1, 3)) is None
assert check(self.function_definition(s4, (1, 4)), 'abs', 0)
assert check(self.function_definition(s4, (1, 8)), 'zip', 0)
assert check(self.function_definition(s4, (1, 9)), 'abs', 0)
#assert check(self.function_definition(s4, (1, 10)), 'abs', 1)
assert check(self.function_definition(s5, (1, 4)), 'abs', 0)
assert check(self.function_definition(s5, (1, 6)), 'abs', 1)
assert check(self.function_definition(s6), 'center', 0)
assert check(self.function_definition(s6, (1, 4)), 'str', 0)
assert check(self.function_definition(s7), 'center', 0)
assert check(self.function_definition(s8), 'zip', 0)
assert check(self.function_definition(s8, (1, 8)), 'str', 0)
s = "import time; abc = time; abc.sleep("
assert check(self.function_definition(s), 'sleep', 0)
# jedi-vim #9
s = "with open("
assert check(self.function_definition(s), 'open', 0)
# jedi-vim #11
s1 = "for sorted("
assert check(self.function_definition(s1), 'sorted', 0)
s2 = "for s in sorted("
assert check(self.function_definition(s2), 'sorted', 0)
# jedi #57
s = "def func(alpha, beta): pass\n" \
"func(alpha='101',"
assert check(self.function_definition(s, (2, 13)), 'func', 0)
def test_function_definition_complex(self):
def check(call_def, name, index):
return call_def and call_def.call_name == name \
and call_def.index == index
s = """
def abc(a,b):
pass
def a(self):
abc(
if 1:
pass
"""
assert check(self.function_definition(s, (6, 24)), 'abc', 0)
s = """
import re
def huhu(it):
re.compile(
return it * 2
"""
assert check(self.function_definition(s, (4, 31)), 'compile', 0)
# jedi-vim #70
s = """def foo("""
assert self.function_definition(s) is None
def test_add_dynamic_mods(self):
api.settings.additional_dynamic_modules = ['dynamic.py']
# Fictional module that defines a function.
src1 = "def ret(a): return a"
# Other fictional modules in another place in the fs.
src2 = 'from .. import setup; setup.ret(1)'
# .parser to load the module
api.modules.Module(os.path.abspath('dynamic.py'), src2).parser
script = jedi.Script(src1, 1, len(src1), '../setup.py')
result = script.definition()
assert len(result) == 1
assert result[0].description == 'class int'
def test_named_import(self):
""" named import - jedi-vim issue #8 """
s = "import time as dt"
assert len(jedi.Script(s, 1, 15, '/').definition()) == 1
assert len(jedi.Script(s, 1, 10, '/').definition()) == 1
def test_unicode_script(self):
""" normally no unicode objects are being used. (<=2.7) """
s = unicode("import datetime; datetime.timedelta")
completions = self.complete(s)
assert len(completions)
assert type(completions[0].description) is unicode
s = utf8("author='öä'; author")
completions = self.complete(s)
x = completions[0].description
assert type(x) is unicode
s = utf8("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author")
s = s.encode('latin-1')
completions = self.complete(s)
assert type(completions[0].description) is unicode
def test_multibyte_script(self):
""" `jedi.Script` must accept multi-byte string source. """
try:
code = unicode("import datetime; datetime.d")
comment = utf8("# multi-byte comment あいうえおä")
s = (unicode('%s\n%s') % (code, comment)).encode('utf-8')
except NameError:
pass # python 3 has no unicode method
else:
assert len(self.complete(s, (1, len(code))))
def test_unicode_attribute(self):
""" github jedi-vim issue #94 """
s1 = utf8('#-*- coding: utf-8 -*-\nclass Person():\n name = "e"\n\nPerson().name.')
completions1 = self.complete(s1)
assert 'strip' in [c.word for c in completions1]
s2 = utf8('#-*- coding: utf-8 -*-\nclass Person():\n name = "é"\n\nPerson().name.')
completions2 = self.complete(s2)
assert 'strip' in [c.word for c in completions2]
def test_os_nowait(self):
""" github issue #45 """
s = self.complete("import os; os.P_")
assert 'P_NOWAIT' in [i.word for i in s]
def test_follow_definition(self):
""" github issue #45 """
c = self.complete("from datetime import timedelta; timedelta")
# type can also point to import, but there will be additional
# attributes
objs = itertools.chain.from_iterable(r.follow_definition() for r in c)
types = [o.type for o in objs]
assert 'Import' not in types and 'Class' in types
def test_keyword_definition_doc(self):
""" github jedi-vim issue #44 """
defs = self.definition("print")
assert [d.doc for d in defs]
defs = self.definition("import")
assert len(defs) == 1
assert [d.doc for d in defs]
def test_goto_following_on_imports(self):
if is_py25:
return
g = self.goto("import multiprocessing.dummy; multiprocessing.dummy")
assert len(g) == 1
assert g[0].start_pos != (0, 0)
def test_points_in_completion(self):
"""At some point, points were inserted into the completions, this
caused problems, sometimes.
"""
c = self.complete("if IndentationErr")
assert c[0].word == 'IndentationError'
self.assertEqual(c[0].complete, 'or')
def test_docstrings_type_str(self):
s = """
def func(arg):
'''
:type arg: str
'''
arg."""
words = [c.word for c in self.complete(s)]
assert 'join' in words
def test_docstrings_type_dotted_import(self):
s = """
def func(arg):
'''
:type arg: threading.Thread
'''
arg."""
words = [c.word for c in self.complete(s)]
assert 'start' in words
class TestFeature(TestBase):
def test_full_name(self):
""" feature request #61"""
assert self.complete('import os; os.path.join')[0].full_name \
== 'os.path.join'
# issue #94
defs = self.definition("""import os; os.path.join(""")
assert defs[0].full_name is None
def test_full_name_builtin(self):
self.assertEqual(self.complete('type')[0].full_name, 'type')
def test_full_name_tuple_mapping(self):
s = """
import re
any_re = re.compile('.*')
any_re"""
self.assertEqual(self.definition(s)[0].full_name, 're.RegexObject')
def test_quick_completion(self):
sources = [
('import json; json.l', (1, 19)),
('import json; json.l ', (1, 19)),
('import json\njson.l', (2, 6)),
('import json\njson.l ', (2, 6)),
('import json\njson.l\n\n', (2, 6)),
('import json\njson.l \n\n', (2, 6)),
('import json\njson.l \n \n\n', (2, 6)),
]
for source, pos in sources:
# Run quick_complete
quick_completions = api._quick_complete(source)
# Run real completion
script = jedi.Script(source, pos[0], pos[1], '')
real_completions = script.complete()
# Compare results
quick_values = [(c.full_name, c.line, c.column) for c in quick_completions]
real_values = [(c.full_name, c.line, c.column) for c in real_completions]
self.assertEqual(quick_values, real_values)
class TestSpeed(TestBase):
def _check_speed(time_per_run, number=4, run_warm=True):
""" Speed checks should typically be very tolerant. Some machines are
faster than others, but the tests should still pass. These tests are
here to assure that certain effects that kill jedi performance are not
reintroduced to Jedi."""
def decorated(func):
@functools.wraps(func)
def wrapper(self):
if run_warm:
func(self)
first = time.time()
for i in range(number):
func(self)
single_time = (time.time() - first) / number
print('\nspeed', func, single_time)
assert single_time < time_per_run
return wrapper
return decorated
@_check_speed(0.1)
def test_os_path_join(self):
s = "from posixpath import join; join('', '')."
assert len(self.complete(s)) > 10 # is a str completion
@_check_speed(0.1)
def test_scipy_speed(self):
s = 'import scipy.weave; scipy.weave.inline('
script = jedi.Script(s, 1, len(s), '')
script.function_definition()
#print(jedi.imports.imports_processed)
if __name__ == '__main__':
unittest.main()