mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-02 02:03:21 +08:00
Merge branch 'refactor'
This commit is contained in:
@@ -473,7 +473,7 @@ def test_func():
|
||||
#? int()
|
||||
tuple({1})[0]
|
||||
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
# -----------------
|
||||
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
||||
# -----------------
|
||||
|
||||
@@ -242,7 +242,7 @@ def x():
|
||||
# yield from
|
||||
# -----------------
|
||||
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
|
||||
def yield_from():
|
||||
yield from iter([1])
|
||||
|
||||
@@ -12,6 +12,8 @@ def from_names_goto():
|
||||
def builtin_test():
|
||||
#? ['math']
|
||||
import math
|
||||
#? ['mmap']
|
||||
import mmap
|
||||
|
||||
# -----------------
|
||||
# completions within imports
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
""" Pep-0484 type hinting """
|
||||
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
|
||||
|
||||
class A():
|
||||
|
||||
@@ -283,7 +283,7 @@ def testnewtype2(y):
|
||||
y
|
||||
#? []
|
||||
y.
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
|
||||
class TestDefaultDict(typing.DefaultDict[str, int]):
|
||||
def setdud(self):
|
||||
@@ -311,7 +311,7 @@ for key in x.keys():
|
||||
for value in x.values():
|
||||
#? int()
|
||||
value
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
|
||||
|
||||
"""
|
||||
@@ -341,9 +341,8 @@ typing.Optional[0]
|
||||
|
||||
TYPE_VARX = typing.TypeVar('TYPE_VARX')
|
||||
TYPE_VAR_CONSTRAINTSX = typing.TypeVar('TYPE_VAR_CONSTRAINTSX', str, int)
|
||||
# TODO there should at least be some results.
|
||||
#? []
|
||||
TYPE_VARX.
|
||||
#? ['__class__']
|
||||
TYPE_VARX.__clas
|
||||
#! ["TYPE_VARX = typing.TypeVar('TYPE_VARX')"]
|
||||
TYPE_VARX
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ def test_p(monkeypatch):
|
||||
#? ['setattr']
|
||||
monkeypatch.setatt
|
||||
|
||||
# python > 3.4
|
||||
# python > 2.7
|
||||
|
||||
#? ['capsysbinary']
|
||||
def test_p(capsysbin
|
||||
|
||||
@@ -359,7 +359,7 @@ class Test(metaclass=Meta):
|
||||
# Enum
|
||||
# -----------------
|
||||
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
import enum
|
||||
|
||||
class X(enum.Enum):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# python >= 3.4
|
||||
# python > 2.7
|
||||
from stub_folder import with_stub, stub_only, with_stub_folder, stub_only_folder
|
||||
|
||||
# -------------------------
|
||||
|
||||
@@ -76,9 +76,11 @@ def pytest_generate_tests(metafunc):
|
||||
|
||||
if 'refactor_case' in metafunc.fixturenames:
|
||||
base_dir = metafunc.config.option.refactor_case_dir
|
||||
cases = list(refactor.collect_dir_tests(base_dir, test_files))
|
||||
metafunc.parametrize(
|
||||
'refactor_case',
|
||||
refactor.collect_dir_tests(base_dir, test_files))
|
||||
'refactor_case', cases,
|
||||
ids=[c.refactor_type + '-' + c.name for c in cases]
|
||||
)
|
||||
|
||||
if 'static_analysis_case' in metafunc.fixturenames:
|
||||
base_dir = os.path.join(os.path.dirname(__file__), 'static_analysis')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import sys
|
||||
sys.path[0:0] = [
|
||||
'/usr/lib/python3.4/site-packages',
|
||||
'/usr/lib/python3.8/site-packages',
|
||||
'/tmp/.buildout/eggs/important_package.egg'
|
||||
]
|
||||
|
||||
|
||||
Binary file not shown.
BIN
test/examples/init_extension_module/__init__.cpython-38-x86_64-linux-gnu.so
Executable file
BIN
test/examples/init_extension_module/__init__.cpython-38-x86_64-linux-gnu.so
Executable file
Binary file not shown.
116
test/refactor.py
Executable file → Normal file
116
test/refactor.py
Executable file → Normal file
@@ -1,99 +1,103 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Refactoring tests work a little bit similar to Black Box tests. But the idea is
|
||||
here to compare two versions of code. **Note: Refactoring is currently not in
|
||||
active development (and was never stable), the tests are therefore not really
|
||||
valuable - just ignore them.**
|
||||
Refactoring tests work a little bit similar to integration tests. But the idea
|
||||
is here to compare two versions of code. If you want to add a new test case,
|
||||
just look at the existing ones in the ``test/refactor`` folder and copy them.
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
|
||||
from parso import split_lines
|
||||
|
||||
from functools import reduce
|
||||
import jedi
|
||||
from jedi import refactoring
|
||||
from .helpers import test_dir
|
||||
|
||||
|
||||
class RefactoringCase(object):
|
||||
|
||||
def __init__(self, name, source, line_nr, index, path,
|
||||
new_name, start_line_test, desired):
|
||||
def __init__(self, name, code, line_nr, index, path, kwargs, type_, desired_result):
|
||||
self.name = name
|
||||
self.source = source
|
||||
self.line_nr = line_nr
|
||||
self.index = index
|
||||
self.path = path
|
||||
self.new_name = new_name
|
||||
self.start_line_test = start_line_test
|
||||
self.desired = desired
|
||||
self._code = code
|
||||
self._line_nr = line_nr
|
||||
self._index = index
|
||||
self._path = path
|
||||
self._kwargs = kwargs
|
||||
self.type = type_
|
||||
self._desired_result = desired_result
|
||||
|
||||
def refactor(self):
|
||||
script = jedi.Script(self.source, self.line_nr, self.index, self.path)
|
||||
f_name = os.path.basename(self.path)
|
||||
refactor_func = getattr(refactoring, f_name.replace('.py', ''))
|
||||
args = (self.new_name,) if self.new_name else ()
|
||||
return refactor_func(script, *args)
|
||||
def get_desired_result(self):
|
||||
|
||||
def run(self):
|
||||
refactor_object = self.refactor()
|
||||
if platform.system().lower() == 'windows' and self.type == 'diff':
|
||||
# Windows uses backslashes to separate paths.
|
||||
lines = split_lines(self._desired_result, keepends=True)
|
||||
for i, line in enumerate(lines):
|
||||
if re.search(' import_tree/', line):
|
||||
lines[i] = line.replace('/', '\\')
|
||||
return ''.join(lines)
|
||||
return self._desired_result
|
||||
|
||||
# try to get the right excerpt of the newfile
|
||||
f = refactor_object.new_files()[self.path]
|
||||
lines = f.splitlines()[self.start_line_test:]
|
||||
@property
|
||||
def refactor_type(self):
|
||||
f_name = os.path.basename(self._path)
|
||||
return f_name.replace('.py', '')
|
||||
|
||||
end = self.start_line_test + len(lines)
|
||||
pop_start = None
|
||||
for i, l in enumerate(lines):
|
||||
if l.startswith('# +++'):
|
||||
end = i
|
||||
break
|
||||
elif '#? ' in l:
|
||||
pop_start = i
|
||||
lines.pop(pop_start)
|
||||
self.result = '\n'.join(lines[:end - 1]).strip()
|
||||
return self.result
|
||||
|
||||
def check(self):
|
||||
return self.run() == self.desired
|
||||
def refactor(self, environment):
|
||||
project = jedi.Project(os.path.join(test_dir, 'refactor'))
|
||||
script = jedi.Script(self._code, path=self._path, project=project, environment=environment)
|
||||
refactor_func = getattr(script, self.refactor_type)
|
||||
return refactor_func(self._line_nr, self._index, **self._kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s: %s:%s>' % (self.__class__.__name__,
|
||||
self.name, self.line_nr - 1)
|
||||
self.name, self._line_nr - 1)
|
||||
|
||||
|
||||
def collect_file_tests(source, path, lines_to_execute):
|
||||
r = r'^# --- ?([^\n]*)\n((?:(?!\n# \+\+\+).)*)' \
|
||||
r'\n# \+\+\+((?:(?!\n# ---).)*)'
|
||||
for match in re.finditer(r, source, re.DOTALL | re.MULTILINE):
|
||||
def _collect_file_tests(code, path, lines_to_execute):
|
||||
r = r'^# -{5,} ?([^\n]*)\n((?:(?!\n# \+{5,}).)*\n)' \
|
||||
r'# \+{5,}\n((?:(?!\n# -{5,}).)*\n)'
|
||||
match = None
|
||||
for match in re.finditer(r, code, re.DOTALL | re.MULTILINE):
|
||||
name = match.group(1).strip()
|
||||
first = match.group(2).strip()
|
||||
second = match.group(3).strip()
|
||||
start_line_test = source[:match.start()].count('\n') + 1
|
||||
first = match.group(2)
|
||||
second = match.group(3)
|
||||
|
||||
# get the line with the position of the operation
|
||||
p = re.match(r'((?:(?!#\?).)*)#\? (\d*) ?([^\n]*)', first, re.DOTALL)
|
||||
p = re.match(r'((?:(?!#\?).)*)#\? (\d*)( error| text|) ?([^\n]*)', first, re.DOTALL)
|
||||
if p is None:
|
||||
print("Please add a test start.")
|
||||
raise Exception("Please add a test start.")
|
||||
continue
|
||||
until = p.group(1)
|
||||
index = int(p.group(2))
|
||||
new_name = p.group(3)
|
||||
type_ = p.group(3).strip() or 'diff'
|
||||
if p.group(4):
|
||||
kwargs = eval(p.group(4))
|
||||
else:
|
||||
kwargs = {}
|
||||
|
||||
line_nr = start_line_test + until.count('\n') + 2
|
||||
line_nr = until.count('\n') + 2
|
||||
if lines_to_execute and line_nr - 1 not in lines_to_execute:
|
||||
continue
|
||||
|
||||
yield RefactoringCase(name, source, line_nr, index, path,
|
||||
new_name, start_line_test, second)
|
||||
yield RefactoringCase(name, first, line_nr, index, path, kwargs, type_, second)
|
||||
if match is None:
|
||||
raise Exception("Didn't match any test")
|
||||
if match.end() != len(code):
|
||||
raise Exception("Didn't match until the end of the file in %s" % path)
|
||||
|
||||
|
||||
def collect_dir_tests(base_dir, test_files):
|
||||
if sys.version_info[0] == 2:
|
||||
return
|
||||
for f_name in os.listdir(base_dir):
|
||||
files_to_execute = [a for a in test_files.items() if a[0] in f_name]
|
||||
lines_to_execute = reduce(lambda x, y: x + y[1], files_to_execute, [])
|
||||
if f_name.endswith(".py") and (not test_files or files_to_execute):
|
||||
path = os.path.join(base_dir, f_name)
|
||||
with open(path) as f:
|
||||
source = f.read()
|
||||
for case in collect_file_tests(source, path, lines_to_execute):
|
||||
with open(path, newline='') as f:
|
||||
code = f.read()
|
||||
for case in _collect_file_tests(code, path, lines_to_execute):
|
||||
yield case
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# --- simple
|
||||
def test():
|
||||
#? 35 a
|
||||
return test(100, (30 + b, c) + 1)
|
||||
|
||||
# +++
|
||||
def test():
|
||||
a = (30 + b, c) + 1
|
||||
return test(100, a)
|
||||
|
||||
|
||||
# --- simple #2
|
||||
def test():
|
||||
#? 25 a
|
||||
return test(100, (30 + b, c) + 1)
|
||||
|
||||
# +++
|
||||
def test():
|
||||
a = 30 + b
|
||||
return test(100, (a, c) + 1)
|
||||
|
||||
|
||||
# --- multiline
|
||||
def test():
|
||||
#? 30 x
|
||||
return test(1, (30 + b, c)
|
||||
+ 1)
|
||||
# +++
|
||||
def test():
|
||||
x = ((30 + b, c)
|
||||
+ 1)
|
||||
return test(1, x
|
||||
)
|
||||
|
||||
|
||||
# --- multiline #2
|
||||
def test():
|
||||
#? 25 x
|
||||
return test(1, (30 + b, c)
|
||||
+ 1)
|
||||
# +++
|
||||
def test():
|
||||
x = 30 + b
|
||||
return test(1, (x, c)
|
||||
+ 1)
|
||||
|
||||
|
||||
447
test/refactor/extract_function.py
Normal file
447
test/refactor/extract_function.py
Normal file
@@ -0,0 +1,447 @@
|
||||
# -------------------------------------------------- in-module-1
|
||||
glob = 3
|
||||
#? 11 text {'new_name': 'a'}
|
||||
test(100, (glob.a + b, c) + 1)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob = 3
|
||||
#? 11 text {'new_name': 'a'}
|
||||
def a(b):
|
||||
return glob.a + b
|
||||
|
||||
|
||||
test(100, (a(b), c) + 1)
|
||||
# -------------------------------------------------- in-module-2
|
||||
#? 0 text {'new_name': 'ab'}
|
||||
100 + 1 * 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 0 text {'new_name': 'ab'}
|
||||
def ab():
|
||||
return 100 + 1 * 2
|
||||
|
||||
|
||||
ab()
|
||||
# -------------------------------------------------- in-function-1
|
||||
def f(x):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return x + 1 * 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def ab(x):
|
||||
return x + 1 * 2
|
||||
|
||||
|
||||
def f(x):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return ab(x)
|
||||
# -------------------------------------------------- in-function-with-dec
|
||||
@classmethod
|
||||
def f(x):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return x + 1 * 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def ab(x):
|
||||
return x + 1 * 2
|
||||
|
||||
|
||||
@classmethod
|
||||
def f(x):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return ab(x)
|
||||
# -------------------------------------------------- in-method-1
|
||||
class X:
|
||||
def z(self): pass
|
||||
|
||||
def f(x, b):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return x + b * 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
class X:
|
||||
def z(self): pass
|
||||
|
||||
def ab(x, b):
|
||||
return x + b * 2
|
||||
|
||||
def f(x, b):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return x.ab(b)
|
||||
# -------------------------------------------------- in-method-2
|
||||
glob1 = 1
|
||||
class X:
|
||||
def g(self): pass
|
||||
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return self.g() or self.f(b) ^ glob1 & b
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob1 = 1
|
||||
class X:
|
||||
def g(self): pass
|
||||
|
||||
def ab(self, b):
|
||||
return self.g() or self.f(b) ^ glob1 & b
|
||||
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab'}
|
||||
return self.ab(b)
|
||||
# -------------------------------------------------- in-method-order
|
||||
class X:
|
||||
def f(self, b, c):
|
||||
#? 18 text {'new_name': 'b'}
|
||||
return b | self.a
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
class X:
|
||||
def b(self, b):
|
||||
return b | self.a
|
||||
|
||||
def f(self, b, c):
|
||||
#? 18 text {'new_name': 'b'}
|
||||
return self.b(b)
|
||||
# -------------------------------------------------- in-classmethod-1
|
||||
class X:
|
||||
@classmethod
|
||||
def f(x):
|
||||
#? 16 text {'new_name': 'ab'}
|
||||
return 25
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
class X:
|
||||
@classmethod
|
||||
def ab(x):
|
||||
return 25
|
||||
|
||||
@classmethod
|
||||
def f(x):
|
||||
#? 16 text {'new_name': 'ab'}
|
||||
return x.ab()
|
||||
# -------------------------------------------------- in-staticmethod-1
|
||||
class X(int):
|
||||
@staticmethod
|
||||
def f(x):
|
||||
#? 16 text {'new_name': 'ab'}
|
||||
return 25 | 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def ab():
|
||||
return 25 | 3
|
||||
|
||||
class X(int):
|
||||
@staticmethod
|
||||
def f(x):
|
||||
#? 16 text {'new_name': 'ab'}
|
||||
return ab()
|
||||
# -------------------------------------------------- in-class-1
|
||||
class Ya():
|
||||
a = 3
|
||||
#? 11 text {'new_name': 'f'}
|
||||
c = a + 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def f(a):
|
||||
return a + 2
|
||||
|
||||
|
||||
class Ya():
|
||||
a = 3
|
||||
#? 11 text {'new_name': 'f'}
|
||||
c = f(a)
|
||||
# -------------------------------------------------- in-closure
|
||||
def x(z):
|
||||
def y(x):
|
||||
#? 15 text {'new_name': 'f'}
|
||||
return -x * z
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def f(x, z):
|
||||
return -x * z
|
||||
|
||||
|
||||
def x(z):
|
||||
def y(x):
|
||||
#? 15 text {'new_name': 'f'}
|
||||
return f(x, z)
|
||||
# -------------------------------------------------- with-range-1
|
||||
#? 0 text {'new_name': 'a', 'until_line': 4}
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x = test(v1 + v2 * v3)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 0 text {'new_name': 'a', 'until_line': 4}
|
||||
def a(test, v3):
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x = test(v1 + v2 * v3)
|
||||
return x
|
||||
|
||||
|
||||
x = a(test, v3)
|
||||
# -------------------------------------------------- with-range-2
|
||||
#? 2 text {'new_name': 'a', 'until_line': 6, 'until_column': 4}
|
||||
#foo
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x, y = test(v1 + v2 * v3)
|
||||
#raaaa
|
||||
y
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 2 text {'new_name': 'a', 'until_line': 6, 'until_column': 4}
|
||||
def a(test, v3):
|
||||
#foo
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x, y = test(v1 + v2 * v3)
|
||||
#raaaa
|
||||
return y
|
||||
|
||||
|
||||
y = a(test, v3)
|
||||
y
|
||||
# -------------------------------------------------- with-range-3
|
||||
#foo
|
||||
#? 2 text {'new_name': 'a', 'until_line': 5, 'until_column': 4}
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x, y = test(v1 + v2 * v3)
|
||||
#raaaa
|
||||
y
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#foo
|
||||
#? 2 text {'new_name': 'a', 'until_line': 5, 'until_column': 4}
|
||||
def a(test, v3):
|
||||
v1 = 3
|
||||
v2 = 2
|
||||
x, y = test(v1 + v2 * v3)
|
||||
return y
|
||||
|
||||
|
||||
y = a(test, v3)
|
||||
#raaaa
|
||||
y
|
||||
# -------------------------------------------------- with-range-func-1
|
||||
import os
|
||||
# comment1
|
||||
@dec
|
||||
# comment2
|
||||
def x(v1):
|
||||
#foo
|
||||
#? 2 text {'new_name': 'a', 'until_line': 9, 'until_column': 5}
|
||||
v2 = 2
|
||||
if 1:
|
||||
x, y = os.listdir(v1 + v2 * v3)
|
||||
#bar
|
||||
return x, y
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
import os
|
||||
# comment1
|
||||
def a(v1, v3):
|
||||
v2 = 2
|
||||
if 1:
|
||||
x, y = os.listdir(v1 + v2 * v3)
|
||||
return x, y
|
||||
|
||||
|
||||
@dec
|
||||
# comment2
|
||||
def x(v1):
|
||||
#foo
|
||||
#? 2 text {'new_name': 'a', 'until_line': 9, 'until_column': 5}
|
||||
x, y = a(v1, v3)
|
||||
#bar
|
||||
return x, y
|
||||
# -------------------------------------------------- with-range-func-2
|
||||
import os
|
||||
# comment1
|
||||
# comment2
|
||||
def x(v1):
|
||||
#? 2 text {'new_name': 'a', 'until_line': 10, 'until_column': 0}
|
||||
#foo
|
||||
v2 = 2
|
||||
if 1:
|
||||
x, y = os.listdir(v1 + v2 * v3)
|
||||
#bar
|
||||
return y
|
||||
x
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
import os
|
||||
# comment1
|
||||
# comment2
|
||||
def a(v1, v3):
|
||||
#foo
|
||||
v2 = 2
|
||||
if 1:
|
||||
x, y = os.listdir(v1 + v2 * v3)
|
||||
#bar
|
||||
return y
|
||||
|
||||
|
||||
def x(v1):
|
||||
#? 2 text {'new_name': 'a', 'until_line': 10, 'until_column': 0}
|
||||
y = a(v1, v3)
|
||||
return y
|
||||
x
|
||||
# -------------------------------------------------- with-range-func-3
|
||||
def x(v1):
|
||||
#? 2 text {'new_name': 'func', 'until_line': 6, 'until_column': 4}
|
||||
#foo
|
||||
v2 = 2
|
||||
x = v1 * 2
|
||||
y = 3
|
||||
#bar
|
||||
return x
|
||||
x
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def func(v1):
|
||||
#foo
|
||||
v2 = 2
|
||||
x = v1 * 2
|
||||
return x
|
||||
|
||||
|
||||
def x(v1):
|
||||
#? 2 text {'new_name': 'func', 'until_line': 6, 'until_column': 4}
|
||||
x = func(v1)
|
||||
y = 3
|
||||
#bar
|
||||
return x
|
||||
x
|
||||
# -------------------------------------------------- in-class-range-1
|
||||
class X1:
|
||||
#? 11 text {'new_name': 'f', 'until_line': 4}
|
||||
a = 3
|
||||
c = a + 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def f():
|
||||
a = 3
|
||||
c = a + 2
|
||||
return c
|
||||
|
||||
|
||||
class X1:
|
||||
#? 11 text {'new_name': 'f', 'until_line': 4}
|
||||
c = f()
|
||||
# -------------------------------------------------- in-method-range-1
|
||||
glob1 = 1
|
||||
class X:
|
||||
# ha
|
||||
def g(self): pass
|
||||
|
||||
# haha
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 12, 'until_column': 28}
|
||||
#foo
|
||||
local1 = 3
|
||||
local2 = 4
|
||||
x= self.g() or self.f(b) ^ glob1 & b is local1
|
||||
# bar
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob1 = 1
|
||||
class X:
|
||||
# ha
|
||||
def g(self): pass
|
||||
|
||||
# haha
|
||||
def ab(self, b):
|
||||
#foo
|
||||
local1 = 3
|
||||
local2 = 4
|
||||
x= self.g() or self.f(b) ^ glob1 & b is local1
|
||||
return x
|
||||
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 12, 'until_column': 28}
|
||||
x = self.ab(b)
|
||||
# bar
|
||||
# -------------------------------------------------- in-method-range-2
|
||||
glob1 = 1
|
||||
class X:
|
||||
# comment
|
||||
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 11, 'until_column': 10}
|
||||
#foo
|
||||
local1 = 3
|
||||
local2 = 4
|
||||
return local1 * glob1 * b
|
||||
# bar
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob1 = 1
|
||||
class X:
|
||||
# comment
|
||||
|
||||
def ab(self, b):
|
||||
#foo
|
||||
local1 = 3
|
||||
local2 = 4
|
||||
return local1 * glob1 * b
|
||||
# bar
|
||||
|
||||
def f(self, b, c):
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 11, 'until_column': 10}
|
||||
return self.ab(b)
|
||||
# -------------------------------------------------- in-method-range-3
|
||||
glob1 = 1
|
||||
class X:
|
||||
def f(self, b, c):
|
||||
local1, local2 = 3, 4
|
||||
#foo
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 7, 'until_column': 29}
|
||||
return local1 & glob1 & b
|
||||
# bar
|
||||
local2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob1 = 1
|
||||
class X:
|
||||
def ab(self, local1, b):
|
||||
return local1 & glob1 & b
|
||||
|
||||
def f(self, b, c):
|
||||
local1, local2 = 3, 4
|
||||
#foo
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 7, 'until_column': 29}
|
||||
return self.ab(local1, b)
|
||||
# bar
|
||||
local2
|
||||
# -------------------------------------------------- in-method-no-param
|
||||
glob1 = 1
|
||||
class X:
|
||||
def f():
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 5, 'until_column': 22}
|
||||
return glob1 + 2
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
glob1 = 1
|
||||
class X:
|
||||
def ab():
|
||||
return glob1 + 2
|
||||
|
||||
def f():
|
||||
#? 11 text {'new_name': 'ab', 'until_line': 5, 'until_column': 22}
|
||||
return ab()
|
||||
# -------------------------------------------------- random-return-1
|
||||
def x():
|
||||
#? 0 error {'new_name': 'ab', 'until_line': 5, 'until_column': 10}
|
||||
if x:
|
||||
return 1
|
||||
return 1
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Can only extract return statements if they are at the end.
|
||||
# -------------------------------------------------- random-return-2
|
||||
def x():
|
||||
#? 0 error {'new_name': 'ab', 'until_line': 5, 'until_column': 10}
|
||||
#
|
||||
return
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Can only extract return statements if they are at the end.
|
||||
# -------------------------------------------------- random-yield-1
|
||||
def x():
|
||||
#? 0 error {'new_name': 'ab', 'until_line': 5, 'until_column': 10}
|
||||
#
|
||||
if (yield 1):
|
||||
return
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract yield statements.
|
||||
# -------------------------------------------------- random-yield-2
|
||||
def x():
|
||||
#? 0 error {'new_name': 'ab', 'until_line': 4, 'until_column': 10}
|
||||
#
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract yield statements.
|
||||
251
test/refactor/extract_variable.py
Normal file
251
test/refactor/extract_variable.py
Normal file
@@ -0,0 +1,251 @@
|
||||
# -------------------------------------------------- simple-1
|
||||
def test():
|
||||
#? 35 text {'new_name': 'a'}
|
||||
return test(100, (30 + b, c) + 1)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def test():
|
||||
#? 35 text {'new_name': 'a'}
|
||||
a = (30 + b, c) + 1
|
||||
return test(100, a)
|
||||
# -------------------------------------------------- simple-2
|
||||
def test():
|
||||
#? 25 text {'new_name': 'a'}
|
||||
return test(100, (30 + b, c) + 1)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def test():
|
||||
#? 25 text {'new_name': 'a'}
|
||||
a = 30 + b
|
||||
return test(100, (a, c) + 1)
|
||||
# -------------------------------------------------- simple-3
|
||||
#? 13 text {'new_name': 'zzx.x'}
|
||||
test(100, {1 |1: 2 + 3})
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 13 text {'new_name': 'zzx.x'}
|
||||
zzx.x = 1 |1
|
||||
test(100, {zzx.x: 2 + 3})
|
||||
# -------------------------------------------------- multiline-1
|
||||
def test():
|
||||
#? 30 text {'new_name': 'x'}
|
||||
return test(1, (30 + b, c)
|
||||
+ 1)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def test():
|
||||
#? 30 text {'new_name': 'x'}
|
||||
x = (30 + b, c)
|
||||
+ 1
|
||||
return test(1, x)
|
||||
# -------------------------------------------------- multiline-2
|
||||
def test():
|
||||
#? 25 text {'new_name': 'x'}
|
||||
return test(1, (30 + b, c)
|
||||
+ 1)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
def test():
|
||||
#? 25 text {'new_name': 'x'}
|
||||
x = 30 + b
|
||||
return test(1, (x, c)
|
||||
+ 1)
|
||||
# -------------------------------------------------- for-param-error-1
|
||||
#? 10 error {'new_name': 'x'}
|
||||
def test(p1):
|
||||
return
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a name that defines something
|
||||
# -------------------------------------------------- for-param-error-2
|
||||
#? 12 error {'new_name': 'x'}
|
||||
def test(p1= 3):
|
||||
return
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "param"
|
||||
# -------------------------------------------------- for-param-1
|
||||
#? 12 text {'new_name': 'x'}
|
||||
def test(p1=20):
|
||||
return
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 12 text {'new_name': 'x'}
|
||||
x = 20
|
||||
def test(p1=x):
|
||||
return
|
||||
# -------------------------------------------------- for-something
|
||||
#? 12 text {'new_name': 'x'}
|
||||
def test(p1=20):
|
||||
return
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 12 text {'new_name': 'x'}
|
||||
x = 20
|
||||
def test(p1=x):
|
||||
return
|
||||
# -------------------------------------------------- class-inheritance-1
|
||||
#? 12 text {'new_name': 'x'}
|
||||
class Foo(foo.Bar):
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 12 text {'new_name': 'x'}
|
||||
x = foo.Bar
|
||||
class Foo(x):
|
||||
pass
|
||||
# -------------------------------------------------- class-inheritance-2
|
||||
#? 16 text {'new_name': 'x'}
|
||||
class Foo(foo.Bar):
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 16 text {'new_name': 'x'}
|
||||
x = foo.Bar
|
||||
class Foo(x):
|
||||
pass
|
||||
# -------------------------------------------------- keyword-pass
|
||||
#? 12 error {'new_name': 'x'}
|
||||
def x(): pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "simple_stmt"
|
||||
# -------------------------------------------------- keyword-continue
|
||||
#? 5 error {'new_name': 'x'}
|
||||
continue
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "simple_stmt"
|
||||
# -------------------------------------------------- keyword-None
|
||||
if 1:
|
||||
#? 4 text {'new_name': 'x'}
|
||||
None
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
if 1:
|
||||
#? 4 text {'new_name': 'x'}
|
||||
x = None
|
||||
x
|
||||
# -------------------------------------------------- with-tuple
|
||||
#? 4 text {'new_name': 'x'}
|
||||
x + 1, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 4 text {'new_name': 'x'}
|
||||
x = x + 1
|
||||
x, 3
|
||||
# -------------------------------------------------- range-1
|
||||
#? 4 text {'new_name': 'x', 'until_column': 9}
|
||||
y + 1, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 4 text {'new_name': 'x', 'until_column': 9}
|
||||
x = y + 1, 3
|
||||
x
|
||||
# -------------------------------------------------- range-2
|
||||
#? 1 text {'new_name': 'x', 'until_column': 3}
|
||||
y + 1, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 1 text {'new_name': 'x', 'until_column': 3}
|
||||
x = y + 1
|
||||
x, 3
|
||||
# -------------------------------------------------- range-3
|
||||
#? 1 text {'new_name': 'x', 'until_column': 6}
|
||||
y + 1, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 1 text {'new_name': 'x', 'until_column': 6}
|
||||
x = y + 1
|
||||
x, 3
|
||||
# -------------------------------------------------- range-4
|
||||
#? 1 text {'new_name': 'x', 'until_column': 1}
|
||||
y + 1, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 1 text {'new_name': 'x', 'until_column': 1}
|
||||
x = y
|
||||
x + 1, 3
|
||||
# -------------------------------------------------- addition-1
|
||||
#? 4 text {'new_name': 'x', 'until_column': 9}
|
||||
z = y + 1 + 2+ 3, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 4 text {'new_name': 'x', 'until_column': 9}
|
||||
x = y + 1
|
||||
z = x + 2+ 3, 3
|
||||
# -------------------------------------------------- addition-2
|
||||
#? 8 text {'new_name': 'x', 'until_column': 12}
|
||||
z = y +1 + 2+ 3, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 8 text {'new_name': 'x', 'until_column': 12}
|
||||
x = 1 + 2
|
||||
z = y +x+ 3, 3
|
||||
# -------------------------------------------------- addition-3
|
||||
#? 10 text {'new_name': 'x', 'until_column': 14}
|
||||
z = y + 1 + 2+ 3, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 10 text {'new_name': 'x', 'until_column': 14}
|
||||
x = 1 + 2+ 3
|
||||
z = y + x, 3
|
||||
# -------------------------------------------------- addition-4
|
||||
#? 13 text {'new_name': 'x', 'until_column': 17}
|
||||
z = y + (1 + 2)+ 3, 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 13 text {'new_name': 'x', 'until_column': 17}
|
||||
x = (1 + 2)+ 3
|
||||
z = y + x, 3
|
||||
# -------------------------------------------------- mult-add-1
|
||||
#? 8 text {'new_name': 'x', 'until_column': 11}
|
||||
z = foo(y+1*2+3, 3)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 8 text {'new_name': 'x', 'until_column': 11}
|
||||
x = y+1
|
||||
z = foo(x*2+3, 3)
|
||||
# -------------------------------------------------- mult-add-2
|
||||
#? 12 text {'new_name': 'x', 'until_column': 15}
|
||||
z = foo(y+1*2+3)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 12 text {'new_name': 'x', 'until_column': 15}
|
||||
x = 2+3
|
||||
z = foo(y+1*x)
|
||||
# -------------------------------------------------- mult-add-3
|
||||
#? 9 text {'new_name': 'x', 'until_column': 13}
|
||||
z = (y+1*2+3)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 9 text {'new_name': 'x', 'until_column': 13}
|
||||
x = (y+1*2+3)
|
||||
z = x
|
||||
# -------------------------------------------------- extract-weird-1
|
||||
#? 0 error {'new_name': 'x', 'until_column': 7}
|
||||
foo = 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "expr_stmt"
|
||||
# -------------------------------------------------- extract-weird-2
|
||||
#? 0 error {'new_name': 'x', 'until_column': 5}
|
||||
def x():
|
||||
foo = 3
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "funcdef"
|
||||
# -------------------------------------------------- extract-weird-3
|
||||
def x():
|
||||
#? 4 error {'new_name': 'x', 'until_column': 8}
|
||||
if 1:
|
||||
pass
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a "if_stmt"
|
||||
# -------------------------------------------------- extract-weird-4
|
||||
#? 4 error {'new_name': 'x', 'until_column': 7}
|
||||
x = foo = 4
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot extract a name that defines something
|
||||
# -------------------------------------------------- keyword-None
|
||||
#? 4 text {'new_name': 'x', 'until_column': 7}
|
||||
yy = not foo or bar
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 4 text {'new_name': 'x', 'until_column': 7}
|
||||
x = not foo
|
||||
yy = x or bar
|
||||
# -------------------------------------------------- augassign
|
||||
yy = ()
|
||||
#? 6 text {'new_name': 'x', 'until_column': 10}
|
||||
yy += 3, 4
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
yy = ()
|
||||
#? 6 text {'new_name': 'x', 'until_column': 10}
|
||||
x = 3, 4
|
||||
yy += x
|
||||
# -------------------------------------------------- if-else
|
||||
#? 9 text {'new_name': 'x', 'until_column': 22}
|
||||
yy = foo(a if y else b)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 9 text {'new_name': 'x', 'until_column': 22}
|
||||
x = a if y else b
|
||||
yy = foo(x)
|
||||
# -------------------------------------------------- lambda
|
||||
#? 8 text {'new_name': 'x', 'until_column': 17}
|
||||
y = foo(lambda x: 3, 5)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
#? 8 text {'new_name': 'x', 'until_column': 17}
|
||||
x = lambda x: 3
|
||||
y = foo(x, 5)
|
||||
1
test/refactor/import_tree/inline_mod.py
Normal file
1
test/refactor/import_tree/inline_mod.py
Normal file
@@ -0,0 +1 @@
|
||||
inline_var = 5 + 3
|
||||
2
test/refactor/import_tree/pkgx/__init__.py
Normal file
2
test/refactor/import_tree/pkgx/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
def pkgx():
|
||||
pass
|
||||
1
test/refactor/import_tree/pkgx/__init__.pyi
Normal file
1
test/refactor/import_tree/pkgx/__init__.pyi
Normal file
@@ -0,0 +1 @@
|
||||
def pkgx() -> int: ...
|
||||
1
test/refactor/import_tree/pkgx/mod.pyi
Normal file
1
test/refactor/import_tree/pkgx/mod.pyi
Normal file
@@ -0,0 +1 @@
|
||||
from . import pkgx
|
||||
1
test/refactor/import_tree/pkgx/mod2.py
Normal file
1
test/refactor/import_tree/pkgx/mod2.py
Normal file
@@ -0,0 +1 @@
|
||||
from .. import pkgx
|
||||
1
test/refactor/import_tree/some_mod.py
Normal file
1
test/refactor/import_tree/some_mod.py
Normal file
@@ -0,0 +1 @@
|
||||
foobar = 3
|
||||
@@ -1,18 +1,243 @@
|
||||
# --- simple
|
||||
# -------------------------------------------------- no-name-error
|
||||
#? 0 error
|
||||
1
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
There is no name under the cursor
|
||||
# -------------------------------------------------- multi-equal-error
|
||||
def test():
|
||||
#? 4 error
|
||||
a = b = 3
|
||||
return test(100, a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a statement with multiple definitions
|
||||
# -------------------------------------------------- no-definition-error
|
||||
#? 5 error
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
No definition found to inline
|
||||
# -------------------------------------------------- multi-names-error
|
||||
#? 0 error
|
||||
a, b[1] = 3
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a statement with multiple definitions
|
||||
# -------------------------------------------------- addition-error
|
||||
#? 0 error
|
||||
a = 2
|
||||
a += 3
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a name with multiple definitions
|
||||
# -------------------------------------------------- only-addition-error
|
||||
#? 0 error
|
||||
a += 3
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a statement with "+="
|
||||
# -------------------------------------------------- with-annotation
|
||||
foobarb: int = 1
|
||||
#? 5
|
||||
test(foobarb)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-foobarb: int = 1
|
||||
#? 5
|
||||
-test(foobarb)
|
||||
+test(1)
|
||||
# -------------------------------------------------- only-annotation-error
|
||||
a: int
|
||||
#? 5 error
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a statement that is defined by an annotation
|
||||
# -------------------------------------------------- builtin
|
||||
import math
|
||||
#? 7 error
|
||||
math.cos
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline builtins/extensions
|
||||
# -------------------------------------------------- module-error
|
||||
from import_tree import inline_mod
|
||||
#? 11 error
|
||||
test(inline_mod)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline imports or modules
|
||||
# -------------------------------------------------- module-works
|
||||
from import_tree import inline_mod
|
||||
#? 22
|
||||
test(x, inline_mod. inline_var.conjugate)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- import_tree/inline_mod.py
|
||||
+++ import_tree/inline_mod.py
|
||||
@@ -1,2 +1 @@
|
||||
-inline_var = 5 + 3
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,4 @@
|
||||
from import_tree import inline_mod
|
||||
#? 22
|
||||
-test(x, inline_mod. inline_var.conjugate)
|
||||
+test(x, (5 + 3).conjugate)
|
||||
# -------------------------------------------------- class
|
||||
class A: pass
|
||||
#? 5 error
|
||||
test(A)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a class
|
||||
# -------------------------------------------------- function
|
||||
def foo(a):
|
||||
return a + 1
|
||||
#? 5 error
|
||||
test(foo(1))
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a function
|
||||
# -------------------------------------------------- for-stmt
|
||||
for x in []:
|
||||
#? 9 error
|
||||
test(x)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Cannot inline a for_stmt
|
||||
# -------------------------------------------------- simple
|
||||
def test():
|
||||
#? 4
|
||||
a = (30 + b, c) + 1
|
||||
return test(100, a)
|
||||
# +++
|
||||
def test():
|
||||
return test(100, (30 + b, c) + 1)
|
||||
|
||||
|
||||
# --- simple
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,5 +1,4 @@
|
||||
def test():
|
||||
#? 4
|
||||
- a = (30 + b, c) + 1
|
||||
- return test(100, a)
|
||||
+ return test(100, (30 + b, c) + 1)
|
||||
# -------------------------------------------------- tuple
|
||||
if 1:
|
||||
#? 4
|
||||
a = 1, 2
|
||||
return test(100, a)
|
||||
# +++
|
||||
if 1:
|
||||
return test(100, (1, 2))
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,5 +1,4 @@
|
||||
if 1:
|
||||
#? 4
|
||||
- a = 1, 2
|
||||
- return test(100, a)
|
||||
+ return test(100, (1, 2))
|
||||
# -------------------------------------------------- multiplication-add-parens1
|
||||
a = 1+2
|
||||
#? 11
|
||||
test(100 * a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-a = 1+2
|
||||
#? 11
|
||||
-test(100 * a)
|
||||
+test(100 * (1+2))
|
||||
# -------------------------------------------------- multiplication-add-parens2
|
||||
a = 1+2
|
||||
#? 11
|
||||
(x, 100 * a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-a = 1+2
|
||||
#? 11
|
||||
-(x, 100 * a)
|
||||
+(x, 100 * (1+2))
|
||||
# -------------------------------------------------- multiplication-add-parens3
|
||||
x
|
||||
a = 1+2
|
||||
#? 9
|
||||
(100 ** a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,5 +1,4 @@
|
||||
x
|
||||
-a = 1+2
|
||||
#? 9
|
||||
-(100 ** a)
|
||||
+(100 ** (1+2))
|
||||
# -------------------------------------------------- no-add-parens1
|
||||
x
|
||||
a = 1+2
|
||||
#? 5
|
||||
test(a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,5 +1,4 @@
|
||||
x
|
||||
-a = 1+2
|
||||
#? 5
|
||||
-test(a)
|
||||
+test(1+2)
|
||||
# -------------------------------------------------- no-add-parens2
|
||||
a = 1+2
|
||||
#? 9
|
||||
test(3, a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-a = 1+2
|
||||
#? 9
|
||||
-test(3, a)
|
||||
+test(3, 1+2)
|
||||
# -------------------------------------------------- no-add-parens3
|
||||
a = 1|2
|
||||
#? 5
|
||||
(3, a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-a = 1|2
|
||||
#? 5
|
||||
-(3, a)
|
||||
+(3, 1|2)
|
||||
# -------------------------------------------------- comment
|
||||
a = 1 and 2 # foo
|
||||
#? 9
|
||||
(3, 3 * a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-a = 1 and 2 # foo
|
||||
+ # foo
|
||||
#? 9
|
||||
-(3, 3 * a)
|
||||
+(3, 3 * (1 and 2))
|
||||
# -------------------------------------------------- semicolon
|
||||
a = 1, 2 ; b = 3
|
||||
#? 9
|
||||
(3, 3 == a)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-a = 1, 2 ; b = 3
|
||||
+ b = 3
|
||||
#? 9
|
||||
-(3, 3 == a)
|
||||
+(3, 3 == (1, 2))
|
||||
# -------------------------------------------------- no-tree-name
|
||||
a = 1 + 2
|
||||
#? 0
|
||||
a.conjugate
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- inline.py
|
||||
+++ inline.py
|
||||
@@ -1,4 +1,3 @@
|
||||
-a = 1 + 2
|
||||
#? 0
|
||||
-a.conjugate
|
||||
+(1 + 2).conjugate
|
||||
|
||||
@@ -3,15 +3,233 @@ Test coverage for renaming is mostly being done by testing
|
||||
`Script.get_references`.
|
||||
"""
|
||||
|
||||
# --- simple
|
||||
# -------------------------------------------------- no-name
|
||||
#? 0 error {'new_name': 'blabla'}
|
||||
1
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
There is no name under the cursor
|
||||
# -------------------------------------------------- simple
|
||||
def test1():
|
||||
#? 7 blabla
|
||||
#? 7 {'new_name': 'blabla'}
|
||||
test1()
|
||||
AssertionError
|
||||
return test1, test1.not_existing
|
||||
# +++
|
||||
def blabla():
|
||||
blabla()
|
||||
AssertionError
|
||||
return blabla, blabla.not_existing
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,6 +1,6 @@
|
||||
-def test1():
|
||||
+def blabla():
|
||||
#? 7 {'new_name': 'blabla'}
|
||||
- test1()
|
||||
+ blabla()
|
||||
AssertionError
|
||||
- return test1, test1.not_existing
|
||||
+ return blabla, blabla.not_existing
|
||||
# -------------------------------------------------- var-not-found
|
||||
undefined_var
|
||||
#? 0 {'new_name': 'lala'}
|
||||
undefined_var
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,4 +1,4 @@
|
||||
undefined_var
|
||||
#? 0 {'new_name': 'lala'}
|
||||
-undefined_var
|
||||
+lala
|
||||
# -------------------------------------------------- different-scopes
|
||||
def x():
|
||||
#? 7 {'new_name': 'v'}
|
||||
some_var = 3
|
||||
some_var
|
||||
def y():
|
||||
some_var = 3
|
||||
some_var
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,7 +1,7 @@
|
||||
def x():
|
||||
#? 7 {'new_name': 'v'}
|
||||
- some_var = 3
|
||||
- some_var
|
||||
+ v = 3
|
||||
+ v
|
||||
def y():
|
||||
some_var = 3
|
||||
some_var
|
||||
# -------------------------------------------------- keyword-param1
|
||||
#? 22 {'new_name': 'lala'}
|
||||
def mykeywordparam1(param1):
|
||||
str(param1)
|
||||
mykeywordparam1(1)
|
||||
mykeywordparam1(param1=3)
|
||||
mykeywordparam1(x, param1=2)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,7 +1,7 @@
|
||||
#? 22 {'new_name': 'lala'}
|
||||
-def mykeywordparam1(param1):
|
||||
- str(param1)
|
||||
+def mykeywordparam1(lala):
|
||||
+ str(lala)
|
||||
mykeywordparam1(1)
|
||||
-mykeywordparam1(param1=3)
|
||||
-mykeywordparam1(x, param1=2)
|
||||
+mykeywordparam1(lala=3)
|
||||
+mykeywordparam1(x, lala=2)
|
||||
# -------------------------------------------------- keyword-param2
|
||||
def mykeywordparam2(param1):
|
||||
str(param1)
|
||||
mykeywordparam2(1)
|
||||
mykeywordparam2(param1=3)
|
||||
#? 22 {'new_name': 'lala'}
|
||||
mykeywordparam2(x, param1=2)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,7 +1,7 @@
|
||||
-def mykeywordparam2(param1):
|
||||
- str(param1)
|
||||
+def mykeywordparam2(lala):
|
||||
+ str(lala)
|
||||
mykeywordparam2(1)
|
||||
-mykeywordparam2(param1=3)
|
||||
+mykeywordparam2(lala=3)
|
||||
#? 22 {'new_name': 'lala'}
|
||||
-mykeywordparam2(x, param1=2)
|
||||
+mykeywordparam2(x, lala=2)
|
||||
# -------------------------------------------------- import
|
||||
from import_tree.some_mod import foobar
|
||||
#? 0 {'new_name': 'renamed'}
|
||||
foobar
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- import_tree/some_mod.py
|
||||
+++ import_tree/some_mod.py
|
||||
@@ -1,2 +1,2 @@
|
||||
-foobar = 3
|
||||
+renamed = 3
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-from import_tree.some_mod import foobar
|
||||
+from import_tree.some_mod import renamed
|
||||
#? 0 {'new_name': 'renamed'}
|
||||
-foobar
|
||||
+renamed
|
||||
# -------------------------------------------------- module
|
||||
from import_tree import some_mod
|
||||
#? 0 {'new_name': 'renamedm'}
|
||||
some_mod
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
rename from import_tree/some_mod.py
|
||||
rename to import_tree/renamedm.py
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-from import_tree import some_mod
|
||||
+from import_tree import renamedm
|
||||
#? 0 {'new_name': 'renamedm'}
|
||||
-some_mod
|
||||
+renamedm
|
||||
# -------------------------------------------------- import-not-found
|
||||
#? 20 {'new_name': 'lala'}
|
||||
import undefined_import
|
||||
haha( undefined_import)
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,4 +1,4 @@
|
||||
#? 20 {'new_name': 'lala'}
|
||||
-import undefined_import
|
||||
-haha( undefined_import)
|
||||
+import lala
|
||||
+haha( lala)
|
||||
# -------------------------------------------------- in-package-with-stub
|
||||
#? 31 {'new_name': 'renamedm'}
|
||||
from import_tree.pkgx import pkgx
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
--- import_tree/pkgx/__init__.py
|
||||
+++ import_tree/pkgx/__init__.py
|
||||
@@ -1,3 +1,3 @@
|
||||
-def pkgx():
|
||||
+def renamedm():
|
||||
pass
|
||||
--- import_tree/pkgx/__init__.pyi
|
||||
+++ import_tree/pkgx/__init__.pyi
|
||||
@@ -1,2 +1,2 @@
|
||||
-def pkgx() -> int: ...
|
||||
+def renamedm() -> int: ...
|
||||
--- import_tree/pkgx/mod.pyi
|
||||
+++ import_tree/pkgx/mod.pyi
|
||||
@@ -1,2 +1,2 @@
|
||||
-from . import pkgx
|
||||
+from . import renamedm
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,3 +1,3 @@
|
||||
#? 31 {'new_name': 'renamedm'}
|
||||
-from import_tree.pkgx import pkgx
|
||||
+from import_tree.pkgx import renamedm
|
||||
# -------------------------------------------------- package-with-stub
|
||||
#? 18 {'new_name': 'renamedp'}
|
||||
from import_tree.pkgx
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
rename from import_tree/pkgx
|
||||
rename to import_tree/renamedp
|
||||
--- import_tree/pkgx/mod2.py
|
||||
+++ import_tree/renamedp/mod2.py
|
||||
@@ -1,2 +1,2 @@
|
||||
-from .. import pkgx
|
||||
+from .. import renamedp
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,3 +1,3 @@
|
||||
#? 18 {'new_name': 'renamedp'}
|
||||
-from import_tree.pkgx
|
||||
+from import_tree.renamedp
|
||||
# -------------------------------------------------- weird-package-mix
|
||||
if random_undefined_variable:
|
||||
from import_tree.pkgx import pkgx
|
||||
else:
|
||||
from import_tree import pkgx
|
||||
#? 4 {'new_name': 'rename'}
|
||||
pkgx
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
rename from import_tree/pkgx
|
||||
rename to import_tree/rename
|
||||
--- import_tree/pkgx/__init__.py
|
||||
+++ import_tree/rename/__init__.py
|
||||
@@ -1,3 +1,3 @@
|
||||
-def pkgx():
|
||||
+def rename():
|
||||
pass
|
||||
--- import_tree/pkgx/__init__.pyi
|
||||
+++ import_tree/rename/__init__.pyi
|
||||
@@ -1,2 +1,2 @@
|
||||
-def pkgx() -> int: ...
|
||||
+def rename() -> int: ...
|
||||
--- import_tree/pkgx/mod.pyi
|
||||
+++ import_tree/rename/mod.pyi
|
||||
@@ -1,2 +1,2 @@
|
||||
-from . import pkgx
|
||||
+from . import rename
|
||||
--- import_tree/pkgx/mod2.py
|
||||
+++ import_tree/rename/mod2.py
|
||||
@@ -1,2 +1,2 @@
|
||||
-from .. import pkgx
|
||||
+from .. import rename
|
||||
--- rename.py
|
||||
+++ rename.py
|
||||
@@ -1,7 +1,7 @@
|
||||
if random_undefined_variable:
|
||||
- from import_tree.pkgx import pkgx
|
||||
+ from import_tree.rename import rename
|
||||
else:
|
||||
- from import_tree import pkgx
|
||||
+ from import_tree import rename
|
||||
#? 4 {'new_name': 'rename'}
|
||||
-pkgx
|
||||
+rename
|
||||
|
||||
91
test/run.py
91
test/run.py
@@ -1,14 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|jedi| is mostly being tested by what I would call "Blackbox Tests". These
|
||||
tests are just testing the interface and do input/output testing. This makes a
|
||||
lot of sense for |jedi|. Jedi supports so many different code structures, that
|
||||
it is just stupid to write 200'000 unittests in the manner of
|
||||
``regression.py``. Also, it is impossible to do doctests/unittests on most of
|
||||
the internal data structures. That's why |jedi| uses mostly these kind of
|
||||
tests.
|
||||
|jedi| is mostly being tested by what I would call "integration tests". These
|
||||
tests are testing type inference with the public API. This makes a
|
||||
lot of sense for |jedi|. Also, it is hard to write doctests/unittests for
|
||||
the internal data structures.
|
||||
|
||||
There are different kind of tests:
|
||||
There are different kinds of tests:
|
||||
|
||||
- completions / inference ``#?``
|
||||
- goto: ``#!``
|
||||
@@ -18,29 +15,31 @@ How to run tests?
|
||||
+++++++++++++++++
|
||||
|
||||
Jedi uses pytest_ to run unit and integration tests. To run tests,
|
||||
simply run ``pytest``. You can also use tox_ to run tests for
|
||||
multiple Python versions.
|
||||
simply run ``pytest``.
|
||||
|
||||
.. _pytest: http://pytest.org
|
||||
.. _tox: http://testrun.org/tox
|
||||
|
||||
Integration test cases are located in ``test/completion`` directory
|
||||
and each test case is indicated by either the comment ``#?`` (completions /
|
||||
inference), ``#!`` (goto), or ``#<`` (references).
|
||||
Most integration test cases are located in the ``test/completion`` directory
|
||||
and each test case starts with one of these comments:
|
||||
|
||||
- ``#?`` (completions / inference)
|
||||
- ``#!`` (goto)
|
||||
- ``#<`` (references)
|
||||
|
||||
There is also support for third party libraries. In a normal test run they are
|
||||
not being executed, you have to provide a ``--thirdparty`` option.
|
||||
|
||||
In addition to standard `-k` and `-m` options in pytest, you can use the
|
||||
`-T` (`--test-files`) option to specify integration test cases to run.
|
||||
In addition to pytest's ``-k`` and ``-m`` options, you can use the
|
||||
``-T`` (``--test-files`) option to specify which test cases should run.
|
||||
It takes the format of ``FILE_NAME[:LINE[,LINE[,...]]]`` where
|
||||
``FILE_NAME`` is a file in ``test/completion`` and ``LINE`` is a line
|
||||
number of the test comment. Here is some recipes:
|
||||
number of the test comment. Here are some examples:
|
||||
|
||||
Run tests only in ``basic.py`` and ``imports.py``::
|
||||
Run tests only in ``completion/basic.py`` and ``completion/imports.py``::
|
||||
|
||||
pytest test/test_integration.py -T basic.py -T imports.py
|
||||
|
||||
Run test at line 4, 6, and 8 in ``basic.py``::
|
||||
Run test at line 4, 6, and 8 in ``completion/basic.py``::
|
||||
|
||||
pytest test/test_integration.py -T basic.py:4,6,8
|
||||
|
||||
@@ -57,38 +56,30 @@ that you can start by running ``./run.py``. The above example could be run by::
|
||||
./run.py basic 4 6 8 50-80
|
||||
|
||||
The advantage of this runner is simplicity and more customized error reports.
|
||||
Using both runners will help you to have a quicker overview of what's
|
||||
happening.
|
||||
|
||||
Auto-Completion Tests
|
||||
+++++++++++++++++++++
|
||||
|
||||
Auto-Completion
|
||||
Uses a comment to specify a test on the next line. The comment defines the
|
||||
expected completions. The comment always begins with `#?`. The last row
|
||||
symbolizes the cursor. For example::
|
||||
|
||||
#? ['upper']
|
||||
a = 'foo'; a.upp
|
||||
|
||||
Inference Tests
|
||||
+++++++++++++++
|
||||
|
||||
Uses comments to specify a test in the next line. The comment says which
|
||||
results are expected. The comment always begins with `#?`. The last row
|
||||
symbolizes the cursor.
|
||||
|
||||
For example::
|
||||
|
||||
#? ['real']
|
||||
a = 3; a.rea
|
||||
|
||||
Because it follows ``a.rea`` and a is an ``int``, which has a ``real``
|
||||
property.
|
||||
|
||||
Inference
|
||||
+++++++++
|
||||
|
||||
Inference tests use the same symbols like completion tests. This is
|
||||
possible because the completion tests are defined with a list::
|
||||
Inference tests look very simliar. The difference is that inference tests don't
|
||||
use brackets::
|
||||
|
||||
#? int()
|
||||
ab = 3; ab
|
||||
|
||||
Goto
|
||||
++++
|
||||
Goto Tests
|
||||
++++++++++
|
||||
|
||||
Tests look like this::
|
||||
Goto Tests look like this::
|
||||
|
||||
abc = 1
|
||||
#! ['abc=1']
|
||||
@@ -100,13 +91,13 @@ describes the position of the test (otherwise it's just the end of line)::
|
||||
#! 2 ['abc=1']
|
||||
abc
|
||||
|
||||
References
|
||||
++++++++++
|
||||
Reference Tests
|
||||
+++++++++++++++
|
||||
|
||||
Tests look like this::
|
||||
|
||||
abc = 1
|
||||
#< abc@1,0 abc@3,0
|
||||
#< (1,0), (3,0)
|
||||
abc
|
||||
"""
|
||||
import os
|
||||
@@ -124,7 +115,7 @@ import pytest
|
||||
import jedi
|
||||
from jedi import debug
|
||||
from jedi._compatibility import unicode, is_py3
|
||||
from jedi.api.classes import Definition
|
||||
from jedi.api.classes import Name
|
||||
from jedi.api.completion import get_user_context
|
||||
from jedi import parser_utils
|
||||
from jedi.api.environment import get_default_environment, get_system_environment
|
||||
@@ -227,7 +218,7 @@ class IntegrationTestCase(BaseTestCase):
|
||||
|
||||
def comparison(definition):
|
||||
suffix = '()' if definition.type == 'instance' else ''
|
||||
return definition.desc_with_module + suffix
|
||||
return definition.full_name + suffix
|
||||
|
||||
def definition(correct, correct_start, path):
|
||||
should_be = set()
|
||||
@@ -244,7 +235,7 @@ class IntegrationTestCase(BaseTestCase):
|
||||
raise Exception('Could not resolve %s on line %s'
|
||||
% (match.string, self.line_nr - 1))
|
||||
|
||||
should_be |= set(Definition(inference_state, r.name) for r in results)
|
||||
should_be |= set(Name(inference_state, r.name) for r in results)
|
||||
debug.dbg('Finished getting types', color='YELLOW')
|
||||
|
||||
# Because the objects have different ids, `repr`, then compare.
|
||||
@@ -411,7 +402,7 @@ def collect_dir_tests(base_dir, test_files, check_thirdparty=False):
|
||||
path = os.path.join(base_dir, f_name)
|
||||
|
||||
if is_py3:
|
||||
with open(path, encoding='utf-8') as f:
|
||||
with open(path, encoding='utf-8', newline='') as f:
|
||||
source = f.read()
|
||||
else:
|
||||
with open(path) as f:
|
||||
@@ -440,7 +431,7 @@ Options:
|
||||
--pdb Enable pdb debugging on fail.
|
||||
-d, --debug Enable text output debugging (please install ``colorama``).
|
||||
--thirdparty Also run thirdparty tests (in ``completion/thirdparty``).
|
||||
--env <dotted> A Python version, like 2.7, 3.4, etc.
|
||||
--env <dotted> A Python version, like 2.7, 3.8, etc.
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
import docopt
|
||||
|
||||
@@ -141,7 +141,7 @@ def test_infer_on_generator(Script):
|
||||
|
||||
def test_goto_definition_not_multiple(Script):
|
||||
"""
|
||||
There should be only one Definition result if it leads back to the same
|
||||
There should be only one result if it leads back to the same
|
||||
origin (e.g. instance method)
|
||||
"""
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ def test_builtins(Script):
|
||||
|
||||
def test_signature_is_definition(Script):
|
||||
"""
|
||||
Through inheritance, a signature is a sub class of Definition.
|
||||
Through inheritance, a signature is a sub class of Name.
|
||||
Check if the attributes match.
|
||||
"""
|
||||
s = """class Spam(): pass\nSpam"""
|
||||
@@ -316,7 +316,8 @@ def test_signature_is_definition(Script):
|
||||
# Now compare all the attributes that a Signature must also have.
|
||||
for attr_name in dir(definition):
|
||||
dont_scan = ['defined_names', 'parent', 'goto_assignments', 'infer',
|
||||
'params', 'get_signatures', 'execute', 'goto']
|
||||
'params', 'get_signatures', 'execute', 'goto',
|
||||
'desc_with_module']
|
||||
if attr_name.startswith('_') or attr_name in dont_scan:
|
||||
continue
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ def test_basedefinition_type(Script, get_names):
|
||||
"""
|
||||
Return a list of definitions for parametrized tests.
|
||||
|
||||
:rtype: [jedi.api_classes.BaseDefinition]
|
||||
:rtype: [jedi.api_classes.BaseName]
|
||||
"""
|
||||
source = dedent("""
|
||||
import sys
|
||||
@@ -193,7 +193,7 @@ def test_hashlib_params(Script, environment):
|
||||
if environment.version_info < (3,):
|
||||
pytest.skip()
|
||||
|
||||
script = Script(source='from hashlib import sha256')
|
||||
script = Script('from hashlib import sha256')
|
||||
c, = script.complete()
|
||||
sig, = c.get_signatures()
|
||||
assert [p.name for p in sig.params] == ['arg']
|
||||
@@ -278,7 +278,7 @@ def test_parent_on_function(Script):
|
||||
code = 'def spam():\n pass'
|
||||
def_, = Script(code).goto(line=1, column=len('def spam'))
|
||||
parent = def_.parent()
|
||||
assert parent.name == ''
|
||||
assert parent.name == '__main__'
|
||||
assert parent.type == 'module'
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ def test_parent_on_closure(Script):
|
||||
assert foo.parent().name == 'inner'
|
||||
assert foo.parent().parent().name == 'bar'
|
||||
assert foo.parent().parent().parent().name == 'Foo'
|
||||
assert foo.parent().parent().parent().parent().name == ''
|
||||
assert foo.parent().parent().parent().parent().name == '__main__'
|
||||
|
||||
assert inner_func.parent().name == 'bar'
|
||||
assert inner_func.parent().parent().name == 'Foo'
|
||||
@@ -344,7 +344,7 @@ def test_parent_on_comprehension(Script):
|
||||
|
||||
assert [name.name for name in ns] == ['spam', 'i']
|
||||
|
||||
assert ns[0].parent().name == ''
|
||||
assert ns[0].parent().name == '__main__'
|
||||
assert ns[0].parent().type == 'module'
|
||||
assert ns[1].parent().name == 'spam'
|
||||
assert ns[1].parent().type == 'function'
|
||||
@@ -375,7 +375,7 @@ def test_type_II(Script):
|
||||
|
||||
|
||||
"""
|
||||
This tests the BaseDefinition.goto function, not the jedi
|
||||
This tests the BaseName.goto function, not the jedi
|
||||
function. They are not really different in functionality, but really
|
||||
different as an implementation.
|
||||
"""
|
||||
|
||||
@@ -6,7 +6,7 @@ from textwrap import dedent
|
||||
import pytest
|
||||
|
||||
from ..helpers import root_dir
|
||||
from jedi.api.helpers import start_match, fuzzy_match
|
||||
from jedi.api.helpers import _start_match, _fuzzy_match
|
||||
from jedi._compatibility import scandir
|
||||
|
||||
|
||||
@@ -92,11 +92,11 @@ def test_complete_expanduser(Script):
|
||||
non_dots = [p for p in possibilities if not p.name.startswith('.') and len(p.name) > 1]
|
||||
item = non_dots[0]
|
||||
line = "'~%s%s'" % (os.sep, item.name)
|
||||
s = Script(line, line=1, column=len(line)-1)
|
||||
s = Script(line)
|
||||
expected_name = item.name
|
||||
if item.is_dir():
|
||||
expected_name += os.path.sep
|
||||
assert expected_name in [c.name for c in s.completions()]
|
||||
assert expected_name in [c.name for c in s.complete(column=len(line)-1)]
|
||||
|
||||
|
||||
def test_fake_subnodes(Script):
|
||||
@@ -312,62 +312,66 @@ def test_file_path_completions(Script, file, code, column, expected):
|
||||
assert [c.complete for c in comps] == expected
|
||||
|
||||
|
||||
def test_file_path_should_have_completions(Script):
|
||||
assert Script('r"').complete() # See GH #1503
|
||||
|
||||
|
||||
_dict_keys_completion_tests = [
|
||||
('ints[', 5, ['1', '50', Ellipsis]),
|
||||
('ints[]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1]', 6, ['']),
|
||||
('ints[1', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1', 6, ['']),
|
||||
('ints[', 5, ['1', '50', Ellipsis]),
|
||||
('ints[]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1]', 6, ['']),
|
||||
('ints[1', 5, ['1', '50', Ellipsis]),
|
||||
('ints[1', 6, ['']),
|
||||
|
||||
('ints[5]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[5]', 6, ['0']),
|
||||
('ints[50', 5, ['1', '50', Ellipsis]),
|
||||
('ints[5', 6, ['0']),
|
||||
('ints[ 5', None, ['0']),
|
||||
('ints [ 5', None, ['0']),
|
||||
('ints[50', 6, ['0']),
|
||||
('ints[50', 7, ['']),
|
||||
('ints[5]', 5, ['1', '50', Ellipsis]),
|
||||
('ints[5]', 6, ['0']),
|
||||
('ints[50', 5, ['1', '50', Ellipsis]),
|
||||
('ints[5', 6, ['0']),
|
||||
('ints[ 5', None, ['0']),
|
||||
('ints [ 5', None, ['0']),
|
||||
('ints[50', 6, ['0']),
|
||||
('ints[50', 7, ['']),
|
||||
|
||||
('strs[', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
|
||||
('strs[]', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
|
||||
("strs['", 6, ["asdf'", "fbar'", "foo'"]),
|
||||
("strs[']", 6, ["asdf'", "fbar'", "foo'"]),
|
||||
('strs["]', 6, ['asdf"', 'fbar"', 'foo"']),
|
||||
('strs["""]', 6, ['asdf', 'fbar', 'foo']),
|
||||
('strs["""]', 8, ['asdf"""', 'fbar"""', 'foo"""']),
|
||||
('strs[b"]', 8, []),
|
||||
('strs[r"asd', 10, ['f"']),
|
||||
('strs[r"asd"', 10, ['f']),
|
||||
('strs[R"asd', 10, ['f"']),
|
||||
('strs[ R"asd', None, ['f"']),
|
||||
('strs[\tR"asd', None, ['f"']),
|
||||
('strs[\nR"asd', None, ['f"']),
|
||||
('strs[f"asd', 10, []),
|
||||
('strs[br"""asd', 13, ['f"""']),
|
||||
('strs[br"""asd"""', 13, ['f']),
|
||||
('strs[ \t"""asd"""', 13, ['f']),
|
||||
('strs[', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
|
||||
('strs[]', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
|
||||
("strs['", 6, ["asdf'", "fbar'", "foo'"]),
|
||||
("strs[']", 6, ["asdf'", "fbar'", "foo'"]),
|
||||
('strs["]', 6, ['asdf"', 'fbar"', 'foo"']),
|
||||
('strs["""]', 6, ['asdf', 'fbar', 'foo']),
|
||||
('strs["""]', 8, ['asdf"""', 'fbar"""', 'foo"""']),
|
||||
('strs[b"]', 8, []),
|
||||
('strs[r"asd', 10, ['f"']),
|
||||
('strs[r"asd"', 10, ['f']),
|
||||
('strs[R"asd', 10, ['f"']),
|
||||
('strs[ R"asd', None, ['f"']),
|
||||
('strs[\tR"asd', None, ['f"']),
|
||||
('strs[\nR"asd', None, ['f"']),
|
||||
('strs[f"asd', 10, []),
|
||||
('strs[br"""asd', 13, ['f"""']),
|
||||
('strs[br"""asd"""', 13, ['f']),
|
||||
('strs[ \t"""asd"""', 13, ['f']),
|
||||
|
||||
('strs["f', 7, ['bar"', 'oo"']),
|
||||
('strs["f"', 7, ['bar', 'oo']),
|
||||
('strs["f]', 7, ['bar"', 'oo"']),
|
||||
('strs["f"]', 7, ['bar', 'oo']),
|
||||
('strs["f', 7, ['bar"', 'oo"']),
|
||||
('strs["f"', 7, ['bar', 'oo']),
|
||||
('strs["f]', 7, ['bar"', 'oo"']),
|
||||
('strs["f"]', 7, ['bar', 'oo']),
|
||||
|
||||
('mixed[', 6, [r"'a\\sdf'", '1', '1.1', "b'foo'", Ellipsis]),
|
||||
('mixed[1', 7, ['', '.1']),
|
||||
('mixed[Non', 9, ['e']),
|
||||
('mixed[', 6, [r"'a\\sdf'", '1', '1.1', "b'foo'", Ellipsis]),
|
||||
('mixed[1', 7, ['', '.1']),
|
||||
('mixed[Non', 9, ['e']),
|
||||
|
||||
('casted["f', 9, ['3"', 'bar"', 'oo"']),
|
||||
('casted["f"', 9, ['3', 'bar', 'oo']),
|
||||
('casted["f3', 10, ['"']),
|
||||
('casted["f3"', 10, ['']),
|
||||
('casted_mod["f', 13, ['3"', 'bar"', 'oo"', 'ull"', 'uuu"']),
|
||||
('casted["f', 9, ['3"', 'bar"', 'oo"']),
|
||||
('casted["f"', 9, ['3', 'bar', 'oo']),
|
||||
('casted["f3', 10, ['"']),
|
||||
('casted["f3"', 10, ['']),
|
||||
('casted_mod["f', 13, ['3"', 'bar"', 'oo"', 'ull"', 'uuu"']),
|
||||
|
||||
('keywords["', None, ['a"']),
|
||||
('keywords[Non', None, ['e']),
|
||||
('keywords[Fa', None, ['lse']),
|
||||
('keywords[Tr', None, ['ue']),
|
||||
('keywords[str', None, ['', 's']),
|
||||
('keywords["', None, ['a"']),
|
||||
('keywords[Non', None, ['e']),
|
||||
('keywords[Fa', None, ['lse']),
|
||||
('keywords[Tr', None, ['ue']),
|
||||
('keywords[str', None, ['', 's']),
|
||||
]
|
||||
|
||||
|
||||
@@ -399,15 +403,15 @@ def test_dict_keys_completions(Script, added_code, column, expected, skip_pre_py
|
||||
|
||||
|
||||
def test_start_match():
|
||||
assert start_match('Condition', 'C')
|
||||
assert _start_match('Condition', 'C')
|
||||
|
||||
|
||||
def test_fuzzy_match():
|
||||
assert fuzzy_match('Condition', 'i')
|
||||
assert not fuzzy_match('Condition', 'p')
|
||||
assert fuzzy_match('Condition', 'ii')
|
||||
assert not fuzzy_match('Condition', 'Ciito')
|
||||
assert fuzzy_match('Condition', 'Cdiio')
|
||||
assert _fuzzy_match('Condition', 'i')
|
||||
assert not _fuzzy_match('Condition', 'p')
|
||||
assert _fuzzy_match('Condition', 'ii')
|
||||
assert not _fuzzy_match('Condition', 'Ciito')
|
||||
assert _fuzzy_match('Condition', 'Cdiio')
|
||||
|
||||
|
||||
def test_ellipsis_completion(Script):
|
||||
@@ -446,7 +450,7 @@ def test_completion_cache(Script, module_injector):
|
||||
|
||||
@pytest.mark.parametrize('module', ['typing', 'os'])
|
||||
def test_module_completions(Script, module):
|
||||
for c in Script('import {module}; {module}.'.format(module=module)).completions():
|
||||
for c in Script('import {module}; {module}.'.format(module=module)).complete():
|
||||
# Just make sure that there are no errors
|
||||
c.type
|
||||
c.docstring()
|
||||
|
||||
@@ -87,7 +87,7 @@ def test_version_info(Script):
|
||||
|
||||
sys.version_info"""))
|
||||
|
||||
c, = s.completions()
|
||||
c, = s.complete()
|
||||
assert c.docstring() == 'sys.version_info\n\nVersion information as a named tuple.'
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def test_find_system_environments():
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'version',
|
||||
['2.7', '3.4', '3.5', '3.6', '3.7']
|
||||
['2.7', '3.5', '3.6', '3.7']
|
||||
)
|
||||
def test_versions(version):
|
||||
try:
|
||||
@@ -118,9 +118,10 @@ def test_create_environment_executable():
|
||||
assert environment.executable == sys.executable
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
|
||||
def test_get_default_environment_from_env_does_not_use_safe(tmpdir, monkeypatch):
|
||||
fake_python = os.path.join(str(tmpdir), 'fake_python')
|
||||
with open(fake_python, 'w') as f:
|
||||
with open(fake_python, 'w', newline='') as f:
|
||||
f.write('')
|
||||
|
||||
def _get_subprocess(self):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Tests for :attr:`.BaseDefinition.full_name`.
|
||||
Tests for :attr:`.BaseName.full_name`.
|
||||
|
||||
There are three kinds of test:
|
||||
|
||||
@@ -121,3 +121,10 @@ def test_param_name(Script):
|
||||
name, = Script('class X:\n def foo(bar): bar''').goto()
|
||||
assert name.type == 'param'
|
||||
assert name.full_name is None
|
||||
|
||||
|
||||
def test_variable_in_func(Script):
|
||||
names = Script('def f(): x = 3').get_names(all_scopes=True)
|
||||
x = names[-1]
|
||||
assert x.name == 'x'
|
||||
assert x.full_name == '__main__.f.x'
|
||||
|
||||
@@ -123,23 +123,17 @@ def _assert_interpreter_complete(source, namespace, completions,
|
||||
|
||||
def test_complete_raw_function():
|
||||
from os.path import join
|
||||
_assert_interpreter_complete('join("").up',
|
||||
locals(),
|
||||
['upper'])
|
||||
_assert_interpreter_complete('join("").up', locals(), ['upper'])
|
||||
|
||||
|
||||
def test_complete_raw_function_different_name():
|
||||
from os.path import join as pjoin
|
||||
_assert_interpreter_complete('pjoin("").up',
|
||||
locals(),
|
||||
['upper'])
|
||||
_assert_interpreter_complete('pjoin("").up', locals(), ['upper'])
|
||||
|
||||
|
||||
def test_complete_raw_module():
|
||||
import os
|
||||
_assert_interpreter_complete('os.path.join("a").up',
|
||||
locals(),
|
||||
['upper'])
|
||||
_assert_interpreter_complete('os.path.join("a").up', locals(), ['upper'])
|
||||
|
||||
|
||||
def test_complete_raw_instance():
|
||||
@@ -148,31 +142,19 @@ def test_complete_raw_instance():
|
||||
completions = ['time', 'timetz', 'timetuple']
|
||||
if is_py3:
|
||||
completions += ['timestamp']
|
||||
_assert_interpreter_complete('(dt - dt).ti',
|
||||
locals(),
|
||||
completions)
|
||||
_assert_interpreter_complete('(dt - dt).ti', locals(), completions)
|
||||
|
||||
|
||||
def test_list():
|
||||
array = ['haha', 1]
|
||||
_assert_interpreter_complete('array[0].uppe',
|
||||
locals(),
|
||||
['upper'])
|
||||
_assert_interpreter_complete('array[0].real',
|
||||
locals(),
|
||||
[])
|
||||
_assert_interpreter_complete('array[0].uppe', locals(), ['upper'])
|
||||
_assert_interpreter_complete('array[0].real', locals(), [])
|
||||
|
||||
# something different, no index given, still just return the right
|
||||
_assert_interpreter_complete('array[int].real',
|
||||
locals(),
|
||||
['real'])
|
||||
_assert_interpreter_complete('array[int()].real',
|
||||
locals(),
|
||||
['real'])
|
||||
_assert_interpreter_complete('array[int].real', locals(), ['real'])
|
||||
_assert_interpreter_complete('array[int()].real', locals(), ['real'])
|
||||
# inexistent index
|
||||
_assert_interpreter_complete('array[2].upper',
|
||||
locals(),
|
||||
['upper'])
|
||||
_assert_interpreter_complete('array[2].upper', locals(), ['upper'])
|
||||
|
||||
|
||||
def test_getattr():
|
||||
@@ -186,9 +168,7 @@ def test_slice():
|
||||
class Foo1:
|
||||
bar = []
|
||||
baz = 'xbarx'
|
||||
_assert_interpreter_complete('getattr(Foo1, baz[1:-1]).append',
|
||||
locals(),
|
||||
['append'])
|
||||
_assert_interpreter_complete('getattr(Foo1, baz[1:-1]).append', locals(), ['append'])
|
||||
|
||||
|
||||
def test_getitem_side_effects():
|
||||
@@ -698,5 +678,5 @@ def bar():
|
||||
def test_string_annotation(annotations, result, code):
|
||||
x = lambda foo: 1
|
||||
x.__annotations__ = annotations
|
||||
defs = jedi.Interpreter(code or 'x()', [locals()]).goto_definitions()
|
||||
defs = jedi.Interpreter(code or 'x()', [locals()]).infer()
|
||||
assert [d.name for d in defs] == result
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ..helpers import get_example_dir, set_cwd, root_dir
|
||||
import pytest
|
||||
|
||||
from ..helpers import get_example_dir, set_cwd, root_dir, test_dir
|
||||
from jedi import Interpreter
|
||||
from jedi.api import Project, get_default_project
|
||||
|
||||
@@ -38,3 +41,113 @@ def test_load_save_project(tmpdir):
|
||||
|
||||
loaded = Project.load(tmpdir.strpath)
|
||||
assert loaded.added_sys_path == ['/foo']
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'string, full_names, kwargs', [
|
||||
('test_load_save_project', ['test_api.test_project.test_load_save_project'], {}),
|
||||
('test_load_savep', [], dict(complete=True)),
|
||||
('test_load_save_p', ['test_api.test_project.test_load_save_project'],
|
||||
dict(complete=True)),
|
||||
('test_load_save_p', ['test_api.test_project.test_load_save_project'],
|
||||
dict(complete=True, all_scopes=True)),
|
||||
|
||||
('some_search_test_var', [], {}),
|
||||
('some_search_test_var', ['test_api.test_project.test_search.some_search_test_var'],
|
||||
dict(all_scopes=True)),
|
||||
('some_search_test_var', ['test_api.test_project.test_search.some_search_test_var'],
|
||||
dict(complete=True, all_scopes=True)),
|
||||
|
||||
('sample_int', ['helpers.sample_int'], {}),
|
||||
('sample_int', ['helpers.sample_int'], dict(all_scopes=True)),
|
||||
('sample_int.real', ['stub:builtins.int.real'], {}),
|
||||
|
||||
('class sample_int.real', [], {}),
|
||||
('foo sample_int.real', [], {}),
|
||||
('def sample_int.real', ['stub:builtins.int.real'], {}),
|
||||
('function sample_int.real', ['stub:builtins.int.real'], {}),
|
||||
|
||||
# With modules
|
||||
('test_project.test_search', ['test_api.test_project.test_search'], {}),
|
||||
('test_project.test_searc', ['test_api.test_project.test_search'], dict(complete=True)),
|
||||
('test_api.test_project.test_search', ['test_api.test_project.test_search'], {}),
|
||||
('test_api.test_project.test_sear', ['test_api.test_project.test_search'],
|
||||
dict(complete=True)),
|
||||
|
||||
# With namespace
|
||||
('implicit_namespace_package.ns1.pkg',
|
||||
['examples.implicit_namespace_package.ns1.pkg'], {}),
|
||||
('implicit_namespace_package.ns1.pkg.ns1_file',
|
||||
['examples.implicit_namespace_package.ns1.pkg.ns1_file'], {}),
|
||||
('examples.implicit_namespace_package.ns1.pkg.ns1_file',
|
||||
['examples.implicit_namespace_package.ns1.pkg.ns1_file'], {}),
|
||||
('implicit_namespace_package.ns1.pkg.',
|
||||
['examples.implicit_namespace_package.ns1.pkg.ns1_file'],
|
||||
dict(complete=True)),
|
||||
('implicit_namespace_package.',
|
||||
['examples.implicit_namespace_package.ns1',
|
||||
'examples.implicit_namespace_package.ns2'],
|
||||
dict(complete=True)),
|
||||
|
||||
# With stubs
|
||||
('with_python.module', ['examples.stub_packages.with_python.module'], {}),
|
||||
('with_python.modul', ['examples.stub_packages.with_python.module'],
|
||||
dict(complete=True)),
|
||||
('no_python.foo', ['stub:examples.stub_packages.no_python.foo'], {}),
|
||||
('no_python.fo', ['stub:examples.stub_packages.no_python.foo'],
|
||||
dict(complete=True)),
|
||||
('with_python-stubs.module', [], {}),
|
||||
('no_python-stubs.foo', [], {}),
|
||||
# Both locations are given, because they live in separate folders (one
|
||||
# suffixed with -stubs.
|
||||
('with_python', ['examples.stub_packages.with_python'], {}),
|
||||
('no_python', ['stub:examples.stub_packages.no_python'], {}),
|
||||
# Completion stubs
|
||||
('stub_only', ['stub:completion.stub_folder.stub_only',
|
||||
'stub:examples.stub_packages.with_python.stub_only'], {}),
|
||||
('with_stub', ['completion.stub_folder.with_stub'], {}),
|
||||
('with_stub.in_with_stub_both',
|
||||
['completion.stub_folder.with_stub.in_with_stub_both'], {}),
|
||||
('with_stub.in_with_stub_python',
|
||||
['completion.stub_folder.with_stub.in_with_stub_python'], {}),
|
||||
('with_stub.in_with_stub_stub',
|
||||
['stub:completion.stub_folder.with_stub.in_with_stub_stub'], {}),
|
||||
# Completion stubs: Folder
|
||||
('with_stub_folder', ['completion.stub_folder.with_stub_folder'], {}),
|
||||
('with_stub_folder.nested_with_stub',
|
||||
['completion.stub_folder.with_stub_folder.nested_with_stub'], {}),
|
||||
('nested_with_stub',
|
||||
['completion.stub_folder.stub_only_folder.nested_with_stub',
|
||||
'completion.stub_folder.with_stub_folder.nested_with_stub'], {}),
|
||||
|
||||
# On sys path
|
||||
('sys.path', ['stub:sys.path'], {}),
|
||||
('json.dumps', ['json.dumps'], {}), # stdlib + stub
|
||||
('multiprocessing', ['multiprocessing'], {}),
|
||||
('multiprocessin', ['multiprocessing'], dict(complete=True)),
|
||||
]
|
||||
)
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason="Ignore Python 2, because EOL")
|
||||
def test_search(string, full_names, kwargs, skip_pre_python36):
|
||||
some_search_test_var = 1.0
|
||||
project = Project(test_dir)
|
||||
if kwargs.pop('complete', False) is True:
|
||||
defs = project.complete_search(string, **kwargs)
|
||||
else:
|
||||
defs = project.search(string, **kwargs)
|
||||
assert [('stub:' if d.is_stub() else '') + d.full_name for d in defs] == full_names
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'string, completions, all_scopes', [
|
||||
('SomeCl', ['ass'], False),
|
||||
('twic', [], False),
|
||||
('twic', ['e', 'e'], True),
|
||||
('test_load_save_p', ['roject'], False),
|
||||
]
|
||||
)
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason="Ignore Python 2, because EOL")
|
||||
def test_complete_search(Script, string, completions, all_scopes, skip_pre_python36):
|
||||
project = Project(test_dir)
|
||||
defs = project.complete_search(string, all_scopes=all_scopes)
|
||||
assert [d.complete for d in defs] == completions
|
||||
|
||||
64
test/test_api/test_refactoring.py
Normal file
64
test/test_api/test_refactoring.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import os
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def skip_old_python(skip_pre_python36):
|
||||
if sys.version_info < (3, 6):
|
||||
pytest.skip()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def dir_with_content(tmpdir):
|
||||
with open(os.path.join(tmpdir.strpath, 'modx.py'), 'w', newline='') as f:
|
||||
f.write('import modx\nfoo\n') # self reference
|
||||
return tmpdir.strpath
|
||||
|
||||
|
||||
def test_rename_mod(Script, dir_with_content):
|
||||
script = Script(
|
||||
'import modx; modx\n',
|
||||
path=os.path.join(dir_with_content, 'some_script.py'),
|
||||
project=jedi.Project(dir_with_content),
|
||||
)
|
||||
refactoring = script.rename(line=1, new_name='modr')
|
||||
refactoring.apply()
|
||||
|
||||
p1 = os.path.join(dir_with_content, 'modx.py')
|
||||
p2 = os.path.join(dir_with_content, 'modr.py')
|
||||
expected_code = 'import modr\nfoo\n'
|
||||
assert not os.path.exists(p1)
|
||||
with open(p2, newline='') as f:
|
||||
assert f.read() == expected_code
|
||||
|
||||
assert refactoring.get_renames() == [(p1, p2)]
|
||||
|
||||
assert refactoring.get_changed_files()[p1].get_new_code() == expected_code
|
||||
|
||||
assert refactoring.get_diff() == dedent('''\
|
||||
rename from modx.py
|
||||
rename to modr.py
|
||||
--- modx.py
|
||||
+++ modr.py
|
||||
@@ -1,3 +1,3 @@
|
||||
-import modx
|
||||
+import modr
|
||||
foo
|
||||
--- some_script.py
|
||||
+++ some_script.py
|
||||
@@ -1,2 +1,2 @@
|
||||
-import modx; modx
|
||||
+import modr; modr
|
||||
''').format(dir=dir_with_content)
|
||||
|
||||
|
||||
def test_rename_none_path(Script):
|
||||
refactoring = Script('foo', path=None).rename(new_name='bar')
|
||||
with pytest.raises(jedi.RefactoringError, match='on a Script with path=None'):
|
||||
refactoring.apply()
|
||||
assert refactoring
|
||||
92
test/test_api/test_search.py
Normal file
92
test/test_api/test_search.py
Normal file
@@ -0,0 +1,92 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class SomeClass:
|
||||
class SomeClass:
|
||||
def twice(self, a):
|
||||
something = os
|
||||
return something
|
||||
|
||||
def twice(self, b):
|
||||
pass
|
||||
|
||||
def some_function():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'string, descriptions, kwargs', [
|
||||
# No completions
|
||||
('SomeClass', ['class SomeClass'], {}),
|
||||
('SomeClass', ['class SomeClass', 'class SomeClass.SomeClass'], dict(all_scopes=True)),
|
||||
('Some', [], dict(all_scopes=True)),
|
||||
('os', ['module os'], {}),
|
||||
('sys', ['module sys'], {}),
|
||||
('sys.path', ['statement sys.path'], {}),
|
||||
('sys.exit', ['function sys.exit'], {}),
|
||||
('something', [], {}),
|
||||
('something', ['statement SomeClass.SomeClass.twice.something'], dict(all_scopes=True)),
|
||||
|
||||
# Completions
|
||||
('class Some', ['class SomeClass', 'class SomeClass.SomeClass'],
|
||||
dict(all_scopes=True, complete=True)),
|
||||
('class Some', ['class SomeClass'], dict(complete=True)),
|
||||
('Some', ['class SomeClass', 'class SomeClass.SomeClass',
|
||||
'statement SomeClass.SomeClass.twice.something',
|
||||
'function SomeClass.some_function'], dict(all_scopes=True, complete=True)),
|
||||
('some', ['class SomeClass', 'class SomeClass.SomeClass',
|
||||
'statement SomeClass.SomeClass.twice.something',
|
||||
'function SomeClass.some_function'], dict(all_scopes=True, complete=True)),
|
||||
|
||||
# Fuzzy
|
||||
('class Smelss', ['class SomeClass'], dict(complete=True, fuzzy=True)),
|
||||
('class Smelss', ['class SomeClass', 'class SomeClass.SomeClass'],
|
||||
dict(complete=True, fuzzy=True, all_scopes=True)),
|
||||
|
||||
# Nested
|
||||
('SomeClass.SomeClass', ['class SomeClass.SomeClass'],
|
||||
dict(all_scopes=True)),
|
||||
('SomeClass.SomeClass.twice', ['function SomeClass.SomeClass.twice'],
|
||||
dict(all_scopes=True)),
|
||||
('SomeClass.SomeClass.twice.__call__', ['function types.FunctionType.__call__'],
|
||||
dict(all_scopes=True)),
|
||||
('SomeClass.SomeClass.twice.something', [], dict(all_scopes=True)),
|
||||
('SomeClass.twice', ['function SomeClass.twice', 'function SomeClass.SomeClass.twice'],
|
||||
dict(all_scopes=True)),
|
||||
|
||||
# Nested completions
|
||||
('SomeClass.twi', ['function SomeClass.twice', 'function SomeClass.SomeClass.twice'],
|
||||
dict(all_scopes=True, complete=True)),
|
||||
|
||||
# Fuzzy unfortunately doesn't work
|
||||
('SomeCl.twice', [], dict(all_scopes=True, complete=True, fuzzy=True)),
|
||||
]
|
||||
)
|
||||
def test_simple_search(Script, string, descriptions, kwargs, skip_pre_python36):
|
||||
if sys.version_info < (3, 6):
|
||||
pytest.skip()
|
||||
|
||||
if kwargs.pop('complete', False) is True:
|
||||
defs = Script(path=__file__).complete_search(string, **kwargs)
|
||||
else:
|
||||
defs = Script(path=__file__).search(string, **kwargs)
|
||||
this_mod = 'test.test_api.test_search.'
|
||||
assert [d.type + ' ' + d.full_name.replace(this_mod, '') for d in defs] == descriptions
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'string, completions, fuzzy, all_scopes', [
|
||||
('SomeCl', ['ass'], False, False),
|
||||
('SomeCl', [None], True, False),
|
||||
('twic', [], False, False),
|
||||
('some_f', [], False, False),
|
||||
('twic', ['e', 'e'], False, True),
|
||||
('some_f', ['unction'], False, True),
|
||||
]
|
||||
)
|
||||
def test_complete_search(Script, string, completions, fuzzy, all_scopes):
|
||||
defs = Script(path=__file__).complete_search(string, fuzzy=fuzzy, all_scopes=all_scopes)
|
||||
assert [d.complete for d in defs] == completions
|
||||
@@ -74,9 +74,3 @@ def test_wrong_encoding(Script, tmpdir):
|
||||
project = Project('.', sys_path=[tmpdir.strpath])
|
||||
c, = Script('import x; x.foo', project=project).complete()
|
||||
assert c.name == 'foobar'
|
||||
|
||||
|
||||
def test_encoding_parameter(Script):
|
||||
name = u('hö')
|
||||
s = Script(name.encode('latin-1'), encoding='latin-1')
|
||||
assert s._module_node.get_code() == name
|
||||
|
||||
@@ -5,22 +5,14 @@ from jedi._compatibility import highest_pickle_protocol
|
||||
def test_highest_pickle_protocol():
|
||||
v = namedtuple('version', 'major, minor')
|
||||
assert highest_pickle_protocol([v(2, 7), v(2, 7)]) == 2
|
||||
assert highest_pickle_protocol([v(2, 7), v(3, 3)]) == 2
|
||||
assert highest_pickle_protocol([v(2, 7), v(3, 4)]) == 2
|
||||
assert highest_pickle_protocol([v(2, 7), v(3, 8)]) == 2
|
||||
assert highest_pickle_protocol([v(2, 7), v(3, 5)]) == 2
|
||||
assert highest_pickle_protocol([v(2, 7), v(3, 6)]) == 2
|
||||
assert highest_pickle_protocol([v(3, 3), v(2, 7)]) == 2
|
||||
assert highest_pickle_protocol([v(3, 3), v(3, 3)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 3), v(3, 4)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 3), v(3, 5)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 3), v(3, 6)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 4), v(2, 7)]) == 2
|
||||
assert highest_pickle_protocol([v(3, 4), v(3, 3)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 4), v(3, 4)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 4), v(3, 5)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 4), v(3, 6)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 8), v(2, 7)]) == 2
|
||||
assert highest_pickle_protocol([v(3, 8), v(3, 8)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 8), v(3, 5)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 8), v(3, 6)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 6), v(2, 7)]) == 2
|
||||
assert highest_pickle_protocol([v(3, 6), v(3, 3)]) == 3
|
||||
assert highest_pickle_protocol([v(3, 6), v(3, 4)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 6), v(3, 8)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 6), v(3, 5)]) == 4
|
||||
assert highest_pickle_protocol([v(3, 6), v(3, 6)]) == 4
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi._compatibility import u
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def check_for_warning(recwarn):
|
||||
warnings.simplefilter("always")
|
||||
with pytest.warns(DeprecationWarning):
|
||||
yield
|
||||
|
||||
|
||||
def test_goto_definitions(Script):
|
||||
int_, = Script('x = 1\nx, y\ny', line=2, column=0).goto_definitions()
|
||||
assert int_.name == 'int'
|
||||
@@ -25,3 +40,9 @@ def test_usages(Script):
|
||||
def test_call_signatures(Script):
|
||||
d1, = Script('abs(float(\nstr(', line=1, column=4).call_signatures()
|
||||
assert d1.name == 'abs'
|
||||
|
||||
|
||||
def test_encoding_parameter(Script):
|
||||
name = u('hö')
|
||||
s = Script(name.encode('latin-1'), encoding='latin-1')
|
||||
assert s._module_node.get_code() == name
|
||||
|
||||
@@ -67,7 +67,7 @@ def test_path_from_sys_path_assignment(Script):
|
||||
|
||||
import sys
|
||||
sys.path[0:0] = [
|
||||
'/usr/lib/python3.4/site-packages',
|
||||
'/usr/lib/python3.8/site-packages',
|
||||
'/home/test/.buildout/eggs/important_package.egg'
|
||||
]
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@ def test_get_signatures_stdlib(Script):
|
||||
assert len(sigs[0].params) == 1
|
||||
|
||||
|
||||
# Check only on linux 64 bit platform and Python3.4.
|
||||
# Check only on linux 64 bit platform and Python3.8.
|
||||
@pytest.mark.parametrize('load_unsafe_extensions', [False, True])
|
||||
@pytest.mark.skipif('sys.platform != "linux" or sys.maxsize <= 2**32 or sys.version_info[:2] != (3, 4)')
|
||||
@pytest.mark.skipif('sys.platform != "linux" or sys.maxsize <= 2**32 or sys.version_info[:2] != (3, 8)')
|
||||
def test_init_extension_module(Script, load_unsafe_extensions):
|
||||
"""
|
||||
``__init__`` extension modules are also packages and Jedi should understand
|
||||
@@ -45,10 +45,10 @@ def test_init_extension_module(Script, load_unsafe_extensions):
|
||||
|
||||
This test was built by the module.c and setup.py combination you can find
|
||||
in the init_extension_module folder. You can easily build the
|
||||
`__init__.cpython-34m.so` by compiling it (create a virtualenv and run
|
||||
`__init__.cpython-38m.so` by compiling it (create a virtualenv and run
|
||||
`setup.py install`.
|
||||
|
||||
This is also why this test only runs on certain systems (and Python 3.4).
|
||||
This is also why this test only runs on certain systems and Python 3.8.
|
||||
"""
|
||||
|
||||
project = jedi.Project(get_example_dir(), load_unsafe_extensions=load_unsafe_extensions)
|
||||
|
||||
@@ -45,7 +45,7 @@ def test_infer_and_goto(Script, code, full_name, has_stub, has_python, way,
|
||||
kwargs, type_, options, environment):
|
||||
if environment.version_info < (3, 5):
|
||||
# We just don't care about much of the detailed Python 2 failures
|
||||
# anymore, because its end-of-life soon. (same for 3.4)
|
||||
# anymore, because its end-of-life soon.
|
||||
pytest.skip()
|
||||
|
||||
if type_ == 'infer' and full_name == 'typing.Sequence' and environment.version_info >= (3, 7):
|
||||
|
||||
@@ -24,9 +24,6 @@ def test_get_typeshed_directories():
|
||||
dirs = get_dirs(PythonVersionInfo(2, 7))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/2', 'third_party/2and3', 'third_party/2'})
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(3, 4))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'third_party/2and3', 'third_party/3'})
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(3, 5))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/3',
|
||||
'third_party/2and3', 'third_party/3'})
|
||||
@@ -139,10 +136,13 @@ def test_math(Script):
|
||||
assert value
|
||||
|
||||
|
||||
def test_type_var(Script):
|
||||
def test_type_var(Script, environment):
|
||||
def_, = Script('import typing; T = typing.TypeVar("T1")').infer()
|
||||
assert def_.name == 'TypeVar'
|
||||
assert def_.description == 'TypeVar = object()'
|
||||
if environment.version_info.major == 2:
|
||||
assert def_.description == 'TypeVar = object()'
|
||||
else:
|
||||
assert def_.description == 'class TypeVar'
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -8,7 +8,7 @@ from jedi import Project
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def skip_not_supported_versions(environment):
|
||||
if environment.version_info < (3, 4):
|
||||
if environment.version_info < (3, 5):
|
||||
pytest.skip()
|
||||
|
||||
|
||||
@@ -58,9 +58,9 @@ def test_implicit_nested_namespace_package(Script):
|
||||
code = 'from implicit_nested_namespaces.namespace.pkg.module import CONST'
|
||||
|
||||
project = Project('.', sys_path=[example_dir])
|
||||
script = Script(project=project, source=code, line=1, column=61)
|
||||
script = Script(code, project=project)
|
||||
|
||||
result = script.infer()
|
||||
result = script.infer(line=1, column=61)
|
||||
|
||||
assert len(result) == 1
|
||||
|
||||
@@ -70,41 +70,41 @@ def test_implicit_nested_namespace_package(Script):
|
||||
|
||||
|
||||
def test_implicit_namespace_package_import_autocomplete(Script):
|
||||
CODE = 'from implicit_name'
|
||||
code = 'from implicit_name'
|
||||
|
||||
project = Project('.', sys_path=[example_dir])
|
||||
script = Script(project=project, source=CODE)
|
||||
script = Script(code, project=project)
|
||||
compl = script.complete()
|
||||
assert [c.name for c in compl] == ['implicit_namespace_package']
|
||||
|
||||
|
||||
def test_namespace_package_in_multiple_directories_autocompletion(Script):
|
||||
CODE = 'from pkg.'
|
||||
code = 'from pkg.'
|
||||
sys_path = [get_example_dir('implicit_namespace_package', 'ns1'),
|
||||
get_example_dir('implicit_namespace_package', 'ns2')]
|
||||
|
||||
project = Project('.', sys_path=sys_path)
|
||||
script = Script(project=project, source=CODE)
|
||||
script = Script(code, project=project)
|
||||
compl = script.complete()
|
||||
assert set(c.name for c in compl) == set(['ns1_file', 'ns2_file'])
|
||||
|
||||
|
||||
def test_namespace_package_in_multiple_directories_goto_definition(Script):
|
||||
CODE = 'from pkg import ns1_file'
|
||||
code = 'from pkg import ns1_file'
|
||||
sys_path = [get_example_dir('implicit_namespace_package', 'ns1'),
|
||||
get_example_dir('implicit_namespace_package', 'ns2')]
|
||||
project = Project('.', sys_path=sys_path)
|
||||
script = Script(project=project, source=CODE)
|
||||
script = Script(code, project=project)
|
||||
result = script.infer()
|
||||
assert len(result) == 1
|
||||
|
||||
|
||||
def test_namespace_name_autocompletion_full_name(Script):
|
||||
CODE = 'from pk'
|
||||
code = 'from pk'
|
||||
sys_path = [get_example_dir('implicit_namespace_package', 'ns1'),
|
||||
get_example_dir('implicit_namespace_package', 'ns2')]
|
||||
|
||||
project = Project('.', sys_path=sys_path)
|
||||
script = Script(project=project, source=CODE)
|
||||
script = Script(code, project=project)
|
||||
compl = script.complete()
|
||||
assert set(c.full_name for c in compl) == set(['pkg'])
|
||||
|
||||
@@ -7,7 +7,7 @@ import os
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi.file_io import FileIO, KnownContentFileIO
|
||||
from jedi.file_io import FileIO
|
||||
from jedi._compatibility import find_module_py33, find_module
|
||||
from jedi.inference import compiled
|
||||
from jedi.inference import imports
|
||||
@@ -259,7 +259,7 @@ def test_goto_following_on_imports(Script):
|
||||
|
||||
|
||||
def test_goto(Script):
|
||||
sys, = Script("import sys", 1, 10).goto(follow_imports=True)
|
||||
sys, = Script("import sys").goto(follow_imports=True)
|
||||
assert sys.type == 'module'
|
||||
|
||||
|
||||
@@ -344,23 +344,6 @@ def test_get_modules_containing_name(inference_state, path, goal, is_package):
|
||||
assert found_module.string_names == goal
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('path', 'base_names', 'is_package', 'names'), [
|
||||
('/foo/bar.py', ('foo',), False, ('foo', 'bar')),
|
||||
('/foo/bar.py', ('foo', 'baz'), False, ('foo', 'baz', 'bar')),
|
||||
('/foo/__init__.py', ('foo',), True, ('foo',)),
|
||||
('/__init__.py', ('foo',), True, ('foo',)),
|
||||
('/foo/bar/__init__.py', ('foo',), True, ('foo',)),
|
||||
('/foo/bar/__init__.py', ('foo', 'bar'), True, ('foo', 'bar')),
|
||||
]
|
||||
)
|
||||
def test_load_module_from_path(inference_state, path, base_names, is_package, names):
|
||||
file_io = KnownContentFileIO(path, '')
|
||||
m = imports.load_module_from_path(inference_state, file_io, base_names)
|
||||
assert m.is_package() == is_package
|
||||
assert m.string_names == names
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'path', ('api/whatever/test_this.py', 'api/whatever/file'))
|
||||
@pytest.mark.parametrize('empty_sys_path', (False, True))
|
||||
@@ -489,6 +472,6 @@ def test_relative_import_star(Script):
|
||||
from . import *
|
||||
furl.c
|
||||
"""
|
||||
script = Script(source, 'export.py')
|
||||
script = Script(source, path='export.py')
|
||||
|
||||
assert script.complete(3, len("furl.c"))
|
||||
|
||||
@@ -71,9 +71,7 @@ def test_nested_namespace_package(Script):
|
||||
|
||||
sys_path = [example_dir]
|
||||
project = Project('.', sys_path=sys_path)
|
||||
script = Script(project=project, source=code)
|
||||
|
||||
result = script.infer(line=1, column=45)
|
||||
result = Script(code, project=project).infer(line=1, column=45)
|
||||
|
||||
assert len(result) == 1
|
||||
|
||||
@@ -82,7 +80,7 @@ def test_relative_import(Script, environment, tmpdir):
|
||||
"""
|
||||
Attempt a relative import in a very simple namespace package.
|
||||
"""
|
||||
if environment.version_info < (3, 4):
|
||||
if environment.version_info < (3, 5):
|
||||
pytest.skip()
|
||||
|
||||
directory = get_example_dir('namespace_package_relative_import')
|
||||
|
||||
@@ -29,11 +29,11 @@ def pyc_project_path(tmpdir):
|
||||
path = tmpdir.strpath
|
||||
dummy_package_path = os.path.join(path, "dummy_package")
|
||||
os.mkdir(dummy_package_path)
|
||||
with open(os.path.join(dummy_package_path, "__init__.py"), 'w'):
|
||||
with open(os.path.join(dummy_package_path, "__init__.py"), 'w', newline=''):
|
||||
pass
|
||||
|
||||
dummy_path = os.path.join(dummy_package_path, 'dummy.py')
|
||||
with open(dummy_path, 'w') as f:
|
||||
with open(dummy_path, 'w', newline='') as f:
|
||||
f.write(SRC)
|
||||
import compileall
|
||||
compileall.compile_file(dummy_path)
|
||||
@@ -56,6 +56,7 @@ def pyc_project_path(tmpdir):
|
||||
|
||||
|
||||
@pytest.mark.parametrize('load_unsafe_extensions', [False, True])
|
||||
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
|
||||
def test_pyc(pyc_project_path, environment, load_unsafe_extensions):
|
||||
"""
|
||||
The list of completion must be greater than 2.
|
||||
|
||||
@@ -4,6 +4,8 @@ import sys
|
||||
import pytest
|
||||
|
||||
from . import helpers
|
||||
from jedi.common.utils import indent_block
|
||||
from jedi import RefactoringError
|
||||
|
||||
|
||||
def assert_case_equal(case, actual, desired):
|
||||
@@ -16,9 +18,11 @@ def assert_case_equal(case, actual, desired):
|
||||
"""
|
||||
assert actual == desired, """
|
||||
Test %r failed.
|
||||
actual = %s
|
||||
desired = %s
|
||||
""" % (case, actual, desired)
|
||||
actual =
|
||||
%s
|
||||
desired =
|
||||
%s
|
||||
""" % (case, indent_block(str(actual)), indent_block(str(desired)))
|
||||
|
||||
|
||||
def assert_static_analysis(case, actual, desired):
|
||||
@@ -56,15 +60,25 @@ def test_static_analysis(static_analysis_case, environment):
|
||||
static_analysis_case.run(assert_static_analysis, environment)
|
||||
|
||||
|
||||
def test_refactor(refactor_case):
|
||||
def test_refactor(refactor_case, skip_pre_python36, environment):
|
||||
"""
|
||||
Run refactoring test case.
|
||||
|
||||
:type refactor_case: :class:`.refactor.RefactoringCase`
|
||||
"""
|
||||
if 0:
|
||||
# TODO Refactoring is not relevant at the moment, it will be changed
|
||||
# significantly in the future, but maybe we can use these tests:
|
||||
refactor_case.run()
|
||||
assert_case_equal(refactor_case,
|
||||
refactor_case.result, refactor_case.desired)
|
||||
if sys.version_info < (3, 6):
|
||||
pytest.skip()
|
||||
|
||||
desired_result = refactor_case.get_desired_result()
|
||||
if refactor_case.type == 'error':
|
||||
with pytest.raises(RefactoringError) as e:
|
||||
refactor_case.refactor(environment)
|
||||
assert e.value.args[0] == desired_result.strip()
|
||||
elif refactor_case.type == 'text':
|
||||
refactoring = refactor_case.refactor(environment)
|
||||
assert not refactoring.get_renames()
|
||||
text = ''.join(f.get_new_code() for f in refactoring.get_changed_files().values())
|
||||
assert_case_equal(refactor_case, text, desired_result)
|
||||
else:
|
||||
diff = refactor_case.refactor(environment).get_diff()
|
||||
assert_case_equal(refactor_case, diff, desired_result)
|
||||
|
||||
@@ -70,7 +70,7 @@ def test_add_to_end(Script):
|
||||
" self."
|
||||
|
||||
def complete(code, line=None, column=None):
|
||||
script = Script(code, 'example.py')
|
||||
script = Script(code, path='example.py')
|
||||
assert script.complete(line, column)
|
||||
|
||||
complete(a, 7, 12)
|
||||
|
||||
Reference in New Issue
Block a user