Removed elpa packages, need to find a way to auto install
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
""" needed for some modules to test against packages. """
|
||||
|
||||
some_variable = 1
|
||||
@@ -0,0 +1,436 @@
|
||||
# -----------------
|
||||
# basic array lookups
|
||||
# -----------------
|
||||
|
||||
|
||||
#? int()
|
||||
[1,""][0]
|
||||
#? str()
|
||||
[1,""][1]
|
||||
#? int() str()
|
||||
[1,""][2]
|
||||
#? int() str()
|
||||
[1,""][20]
|
||||
#? int() str()
|
||||
[1,""][str(hello)]
|
||||
|
||||
a = list()
|
||||
#? list()
|
||||
[a][0]
|
||||
|
||||
#? list()
|
||||
[[a,a,a]][2][100]
|
||||
|
||||
c = [[a,""]]
|
||||
#? str()
|
||||
c[0][1]
|
||||
|
||||
b = [6,7]
|
||||
|
||||
#? int()
|
||||
b[8-7]
|
||||
|
||||
# -----------------
|
||||
# Slices
|
||||
# -----------------
|
||||
#? list()
|
||||
b[8:]
|
||||
|
||||
#? list()
|
||||
b[int():]
|
||||
|
||||
#? list()
|
||||
b[:]
|
||||
|
||||
|
||||
class _StrangeSlice():
|
||||
def __getitem__(self, sliced):
|
||||
return sliced
|
||||
|
||||
# Should not result in an error, just because the slice itself is returned.
|
||||
#? slice()
|
||||
_StrangeSlice()[1:2]
|
||||
|
||||
|
||||
# -----------------
|
||||
# iterable multiplication
|
||||
# -----------------
|
||||
a = ['']*2
|
||||
#? list()
|
||||
a
|
||||
|
||||
# -----------------
|
||||
# tuple assignments
|
||||
# -----------------
|
||||
a1, b1 = (1, "")
|
||||
#? int()
|
||||
a1
|
||||
#? str()
|
||||
b1
|
||||
|
||||
(a2, b2) = (1, "")
|
||||
#? int()
|
||||
a2
|
||||
#? str()
|
||||
b2
|
||||
|
||||
# list assignment
|
||||
[list1, list2] = (1, "")
|
||||
#? int()
|
||||
list1
|
||||
#? str()
|
||||
list2
|
||||
|
||||
[list3, list4] = [1, ""]
|
||||
#? int()
|
||||
list3
|
||||
#? str()
|
||||
list4
|
||||
|
||||
# -----------------
|
||||
# subtuple assignment
|
||||
# -----------------
|
||||
(a3, (b3, c3)) = (1, ("", list))
|
||||
#? list
|
||||
c3
|
||||
|
||||
a4, (b4, c4) = (1, ("", list))
|
||||
#? list
|
||||
c4
|
||||
#? int()
|
||||
a4
|
||||
#? str()
|
||||
b4
|
||||
|
||||
|
||||
# -----------------
|
||||
# multiple assignments
|
||||
# -----------------
|
||||
a = b = 1
|
||||
#? int()
|
||||
a
|
||||
#? int()
|
||||
b
|
||||
|
||||
(a, b) = (c, (e, f)) = ('2', (3, 4))
|
||||
#? str()
|
||||
a
|
||||
#? tuple()
|
||||
b
|
||||
#? str()
|
||||
c
|
||||
#? int()
|
||||
e
|
||||
#? int()
|
||||
f
|
||||
|
||||
|
||||
# -----------------
|
||||
# unnessecary braces
|
||||
# -----------------
|
||||
a = (1)
|
||||
#? int()
|
||||
a
|
||||
#? int()
|
||||
(1)
|
||||
#? int()
|
||||
((1))
|
||||
#? int()
|
||||
((1)+1)
|
||||
|
||||
u, v = 1, ""
|
||||
#? int()
|
||||
u
|
||||
|
||||
((u1, v1)) = 1, ""
|
||||
#? int()
|
||||
u1
|
||||
#? int()
|
||||
(u1)
|
||||
|
||||
(a), b = 1, ''
|
||||
#? int()
|
||||
a
|
||||
|
||||
def a(): return ''
|
||||
#? str()
|
||||
(a)()
|
||||
#? str()
|
||||
(a)().replace()
|
||||
#? int()
|
||||
(tuple).index()
|
||||
#? int()
|
||||
(tuple)().index()
|
||||
|
||||
class C():
|
||||
def __init__(self):
|
||||
self.a = (str()).upper()
|
||||
|
||||
#? str()
|
||||
C().a
|
||||
|
||||
# -----------------
|
||||
# imbalanced sides
|
||||
# -----------------
|
||||
(f, g) = (1,)
|
||||
#? int()
|
||||
f
|
||||
#? []
|
||||
g.
|
||||
|
||||
(f, g, h) = (1,'')
|
||||
#? int()
|
||||
f
|
||||
#? str()
|
||||
g
|
||||
#? []
|
||||
h.
|
||||
|
||||
(f1, g1) = 1
|
||||
#? []
|
||||
f1.
|
||||
#? []
|
||||
g1.
|
||||
|
||||
(f, g) = (1,'',1.0)
|
||||
#? int()
|
||||
f
|
||||
#? str()
|
||||
g
|
||||
|
||||
# -----------------
|
||||
# dicts
|
||||
# -----------------
|
||||
dic2 = {'asdf': 3, 'b': 'str'}
|
||||
#? int()
|
||||
dic2['asdf']
|
||||
|
||||
# string literal
|
||||
#? int()
|
||||
dic2[r'asdf']
|
||||
#? int()
|
||||
dic2[r'asdf']
|
||||
#? int()
|
||||
dic2[r'as' 'd' u'f']
|
||||
#? int() str()
|
||||
dic2['just_something']
|
||||
|
||||
# unpacking
|
||||
a, b = dic2
|
||||
#? str()
|
||||
a
|
||||
a, b = {1: 'x', 2.0: 1j}
|
||||
#? int() float()
|
||||
a
|
||||
#? int() float()
|
||||
b
|
||||
|
||||
|
||||
def f():
|
||||
""" github #83 """
|
||||
r = {}
|
||||
r['status'] = (200, 'ok')
|
||||
return r
|
||||
|
||||
#? dict()
|
||||
f()
|
||||
|
||||
# completion within dicts
|
||||
#? 9 ['str']
|
||||
{str: str}
|
||||
|
||||
# iteration problem (detected with sith)
|
||||
d = dict({'a':''})
|
||||
def y(a):
|
||||
return a
|
||||
#?
|
||||
y(**d)
|
||||
|
||||
# problem with more complicated casts
|
||||
dic = {str(key): ''}
|
||||
#? str()
|
||||
dic['']
|
||||
|
||||
|
||||
for x in {1: 3.0, '': 1j}:
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
# -----------------
|
||||
# with variable as index
|
||||
# -----------------
|
||||
a = (1, "")
|
||||
index = 1
|
||||
#? str()
|
||||
a[index]
|
||||
|
||||
# these should just ouput the whole array
|
||||
index = int
|
||||
#? int() str()
|
||||
a[index]
|
||||
index = int()
|
||||
#? int() str()
|
||||
a[index]
|
||||
|
||||
# dicts
|
||||
index = 'asdf'
|
||||
|
||||
dic2 = {'asdf': 3, 'b': 'str'}
|
||||
#? int()
|
||||
dic2[index]
|
||||
|
||||
# -----------------
|
||||
# __getitem__
|
||||
# -----------------
|
||||
|
||||
class GetItem():
|
||||
def __getitem__(self, index):
|
||||
return 1.0
|
||||
|
||||
#? float()
|
||||
GetItem()[0]
|
||||
|
||||
class GetItem():
|
||||
def __init__(self, el):
|
||||
self.el = el
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.el
|
||||
|
||||
#? str()
|
||||
GetItem("")[1]
|
||||
|
||||
class GetItemWithList():
|
||||
def __getitem__(self, index):
|
||||
return [1, 1.0, 's'][index]
|
||||
|
||||
#? float()
|
||||
GetItemWithList()[1]
|
||||
|
||||
for i in 0, 2:
|
||||
#? int() str()
|
||||
GetItemWithList()[i]
|
||||
|
||||
|
||||
# With super
|
||||
class SuperYeah(list):
|
||||
def __getitem__(self, index):
|
||||
return super()[index]
|
||||
|
||||
#?
|
||||
SuperYeah([1])[0]
|
||||
#?
|
||||
SuperYeah()[0]
|
||||
|
||||
# -----------------
|
||||
# conversions
|
||||
# -----------------
|
||||
|
||||
a = [1, ""]
|
||||
#? int() str()
|
||||
list(a)[1]
|
||||
|
||||
#? int() str()
|
||||
list(a)[0]
|
||||
#?
|
||||
set(a)[0]
|
||||
|
||||
#? int() str()
|
||||
list(set(a))[1]
|
||||
#? int() str()
|
||||
next(iter(set(a)))
|
||||
#? int() str()
|
||||
list(list(set(a)))[1]
|
||||
|
||||
# does not yet work, because the recursion catching is not good enough (catches # to much)
|
||||
#? int() str()
|
||||
list(set(list(set(a))))[1]
|
||||
#? int() str()
|
||||
list(set(set(a)))[1]
|
||||
|
||||
# frozenset
|
||||
#? int() str()
|
||||
list(frozenset(a))[1]
|
||||
#? int() str()
|
||||
list(set(frozenset(a)))[1]
|
||||
|
||||
# iter
|
||||
#? int() str()
|
||||
list(iter(a))[1]
|
||||
#? int() str()
|
||||
list(iter(list(set(a))))[1]
|
||||
|
||||
# tuple
|
||||
#? int() str()
|
||||
tuple(a)[1]
|
||||
#? int() str()
|
||||
tuple(list(set(a)))[1]
|
||||
|
||||
#? int()
|
||||
tuple((1,))[0]
|
||||
|
||||
# implementation detail for lists, should not be visible
|
||||
#? []
|
||||
list().__iterable
|
||||
|
||||
# With a list comprehension.
|
||||
for i in set(a for a in [1]):
|
||||
#? int()
|
||||
i
|
||||
|
||||
|
||||
# -----------------
|
||||
# Merged Arrays
|
||||
# -----------------
|
||||
|
||||
for x in [1] + ['']:
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
# -----------------
|
||||
# For loops with attribute assignment.
|
||||
# -----------------
|
||||
def test_func():
|
||||
x = 'asdf'
|
||||
for x.something in [6,7,8]:
|
||||
pass
|
||||
#? str()
|
||||
x
|
||||
|
||||
for x.something, b in [[6, 6.0]]:
|
||||
pass
|
||||
#? str()
|
||||
x
|
||||
|
||||
|
||||
# python >= 2.7
|
||||
# Set literals are not valid in 2.6.
|
||||
#? int()
|
||||
tuple({1})[0]
|
||||
|
||||
# python >= 3.3
|
||||
# -----------------
|
||||
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
||||
# -----------------
|
||||
|
||||
a, *b, c = [1, 'b', list, dict]
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
b
|
||||
#? list
|
||||
c
|
||||
|
||||
# Not valid syntax
|
||||
a, *b, *c = [1, 'd', list]
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
b
|
||||
#? list
|
||||
c
|
||||
|
||||
lc = [x for a, *x in [(1, '', 1.0)]]
|
||||
|
||||
#?
|
||||
lc[0][0]
|
||||
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
Tests for all async use cases.
|
||||
|
||||
Currently we're not supporting completion of them, but they should at least not
|
||||
raise errors or return extremely strange results.
|
||||
"""
|
||||
|
||||
async def x():
|
||||
argh = await x()
|
||||
#?
|
||||
argh
|
||||
return 2
|
||||
|
||||
#? int()
|
||||
x()
|
||||
|
||||
a = await x()
|
||||
#?
|
||||
a
|
||||
|
||||
|
||||
async def x2():
|
||||
async with open('asdf') as f:
|
||||
#? ['readlines']
|
||||
f.readlines
|
||||
|
||||
class A():
|
||||
@staticmethod
|
||||
async def b(c=1, d=2):
|
||||
return 1
|
||||
|
||||
#! 9 ['def b']
|
||||
await A.b()
|
||||
|
||||
#! 11 ['param d=2']
|
||||
await A.b(d=3)
|
||||
@@ -0,0 +1,295 @@
|
||||
# -----------------
|
||||
# cursor position
|
||||
# -----------------
|
||||
#? 0 int
|
||||
int()
|
||||
#? 3 int
|
||||
int()
|
||||
#? 4 str
|
||||
int(str)
|
||||
|
||||
|
||||
# -----------------
|
||||
# should not complete
|
||||
# -----------------
|
||||
#? []
|
||||
.
|
||||
#? []
|
||||
str..
|
||||
#? []
|
||||
a(0):.
|
||||
|
||||
# -----------------
|
||||
# if/else/elif
|
||||
# -----------------
|
||||
|
||||
if (random.choice([0, 1])):
|
||||
1
|
||||
elif(random.choice([0, 1])):
|
||||
a = 3
|
||||
else:
|
||||
a = ''
|
||||
#? int() str()
|
||||
a
|
||||
def func():
|
||||
if random.choice([0, 1]):
|
||||
1
|
||||
elif(random.choice([0, 1])):
|
||||
a = 3
|
||||
else:
|
||||
a = ''
|
||||
#? int() str()
|
||||
return a
|
||||
#? int() str()
|
||||
func()
|
||||
|
||||
# -----------------
|
||||
# keywords
|
||||
# -----------------
|
||||
|
||||
#? list()
|
||||
assert []
|
||||
|
||||
def focus_return():
|
||||
#? list()
|
||||
return []
|
||||
|
||||
|
||||
# -----------------
|
||||
# for loops
|
||||
# -----------------
|
||||
|
||||
for a in [1,2]:
|
||||
#? int()
|
||||
a
|
||||
|
||||
for a1 in 1,"":
|
||||
#? int() str()
|
||||
a1
|
||||
|
||||
for a3, b3 in (1,""), (1,""), (1,""):
|
||||
#? int()
|
||||
a3
|
||||
#? str()
|
||||
b3
|
||||
|
||||
for a4, (b4, c4) in (1,("", list)), (1,("", list)):
|
||||
#? int()
|
||||
a4
|
||||
#? str()
|
||||
b4
|
||||
#? list
|
||||
c4
|
||||
|
||||
a = []
|
||||
for i in [1,'']:
|
||||
#? int() str()
|
||||
i
|
||||
a += [i]
|
||||
|
||||
#? int() str()
|
||||
a[0]
|
||||
|
||||
for i in list([1,'']):
|
||||
#? int() str()
|
||||
i
|
||||
|
||||
#? int() str()
|
||||
for x in [1,'']: x
|
||||
|
||||
a = []
|
||||
b = [1.0,'']
|
||||
for i in b:
|
||||
a += [i]
|
||||
|
||||
#? float() str()
|
||||
a[0]
|
||||
|
||||
for i in [1,2,3]:
|
||||
#? int()
|
||||
i
|
||||
else:
|
||||
i
|
||||
|
||||
|
||||
# -----------------
|
||||
# range()
|
||||
# -----------------
|
||||
for i in range(10):
|
||||
#? int()
|
||||
i
|
||||
|
||||
# -----------------
|
||||
# ternary operator
|
||||
# -----------------
|
||||
|
||||
a = 3
|
||||
b = '' if a else set()
|
||||
#? str() set()
|
||||
b
|
||||
|
||||
def ret(a):
|
||||
return ['' if a else set()]
|
||||
|
||||
#? str() set()
|
||||
ret(1)[0]
|
||||
#? str() set()
|
||||
ret()[0]
|
||||
|
||||
# -----------------
|
||||
# global vars
|
||||
# -----------------
|
||||
|
||||
def global_define():
|
||||
global global_var_in_func
|
||||
global_var_in_func = 3
|
||||
|
||||
#? int()
|
||||
global_var_in_func
|
||||
|
||||
|
||||
def funct1():
|
||||
# From issue #610
|
||||
global global_dict_var
|
||||
global_dict_var = dict()
|
||||
def funct2():
|
||||
global global_dict_var
|
||||
#? dict()
|
||||
global_dict_var
|
||||
|
||||
|
||||
# -----------------
|
||||
# within docstrs
|
||||
# -----------------
|
||||
|
||||
def a():
|
||||
"""
|
||||
#? ['global_define']
|
||||
global_define
|
||||
"""
|
||||
pass
|
||||
|
||||
#?
|
||||
# str literals in comment """ upper
|
||||
|
||||
def completion_in_comment():
|
||||
#? ['Exception']
|
||||
# might fail because the comment is not a leaf: Exception
|
||||
pass
|
||||
|
||||
some_word
|
||||
#? ['Exception']
|
||||
# Very simple comment completion: Exception
|
||||
# Commment after it
|
||||
|
||||
# -----------------
|
||||
# magic methods
|
||||
# -----------------
|
||||
|
||||
class A(object): pass
|
||||
class B(): pass
|
||||
|
||||
#? ['__init__']
|
||||
A.__init__
|
||||
#? ['__init__']
|
||||
B.__init__
|
||||
|
||||
#? ['__init__']
|
||||
int().__init__
|
||||
|
||||
# -----------------
|
||||
# comments
|
||||
# -----------------
|
||||
|
||||
class A():
|
||||
def __init__(self):
|
||||
self.hello = {} # comment shouldn't be a string
|
||||
#? dict()
|
||||
A().hello
|
||||
|
||||
# -----------------
|
||||
# unicode
|
||||
# -----------------
|
||||
a = 'smörbröd'
|
||||
#? str()
|
||||
a
|
||||
xyz = 'smörbröd.py'
|
||||
if 1:
|
||||
#? str()
|
||||
xyz
|
||||
|
||||
#?
|
||||
¹.
|
||||
|
||||
# -----------------
|
||||
# exceptions
|
||||
# -----------------
|
||||
try:
|
||||
import math
|
||||
except ImportError as i_a:
|
||||
#? ['i_a']
|
||||
i_a
|
||||
#? ImportError()
|
||||
i_a
|
||||
try:
|
||||
import math
|
||||
except ImportError, i_b:
|
||||
# TODO check this only in Python2
|
||||
##? ['i_b']
|
||||
i_b
|
||||
##? ImportError()
|
||||
i_b
|
||||
|
||||
|
||||
class MyException(Exception):
|
||||
def __init__(self, my_attr):
|
||||
self.my_attr = my_attr
|
||||
|
||||
try:
|
||||
raise MyException(1)
|
||||
except MyException as e:
|
||||
#? ['my_attr']
|
||||
e.my_attr
|
||||
#? 22 ['my_attr']
|
||||
for x in e.my_attr:
|
||||
pass
|
||||
|
||||
|
||||
# -----------------
|
||||
# continuations
|
||||
# -----------------
|
||||
|
||||
foo = \
|
||||
1
|
||||
#? int()
|
||||
foo
|
||||
|
||||
# -----------------
|
||||
# module attributes
|
||||
# -----------------
|
||||
|
||||
# Don't move this to imports.py, because there's a star import.
|
||||
#? str()
|
||||
__file__
|
||||
#? ['__file__']
|
||||
__file__
|
||||
|
||||
|
||||
# -----------------
|
||||
# with statements
|
||||
# -----------------
|
||||
|
||||
with open('') as f:
|
||||
#? ['closed']
|
||||
f.closed
|
||||
for line in f:
|
||||
#? str()
|
||||
line
|
||||
|
||||
# Nested with statements don't exist in Python 2.6.
|
||||
# python >= 2.7
|
||||
with open('') as f1, open('') as f2:
|
||||
#? ['closed']
|
||||
f1.closed
|
||||
#? ['closed']
|
||||
f2.closed
|
||||
@@ -0,0 +1,535 @@
|
||||
def find_class():
|
||||
""" This scope is special, because its in front of TestClass """
|
||||
#? ['ret']
|
||||
TestClass.ret
|
||||
if 1:
|
||||
#? ['ret']
|
||||
TestClass.ret
|
||||
|
||||
class FindClass():
|
||||
#? []
|
||||
TestClass.ret
|
||||
if a:
|
||||
#? []
|
||||
TestClass.ret
|
||||
|
||||
def find_class(self):
|
||||
#? ['ret']
|
||||
TestClass.ret
|
||||
if 1:
|
||||
#? ['ret']
|
||||
TestClass.ret
|
||||
|
||||
#? []
|
||||
FindClass().find_class.self
|
||||
#? []
|
||||
FindClass().find_class.self.find_class
|
||||
|
||||
# set variables, which should not be included, because they don't belong to the
|
||||
# class
|
||||
second = 1
|
||||
second = ""
|
||||
class TestClass(object):
|
||||
var_class = TestClass(1)
|
||||
|
||||
def __init__(self2, first_param, second_param, third=1.0):
|
||||
self2.var_inst = first_param
|
||||
self2.second = second_param
|
||||
self2.first = first_param
|
||||
a = 3
|
||||
|
||||
def var_func(self):
|
||||
return 1
|
||||
|
||||
def get_first(self):
|
||||
# traversal
|
||||
self.second_new = self.second
|
||||
return self.var_inst
|
||||
|
||||
def values(self):
|
||||
self.var_local = 3
|
||||
#? ['var_class', 'var_func', 'var_inst', 'var_local']
|
||||
self.var_
|
||||
#?
|
||||
var_local
|
||||
|
||||
def ret(self, a1):
|
||||
# should not know any class functions!
|
||||
#? []
|
||||
values
|
||||
#? ['return']
|
||||
ret
|
||||
return a1
|
||||
|
||||
# should not work
|
||||
#? []
|
||||
var_local
|
||||
#? []
|
||||
var_inst
|
||||
#? []
|
||||
var_func
|
||||
|
||||
# instance
|
||||
inst = TestClass(1)
|
||||
|
||||
#? ['var_class', 'var_func', 'var_inst', 'var_local']
|
||||
inst.var
|
||||
|
||||
#? ['var_class', 'var_func']
|
||||
TestClass.var
|
||||
|
||||
#? int()
|
||||
inst.var_local
|
||||
#? []
|
||||
TestClass.var_local.
|
||||
|
||||
#? int()
|
||||
TestClass().ret(1)
|
||||
# Should not return int(), because we want the type before `.ret(1)`.
|
||||
#? 11 TestClass()
|
||||
TestClass().ret(1)
|
||||
#? int()
|
||||
inst.ret(1)
|
||||
|
||||
myclass = TestClass(1, '', 3.0)
|
||||
#? int()
|
||||
myclass.get_first()
|
||||
#? []
|
||||
myclass.get_first.real
|
||||
|
||||
# too many params
|
||||
#? int()
|
||||
TestClass(1,1,1).var_inst
|
||||
|
||||
# too few params
|
||||
#? int()
|
||||
TestClass(1).first
|
||||
#? []
|
||||
TestClass(1).second.
|
||||
|
||||
# complicated variable settings in class
|
||||
#? str()
|
||||
myclass.second
|
||||
#? str()
|
||||
myclass.second_new
|
||||
|
||||
# multiple classes / ordering
|
||||
ints = TestClass(1, 1.0)
|
||||
strs = TestClass("", '')
|
||||
#? float()
|
||||
ints.second
|
||||
#? str()
|
||||
strs.second
|
||||
|
||||
#? ['var_class']
|
||||
TestClass.var_class.var_class.var_class.var_class
|
||||
|
||||
# operations (+, *, etc) shouldn't be InstanceElements - #246
|
||||
class A():
|
||||
def __init__(self):
|
||||
self.addition = 1 + 2
|
||||
#? int()
|
||||
A().addition
|
||||
|
||||
# should also work before `=`
|
||||
#? 8 int()
|
||||
A().addition = None
|
||||
#? 8 int()
|
||||
A(1).addition = None
|
||||
#? 1 A
|
||||
A(1).addition = None
|
||||
a = A()
|
||||
#? 8 int()
|
||||
a.addition = None
|
||||
|
||||
|
||||
# -----------------
|
||||
# inheritance
|
||||
# -----------------
|
||||
|
||||
class Base(object):
|
||||
def method_base(self):
|
||||
return 1
|
||||
|
||||
class SuperClass(Base):
|
||||
class_super = 3
|
||||
def __init__(self):
|
||||
self.var_super = ''
|
||||
def method_super(self):
|
||||
self.var2_super = list
|
||||
|
||||
class Mixin(SuperClass):
|
||||
def method_mixin(self):
|
||||
return int
|
||||
|
||||
#? 20 SuperClass
|
||||
class SubClass(SuperClass):
|
||||
class_sub = 3
|
||||
def __init__(self):
|
||||
self.var_sub = ''
|
||||
def method_sub(self):
|
||||
self.var_sub = list
|
||||
return tuple
|
||||
|
||||
instance = SubClass()
|
||||
|
||||
#? ['method_base', 'method_sub', 'method_super']
|
||||
instance.method_
|
||||
#? ['var2_super', 'var_sub', 'var_super']
|
||||
instance.var
|
||||
#? ['class_sub', 'class_super']
|
||||
instance.class_
|
||||
|
||||
#? ['method_base', 'method_sub', 'method_super']
|
||||
SubClass.method_
|
||||
#? []
|
||||
SubClass.var
|
||||
#? ['class_sub', 'class_super']
|
||||
SubClass.class_
|
||||
|
||||
# -----------------
|
||||
# inheritance of builtins
|
||||
# -----------------
|
||||
|
||||
class Base(str):
|
||||
pass
|
||||
|
||||
#? ['upper']
|
||||
Base.upper
|
||||
#? ['upper']
|
||||
Base().upper
|
||||
|
||||
# -----------------
|
||||
# dynamic inheritance
|
||||
# -----------------
|
||||
|
||||
class Angry(object):
|
||||
def shout(self):
|
||||
return 'THIS IS MALARKEY!'
|
||||
|
||||
def classgetter():
|
||||
return Angry
|
||||
|
||||
class Dude(classgetter()):
|
||||
def react(self):
|
||||
#? ['shout']
|
||||
self.s
|
||||
|
||||
# -----------------
|
||||
# __call__
|
||||
# -----------------
|
||||
|
||||
class CallClass():
|
||||
def __call__(self):
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
CallClass()()
|
||||
|
||||
# -----------------
|
||||
# variable assignments
|
||||
# -----------------
|
||||
|
||||
class V:
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
|
||||
def ret(self):
|
||||
return self.a
|
||||
|
||||
d = b
|
||||
b = ret
|
||||
if 1:
|
||||
c = b
|
||||
|
||||
#? int()
|
||||
V(1).b()
|
||||
#? int()
|
||||
V(1).c()
|
||||
#?
|
||||
V(1).d()
|
||||
# Only keywords should be possible to complete.
|
||||
#? ['is', 'in', 'not', 'and', 'or', 'if']
|
||||
V(1).d()
|
||||
|
||||
|
||||
# -----------------
|
||||
# ordering
|
||||
# -----------------
|
||||
class A():
|
||||
def b(self):
|
||||
#? int()
|
||||
a_func()
|
||||
#? str()
|
||||
self.a_func()
|
||||
return a_func()
|
||||
|
||||
def a_func(self):
|
||||
return ""
|
||||
|
||||
def a_func():
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
A().b()
|
||||
#? str()
|
||||
A().a_func()
|
||||
|
||||
# -----------------
|
||||
# nested classes
|
||||
# -----------------
|
||||
class A():
|
||||
class B():
|
||||
pass
|
||||
def b(self):
|
||||
return 1.0
|
||||
|
||||
#? float()
|
||||
A().b()
|
||||
|
||||
class A():
|
||||
def b(self):
|
||||
class B():
|
||||
def b(self):
|
||||
return []
|
||||
return B().b()
|
||||
|
||||
#? list()
|
||||
A().b()
|
||||
|
||||
# -----------------
|
||||
# ducktyping
|
||||
# -----------------
|
||||
|
||||
def meth(self):
|
||||
return self.a, self.b
|
||||
|
||||
class WithoutMethod():
|
||||
a = 1
|
||||
def __init__(self):
|
||||
self.b = 1.0
|
||||
def blub(self):
|
||||
return self.b
|
||||
m = meth
|
||||
|
||||
class B():
|
||||
b = ''
|
||||
|
||||
a = WithoutMethod().m()
|
||||
#? int()
|
||||
a[0]
|
||||
#? float()
|
||||
a[1]
|
||||
|
||||
#? float()
|
||||
WithoutMethod.blub(WithoutMethod())
|
||||
#? str()
|
||||
WithoutMethod.blub(B())
|
||||
|
||||
# -----------------
|
||||
# __getattr__ / getattr() / __getattribute__
|
||||
# -----------------
|
||||
|
||||
#? str().upper
|
||||
getattr(str(), 'upper')
|
||||
#? str.upper
|
||||
getattr(str, 'upper')
|
||||
|
||||
# some strange getattr calls
|
||||
#?
|
||||
getattr(str, 1)
|
||||
#?
|
||||
getattr()
|
||||
#?
|
||||
getattr(str)
|
||||
#?
|
||||
getattr(getattr, 1)
|
||||
#?
|
||||
getattr(str, [])
|
||||
|
||||
|
||||
class Base():
|
||||
def ret(self, b):
|
||||
return b
|
||||
|
||||
class Wrapper():
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.obj, name)
|
||||
|
||||
class Wrapper2():
|
||||
def __getattribute__(self, name):
|
||||
return getattr(Base(), name)
|
||||
|
||||
#? int()
|
||||
Wrapper(Base()).ret(3)
|
||||
|
||||
#? int()
|
||||
Wrapper2(Base()).ret(3)
|
||||
|
||||
class GetattrArray():
|
||||
def __getattr__(self, name):
|
||||
return [1]
|
||||
|
||||
#? int()
|
||||
GetattrArray().something[0]
|
||||
|
||||
|
||||
# -----------------
|
||||
# private vars
|
||||
# -----------------
|
||||
class PrivateVar():
|
||||
def __init__(self):
|
||||
self.__var = 1
|
||||
#? int()
|
||||
self.__var
|
||||
#? ['__var']
|
||||
self.__var
|
||||
|
||||
def __private_func(self):
|
||||
return 1
|
||||
|
||||
def wrap_private(self):
|
||||
return self.__private_func()
|
||||
#? []
|
||||
PrivateVar().__var
|
||||
#?
|
||||
PrivateVar().__var
|
||||
#? []
|
||||
PrivateVar().__private_func
|
||||
#? int()
|
||||
PrivateVar().wrap_private()
|
||||
|
||||
|
||||
class PrivateSub(PrivateVar):
|
||||
def test(self):
|
||||
#? []
|
||||
self.__var
|
||||
|
||||
def wrap_private(self):
|
||||
#? []
|
||||
self.__var
|
||||
|
||||
#? []
|
||||
PrivateSub().__var
|
||||
|
||||
# -----------------
|
||||
# super
|
||||
# -----------------
|
||||
class Super(object):
|
||||
a = 3
|
||||
def return_sup(self):
|
||||
return 1
|
||||
|
||||
class TestSuper(Super):
|
||||
#?
|
||||
super()
|
||||
def test(self):
|
||||
#? Super()
|
||||
super()
|
||||
#? ['a']
|
||||
super().a
|
||||
if 1:
|
||||
#? Super()
|
||||
super()
|
||||
def a():
|
||||
#?
|
||||
super()
|
||||
|
||||
def return_sup(self):
|
||||
#? int()
|
||||
return super().return_sup()
|
||||
|
||||
#? int()
|
||||
TestSuper().return_sup()
|
||||
|
||||
|
||||
# -----------------
|
||||
# if flow at class level
|
||||
# -----------------
|
||||
class TestX(object):
|
||||
def normal_method(self):
|
||||
return 1
|
||||
|
||||
if True:
|
||||
def conditional_method(self):
|
||||
var = self.normal_method()
|
||||
#? int()
|
||||
var
|
||||
return 2
|
||||
|
||||
def other_method(self):
|
||||
var = self.conditional_method()
|
||||
#? int()
|
||||
var
|
||||
|
||||
# -----------------
|
||||
# mro method
|
||||
# -----------------
|
||||
|
||||
class A(object):
|
||||
a = 3
|
||||
|
||||
#? ['mro']
|
||||
A.mro
|
||||
#? []
|
||||
A().mro
|
||||
|
||||
|
||||
# -----------------
|
||||
# mro resolution
|
||||
# -----------------
|
||||
|
||||
class B(A()):
|
||||
b = 3
|
||||
|
||||
#?
|
||||
B.a
|
||||
#?
|
||||
B().a
|
||||
#? int()
|
||||
B.b
|
||||
#? int()
|
||||
B().b
|
||||
|
||||
|
||||
# -----------------
|
||||
# With import
|
||||
# -----------------
|
||||
|
||||
from import_tree.classes import Config2, BaseClass
|
||||
|
||||
class Config(BaseClass):
|
||||
"""#884"""
|
||||
|
||||
#? Config2()
|
||||
Config.mode
|
||||
|
||||
#? int()
|
||||
Config.mode2
|
||||
|
||||
|
||||
# -----------------
|
||||
# Nested class/def/class
|
||||
# -----------------
|
||||
class Foo(object):
|
||||
a = 3
|
||||
def create_class(self):
|
||||
class X():
|
||||
a = self.a
|
||||
self.b = 3.0
|
||||
return X
|
||||
|
||||
#? int()
|
||||
Foo().create_class().a
|
||||
#? float()
|
||||
Foo().b
|
||||
|
||||
class Foo(object):
|
||||
def comprehension_definition(self):
|
||||
return [1 for self.b in [1]]
|
||||
|
||||
#? int()
|
||||
Foo().b
|
||||
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Special cases of completions (typically special positions that caused issues
|
||||
with context parsing.
|
||||
"""
|
||||
|
||||
def pass_decorator(func):
|
||||
return func
|
||||
|
||||
|
||||
def x():
|
||||
return (
|
||||
1,
|
||||
#? ["tuple"]
|
||||
tuple
|
||||
)
|
||||
|
||||
# Comment just somewhere
|
||||
|
||||
|
||||
class MyClass:
|
||||
@pass_decorator
|
||||
def x(foo,
|
||||
#? 5 ["tuple"]
|
||||
tuple,
|
||||
):
|
||||
return 1
|
||||
|
||||
|
||||
if x:
|
||||
pass
|
||||
#? ['else']
|
||||
else
|
||||
|
||||
try:
|
||||
pass
|
||||
#? ['except', 'Exception']
|
||||
except
|
||||
|
||||
try:
|
||||
pass
|
||||
#? 6 ['except', 'Exception']
|
||||
except AttributeError:
|
||||
pass
|
||||
#? ['finally']
|
||||
finally
|
||||
|
||||
for x in y:
|
||||
pass
|
||||
#? ['else']
|
||||
else
|
||||
@@ -0,0 +1,14 @@
|
||||
""" Mostly for stupid error reports of @dbrgn. :-) """
|
||||
|
||||
import time
|
||||
|
||||
class Foo(object):
|
||||
global time
|
||||
asdf = time
|
||||
|
||||
def asdfy():
|
||||
return Foo
|
||||
|
||||
xorz = getattr(asdfy()(), 'asdf')
|
||||
#? time
|
||||
xorz
|
||||
@@ -0,0 +1,215 @@
|
||||
# -----------------
|
||||
# list comprehensions
|
||||
# -----------------
|
||||
|
||||
# basics:
|
||||
|
||||
a = ['' for a in [1]]
|
||||
#? str()
|
||||
a[0]
|
||||
#? ['insert']
|
||||
a.insert
|
||||
|
||||
a = [a for a in [1]]
|
||||
#? int()
|
||||
a[0]
|
||||
|
||||
y = 1.0
|
||||
# Should not leak.
|
||||
[y for y in [3]]
|
||||
#? float()
|
||||
y
|
||||
|
||||
a = [a for a in (1, 2)]
|
||||
#? int()
|
||||
a[0]
|
||||
|
||||
a = [a for a,b in [(1,'')]]
|
||||
#? int()
|
||||
a[0]
|
||||
|
||||
arr = [1,'']
|
||||
a = [a for a in arr]
|
||||
#? int()
|
||||
a[0]
|
||||
#? str()
|
||||
a[1]
|
||||
#? int() str()
|
||||
a[2]
|
||||
|
||||
a = [a if 1.0 else '' for a in [1] if [1.0]]
|
||||
#? int() str()
|
||||
a[0]
|
||||
|
||||
# name resolve should be correct
|
||||
left, right = 'a', 'b'
|
||||
left, right = [x for x in (left, right)]
|
||||
#? str()
|
||||
left
|
||||
|
||||
# with a dict literal
|
||||
#? int()
|
||||
[a for a in {1:'x'}][0]
|
||||
|
||||
# list comprehensions should also work in combination with functions
|
||||
def listen(arg):
|
||||
for x in arg:
|
||||
#? str()
|
||||
x
|
||||
|
||||
listen(['' for x in [1]])
|
||||
#?
|
||||
([str for x in []])[0]
|
||||
|
||||
# -----------------
|
||||
# nested list comprehensions
|
||||
# -----------------
|
||||
|
||||
b = [a for arr in [[1, 1.0]] for a in arr]
|
||||
#? int()
|
||||
b[0]
|
||||
#? float()
|
||||
b[1]
|
||||
|
||||
b = [arr for arr in [[1, 1.0]] for a in arr]
|
||||
#? int()
|
||||
b[0][0]
|
||||
#? float()
|
||||
b[1][1]
|
||||
|
||||
b = [a for arr in [[1]] if '' for a in arr if '']
|
||||
#? int()
|
||||
b[0]
|
||||
|
||||
b = [b for arr in [[[1.0]]] for a in arr for b in a]
|
||||
#? float()
|
||||
b[0]
|
||||
|
||||
#? str()
|
||||
[x for x in 'chr'][0]
|
||||
|
||||
# jedi issue #26
|
||||
#? list()
|
||||
a = [[int(v) for v in line.strip().split() if v] for line in ["123", str(), "123"] if line]
|
||||
#? list()
|
||||
a[0]
|
||||
#? int()
|
||||
a[0][0]
|
||||
|
||||
# -----------------
|
||||
# generator comprehensions
|
||||
# -----------------
|
||||
|
||||
left, right = (i for i in (1, ''))
|
||||
|
||||
#? int()
|
||||
left
|
||||
#? str()
|
||||
right
|
||||
|
||||
gen = (i for i in (1,))
|
||||
|
||||
#? int()
|
||||
next(gen)
|
||||
#?
|
||||
gen[0]
|
||||
|
||||
gen = (a for arr in [[1.0]] for a in arr)
|
||||
#? float()
|
||||
next(gen)
|
||||
|
||||
#? int()
|
||||
(i for i in (1,)).send()
|
||||
|
||||
# issues with different formats
|
||||
left, right = (i for i in
|
||||
('1', 2))
|
||||
#? str()
|
||||
left
|
||||
#? int()
|
||||
right
|
||||
|
||||
# -----------------
|
||||
# name resolution in comprehensions.
|
||||
# -----------------
|
||||
|
||||
def x():
|
||||
"""Should not try to resolve to the if hio, which was a bug."""
|
||||
#? 22
|
||||
[a for a in h if hio]
|
||||
if hio: pass
|
||||
|
||||
# -----------------
|
||||
# slices
|
||||
# -----------------
|
||||
|
||||
#? list()
|
||||
foo = [x for x in [1, '']][:1]
|
||||
#? int()
|
||||
foo[0]
|
||||
#? str()
|
||||
foo[1]
|
||||
|
||||
# -----------------
|
||||
# In class
|
||||
# -----------------
|
||||
|
||||
class X():
|
||||
def __init__(self, bar):
|
||||
self.bar = bar
|
||||
|
||||
def foo(self):
|
||||
x = [a for a in self.bar][0]
|
||||
#? int()
|
||||
x
|
||||
return x
|
||||
|
||||
#? int()
|
||||
X([1]).foo()
|
||||
|
||||
# set/dict comprehensions were introduced in 2.7, therefore:
|
||||
# python >= 2.7
|
||||
# -----------------
|
||||
# dict comprehensions
|
||||
# -----------------
|
||||
|
||||
#? int()
|
||||
list({a - 1: 3 for a in [1]})[0]
|
||||
|
||||
d = {a - 1: b for a, b in {1: 'a', 3: 1.0}.items()}
|
||||
#? int()
|
||||
list(d)[0]
|
||||
#? str() float()
|
||||
d.values()[0]
|
||||
#? str()
|
||||
d[0]
|
||||
#? float() str()
|
||||
d[1]
|
||||
#? float()
|
||||
d[2]
|
||||
|
||||
# -----------------
|
||||
# set comprehensions
|
||||
# -----------------
|
||||
|
||||
#? set()
|
||||
{a - 1 for a in [1]}
|
||||
|
||||
#? set()
|
||||
{a for a in range(10)}
|
||||
|
||||
#? int()
|
||||
[x for x in {a for a in range(10)}][0]
|
||||
|
||||
#? int()
|
||||
{a for a in range(10)}.pop()
|
||||
#? float() str()
|
||||
{b for a in [[3.0], ['']] for b in a}.pop()
|
||||
|
||||
#? int()
|
||||
next(iter({a for a in range(10)}))
|
||||
|
||||
|
||||
# with a set literal (also doesn't work in 2.6).
|
||||
#? int()
|
||||
[a for a in {1, 2, 3}][0]
|
||||
@@ -0,0 +1,45 @@
|
||||
class Base():
|
||||
myfoobar = 3
|
||||
|
||||
|
||||
class X(Base):
|
||||
def func(self, foo):
|
||||
pass
|
||||
|
||||
|
||||
class Y(X):
|
||||
def actual_function(self):
|
||||
pass
|
||||
|
||||
#? []
|
||||
def actual_function
|
||||
#? ['func']
|
||||
def f
|
||||
|
||||
#? []
|
||||
def __class__
|
||||
|
||||
#? ['__repr__']
|
||||
def __repr__
|
||||
|
||||
#? []
|
||||
def mro
|
||||
|
||||
#? ['myfoobar']
|
||||
myfoobar
|
||||
|
||||
#? []
|
||||
myfoobar
|
||||
|
||||
# -----------------
|
||||
# Inheritance
|
||||
# -----------------
|
||||
|
||||
class Super():
|
||||
enabled = True
|
||||
if enabled:
|
||||
yo_dude = 4
|
||||
|
||||
class Sub(Super):
|
||||
#? ['yo_dude']
|
||||
yo_dud
|
||||
@@ -0,0 +1,318 @@
|
||||
# -----------------
|
||||
# normal decorators
|
||||
# -----------------
|
||||
|
||||
def decorator(func):
|
||||
def wrapper(*args):
|
||||
return func(1, *args)
|
||||
return wrapper
|
||||
|
||||
@decorator
|
||||
def decorated(a,b):
|
||||
return a,b
|
||||
|
||||
exe = decorated(set, '')
|
||||
|
||||
#? set
|
||||
exe[1]
|
||||
|
||||
#? int()
|
||||
exe[0]
|
||||
|
||||
# more complicated with args/kwargs
|
||||
def dec(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
@dec
|
||||
def fu(a, b, c, *args, **kwargs):
|
||||
return a, b, c, args, kwargs
|
||||
|
||||
exe = fu(list, c=set, b=3, d='')
|
||||
|
||||
#? list
|
||||
exe[0]
|
||||
#? int()
|
||||
exe[1]
|
||||
#? set
|
||||
exe[2]
|
||||
#? []
|
||||
exe[3][0].
|
||||
#? str()
|
||||
exe[4]['d']
|
||||
|
||||
|
||||
exe = fu(list, set, 3, '', d='')
|
||||
|
||||
#? str()
|
||||
exe[3][0]
|
||||
|
||||
# -----------------
|
||||
# multiple decorators
|
||||
# -----------------
|
||||
def dec2(func2):
|
||||
def wrapper2(first_arg, *args2, **kwargs2):
|
||||
return func2(first_arg, *args2, **kwargs2)
|
||||
return wrapper2
|
||||
|
||||
@dec2
|
||||
@dec
|
||||
def fu2(a, b, c, *args, **kwargs):
|
||||
return a, b, c, args, kwargs
|
||||
|
||||
exe = fu2(list, c=set, b=3, d='str')
|
||||
|
||||
#? list
|
||||
exe[0]
|
||||
#? int()
|
||||
exe[1]
|
||||
#? set
|
||||
exe[2]
|
||||
#? []
|
||||
exe[3][0].
|
||||
#? str()
|
||||
exe[4]['d']
|
||||
|
||||
|
||||
# -----------------
|
||||
# Decorator is a class
|
||||
# -----------------
|
||||
def same_func(func):
|
||||
return func
|
||||
|
||||
class Decorator(object):
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.func(1, *args, **kwargs)
|
||||
|
||||
@Decorator
|
||||
def nothing(a,b,c):
|
||||
return a,b,c
|
||||
|
||||
#? int()
|
||||
nothing("")[0]
|
||||
#? str()
|
||||
nothing("")[1]
|
||||
|
||||
|
||||
@same_func
|
||||
@Decorator
|
||||
def nothing(a,b,c):
|
||||
return a,b,c
|
||||
|
||||
#? int()
|
||||
nothing("")[0]
|
||||
|
||||
class MethodDecoratorAsClass():
|
||||
class_var = 3
|
||||
@Decorator
|
||||
def func_without_self(arg, arg2):
|
||||
return arg, arg2
|
||||
|
||||
@Decorator
|
||||
def func_with_self(self, arg):
|
||||
return self.class_var
|
||||
|
||||
#? int()
|
||||
MethodDecoratorAsClass().func_without_self('')[0]
|
||||
#? str()
|
||||
MethodDecoratorAsClass().func_without_self('')[1]
|
||||
#?
|
||||
MethodDecoratorAsClass().func_with_self(1)
|
||||
|
||||
|
||||
class SelfVars():
|
||||
"""Init decorator problem as an instance, #247"""
|
||||
@Decorator
|
||||
def __init__(self):
|
||||
"""
|
||||
__init__ decorators should be ignored when looking up variables in the
|
||||
class.
|
||||
"""
|
||||
self.c = list
|
||||
|
||||
@Decorator
|
||||
def shouldnt_expose_var(not_self):
|
||||
"""
|
||||
Even though in real Python this shouldn't expose the variable, in this
|
||||
case Jedi exposes the variable, because these kind of decorators are
|
||||
normally descriptors, which SHOULD be exposed (at least 90%).
|
||||
"""
|
||||
not_self.b = 1.0
|
||||
|
||||
def other_method(self):
|
||||
#? float()
|
||||
self.b
|
||||
#? list
|
||||
self.c
|
||||
|
||||
# -----------------
|
||||
# not found decorators (are just ignored)
|
||||
# -----------------
|
||||
@not_found_decorator
|
||||
def just_a_func():
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
just_a_func()
|
||||
|
||||
#? ['__closure__']
|
||||
just_a_func.__closure__
|
||||
|
||||
|
||||
class JustAClass:
|
||||
@not_found_decorator2
|
||||
def a(self):
|
||||
return 1
|
||||
|
||||
#? ['__call__']
|
||||
JustAClass().a.__call__
|
||||
#? int()
|
||||
JustAClass().a()
|
||||
#? ['__call__']
|
||||
JustAClass.a.__call__
|
||||
#? int()
|
||||
JustAClass.a()
|
||||
|
||||
# -----------------
|
||||
# illegal decorators
|
||||
# -----------------
|
||||
|
||||
class DecoratorWithoutCall():
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
@DecoratorWithoutCall
|
||||
def f():
|
||||
return 1
|
||||
|
||||
# cannot be resolved - should be ignored
|
||||
@DecoratorWithoutCall(None)
|
||||
def g():
|
||||
return 1
|
||||
|
||||
#?
|
||||
f()
|
||||
#? int()
|
||||
g()
|
||||
|
||||
|
||||
class X():
|
||||
@str
|
||||
def x(self):
|
||||
pass
|
||||
|
||||
def y(self):
|
||||
#? str()
|
||||
self.x
|
||||
#?
|
||||
self.x()
|
||||
|
||||
# -----------------
|
||||
# method decorators
|
||||
# -----------------
|
||||
|
||||
def dec(f):
|
||||
def wrapper(s):
|
||||
return f(s)
|
||||
return wrapper
|
||||
|
||||
class MethodDecorators():
|
||||
_class_var = 1
|
||||
def __init__(self):
|
||||
self._method_var = ''
|
||||
|
||||
@dec
|
||||
def constant(self):
|
||||
return 1.0
|
||||
|
||||
@dec
|
||||
def class_var(self):
|
||||
return self._class_var
|
||||
|
||||
@dec
|
||||
def method_var(self):
|
||||
return self._method_var
|
||||
|
||||
#? float()
|
||||
MethodDecorators().constant()
|
||||
#? int()
|
||||
MethodDecorators().class_var()
|
||||
#? str()
|
||||
MethodDecorators().method_var()
|
||||
|
||||
|
||||
class Base():
|
||||
@not_existing
|
||||
def __init__(self):
|
||||
pass
|
||||
@not_existing
|
||||
def b(self):
|
||||
return ''
|
||||
@dec
|
||||
def c(self):
|
||||
return 1
|
||||
|
||||
class MethodDecoratorDoesntExist(Base):
|
||||
"""#272 github: combination of method decorators and super()"""
|
||||
def a(self):
|
||||
#?
|
||||
super().__init__()
|
||||
#? str()
|
||||
super().b()
|
||||
#? int()
|
||||
super().c()
|
||||
#? float()
|
||||
self.d()
|
||||
|
||||
@doesnt_exist
|
||||
def d(self):
|
||||
return 1.0
|
||||
|
||||
# -----------------
|
||||
# others
|
||||
# -----------------
|
||||
def memoize(function):
|
||||
def wrapper(*args):
|
||||
if random.choice([0, 1]):
|
||||
pass
|
||||
else:
|
||||
rv = function(*args)
|
||||
return rv
|
||||
return wrapper
|
||||
|
||||
@memoize
|
||||
def follow_statement(stmt):
|
||||
return stmt
|
||||
|
||||
# here we had problems with the else clause, because the parent was not right.
|
||||
#? int()
|
||||
follow_statement(1)
|
||||
|
||||
# -----------------
|
||||
# class decorators
|
||||
# -----------------
|
||||
|
||||
# class decorators should just be ignored
|
||||
@should_ignore
|
||||
class A():
|
||||
def ret(self):
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
A().ret()
|
||||
|
||||
|
||||
# -----------------
|
||||
# On decorator completions
|
||||
# -----------------
|
||||
|
||||
import abc
|
||||
#? ['abc']
|
||||
@abc
|
||||
|
||||
#? ['abstractmethod']
|
||||
@abc.abstractmethod
|
||||
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
Fallback to callee definition when definition not found.
|
||||
- https://github.com/davidhalter/jedi/issues/131
|
||||
- https://github.com/davidhalter/jedi/pull/149
|
||||
"""
|
||||
|
||||
"""Parenthesis closed at next line."""
|
||||
|
||||
# Ignore these definitions for a little while, not sure if we really want them.
|
||||
# python <= 2.5
|
||||
|
||||
#? isinstance
|
||||
isinstance(
|
||||
)
|
||||
|
||||
#? isinstance
|
||||
isinstance(
|
||||
)
|
||||
|
||||
#? isinstance
|
||||
isinstance(None,
|
||||
)
|
||||
|
||||
#? isinstance
|
||||
isinstance(None,
|
||||
)
|
||||
|
||||
"""Parenthesis closed at same line."""
|
||||
|
||||
# Note: len('isinstance(') == 11
|
||||
#? 11 isinstance
|
||||
isinstance()
|
||||
|
||||
# Note: len('isinstance(None,') == 16
|
||||
##? 16 isinstance
|
||||
isinstance(None,)
|
||||
|
||||
# Note: len('isinstance(None,') == 16
|
||||
##? 16 isinstance
|
||||
isinstance(None, )
|
||||
|
||||
# Note: len('isinstance(None, ') == 17
|
||||
##? 17 isinstance
|
||||
isinstance(None, )
|
||||
|
||||
# Note: len('isinstance( ') == 12
|
||||
##? 12 isinstance
|
||||
isinstance( )
|
||||
|
||||
"""Unclosed parenthesis."""
|
||||
|
||||
#? isinstance
|
||||
isinstance(
|
||||
|
||||
def x(): pass # acts like EOF
|
||||
|
||||
##? isinstance
|
||||
isinstance(
|
||||
|
||||
def x(): pass # acts like EOF
|
||||
|
||||
#? isinstance
|
||||
isinstance(None,
|
||||
|
||||
def x(): pass # acts like EOF
|
||||
|
||||
##? isinstance
|
||||
isinstance(None,
|
||||
@@ -0,0 +1,221 @@
|
||||
class RevealAccess(object):
|
||||
"""
|
||||
A data descriptor that sets and returns values
|
||||
normally and prints a message logging their access.
|
||||
"""
|
||||
def __init__(self, initval=None, name='var'):
|
||||
self.val = initval
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj, objtype):
|
||||
print('Retrieving', self.name)
|
||||
return self.val
|
||||
|
||||
def __set__(self, obj, val):
|
||||
print('Updating', self.name)
|
||||
self.val = val
|
||||
|
||||
def just_a_method(self):
|
||||
pass
|
||||
|
||||
class C(object):
|
||||
x = RevealAccess(10, 'var "x"')
|
||||
#? RevealAccess()
|
||||
x
|
||||
#? ['just_a_method']
|
||||
x.just_a_method
|
||||
y = 5.0
|
||||
def __init__(self):
|
||||
#? int()
|
||||
self.x
|
||||
|
||||
#? []
|
||||
self.just_a_method
|
||||
#? []
|
||||
C.just_a_method
|
||||
|
||||
m = C()
|
||||
#? int()
|
||||
m.x
|
||||
#? float()
|
||||
m.y
|
||||
#? int()
|
||||
C.x
|
||||
|
||||
#? []
|
||||
m.just_a_method
|
||||
#? []
|
||||
C.just_a_method
|
||||
|
||||
# -----------------
|
||||
# properties
|
||||
# -----------------
|
||||
class B():
|
||||
@property
|
||||
def r(self):
|
||||
return 1
|
||||
@r.setter
|
||||
def r(self, value):
|
||||
return ''
|
||||
def t(self):
|
||||
return ''
|
||||
p = property(t)
|
||||
|
||||
#? []
|
||||
B().r().
|
||||
#? int()
|
||||
B().r
|
||||
|
||||
#? str()
|
||||
B().p
|
||||
#? []
|
||||
B().p().
|
||||
|
||||
class PropClass():
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
@property
|
||||
def ret(self):
|
||||
return self.a
|
||||
|
||||
@ret.setter
|
||||
def ret(self, value):
|
||||
return 1.0
|
||||
|
||||
def ret2(self):
|
||||
return self.a
|
||||
ret2 = property(ret2)
|
||||
|
||||
@property
|
||||
def nested(self):
|
||||
""" causes recusions in properties, should work """
|
||||
return self.ret
|
||||
|
||||
@property
|
||||
def nested2(self):
|
||||
""" causes recusions in properties, should not work """
|
||||
return self.nested2
|
||||
|
||||
@property
|
||||
def join1(self):
|
||||
""" mutual recusion """
|
||||
return self.join2
|
||||
|
||||
@property
|
||||
def join2(self):
|
||||
""" mutual recusion """
|
||||
return self.join1
|
||||
|
||||
#? str()
|
||||
PropClass("").ret
|
||||
#? []
|
||||
PropClass().ret.
|
||||
|
||||
#? str()
|
||||
PropClass("").ret2
|
||||
#?
|
||||
PropClass().ret2
|
||||
|
||||
#? int()
|
||||
PropClass(1).nested
|
||||
#? []
|
||||
PropClass().nested.
|
||||
|
||||
#?
|
||||
PropClass(1).nested2
|
||||
#? []
|
||||
PropClass().nested2.
|
||||
|
||||
#?
|
||||
PropClass(1).join1
|
||||
# -----------------
|
||||
# staticmethod/classmethod
|
||||
# -----------------
|
||||
|
||||
class E(object):
|
||||
a = ''
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
|
||||
def f(x):
|
||||
return x
|
||||
f = staticmethod(f)
|
||||
#?
|
||||
f.__func
|
||||
|
||||
@staticmethod
|
||||
def g(x):
|
||||
return x
|
||||
|
||||
def s(cls, x):
|
||||
return x
|
||||
s = classmethod(s)
|
||||
|
||||
@classmethod
|
||||
def t(cls, x):
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def u(cls, x):
|
||||
return cls.a
|
||||
|
||||
e = E(1)
|
||||
#? int()
|
||||
e.f(1)
|
||||
#? int()
|
||||
E.f(1)
|
||||
#? int()
|
||||
e.g(1)
|
||||
#? int()
|
||||
E.g(1)
|
||||
|
||||
#? int()
|
||||
e.s(1)
|
||||
#? int()
|
||||
E.s(1)
|
||||
#? int()
|
||||
e.t(1)
|
||||
#? int()
|
||||
E.t(1)
|
||||
|
||||
#? str()
|
||||
e.u(1)
|
||||
#? str()
|
||||
E.u(1)
|
||||
|
||||
# -----------------
|
||||
# Conditions
|
||||
# -----------------
|
||||
|
||||
from functools import partial
|
||||
|
||||
|
||||
class Memoize():
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
def __get__(self, obj, objtype):
|
||||
if obj is None:
|
||||
return self.func
|
||||
|
||||
return partial(self, obj)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
# We don't do caching here, but that's what would normally happen.
|
||||
return self.func(*args, **kwargs)
|
||||
|
||||
|
||||
class MemoizeTest():
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
|
||||
@Memoize
|
||||
def some_func(self):
|
||||
return self.x
|
||||
|
||||
|
||||
#? int()
|
||||
MemoizeTest(10).some_func()
|
||||
# Now also call the same function over the class (see if clause above).
|
||||
#? float()
|
||||
MemoizeTest.some_func(MemoizeTest(10.0))
|
||||
@@ -0,0 +1,246 @@
|
||||
""" Test docstrings in functions and classes, which are used to infer types """
|
||||
|
||||
# -----------------
|
||||
# sphinx style
|
||||
# -----------------
|
||||
def sphinxy(a, b, c, d, x):
|
||||
""" asdfasdf
|
||||
:param a: blablabla
|
||||
:type a: str
|
||||
:type b: (str, int)
|
||||
:type c: random.Random
|
||||
:type d: :class:`random.Random`
|
||||
:param str x: blablabla
|
||||
:rtype: dict
|
||||
"""
|
||||
#? str()
|
||||
a
|
||||
#? str()
|
||||
b[0]
|
||||
#? int()
|
||||
b[1]
|
||||
#? ['seed']
|
||||
c.seed
|
||||
#? ['seed']
|
||||
d.seed
|
||||
#? ['lower']
|
||||
x.lower
|
||||
|
||||
#? dict()
|
||||
sphinxy()
|
||||
|
||||
# wrong declarations
|
||||
def sphinxy2(a, b, x):
|
||||
"""
|
||||
:param a: Forgot type declaration
|
||||
:type a:
|
||||
:param b: Just something
|
||||
:type b: ``
|
||||
:param x: Just something without type
|
||||
:rtype:
|
||||
"""
|
||||
#?
|
||||
a
|
||||
#?
|
||||
b
|
||||
#?
|
||||
x
|
||||
|
||||
#?
|
||||
sphinxy2()
|
||||
|
||||
|
||||
def sphinxy_param_type_wrapped(a):
|
||||
"""
|
||||
:param str a:
|
||||
Some description wrapped onto the next line with no space after the
|
||||
colon.
|
||||
"""
|
||||
#? str()
|
||||
a
|
||||
|
||||
|
||||
# local classes -> github #370
|
||||
class ProgramNode():
|
||||
pass
|
||||
|
||||
def local_classes(node, node2):
|
||||
"""
|
||||
:type node: ProgramNode
|
||||
... and the class definition after this func definition:
|
||||
:type node2: ProgramNode2
|
||||
"""
|
||||
#? ProgramNode()
|
||||
node
|
||||
#? ProgramNode2()
|
||||
node2
|
||||
|
||||
class ProgramNode2():
|
||||
pass
|
||||
|
||||
|
||||
def list_with_non_imports(lst):
|
||||
"""
|
||||
Should be able to work with tuples and lists and still import stuff.
|
||||
|
||||
:type lst: (random.Random, [collections.defaultdict, ...])
|
||||
"""
|
||||
#? ['seed']
|
||||
lst[0].seed
|
||||
|
||||
import collections as col
|
||||
# use some weird index
|
||||
#? col.defaultdict()
|
||||
lst[1][10]
|
||||
|
||||
|
||||
def two_dots(a):
|
||||
"""
|
||||
:type a: json.decoder.JSONDecoder
|
||||
"""
|
||||
#? ['raw_decode']
|
||||
a.raw_decode
|
||||
|
||||
|
||||
# sphinx returns
|
||||
def return_module_object():
|
||||
"""
|
||||
:rtype: :class:`random.Random`
|
||||
"""
|
||||
|
||||
#? ['seed']
|
||||
return_module_object().seed
|
||||
|
||||
|
||||
# -----------------
|
||||
# epydoc style
|
||||
# -----------------
|
||||
def epydoc(a, b):
|
||||
""" asdfasdf
|
||||
@type a: str
|
||||
@param a: blablabla
|
||||
@type b: (str, int)
|
||||
@param b: blablah
|
||||
@rtype: list
|
||||
"""
|
||||
#? str()
|
||||
a
|
||||
#? str()
|
||||
b[0]
|
||||
|
||||
#? int()
|
||||
b[1]
|
||||
|
||||
#? list()
|
||||
epydoc()
|
||||
|
||||
|
||||
# Returns with param type only
|
||||
def rparam(a,b):
|
||||
"""
|
||||
@type a: str
|
||||
"""
|
||||
return a
|
||||
|
||||
#? str()
|
||||
rparam()
|
||||
|
||||
|
||||
# Composite types
|
||||
def composite():
|
||||
"""
|
||||
@rtype: (str, int, dict)
|
||||
"""
|
||||
|
||||
x, y, z = composite()
|
||||
#? str()
|
||||
x
|
||||
#? int()
|
||||
y
|
||||
#? dict()
|
||||
z
|
||||
|
||||
|
||||
# Both docstring and calculated return type
|
||||
def both():
|
||||
"""
|
||||
@rtype: str
|
||||
"""
|
||||
return 23
|
||||
|
||||
#? str() int()
|
||||
both()
|
||||
|
||||
class Test(object):
|
||||
def __init__(self):
|
||||
self.teststr = ""
|
||||
"""
|
||||
# jedi issue #210
|
||||
"""
|
||||
def test(self):
|
||||
#? ['teststr']
|
||||
self.teststr
|
||||
|
||||
# -----------------
|
||||
# statement docstrings
|
||||
# -----------------
|
||||
d = ''
|
||||
""" bsdf """
|
||||
#? str()
|
||||
d.upper()
|
||||
|
||||
# -----------------
|
||||
# class docstrings
|
||||
# -----------------
|
||||
|
||||
class InInit():
|
||||
def __init__(self, foo):
|
||||
"""
|
||||
:type foo: str
|
||||
"""
|
||||
#? str()
|
||||
foo
|
||||
|
||||
|
||||
class InClass():
|
||||
"""
|
||||
:type foo: str
|
||||
"""
|
||||
def __init__(self, foo):
|
||||
#? str()
|
||||
foo
|
||||
|
||||
|
||||
class InBoth():
|
||||
"""
|
||||
:type foo: str
|
||||
"""
|
||||
def __init__(self, foo):
|
||||
"""
|
||||
:type foo: int
|
||||
"""
|
||||
#? str() int()
|
||||
foo
|
||||
|
||||
|
||||
def __init__(foo):
|
||||
"""
|
||||
:type foo: str
|
||||
"""
|
||||
#? str()
|
||||
foo
|
||||
|
||||
|
||||
# -----------------
|
||||
# Renamed imports (#507)
|
||||
# -----------------
|
||||
|
||||
import datetime
|
||||
from datetime import datetime as datetime_imported
|
||||
|
||||
def import_issues(foo):
|
||||
"""
|
||||
@type foo: datetime_imported
|
||||
"""
|
||||
#? datetime.datetime()
|
||||
foo
|
||||
@@ -0,0 +1,310 @@
|
||||
"""
|
||||
Checking for ``list.append`` and all the other possible array modifications.
|
||||
"""
|
||||
# -----------------
|
||||
# list.append
|
||||
# -----------------
|
||||
arr = []
|
||||
for a in [1,2]:
|
||||
arr.append(a);
|
||||
|
||||
arr.append # should not cause an exception
|
||||
arr.append() # should not cause an exception
|
||||
|
||||
#? int()
|
||||
arr[10]
|
||||
|
||||
arr = [tuple()]
|
||||
for a in [1,2]:
|
||||
arr.append(a);
|
||||
|
||||
#? int() tuple()
|
||||
arr[10]
|
||||
#? int()
|
||||
arr[10].index()
|
||||
|
||||
arr = list([])
|
||||
arr.append(1)
|
||||
#? int()
|
||||
arr[0]
|
||||
|
||||
# -----------------
|
||||
# list.insert
|
||||
# -----------------
|
||||
arr = [""]
|
||||
arr.insert(0, 1.0)
|
||||
|
||||
# on exception due to this, please!
|
||||
arr.insert(0)
|
||||
arr.insert()
|
||||
|
||||
#? float() str()
|
||||
arr[10]
|
||||
|
||||
for a in arr:
|
||||
#? float() str()
|
||||
a
|
||||
|
||||
#? float() str()
|
||||
list(arr)[10]
|
||||
|
||||
# -----------------
|
||||
# list.extend / set.update
|
||||
# -----------------
|
||||
|
||||
arr = [1.0]
|
||||
arr.extend([1,2,3])
|
||||
arr.extend([])
|
||||
arr.extend("") # should ignore
|
||||
|
||||
#? float() int()
|
||||
arr[100]
|
||||
|
||||
a = set(arr)
|
||||
a.update(list(["", 1]))
|
||||
|
||||
#? float() int() str()
|
||||
list(a)[0]
|
||||
# -----------------
|
||||
# set/list initialized as functions
|
||||
# -----------------
|
||||
|
||||
st = set()
|
||||
st.add(1)
|
||||
|
||||
#? int()
|
||||
for s in st: s
|
||||
|
||||
lst = list()
|
||||
lst.append(1)
|
||||
|
||||
#? int()
|
||||
for i in lst: i
|
||||
|
||||
# -----------------
|
||||
# renames / type changes
|
||||
# -----------------
|
||||
arr = []
|
||||
arr2 = arr
|
||||
arr2.append('')
|
||||
#? str()
|
||||
arr2[0]
|
||||
|
||||
|
||||
lst = [1]
|
||||
lst.append(1.0)
|
||||
s = set(lst)
|
||||
s.add("")
|
||||
lst = list(s)
|
||||
lst.append({})
|
||||
|
||||
#? dict() int() float() str()
|
||||
lst[0]
|
||||
|
||||
# should work with tuple conversion, too.
|
||||
#? dict() int() float() str()
|
||||
tuple(lst)[0]
|
||||
|
||||
# but not with an iterator
|
||||
#?
|
||||
iter(lst)[0]
|
||||
|
||||
# -----------------
|
||||
# complex including +=
|
||||
# -----------------
|
||||
class C(): pass
|
||||
class D(): pass
|
||||
class E(): pass
|
||||
lst = [1]
|
||||
lst.append(1.0)
|
||||
lst += [C]
|
||||
s = set(lst)
|
||||
s.add("")
|
||||
s += [D]
|
||||
lst = list(s)
|
||||
lst.append({})
|
||||
lst += [E]
|
||||
|
||||
##? dict() int() float() str() C D E
|
||||
lst[0]
|
||||
|
||||
# -----------------
|
||||
# functions
|
||||
# -----------------
|
||||
|
||||
def arr_append(arr4, a):
|
||||
arr4.append(a)
|
||||
|
||||
def add_to_arr(arr2, a):
|
||||
arr2.append(a)
|
||||
return arr2
|
||||
|
||||
def app(a):
|
||||
arr3.append(a)
|
||||
|
||||
arr3 = [1.0]
|
||||
res = add_to_arr(arr3, 1)
|
||||
arr_append(arr3, 'str')
|
||||
app(set())
|
||||
|
||||
#? float() str() int() set()
|
||||
arr3[10]
|
||||
|
||||
#? float() str() int() set()
|
||||
res[10]
|
||||
|
||||
# -----------------
|
||||
# returns, special because the module dicts are not correct here.
|
||||
# -----------------
|
||||
def blub():
|
||||
a = []
|
||||
a.append(1.0)
|
||||
#? float()
|
||||
a[0]
|
||||
return a
|
||||
|
||||
#? float()
|
||||
blub()[0]
|
||||
|
||||
# list with default
|
||||
def blub():
|
||||
a = list([1])
|
||||
a.append(1.0)
|
||||
return a
|
||||
|
||||
#? int() float()
|
||||
blub()[0]
|
||||
|
||||
# empty list
|
||||
def blub():
|
||||
a = list()
|
||||
a.append(1.0)
|
||||
return a
|
||||
#? float()
|
||||
blub()[0]
|
||||
|
||||
# with if
|
||||
def blub():
|
||||
if 1:
|
||||
a = []
|
||||
a.append(1.0)
|
||||
return a
|
||||
|
||||
#? float()
|
||||
blub()[0]
|
||||
|
||||
# with else clause
|
||||
def blub():
|
||||
if random.choice([0, 1]):
|
||||
1
|
||||
else:
|
||||
a = []
|
||||
a.append(1)
|
||||
return a
|
||||
|
||||
#? int()
|
||||
blub()[0]
|
||||
# -----------------
|
||||
# returns, the same for classes
|
||||
# -----------------
|
||||
class C():
|
||||
def blub(self, b):
|
||||
if 1:
|
||||
a = []
|
||||
a.append(b)
|
||||
return a
|
||||
|
||||
def blub2(self):
|
||||
""" mapper function """
|
||||
a = self.blub(1.0)
|
||||
#? float()
|
||||
a[0]
|
||||
return a
|
||||
|
||||
def literal_arr(self, el):
|
||||
self.a = []
|
||||
self.a.append(el)
|
||||
#? int()
|
||||
self.a[0]
|
||||
return self.a
|
||||
|
||||
def list_arr(self, el):
|
||||
self.b = list([])
|
||||
self.b.append(el)
|
||||
#? float()
|
||||
self.b[0]
|
||||
return self.b
|
||||
|
||||
#? int()
|
||||
C().blub(1)[0]
|
||||
#? float()
|
||||
C().blub2(1)[0]
|
||||
|
||||
#? int()
|
||||
C().a[0]
|
||||
#? int()
|
||||
C().literal_arr(1)[0]
|
||||
|
||||
#? float()
|
||||
C().b[0]
|
||||
#? float()
|
||||
C().list_arr(1.0)[0]
|
||||
|
||||
# -----------------
|
||||
# array recursions
|
||||
# -----------------
|
||||
|
||||
a = set([1.0])
|
||||
a.update(a)
|
||||
a.update([1])
|
||||
|
||||
#? float() int()
|
||||
list(a)[0]
|
||||
|
||||
def first(a):
|
||||
b = []
|
||||
b.append(a)
|
||||
b.extend(second(a))
|
||||
return list(b)
|
||||
|
||||
def second(a):
|
||||
b = []
|
||||
b.extend(first(a))
|
||||
return list(b)
|
||||
|
||||
#? float()
|
||||
first(1.0)[0]
|
||||
|
||||
def third():
|
||||
b = []
|
||||
b.extend
|
||||
extend()
|
||||
b.extend(first())
|
||||
return list(b)
|
||||
#?
|
||||
third()[0]
|
||||
|
||||
|
||||
# -----------------
|
||||
# set.add
|
||||
# -----------------
|
||||
# Set literals are not valid in 2.6.
|
||||
# python >= 2.7
|
||||
st = {1.0}
|
||||
for a in [1,2]:
|
||||
st.add(a)
|
||||
|
||||
st.append('') # lists should not have an influence
|
||||
|
||||
st.add # should not cause an exception
|
||||
st.add()
|
||||
|
||||
st = {1.0}
|
||||
st.add(1)
|
||||
lst = list(st)
|
||||
|
||||
lst.append('')
|
||||
|
||||
#? float() int() str()
|
||||
lst[0]
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
"""
|
||||
This is used for dynamic object completion.
|
||||
Jedi tries to guess param types with a backtracking approach.
|
||||
"""
|
||||
def func(a, default_arg=2):
|
||||
#? int()
|
||||
default_arg
|
||||
#? int() str()
|
||||
return a
|
||||
|
||||
#? int()
|
||||
func(1)
|
||||
|
||||
func
|
||||
|
||||
int(1) + (int(2))+ func('')
|
||||
|
||||
# Again the same function, but with another call.
|
||||
def func(a):
|
||||
#? float()
|
||||
return a
|
||||
|
||||
func(1.0)
|
||||
|
||||
# Again the same function, but with no call.
|
||||
def func(a):
|
||||
#?
|
||||
return a
|
||||
|
||||
def func(a):
|
||||
#? float()
|
||||
return a
|
||||
str(func(1.0))
|
||||
|
||||
# -----------------
|
||||
# *args, **args
|
||||
# -----------------
|
||||
def arg(*args):
|
||||
#? tuple()
|
||||
args
|
||||
#? int()
|
||||
args[0]
|
||||
|
||||
arg(1,"")
|
||||
# -----------------
|
||||
# decorators
|
||||
# -----------------
|
||||
def def_func(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
@def_func
|
||||
def func(c):
|
||||
#? str()
|
||||
return c
|
||||
|
||||
#? str()
|
||||
func("something")
|
||||
|
||||
@def_func
|
||||
def func(c=1):
|
||||
#? float()
|
||||
return c
|
||||
|
||||
func(1.0)
|
||||
|
||||
def tricky_decorator(func):
|
||||
def wrapper(*args):
|
||||
return func(1, *args)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@tricky_decorator
|
||||
def func(a, b):
|
||||
#? int()
|
||||
a
|
||||
#? float()
|
||||
b
|
||||
|
||||
func(1.0)
|
||||
|
||||
# Needs to be here, because in this case func is an import -> shouldn't lead to
|
||||
# exceptions.
|
||||
import sys as func
|
||||
func.sys
|
||||
|
||||
# -----------------
|
||||
# classes
|
||||
# -----------------
|
||||
|
||||
class A():
|
||||
def __init__(self, a):
|
||||
#? str()
|
||||
a
|
||||
|
||||
A("s")
|
||||
|
||||
class A():
|
||||
def __init__(self, a):
|
||||
#? int()
|
||||
a
|
||||
self.a = a
|
||||
|
||||
def test(self, a):
|
||||
#? float()
|
||||
a
|
||||
self.c = self.test2()
|
||||
|
||||
def test2(self):
|
||||
#? int()
|
||||
return self.a
|
||||
|
||||
def test3(self):
|
||||
#? int()
|
||||
self.test2()
|
||||
#? int()
|
||||
self.c
|
||||
|
||||
A(3).test(2.0)
|
||||
A(3).test2()
|
||||
|
||||
|
||||
# -----------------
|
||||
# comprehensions
|
||||
# -----------------
|
||||
|
||||
def from_comprehension(foo):
|
||||
#? int() float()
|
||||
return foo
|
||||
|
||||
[from_comprehension(1.0) for n in (1,)]
|
||||
[from_comprehension(n) for n in (1,)]
|
||||
@@ -0,0 +1,298 @@
|
||||
# -----------------
|
||||
# First a few name resolution things
|
||||
# -----------------
|
||||
|
||||
x = 3
|
||||
if NOT_DEFINED:
|
||||
x = ''
|
||||
#? 6 int()
|
||||
elif x:
|
||||
pass
|
||||
else:
|
||||
#? int()
|
||||
x
|
||||
|
||||
x = 1
|
||||
try:
|
||||
x = ''
|
||||
#? 8 int() str()
|
||||
except x:
|
||||
#? 5 int() str()
|
||||
x
|
||||
x = 1.0
|
||||
else:
|
||||
#? 5 int() str()
|
||||
x
|
||||
x = list
|
||||
finally:
|
||||
#? 5 int() str() float() list
|
||||
x
|
||||
x = tuple
|
||||
|
||||
|
||||
# -----------------
|
||||
# Return checks
|
||||
# -----------------
|
||||
|
||||
def foo(x):
|
||||
if 1.0:
|
||||
return 1
|
||||
else:
|
||||
return ''
|
||||
|
||||
#? int()
|
||||
foo(1)
|
||||
|
||||
|
||||
# Exceptions are not analyzed. So check both if branches
|
||||
def try_except(x):
|
||||
try:
|
||||
if 0:
|
||||
return 1
|
||||
else:
|
||||
return ''
|
||||
except AttributeError:
|
||||
return 1.0
|
||||
|
||||
#? float() str()
|
||||
try_except(1)
|
||||
|
||||
|
||||
# Exceptions are not analyzed. So check both if branches
|
||||
def try_except(x):
|
||||
try:
|
||||
if 0:
|
||||
return 1
|
||||
else:
|
||||
return ''
|
||||
except AttributeError:
|
||||
return 1.0
|
||||
|
||||
#? float() str()
|
||||
try_except(1)
|
||||
|
||||
|
||||
# -----------------
|
||||
# elif
|
||||
# -----------------
|
||||
|
||||
def elif_flows1(x):
|
||||
if False:
|
||||
return 1
|
||||
elif True:
|
||||
return 1.0
|
||||
else:
|
||||
return ''
|
||||
|
||||
#? float()
|
||||
elif_flows1(1)
|
||||
|
||||
|
||||
def elif_flows2(x):
|
||||
try:
|
||||
if False:
|
||||
return 1
|
||||
elif 0:
|
||||
return 1.0
|
||||
else:
|
||||
return ''
|
||||
except ValueError:
|
||||
return set
|
||||
|
||||
#? str() set
|
||||
elif_flows2(1)
|
||||
|
||||
|
||||
def elif_flows3(x):
|
||||
try:
|
||||
if True:
|
||||
return 1
|
||||
elif 0:
|
||||
return 1.0
|
||||
else:
|
||||
return ''
|
||||
except ValueError:
|
||||
return set
|
||||
|
||||
#? int() set
|
||||
elif_flows3(1)
|
||||
|
||||
# -----------------
|
||||
# mid-difficulty if statements
|
||||
# -----------------
|
||||
def check(a):
|
||||
if a is None:
|
||||
return 1
|
||||
return ''
|
||||
return set
|
||||
|
||||
#? int()
|
||||
check(None)
|
||||
#? str()
|
||||
check('asb')
|
||||
|
||||
a = list
|
||||
if 2 == True:
|
||||
a = set
|
||||
elif 1 == True:
|
||||
a = 0
|
||||
|
||||
#? int()
|
||||
a
|
||||
if check != 1:
|
||||
a = ''
|
||||
#? str()
|
||||
a
|
||||
if check == check:
|
||||
a = list
|
||||
#? list
|
||||
a
|
||||
if check != check:
|
||||
a = set
|
||||
else:
|
||||
a = dict
|
||||
#? dict
|
||||
a
|
||||
if not (check is not check):
|
||||
a = 1
|
||||
#? int()
|
||||
a
|
||||
|
||||
|
||||
# -----------------
|
||||
# name resolution
|
||||
# -----------------
|
||||
|
||||
a = list
|
||||
def elif_name(x):
|
||||
try:
|
||||
if True:
|
||||
a = 1
|
||||
elif 0:
|
||||
a = 1.0
|
||||
else:
|
||||
return ''
|
||||
except ValueError:
|
||||
a = x
|
||||
return a
|
||||
|
||||
#? int() set
|
||||
elif_name(set)
|
||||
|
||||
if 0:
|
||||
a = ''
|
||||
else:
|
||||
a = int
|
||||
|
||||
#? int
|
||||
a
|
||||
|
||||
# -----------------
|
||||
# isinstance
|
||||
# -----------------
|
||||
|
||||
class A(): pass
|
||||
|
||||
def isinst(x):
|
||||
if isinstance(x, A):
|
||||
return dict
|
||||
elif isinstance(x, int) and x == 1 or x is True:
|
||||
return set
|
||||
elif isinstance(x, (float, reversed)):
|
||||
return list
|
||||
elif not isinstance(x, str):
|
||||
return tuple
|
||||
return 1
|
||||
|
||||
#? dict
|
||||
isinst(A())
|
||||
#? set
|
||||
isinst(True)
|
||||
#? set
|
||||
isinst(1)
|
||||
#? tuple
|
||||
isinst(2)
|
||||
#? list
|
||||
isinst(1.0)
|
||||
#? tuple
|
||||
isinst(False)
|
||||
#? int()
|
||||
isinst('')
|
||||
|
||||
# -----------------
|
||||
# flows that are not reachable should be able to access parent scopes.
|
||||
# -----------------
|
||||
|
||||
foobar = ''
|
||||
|
||||
if 0:
|
||||
within_flow = 1.0
|
||||
#? float()
|
||||
within_flow
|
||||
#? str()
|
||||
foobar
|
||||
if 0:
|
||||
nested = 1
|
||||
#? int()
|
||||
nested
|
||||
#? float()
|
||||
within_flow
|
||||
#? str()
|
||||
foobar
|
||||
#?
|
||||
nested
|
||||
|
||||
if False:
|
||||
in_false = 1
|
||||
#? ['in_false']
|
||||
in_false
|
||||
|
||||
# -----------------
|
||||
# True objects like modules
|
||||
# -----------------
|
||||
|
||||
class X():
|
||||
pass
|
||||
if X:
|
||||
a = 1
|
||||
else:
|
||||
a = ''
|
||||
#? int()
|
||||
a
|
||||
|
||||
|
||||
# -----------------
|
||||
# Recursion issues
|
||||
# -----------------
|
||||
|
||||
def possible_recursion_error(filename):
|
||||
if filename == 'a':
|
||||
return filename
|
||||
# It seems like without the brackets there wouldn't be a RecursionError.
|
||||
elif type(filename) == str:
|
||||
return filename
|
||||
|
||||
|
||||
if NOT_DEFINED:
|
||||
s = str()
|
||||
else:
|
||||
s = str()
|
||||
#? str()
|
||||
possible_recursion_error(s)
|
||||
|
||||
|
||||
# -----------------
|
||||
# In combination with imports
|
||||
# -----------------
|
||||
|
||||
from import_tree import flow_import
|
||||
|
||||
if 1 == flow_import.env:
|
||||
a = 1
|
||||
elif 2 == flow_import.env:
|
||||
a = ''
|
||||
elif 3 == flow_import.env:
|
||||
a = 1.0
|
||||
|
||||
#? int() str()
|
||||
a
|
||||
@@ -0,0 +1,481 @@
|
||||
def x():
|
||||
return
|
||||
|
||||
#? None
|
||||
x()
|
||||
|
||||
def array(first_param):
|
||||
#? ['first_param']
|
||||
first_param
|
||||
return list()
|
||||
|
||||
#? []
|
||||
array.first_param
|
||||
#? []
|
||||
array.first_param.
|
||||
func = array
|
||||
#? []
|
||||
func.first_param
|
||||
|
||||
#? list()
|
||||
array()
|
||||
|
||||
#? ['array']
|
||||
arr
|
||||
|
||||
|
||||
def inputs(param):
|
||||
return param
|
||||
|
||||
#? list
|
||||
inputs(list)
|
||||
|
||||
def variable_middle():
|
||||
var = 3
|
||||
return var
|
||||
|
||||
#? int()
|
||||
variable_middle()
|
||||
|
||||
def variable_rename(param):
|
||||
var = param
|
||||
return var
|
||||
|
||||
#? int()
|
||||
variable_rename(1)
|
||||
|
||||
def multi_line_func(a, # comment blabla
|
||||
|
||||
b):
|
||||
return b
|
||||
|
||||
#? str()
|
||||
multi_line_func(1,'')
|
||||
|
||||
def multi_line_call(b):
|
||||
return b
|
||||
|
||||
|
||||
multi_line_call(
|
||||
#? int()
|
||||
b=1)
|
||||
|
||||
|
||||
# nothing after comma
|
||||
def asdf(a):
|
||||
return a
|
||||
|
||||
x = asdf(a=1,
|
||||
)
|
||||
#? int()
|
||||
x
|
||||
|
||||
# -----------------
|
||||
# double execution
|
||||
# -----------------
|
||||
def double_exe(param):
|
||||
return param
|
||||
|
||||
#? str()
|
||||
variable_rename(double_exe)("")
|
||||
|
||||
# -> shouldn't work (and throw no error)
|
||||
#? []
|
||||
variable_rename(list())().
|
||||
#? []
|
||||
variable_rename(1)().
|
||||
|
||||
# -----------------
|
||||
# recursions (should ignore)
|
||||
# -----------------
|
||||
def recursion(a, b):
|
||||
if a:
|
||||
return b
|
||||
else:
|
||||
return recursion(a+".", b+1)
|
||||
|
||||
# Does not also return int anymore, because we now support operators in simple cases.
|
||||
#? float()
|
||||
recursion("a", 1.0)
|
||||
|
||||
def other(a):
|
||||
return recursion2(a)
|
||||
|
||||
def recursion2(a):
|
||||
if random.choice([0, 1]):
|
||||
return other(a)
|
||||
else:
|
||||
if random.choice([0, 1]):
|
||||
return recursion2("")
|
||||
else:
|
||||
return a
|
||||
|
||||
#? int() str()
|
||||
recursion2(1)
|
||||
|
||||
# -----------------
|
||||
# ordering
|
||||
# -----------------
|
||||
|
||||
def a():
|
||||
#? int()
|
||||
b()
|
||||
return b()
|
||||
|
||||
def b():
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
a()
|
||||
|
||||
# -----------------
|
||||
# keyword arguments
|
||||
# -----------------
|
||||
|
||||
def func(a=1, b=''):
|
||||
return a, b
|
||||
|
||||
exe = func(b=list, a=tuple)
|
||||
#? tuple
|
||||
exe[0]
|
||||
|
||||
#? list
|
||||
exe[1]
|
||||
|
||||
# -----------------
|
||||
# default arguments
|
||||
# -----------------
|
||||
|
||||
#? int()
|
||||
func()[0]
|
||||
#? str()
|
||||
func()[1]
|
||||
#? float()
|
||||
func(1.0)[0]
|
||||
#? str()
|
||||
func(1.0)[1]
|
||||
|
||||
|
||||
#? float()
|
||||
func(a=1.0)[0]
|
||||
#? str()
|
||||
func(a=1.0)[1]
|
||||
#? int()
|
||||
func(b=1.0)[0]
|
||||
#? float()
|
||||
func(b=1.0)[1]
|
||||
#? list
|
||||
func(a=list, b=set)[0]
|
||||
#? set
|
||||
func(a=list, b=set)[1]
|
||||
|
||||
|
||||
def func_default(a, b=1):
|
||||
return a, b
|
||||
|
||||
|
||||
def nested_default(**kwargs):
|
||||
return func_default(**kwargs)
|
||||
|
||||
#? float()
|
||||
nested_default(a=1.0)[0]
|
||||
#? int()
|
||||
nested_default(a=1.0)[1]
|
||||
#? str()
|
||||
nested_default(a=1.0, b='')[1]
|
||||
|
||||
# Defaults should only work if they are defined before - not after.
|
||||
def default_function(a=default):
|
||||
#?
|
||||
return a
|
||||
|
||||
#?
|
||||
default_function()
|
||||
|
||||
default = int()
|
||||
|
||||
def default_function(a=default):
|
||||
#? int()
|
||||
return a
|
||||
|
||||
#? int()
|
||||
default_function()
|
||||
|
||||
|
||||
# -----------------
|
||||
# closures
|
||||
# -----------------
|
||||
def a():
|
||||
l = 3
|
||||
def func_b():
|
||||
l = ''
|
||||
#? str()
|
||||
l
|
||||
#? ['func_b']
|
||||
func_b
|
||||
#? int()
|
||||
l
|
||||
|
||||
# -----------------
|
||||
# *args
|
||||
# -----------------
|
||||
|
||||
def args_func(*args):
|
||||
#? tuple()
|
||||
return args
|
||||
|
||||
exe = args_func(1, "")
|
||||
#? int()
|
||||
exe[0]
|
||||
#? str()
|
||||
exe[1]
|
||||
|
||||
# illegal args (TypeError)
|
||||
#?
|
||||
args_func(*1)[0]
|
||||
# iterator
|
||||
#? int()
|
||||
args_func(*iter([1]))[0]
|
||||
|
||||
# different types
|
||||
e = args_func(*[1+"", {}])
|
||||
#? int() str()
|
||||
e[0]
|
||||
#? dict()
|
||||
e[1]
|
||||
|
||||
_list = [1,""]
|
||||
exe2 = args_func(_list)[0]
|
||||
|
||||
#? str()
|
||||
exe2[1]
|
||||
|
||||
exe3 = args_func([1,""])[0]
|
||||
|
||||
#? str()
|
||||
exe3[1]
|
||||
|
||||
def args_func(arg1, *args):
|
||||
return arg1, args
|
||||
|
||||
exe = args_func(1, "", list)
|
||||
#? int()
|
||||
exe[0]
|
||||
#? tuple()
|
||||
exe[1]
|
||||
#? list
|
||||
exe[1][1]
|
||||
|
||||
|
||||
# In a dynamic search, both inputs should be given.
|
||||
def simple(a):
|
||||
#? int() str()
|
||||
return a
|
||||
def xargs(*args):
|
||||
return simple(*args)
|
||||
|
||||
xargs(1)
|
||||
xargs('')
|
||||
|
||||
|
||||
# *args without a self symbol
|
||||
def memoize(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
class Something():
|
||||
@memoize
|
||||
def x(self, a, b=1):
|
||||
return a
|
||||
|
||||
#? int()
|
||||
Something().x(1)
|
||||
|
||||
|
||||
# -----------------
|
||||
# ** kwargs
|
||||
# -----------------
|
||||
def kwargs_func(**kwargs):
|
||||
#? ['keys']
|
||||
kwargs.keys
|
||||
#? dict()
|
||||
return kwargs
|
||||
|
||||
exe = kwargs_func(a=3,b=4.0)
|
||||
#? dict()
|
||||
exe
|
||||
#? int()
|
||||
exe['a']
|
||||
#? float()
|
||||
exe['b']
|
||||
#? int() float()
|
||||
exe['c']
|
||||
|
||||
a = 'a'
|
||||
exe2 = kwargs_func(**{a:3,
|
||||
'b':4.0})
|
||||
#? int()
|
||||
exe2['a']
|
||||
#? float()
|
||||
exe2['b']
|
||||
#? int() float()
|
||||
exe2['c']
|
||||
|
||||
# -----------------
|
||||
# *args / ** kwargs
|
||||
# -----------------
|
||||
|
||||
def func_without_call(*args, **kwargs):
|
||||
#? tuple()
|
||||
args
|
||||
#? dict()
|
||||
kwargs
|
||||
|
||||
def fu(a=1, b="", *args, **kwargs):
|
||||
return a, b, args, kwargs
|
||||
|
||||
exe = fu(list, 1, "", c=set, d="")
|
||||
|
||||
#? list
|
||||
exe[0]
|
||||
#? int()
|
||||
exe[1]
|
||||
#? tuple()
|
||||
exe[2]
|
||||
#? str()
|
||||
exe[2][0]
|
||||
#? dict()
|
||||
exe[3]
|
||||
#? set
|
||||
exe[3]['c']
|
||||
|
||||
|
||||
def kwargs_iteration(**kwargs):
|
||||
return kwargs
|
||||
|
||||
for x in kwargs_iteration(d=3):
|
||||
#? float()
|
||||
{'d': 1.0, 'c': '1'}[x]
|
||||
|
||||
|
||||
# -----------------
|
||||
# nested *args
|
||||
# -----------------
|
||||
def function_args(a, b, c):
|
||||
return b
|
||||
|
||||
def nested_args(*args):
|
||||
return function_args(*args)
|
||||
|
||||
def nested_args2(*args, **kwargs):
|
||||
return nested_args(*args)
|
||||
|
||||
#? int()
|
||||
nested_args('', 1, 1.0, list)
|
||||
#? []
|
||||
nested_args('').
|
||||
|
||||
#? int()
|
||||
nested_args2('', 1, 1.0)
|
||||
#? []
|
||||
nested_args2('').
|
||||
|
||||
# -----------------
|
||||
# nested **kwargs
|
||||
# -----------------
|
||||
def nested_kw(**kwargs1):
|
||||
return function_args(**kwargs1)
|
||||
|
||||
def nested_kw2(**kwargs2):
|
||||
return nested_kw(**kwargs2)
|
||||
|
||||
# invalid command, doesn't need to return anything
|
||||
#?
|
||||
nested_kw(b=1, c=1.0, list)
|
||||
#? int()
|
||||
nested_kw(b=1)
|
||||
# invalid command, doesn't need to return anything
|
||||
#?
|
||||
nested_kw(d=1.0, b=1, list)
|
||||
#? int()
|
||||
nested_kw(a=3.0, b=1)
|
||||
#? int()
|
||||
nested_kw(b=1, a=r"")
|
||||
#? []
|
||||
nested_kw(1, '').
|
||||
#? []
|
||||
nested_kw(a='').
|
||||
|
||||
#? int()
|
||||
nested_kw2(b=1)
|
||||
#? int()
|
||||
nested_kw2(b=1, c=1.0)
|
||||
#? int()
|
||||
nested_kw2(c=1.0, b=1)
|
||||
#? []
|
||||
nested_kw2('').
|
||||
#? []
|
||||
nested_kw2(a='').
|
||||
#? []
|
||||
nested_kw2('', b=1).
|
||||
|
||||
# -----------------
|
||||
# nested *args/**kwargs
|
||||
# -----------------
|
||||
def nested_both(*args, **kwargs):
|
||||
return function_args(*args, **kwargs)
|
||||
|
||||
def nested_both2(*args, **kwargs):
|
||||
return nested_both(*args, **kwargs)
|
||||
|
||||
# invalid commands, may return whatever.
|
||||
#? list
|
||||
nested_both('', b=1, c=1.0, list)
|
||||
#? list
|
||||
nested_both('', c=1.0, b=1, list)
|
||||
|
||||
#? []
|
||||
nested_both('').
|
||||
|
||||
#? int()
|
||||
nested_both2('', b=1, c=1.0)
|
||||
#? int()
|
||||
nested_both2('', c=1.0, b=1)
|
||||
#? []
|
||||
nested_both2('').
|
||||
|
||||
# -----------------
|
||||
# nested *args/**kwargs with a default arg
|
||||
# -----------------
|
||||
def function_def(a, b, c):
|
||||
return a, b
|
||||
|
||||
def nested_def(a, *args, **kwargs):
|
||||
return function_def(a, *args, **kwargs)
|
||||
|
||||
def nested_def2(*args, **kwargs):
|
||||
return nested_def(*args, **kwargs)
|
||||
|
||||
#? str()
|
||||
nested_def2('', 1, 1.0)[0]
|
||||
#? str()
|
||||
nested_def2('', b=1, c=1.0)[0]
|
||||
#? str()
|
||||
nested_def2('', c=1.0, b=1)[0]
|
||||
#? int()
|
||||
nested_def2('', 1, 1.0)[1]
|
||||
#? int()
|
||||
nested_def2('', b=1, c=1.0)[1]
|
||||
#? int()
|
||||
nested_def2('', c=1.0, b=1)[1]
|
||||
#? []
|
||||
nested_def2('')[1].
|
||||
|
||||
# -----------------
|
||||
# magic methods
|
||||
# -----------------
|
||||
def a(): pass
|
||||
#? ['__closure__']
|
||||
a.__closure__
|
||||
@@ -0,0 +1,231 @@
|
||||
# -----------------
|
||||
# yield statement
|
||||
# -----------------
|
||||
def gen():
|
||||
if random.choice([0, 1]):
|
||||
yield 1
|
||||
else:
|
||||
yield ""
|
||||
|
||||
gen_exe = gen()
|
||||
#? int() str()
|
||||
next(gen_exe)
|
||||
|
||||
#? int() str() list
|
||||
next(gen_exe, list)
|
||||
|
||||
|
||||
def gen_ret(value):
|
||||
yield value
|
||||
|
||||
#? int()
|
||||
next(gen_ret(1))
|
||||
|
||||
#? []
|
||||
next(gen_ret()).
|
||||
|
||||
# generators evaluate to true if cast by bool.
|
||||
a = ''
|
||||
if gen_ret():
|
||||
a = 3
|
||||
#? int()
|
||||
a
|
||||
|
||||
|
||||
# -----------------
|
||||
# generators should not be indexable
|
||||
# -----------------
|
||||
def get(param):
|
||||
if random.choice([0, 1]):
|
||||
yield 1
|
||||
else:
|
||||
yield ""
|
||||
|
||||
#? []
|
||||
get()[0].
|
||||
|
||||
# -----------------
|
||||
# __iter__
|
||||
# -----------------
|
||||
for a in get():
|
||||
#? int() str()
|
||||
a
|
||||
|
||||
|
||||
class Get():
|
||||
def __iter__(self):
|
||||
if random.choice([0, 1]):
|
||||
yield 1
|
||||
else:
|
||||
yield ""
|
||||
|
||||
b = []
|
||||
for a in Get():
|
||||
#? int() str()
|
||||
a
|
||||
b += [a]
|
||||
|
||||
#? list()
|
||||
b
|
||||
#? int() str()
|
||||
b[0]
|
||||
|
||||
g = iter(Get())
|
||||
#? int() str()
|
||||
next(g)
|
||||
|
||||
g = iter([1.0])
|
||||
#? float()
|
||||
next(g)
|
||||
|
||||
|
||||
# -----------------
|
||||
# __next__
|
||||
# -----------------
|
||||
class Counter:
|
||||
def __init__(self, low, high):
|
||||
self.current = low
|
||||
self.high = high
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
""" need to have both __next__ and next, because of py2/3 testing """
|
||||
return self.__next__()
|
||||
|
||||
def __next__(self):
|
||||
if self.current > self.high:
|
||||
raise StopIteration
|
||||
else:
|
||||
self.current += 1
|
||||
return self.current - 1
|
||||
|
||||
|
||||
for c in Counter(3, 8):
|
||||
#? int()
|
||||
print c
|
||||
|
||||
|
||||
# -----------------
|
||||
# tuple assignments
|
||||
# -----------------
|
||||
def gen():
|
||||
if random.choice([0,1]):
|
||||
yield 1, ""
|
||||
else:
|
||||
yield 2, 1.0
|
||||
|
||||
|
||||
a, b = next(gen())
|
||||
#? int()
|
||||
a
|
||||
#? str() float()
|
||||
b
|
||||
|
||||
|
||||
def simple():
|
||||
if random.choice([0, 1]):
|
||||
yield 1
|
||||
else:
|
||||
yield ""
|
||||
|
||||
a, b = simple()
|
||||
#? int() str()
|
||||
a
|
||||
# For now this is ok.
|
||||
#?
|
||||
b
|
||||
|
||||
|
||||
def simple2():
|
||||
yield 1
|
||||
yield ""
|
||||
|
||||
a, b = simple2()
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
b
|
||||
|
||||
a, = (a for a in [1])
|
||||
#? int()
|
||||
a
|
||||
|
||||
# -----------------
|
||||
# More complicated access
|
||||
# -----------------
|
||||
|
||||
# `close` is a method wrapper.
|
||||
#? ['__call__']
|
||||
gen().close.__call__
|
||||
|
||||
#?
|
||||
gen().throw()
|
||||
|
||||
#? ['co_consts']
|
||||
gen().gi_code.co_consts
|
||||
|
||||
#? []
|
||||
gen.gi_code.co_consts
|
||||
|
||||
# `send` is also a method wrapper.
|
||||
#? ['__call__']
|
||||
gen().send.__call__
|
||||
|
||||
#? tuple()
|
||||
gen().send()
|
||||
|
||||
#?
|
||||
gen()()
|
||||
|
||||
# -----------------
|
||||
# empty yield
|
||||
# -----------------
|
||||
|
||||
def x():
|
||||
yield
|
||||
|
||||
#? None
|
||||
next(x())
|
||||
#? gen()
|
||||
x()
|
||||
|
||||
def x():
|
||||
for i in range(3):
|
||||
yield
|
||||
|
||||
#? None
|
||||
next(x())
|
||||
|
||||
# -----------------
|
||||
# yield in expression
|
||||
# -----------------
|
||||
|
||||
def x():
|
||||
a= [(yield 1)]
|
||||
|
||||
#? int()
|
||||
next(x())
|
||||
|
||||
# -----------------
|
||||
# yield from
|
||||
# -----------------
|
||||
|
||||
# python >= 3.3
|
||||
|
||||
def yield_from():
|
||||
yield from iter([1])
|
||||
|
||||
#? int()
|
||||
next(yield_from())
|
||||
|
||||
def yield_from_multiple():
|
||||
yield from iter([1])
|
||||
yield str()
|
||||
|
||||
x, y = yield_from_multiple()
|
||||
#? int()
|
||||
x
|
||||
#? str()
|
||||
y
|
||||
@@ -0,0 +1,231 @@
|
||||
# goto_assignments command tests are different in syntax
|
||||
|
||||
definition = 3
|
||||
#! 0 ['a = definition']
|
||||
a = definition
|
||||
|
||||
#! []
|
||||
b
|
||||
#! ['a = definition']
|
||||
a
|
||||
|
||||
b = a
|
||||
c = b
|
||||
#! ['c = b']
|
||||
c
|
||||
|
||||
cd = 1
|
||||
#! 1 ['cd = c']
|
||||
cd = c
|
||||
#! 0 ['cd = e']
|
||||
cd = e
|
||||
|
||||
#! ['module math']
|
||||
import math
|
||||
#! ['module math']
|
||||
math
|
||||
|
||||
#! ['module math']
|
||||
b = math
|
||||
#! ['b = math']
|
||||
b
|
||||
|
||||
#! 18 ['foo = 10']
|
||||
foo = 10;print(foo)
|
||||
|
||||
# -----------------
|
||||
# classes
|
||||
# -----------------
|
||||
class C(object):
|
||||
def b(self):
|
||||
#! ['b = math']
|
||||
b
|
||||
#! ['def b']
|
||||
self.b
|
||||
#! 14 ['def b']
|
||||
self.b()
|
||||
#! 11 ['param self']
|
||||
self.b
|
||||
return 1
|
||||
|
||||
#! ['def b']
|
||||
b
|
||||
|
||||
#! ['b = math']
|
||||
b
|
||||
|
||||
#! ['def b']
|
||||
C.b
|
||||
#! ['def b']
|
||||
C().b
|
||||
#! 0 ['class C']
|
||||
C().b
|
||||
#! 0 ['class C']
|
||||
C().b
|
||||
|
||||
D = C
|
||||
#! ['def b']
|
||||
D.b
|
||||
#! ['def b']
|
||||
D().b
|
||||
|
||||
#! 0 ['D = C']
|
||||
D().b
|
||||
#! 0 ['D = C']
|
||||
D().b
|
||||
|
||||
def c():
|
||||
return ''
|
||||
|
||||
#! ['def c']
|
||||
c
|
||||
#! 0 ['def c']
|
||||
c()
|
||||
|
||||
|
||||
class ClassVar():
|
||||
x = 3
|
||||
|
||||
#! ['x = 3']
|
||||
ClassVar.x
|
||||
#! ['x = 3']
|
||||
ClassVar().x
|
||||
|
||||
# before assignments
|
||||
#! 10 ['x = 3']
|
||||
ClassVar.x = ''
|
||||
#! 12 ['x = 3']
|
||||
ClassVar().x = ''
|
||||
|
||||
# Recurring use of the same var name, github #315
|
||||
def f(t=None):
|
||||
#! 9 ['param t=None']
|
||||
t = t or 1
|
||||
|
||||
|
||||
class X():
|
||||
pass
|
||||
|
||||
#! 3 []
|
||||
X(foo=x)
|
||||
|
||||
# -----------------
|
||||
# imports
|
||||
# -----------------
|
||||
|
||||
#! ['module import_tree']
|
||||
import import_tree
|
||||
#! ["a = ''"]
|
||||
import_tree.a
|
||||
|
||||
#! ['module mod1']
|
||||
import import_tree.mod1
|
||||
#! ['a = 1']
|
||||
import_tree.mod1.a
|
||||
|
||||
#! ['module pkg']
|
||||
import import_tree.pkg
|
||||
#! ['a = list']
|
||||
import_tree.pkg.a
|
||||
|
||||
#! ['module mod1']
|
||||
import import_tree.pkg.mod1
|
||||
#! ['a = 1.0']
|
||||
import_tree.pkg.mod1.a
|
||||
#! ["a = ''"]
|
||||
import_tree.a
|
||||
|
||||
#! ['module mod1']
|
||||
from import_tree.pkg import mod1
|
||||
#! ['a = 1.0']
|
||||
mod1.a
|
||||
|
||||
#! ['module mod1']
|
||||
from import_tree import mod1
|
||||
#! ['a = 1']
|
||||
mod1.a
|
||||
|
||||
#! ['a = 1.0']
|
||||
from import_tree.pkg.mod1 import a
|
||||
|
||||
#! ['module os']
|
||||
from .imports import os
|
||||
|
||||
#! ['some_variable = 1']
|
||||
from . import some_variable
|
||||
|
||||
# -----------------
|
||||
# anonymous classes
|
||||
# -----------------
|
||||
def func():
|
||||
class A():
|
||||
def b(self):
|
||||
return 1
|
||||
return A()
|
||||
|
||||
#! 8 ['def b']
|
||||
func().b()
|
||||
|
||||
# -----------------
|
||||
# on itself
|
||||
# -----------------
|
||||
|
||||
#! 7 ['class ClassDef']
|
||||
class ClassDef():
|
||||
""" abc """
|
||||
pass
|
||||
|
||||
# -----------------
|
||||
# params
|
||||
# -----------------
|
||||
|
||||
param = ClassDef
|
||||
#! 8 ['param param']
|
||||
def ab1(param): pass
|
||||
#! 9 ['param param']
|
||||
def ab2(param): pass
|
||||
#! 11 ['param = ClassDef']
|
||||
def ab3(a=param): pass
|
||||
|
||||
ab1(ClassDef);ab2(ClassDef);ab3(ClassDef)
|
||||
|
||||
# -----------------
|
||||
# for loops
|
||||
# -----------------
|
||||
|
||||
for i in range(1):
|
||||
#! ['for i in range(1): i']
|
||||
i
|
||||
|
||||
for key, value in [(1,2)]:
|
||||
#! ['for key, value in [(1,2)]: key']
|
||||
key
|
||||
|
||||
for i in []:
|
||||
#! ['for i in []: i']
|
||||
i
|
||||
|
||||
# -----------------
|
||||
# decorator
|
||||
# -----------------
|
||||
def dec(dec_param=3):
|
||||
pass
|
||||
|
||||
#! 8 ['param dec_param=3']
|
||||
@dec(dec_param=5)
|
||||
def y():
|
||||
pass
|
||||
|
||||
class ClassDec():
|
||||
def class_func(func):
|
||||
return func
|
||||
|
||||
#! 14 ['def class_func']
|
||||
@ClassDec.class_func
|
||||
def x():
|
||||
pass
|
||||
|
||||
#! 2 ['class ClassDec']
|
||||
@ClassDec.class_func
|
||||
def z():
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
a = ''
|
||||
|
||||
from . import invisible_pkg
|
||||
|
||||
the_pkg = invisible_pkg
|
||||
|
||||
invisible_pkg = 1
|
||||
@@ -0,0 +1,10 @@
|
||||
blub = 1
|
||||
|
||||
class Config2():
|
||||
pass
|
||||
|
||||
|
||||
class BaseClass():
|
||||
mode = Config2()
|
||||
if isinstance(whaat, int):
|
||||
mode2 = whaat
|
||||
@@ -0,0 +1,4 @@
|
||||
if name:
|
||||
env = 1
|
||||
else:
|
||||
env = 2
|
||||
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
It should not be possible to import this pkg except for the import_tree itself,
|
||||
because it is overwritten there. (It would be possible with a sys.path
|
||||
modification, though).
|
||||
"""
|
||||
|
||||
foo = 1.0
|
||||
@@ -0,0 +1,4 @@
|
||||
a = 1
|
||||
from import_tree.random import a as c
|
||||
|
||||
foobarbaz = 3.0
|
||||
@@ -0,0 +1 @@
|
||||
from . import mod1 as fake
|
||||
@@ -0,0 +1,3 @@
|
||||
a = list
|
||||
|
||||
from math import *
|
||||
@@ -0,0 +1,3 @@
|
||||
a = 1.0
|
||||
|
||||
from ..random import foobar
|
||||
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
Here because random is also a builtin module.
|
||||
"""
|
||||
a = set
|
||||
|
||||
foobar = 0
|
||||
@@ -0,0 +1,5 @@
|
||||
import recurse_class2
|
||||
|
||||
class C(recurse_class2.C):
|
||||
def a(self):
|
||||
pass
|
||||
@@ -0,0 +1,4 @@
|
||||
import recurse_class1
|
||||
|
||||
class C(recurse_class1.C):
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
""" used for renaming tests """
|
||||
|
||||
abc = 3
|
||||
@@ -0,0 +1,6 @@
|
||||
""" used for renaming tests """
|
||||
|
||||
|
||||
from rename1 import abc
|
||||
|
||||
abc
|
||||
@@ -0,0 +1,295 @@
|
||||
# -----------------
|
||||
# own structure
|
||||
# -----------------
|
||||
|
||||
# do separate scopes
|
||||
def scope_basic():
|
||||
from import_tree import mod1
|
||||
|
||||
#? int()
|
||||
mod1.a
|
||||
|
||||
#? []
|
||||
import_tree.a
|
||||
|
||||
#? []
|
||||
import_tree.mod1
|
||||
|
||||
import import_tree
|
||||
#? str()
|
||||
import_tree.a
|
||||
|
||||
|
||||
def scope_pkg():
|
||||
import import_tree.mod1
|
||||
|
||||
#? str()
|
||||
import_tree.a
|
||||
|
||||
#? ['mod1']
|
||||
import_tree.mod1
|
||||
|
||||
#? int()
|
||||
import_tree.mod1.a
|
||||
|
||||
def scope_nested():
|
||||
import import_tree.pkg.mod1
|
||||
|
||||
#? str()
|
||||
import_tree.a
|
||||
|
||||
#? list
|
||||
import_tree.pkg.a
|
||||
|
||||
#? ['sqrt']
|
||||
import_tree.pkg.sqrt
|
||||
|
||||
#? ['pkg']
|
||||
import_tree.p
|
||||
|
||||
#? float()
|
||||
import_tree.pkg.mod1.a
|
||||
#? ['a', 'foobar', '__name__', '__package__', '__file__', '__doc__']
|
||||
a = import_tree.pkg.mod1.
|
||||
|
||||
import import_tree.random
|
||||
#? set
|
||||
import_tree.random.a
|
||||
|
||||
def scope_nested2():
|
||||
"""Multiple modules should be indexable, if imported"""
|
||||
import import_tree.mod1
|
||||
import import_tree.pkg
|
||||
#? ['mod1']
|
||||
import_tree.mod1
|
||||
#? ['pkg']
|
||||
import_tree.pkg
|
||||
|
||||
# With the latest changes this completion also works, because submodules
|
||||
# are always included (some nested import structures lead to this,
|
||||
# typically).
|
||||
#? ['rename1']
|
||||
import_tree.rename1
|
||||
|
||||
def scope_from_import_variable():
|
||||
"""
|
||||
All of them shouldn't work, because "fake" imports don't work in python
|
||||
without the use of ``sys.modules`` modifications (e.g. ``os.path`` see also
|
||||
github issue #213 for clarification.
|
||||
"""
|
||||
a = 3
|
||||
#?
|
||||
from import_tree.mod2.fake import a
|
||||
#?
|
||||
from import_tree.mod2.fake import c
|
||||
|
||||
#?
|
||||
a
|
||||
#?
|
||||
c
|
||||
|
||||
def scope_from_import_variable_with_parenthesis():
|
||||
from import_tree.mod2.fake import (
|
||||
a, foobarbaz
|
||||
)
|
||||
|
||||
#?
|
||||
a
|
||||
#?
|
||||
foobarbaz
|
||||
# shouldn't complete, should still list the name though.
|
||||
#? ['foobarbaz']
|
||||
foobarbaz
|
||||
|
||||
|
||||
def as_imports():
|
||||
from import_tree.mod1 import a as xyz
|
||||
#? int()
|
||||
xyz
|
||||
import not_existant, import_tree.mod1 as foo
|
||||
#? int()
|
||||
foo.a
|
||||
import import_tree.mod1 as bar
|
||||
#? int()
|
||||
bar.a
|
||||
|
||||
|
||||
def test_import_priorities():
|
||||
"""
|
||||
It's possible to overwrite import paths in an ``__init__.py`` file, by
|
||||
just assigining something there.
|
||||
|
||||
See also #536.
|
||||
"""
|
||||
from import_tree import the_pkg, invisible_pkg
|
||||
#? int()
|
||||
invisible_pkg
|
||||
# In real Python, this would be the module, but it's not, because Jedi
|
||||
# doesn't care about most stateful issues such as __dict__, which it would
|
||||
# need to, to do this in a correct way.
|
||||
#? int()
|
||||
the_pkg
|
||||
# Importing foo is still possible, even though inivisible_pkg got changed.
|
||||
#? float()
|
||||
from import_tree.invisible_pkg import foo
|
||||
|
||||
|
||||
# -----------------
|
||||
# std lib modules
|
||||
# -----------------
|
||||
import tokenize
|
||||
#? ['tok_name']
|
||||
tokenize.tok_name
|
||||
|
||||
from pyclbr import *
|
||||
|
||||
#? ['readmodule_ex']
|
||||
readmodule_ex
|
||||
import os
|
||||
|
||||
#? ['dirname']
|
||||
os.path.dirname
|
||||
|
||||
from os.path import (
|
||||
expanduser
|
||||
)
|
||||
|
||||
#? os.path.expanduser
|
||||
expanduser
|
||||
|
||||
from itertools import (tee,
|
||||
islice)
|
||||
#? ['islice']
|
||||
islice
|
||||
|
||||
from functools import (partial, wraps)
|
||||
#? ['wraps']
|
||||
wraps
|
||||
|
||||
from keyword import kwlist, \
|
||||
iskeyword
|
||||
#? ['kwlist']
|
||||
kwlist
|
||||
|
||||
#? []
|
||||
from keyword import not_existing1, not_existing2
|
||||
|
||||
from tokenize import io
|
||||
tokenize.generate_tokens
|
||||
|
||||
# -----------------
|
||||
# builtins
|
||||
# -----------------
|
||||
|
||||
import sys
|
||||
#? ['prefix']
|
||||
sys.prefix
|
||||
|
||||
#? ['append']
|
||||
sys.path.append
|
||||
|
||||
from math import *
|
||||
#? ['cos', 'cosh']
|
||||
cos
|
||||
|
||||
def func_with_import():
|
||||
import time
|
||||
return time
|
||||
|
||||
#? ['sleep']
|
||||
func_with_import().sleep
|
||||
|
||||
# -----------------
|
||||
# relative imports
|
||||
# -----------------
|
||||
|
||||
from .import_tree import mod1
|
||||
#? int()
|
||||
mod1.a
|
||||
|
||||
from ..import_tree import mod1
|
||||
#?
|
||||
mod1.a
|
||||
|
||||
from .......import_tree import mod1
|
||||
#?
|
||||
mod1.a
|
||||
|
||||
from .. import helpers
|
||||
#? int()
|
||||
helpers.sample_int
|
||||
|
||||
from ..helpers import sample_int as f
|
||||
#? int()
|
||||
f
|
||||
|
||||
from . import run
|
||||
#? []
|
||||
run.
|
||||
|
||||
from . import import_tree as imp_tree
|
||||
#? str()
|
||||
imp_tree.a
|
||||
|
||||
from . import datetime as mod1
|
||||
#? []
|
||||
mod1.
|
||||
|
||||
# self import
|
||||
# this can cause recursions
|
||||
from imports import *
|
||||
|
||||
# -----------------
|
||||
# packages
|
||||
# -----------------
|
||||
|
||||
from import_tree.mod1 import c
|
||||
#? set
|
||||
c
|
||||
|
||||
from import_tree import recurse_class1
|
||||
|
||||
#? ['a']
|
||||
recurse_class1.C.a
|
||||
# github #239 RecursionError
|
||||
#? ['a']
|
||||
recurse_class1.C().a
|
||||
|
||||
# -----------------
|
||||
# Jedi debugging
|
||||
# -----------------
|
||||
|
||||
# memoizing issues (check git history for the fix)
|
||||
import not_existing_import
|
||||
|
||||
if not_existing_import:
|
||||
a = not_existing_import
|
||||
else:
|
||||
a = not_existing_import
|
||||
#?
|
||||
a
|
||||
|
||||
# -----------------
|
||||
# module underscore descriptors
|
||||
# -----------------
|
||||
|
||||
def underscore():
|
||||
import keyword
|
||||
#? ['__file__']
|
||||
keyword.__file__
|
||||
#? str()
|
||||
keyword.__file__
|
||||
|
||||
# Does that also work for the our own module?
|
||||
#? ['__file__']
|
||||
__file__
|
||||
|
||||
|
||||
# -----------------
|
||||
# complex relative imports #784
|
||||
# -----------------
|
||||
def relative():
|
||||
#? ['foobar']
|
||||
from import_tree.pkg.mod1 import foobar
|
||||
#? int()
|
||||
foobar
|
||||
@@ -0,0 +1,214 @@
|
||||
"""
|
||||
This file is less about the results and much more about the fact, that no
|
||||
exception should be thrown.
|
||||
|
||||
Basically this file could change depending on the current implementation. But
|
||||
there should never be any errors.
|
||||
"""
|
||||
|
||||
# wait until keywords are out of definitions (pydoc function).
|
||||
##? 5
|
||||
's'()
|
||||
|
||||
#? []
|
||||
str()).upper
|
||||
|
||||
# -----------------
|
||||
# funcs
|
||||
# -----------------
|
||||
def asdf(a or b): # multiple param names
|
||||
return a
|
||||
|
||||
#?
|
||||
asdf(2)
|
||||
|
||||
asdf = ''
|
||||
|
||||
from a import (b
|
||||
def blub():
|
||||
return 0
|
||||
def wrong_indents():
|
||||
asdf = 3
|
||||
asdf
|
||||
asdf(
|
||||
# TODO this seems to be wrong now?
|
||||
##? int()
|
||||
asdf
|
||||
def openbrace():
|
||||
asdf = 3
|
||||
asdf(
|
||||
#? int()
|
||||
asdf
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
openbrace()
|
||||
|
||||
blub([
|
||||
#? int()
|
||||
openbrace()
|
||||
|
||||
def indentfault():
|
||||
asd(
|
||||
indentback
|
||||
|
||||
#? []
|
||||
indentfault().
|
||||
|
||||
def openbrace2():
|
||||
asd(
|
||||
def normalfunc():
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
normalfunc()
|
||||
|
||||
# dots in param
|
||||
def f(seq1...=None):
|
||||
return seq1
|
||||
#?
|
||||
f(1)
|
||||
|
||||
@
|
||||
def test_empty_decorator():
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
test_empty_decorator()
|
||||
|
||||
def invalid_param(param=):
|
||||
#?
|
||||
param
|
||||
# -----------------
|
||||
# flows
|
||||
# -----------------
|
||||
|
||||
# first part not complete (raised errors)
|
||||
if a
|
||||
a
|
||||
else:
|
||||
#? ['AttributeError']
|
||||
AttributeError
|
||||
|
||||
try
|
||||
#? ['AttributeError']
|
||||
except AttributeError
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
|
||||
#? ['isinstance']
|
||||
if isi
|
||||
try:
|
||||
except TypeError:
|
||||
#? str()
|
||||
str()
|
||||
|
||||
def break(): pass
|
||||
# wrong ternary expression
|
||||
a = ''
|
||||
a = 1 if
|
||||
#? str()
|
||||
a
|
||||
|
||||
# No completions for for loops without the right syntax
|
||||
for for_local in :
|
||||
for_local
|
||||
#? []
|
||||
for_local
|
||||
#?
|
||||
for_local
|
||||
|
||||
|
||||
# -----------------
|
||||
# list comprehensions
|
||||
# -----------------
|
||||
|
||||
a2 = [for a2 in [0]]
|
||||
#?
|
||||
a2[0]
|
||||
|
||||
a3 = [for xyz in]
|
||||
#?
|
||||
a3[0]
|
||||
|
||||
a3 = [a4 for in 'b']
|
||||
#?
|
||||
a3[0]
|
||||
|
||||
a3 = [a4 for a in for x in y]
|
||||
#?
|
||||
a3[0]
|
||||
|
||||
a = [for a in
|
||||
def break(): pass
|
||||
|
||||
#?
|
||||
a[0]
|
||||
|
||||
a = [a for a in [1,2]
|
||||
def break(): pass
|
||||
#?
|
||||
a[0]
|
||||
|
||||
#? []
|
||||
int()).real
|
||||
|
||||
# -----------------
|
||||
# keywords
|
||||
# -----------------
|
||||
|
||||
#! []
|
||||
as
|
||||
|
||||
def empty_assert():
|
||||
x = 3
|
||||
assert
|
||||
#? int()
|
||||
x
|
||||
|
||||
import datetime as
|
||||
|
||||
|
||||
# -----------------
|
||||
# statements
|
||||
# -----------------
|
||||
|
||||
call = ''
|
||||
invalid = .call
|
||||
#?
|
||||
invalid
|
||||
|
||||
invalid = call?.call
|
||||
#? str()
|
||||
invalid
|
||||
|
||||
# comma
|
||||
invalid = ,call
|
||||
#? str()
|
||||
invalid
|
||||
|
||||
|
||||
# -----------------
|
||||
# classes
|
||||
# -----------------
|
||||
|
||||
class BrokenPartsOfClass():
|
||||
def foo(self):
|
||||
# This construct contains two places where Jedi with Python 3 can fail.
|
||||
# It should just ignore those constructs and still execute `bar`.
|
||||
pass
|
||||
if 2:
|
||||
try:
|
||||
pass
|
||||
except ValueError, e:
|
||||
raise TypeError, e
|
||||
else:
|
||||
pass
|
||||
|
||||
def bar(self):
|
||||
self.x = 3
|
||||
return ''
|
||||
|
||||
#? str()
|
||||
BrokenPartsOfClass().bar()
|
||||
@@ -0,0 +1,101 @@
|
||||
if isinstance(i, str):
|
||||
#? str()
|
||||
i
|
||||
|
||||
if isinstance(j, (str, int)):
|
||||
#? str() int()
|
||||
j
|
||||
|
||||
while isinstance(k, (str, int)):
|
||||
#? str() int()
|
||||
k
|
||||
|
||||
if not isinstance(k, (str, int)):
|
||||
#?
|
||||
k
|
||||
|
||||
while not isinstance(k, (str, int)):
|
||||
#?
|
||||
k
|
||||
|
||||
assert isinstance(ass, int)
|
||||
#? int()
|
||||
ass
|
||||
|
||||
assert isinstance(ass, str)
|
||||
assert not isinstance(ass, int)
|
||||
|
||||
if 2:
|
||||
#? str()
|
||||
ass
|
||||
|
||||
# -----------------
|
||||
# invalid arguments
|
||||
# -----------------
|
||||
|
||||
if isinstance(wrong, str()):
|
||||
#?
|
||||
wrong
|
||||
|
||||
# -----------------
|
||||
# in functions
|
||||
# -----------------
|
||||
|
||||
import datetime
|
||||
|
||||
|
||||
def fooooo(obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
#? datetime.datetime()
|
||||
obj
|
||||
|
||||
|
||||
def fooooo2(obj):
|
||||
if isinstance(obj, datetime.date):
|
||||
return obj
|
||||
else:
|
||||
return 1
|
||||
|
||||
a
|
||||
# In earlier versions of Jedi, this returned both datetime and int, but now
|
||||
# Jedi does flow checks and realizes that the top return isn't executed.
|
||||
#? int()
|
||||
fooooo2('')
|
||||
|
||||
|
||||
def isinstance_func(arr):
|
||||
for value in arr:
|
||||
if isinstance(value, dict):
|
||||
# Shouldn't fail, even with the dot.
|
||||
#? 17 dict()
|
||||
value.
|
||||
elif isinstance(value, int):
|
||||
x = value
|
||||
#? int()
|
||||
x
|
||||
|
||||
# -----------------
|
||||
# Names with multiple indices.
|
||||
# -----------------
|
||||
|
||||
class Test():
|
||||
def __init__(self, testing):
|
||||
if isinstance(testing, str):
|
||||
self.testing = testing
|
||||
else:
|
||||
self.testing = 10
|
||||
|
||||
def boo(self):
|
||||
if isinstance(self.testing, str):
|
||||
# TODO this is wrong, it should only be str.
|
||||
#? str() int()
|
||||
self.testing
|
||||
#? Test()
|
||||
self
|
||||
|
||||
# -----------------
|
||||
# Syntax
|
||||
# -----------------
|
||||
|
||||
#?
|
||||
isinstance(1, int())
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
#? ['raise']
|
||||
raise
|
||||
|
||||
#? ['Exception']
|
||||
except
|
||||
|
||||
#? []
|
||||
b + continu
|
||||
|
||||
#? []
|
||||
b + continue
|
||||
|
||||
#? ['continue']
|
||||
b; continue
|
||||
|
||||
#? ['continue']
|
||||
b; continu
|
||||
|
||||
#? []
|
||||
c + brea
|
||||
|
||||
#? []
|
||||
a + break
|
||||
|
||||
#? ['break']
|
||||
b; break
|
||||
|
||||
# -----------------
|
||||
# Keywords should not appear everywhere.
|
||||
# -----------------
|
||||
|
||||
#? []
|
||||
with open() as f
|
||||
#? []
|
||||
def i
|
||||
#? []
|
||||
class i
|
||||
|
||||
#? []
|
||||
continue i
|
||||
|
||||
# More syntax details, e.g. while only after newline, but not after semicolon,
|
||||
# continue also after semicolon
|
||||
#? ['while']
|
||||
while
|
||||
#? []
|
||||
x while
|
||||
#? []
|
||||
x; while
|
||||
#? ['continue']
|
||||
x; continue
|
||||
|
||||
#? []
|
||||
and
|
||||
#? ['and']
|
||||
x and
|
||||
#? []
|
||||
x * and
|
||||
@@ -0,0 +1,113 @@
|
||||
# -----------------
|
||||
# lambdas
|
||||
# -----------------
|
||||
a = lambda: 3
|
||||
#? int()
|
||||
a()
|
||||
|
||||
x = []
|
||||
a = lambda x: x
|
||||
#? int()
|
||||
a(0)
|
||||
|
||||
#? float()
|
||||
(lambda x: x)(3.0)
|
||||
|
||||
arg_l = lambda x, y: y, x
|
||||
#? float()
|
||||
arg_l[0]('', 1.0)
|
||||
#? list()
|
||||
arg_l[1]
|
||||
|
||||
arg_l = lambda x, y: (y, x)
|
||||
args = 1,""
|
||||
result = arg_l(*args)
|
||||
#? tuple()
|
||||
result
|
||||
#? str()
|
||||
result[0]
|
||||
#? int()
|
||||
result[1]
|
||||
|
||||
def with_lambda(callable_lambda, *args, **kwargs):
|
||||
return callable_lambda(1, *args, **kwargs)
|
||||
|
||||
#? int()
|
||||
with_lambda(arg_l, 1.0)[1]
|
||||
#? float()
|
||||
with_lambda(arg_l, 1.0)[0]
|
||||
#? float()
|
||||
with_lambda(arg_l, y=1.0)[0]
|
||||
#? int()
|
||||
with_lambda(lambda x: x)
|
||||
#? float()
|
||||
with_lambda(lambda x, y: y, y=1.0)
|
||||
|
||||
arg_func = lambda *args, **kwargs: (args[0], kwargs['a'])
|
||||
#? int()
|
||||
arg_func(1, 2, a='', b=10)[0]
|
||||
#? list()
|
||||
arg_func(1, 2, a=[], b=10)[1]
|
||||
|
||||
# magic method
|
||||
a = lambda: 3
|
||||
#? ['__closure__']
|
||||
a.__closure__
|
||||
|
||||
class C():
|
||||
def __init__(self, foo=1.0):
|
||||
self.a = lambda: 1
|
||||
self.foo = foo
|
||||
|
||||
def ret(self):
|
||||
return lambda: self.foo
|
||||
|
||||
def with_param(self):
|
||||
return lambda x: x + self.a()
|
||||
|
||||
lambd = lambda self: self.foo
|
||||
|
||||
#? int()
|
||||
C().a()
|
||||
|
||||
#? str()
|
||||
C('foo').ret()()
|
||||
|
||||
index = C().with_param()(1)
|
||||
#? float()
|
||||
['', 1, 1.0][index]
|
||||
|
||||
#? float()
|
||||
C().lambd()
|
||||
#? int()
|
||||
C(1).lambd()
|
||||
|
||||
|
||||
def xy(param):
|
||||
def ret(a, b):
|
||||
return a + b
|
||||
|
||||
return lambda b: ret(param, b)
|
||||
|
||||
#? int()
|
||||
xy(1)(2)
|
||||
|
||||
# -----------------
|
||||
# lambda param (#379)
|
||||
# -----------------
|
||||
class Test(object):
|
||||
def __init__(self, pred=lambda a, b: a):
|
||||
self.a = 1
|
||||
#? int()
|
||||
self.a
|
||||
#? float()
|
||||
pred(1.0, 2)
|
||||
|
||||
# -----------------
|
||||
# test_nocond in grammar (happens in list comprehensions with `if`)
|
||||
# -----------------
|
||||
# Doesn't need to do anything yet. It should just not raise an error. These
|
||||
# nocond lambdas make no sense at all.
|
||||
|
||||
#? int()
|
||||
[a for a in [1,2] if lambda: 3][0]
|
||||
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
Named Params:
|
||||
>>> def a(abc): pass
|
||||
...
|
||||
>>> a(abc=3) # <- this stuff (abc)
|
||||
"""
|
||||
|
||||
def a(abc):
|
||||
pass
|
||||
|
||||
#? 5 ['abc']
|
||||
a(abc)
|
||||
|
||||
|
||||
def a(*some_args, **some_kwargs):
|
||||
pass
|
||||
|
||||
#? 11 []
|
||||
a(some_args)
|
||||
|
||||
#? 13 []
|
||||
a(some_kwargs)
|
||||
|
||||
def multiple(foo, bar):
|
||||
pass
|
||||
|
||||
#? 17 ['bar']
|
||||
multiple(foo, bar)
|
||||
|
||||
#? ['bar']
|
||||
multiple(foo, bar
|
||||
|
||||
my_lambda = lambda lambda_param: lambda_param + 1
|
||||
#? 22 ['lambda_param']
|
||||
my_lambda(lambda_param)
|
||||
|
||||
# __call__ / __init__
|
||||
class Test(object):
|
||||
def __init__(self, hello_other):
|
||||
pass
|
||||
|
||||
def __call__(self, hello):
|
||||
pass
|
||||
|
||||
def test(self, blub):
|
||||
pass
|
||||
|
||||
#? 10 ['hello_other']
|
||||
Test(hello=)
|
||||
#? 12 ['hello']
|
||||
Test()(hello=)
|
||||
#? 11 []
|
||||
Test()(self=)
|
||||
#? 16 []
|
||||
Test().test(self=)
|
||||
#? 16 ['blub']
|
||||
Test().test(blub=)
|
||||
|
||||
# builtins
|
||||
|
||||
#? 12 []
|
||||
any(iterable=)
|
||||
@@ -0,0 +1,110 @@
|
||||
def from_names():
|
||||
#? ['mod1']
|
||||
from import_tree.pkg.
|
||||
#? ['path']
|
||||
from os.
|
||||
|
||||
def from_names_goto():
|
||||
from import_tree import pkg
|
||||
#? pkg
|
||||
from import_tree.pkg
|
||||
|
||||
def builtin_test():
|
||||
#? ['math']
|
||||
import math
|
||||
|
||||
# -----------------
|
||||
# completions within imports
|
||||
# -----------------
|
||||
|
||||
#? ['sqlite3']
|
||||
import sqlite3
|
||||
|
||||
#? ['classes']
|
||||
import classes
|
||||
|
||||
#? ['timedelta']
|
||||
from datetime import timedel
|
||||
#? 21 []
|
||||
from datetime.timedel import timedel
|
||||
|
||||
# should not be possible, because names can only be looked up 1 level deep.
|
||||
#? []
|
||||
from datetime.timedelta import resolution
|
||||
#? []
|
||||
from datetime.timedelta import
|
||||
|
||||
#? ['Cursor']
|
||||
from sqlite3 import Cursor
|
||||
|
||||
#? ['some_variable']
|
||||
from . import some_variable
|
||||
#? ['arrays']
|
||||
from . import arrays
|
||||
#? []
|
||||
from . import import_tree as ren
|
||||
#? []
|
||||
import json as
|
||||
|
||||
import os
|
||||
#? os.path.join
|
||||
from os.path import join
|
||||
|
||||
# -----------------
|
||||
# special positions -> edge cases
|
||||
# -----------------
|
||||
import datetime
|
||||
|
||||
#? 6 datetime
|
||||
from datetime.time import time
|
||||
|
||||
#? []
|
||||
import datetime.
|
||||
#? []
|
||||
import datetime.date
|
||||
|
||||
#? 21 ['import']
|
||||
from import_tree.pkg import pkg
|
||||
#? 49 ['a', 'foobar', '__name__', '__doc__', '__file__', '__package__']
|
||||
from import_tree.pkg.mod1 import not_existant, # whitespace before
|
||||
#? ['a', 'foobar', '__name__', '__doc__', '__file__', '__package__']
|
||||
from import_tree.pkg.mod1 import not_existant,
|
||||
#? 22 ['mod1']
|
||||
from import_tree.pkg. import mod1
|
||||
#? 17 ['mod1', 'mod2', 'random', 'pkg', 'rename1', 'rename2', 'classes', 'recurse_class1', 'recurse_class2', 'invisible_pkg', 'flow_import']
|
||||
from import_tree. import pkg
|
||||
|
||||
#? 18 ['pkg']
|
||||
from import_tree.p import pkg
|
||||
|
||||
#? 17 ['import_tree']
|
||||
from .import_tree import
|
||||
#? 10 ['run']
|
||||
from ..run import
|
||||
#? ['run']
|
||||
from ..run
|
||||
#? 10 ['run']
|
||||
from ..run.
|
||||
#? []
|
||||
from ..run.
|
||||
|
||||
#? ['run']
|
||||
from .. import run
|
||||
|
||||
#? []
|
||||
from not_a_module import
|
||||
|
||||
|
||||
#137
|
||||
import json
|
||||
#? 23 json.dump
|
||||
from json import load, dump
|
||||
#? 17 json.load
|
||||
from json import load, dump
|
||||
# without the from clause:
|
||||
import json, datetime
|
||||
#? 7 json
|
||||
import json, datetime
|
||||
#? 13 datetime
|
||||
import json, datetime
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
# -----------------
|
||||
# normal
|
||||
# -----------------
|
||||
a = ""
|
||||
a = 1
|
||||
|
||||
#? int()
|
||||
a
|
||||
#? []
|
||||
a.append
|
||||
|
||||
a = list
|
||||
|
||||
b = 1; b = ""
|
||||
#? str()
|
||||
b
|
||||
|
||||
# temp should not be accessible before definition
|
||||
#? []
|
||||
temp
|
||||
|
||||
a = 1
|
||||
temp = b;
|
||||
b = a
|
||||
a = temp
|
||||
#? int()
|
||||
b
|
||||
#? int()
|
||||
b
|
||||
#? str()
|
||||
a
|
||||
|
||||
a = tuple
|
||||
if 1:
|
||||
a = list
|
||||
|
||||
#? ['append']
|
||||
a.append
|
||||
#? ['index']
|
||||
a.index
|
||||
|
||||
# -----------------
|
||||
# tuples exchanges
|
||||
# -----------------
|
||||
a, b = 1, ""
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
b
|
||||
|
||||
b, a = a, b
|
||||
#? int()
|
||||
b
|
||||
#? str()
|
||||
a
|
||||
|
||||
b, a = a, b
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
b
|
||||
|
||||
# -----------------
|
||||
# function
|
||||
# -----------------
|
||||
def a(a=3):
|
||||
#? int()
|
||||
a
|
||||
#? []
|
||||
a.func
|
||||
return a
|
||||
|
||||
#? int()
|
||||
a(2)
|
||||
#? []
|
||||
a(2).func
|
||||
|
||||
a_param = 3
|
||||
def func(a_param):
|
||||
# should not be int
|
||||
#? []
|
||||
a_param.
|
||||
|
||||
from os import path
|
||||
|
||||
|
||||
# should not return a function, because `a` is a function above
|
||||
def f(b, a): return a
|
||||
#? []
|
||||
f(b=3).
|
||||
|
||||
# -----------------
|
||||
# closure
|
||||
# -----------------
|
||||
|
||||
def x():
|
||||
a = 0
|
||||
|
||||
def x():
|
||||
return a
|
||||
|
||||
a = 3.0
|
||||
return x()
|
||||
|
||||
#? float()
|
||||
x()
|
||||
|
||||
# -----------------
|
||||
# class
|
||||
# -----------------
|
||||
class A(object):
|
||||
a = ""
|
||||
a = 3
|
||||
#? int()
|
||||
a
|
||||
a = list()
|
||||
def __init__(self):
|
||||
self.b = ""
|
||||
|
||||
def before(self):
|
||||
self.b = 3
|
||||
# TODO should this be so? include entries after cursor?
|
||||
#? int() str() list
|
||||
self.b
|
||||
self.b = list
|
||||
|
||||
self.a = 1
|
||||
#? str() int()
|
||||
self.a
|
||||
|
||||
#? ['after']
|
||||
self.after
|
||||
|
||||
self.c = 3
|
||||
#? int()
|
||||
self.c
|
||||
|
||||
def after(self):
|
||||
self.a = ''
|
||||
|
||||
c = set()
|
||||
|
||||
#? list()
|
||||
A.a
|
||||
|
||||
a = A()
|
||||
#? ['after']
|
||||
a.after
|
||||
#? []
|
||||
a.upper
|
||||
#? []
|
||||
a.append
|
||||
#? []
|
||||
a.real
|
||||
|
||||
#? str() int()
|
||||
a.a
|
||||
|
||||
a = 3
|
||||
class a():
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
|
||||
#? float()
|
||||
a(1.0).a
|
||||
#?
|
||||
a().a
|
||||
|
||||
# -----------------
|
||||
# imports
|
||||
# -----------------
|
||||
|
||||
math = 3
|
||||
import math
|
||||
#? ['cosh']
|
||||
math.cosh
|
||||
#? []
|
||||
math.real
|
||||
|
||||
math = 3
|
||||
#? int()
|
||||
math
|
||||
#? []
|
||||
math.cos
|
||||
|
||||
# do the same for star imports
|
||||
cosh = 3
|
||||
from math import *
|
||||
# cosh doesn't work, but that's not a problem, star imports should be at the
|
||||
# start of EVERY script!
|
||||
cosh.real
|
||||
|
||||
cosh = 3
|
||||
#? int()
|
||||
cosh
|
||||
@@ -0,0 +1,43 @@
|
||||
"""
|
||||
Issues with the parser and not the type inference should be part of this file.
|
||||
"""
|
||||
|
||||
class IndentIssues():
|
||||
"""
|
||||
issue jedi-vim#288
|
||||
Which is really a fast parser issue. It used to start a new block at the
|
||||
parentheses, because it had problems with the indentation.
|
||||
"""
|
||||
def one_param(
|
||||
self,
|
||||
):
|
||||
return 1
|
||||
|
||||
def with_param(
|
||||
self,
|
||||
y):
|
||||
return y
|
||||
|
||||
|
||||
|
||||
#? int()
|
||||
IndentIssues().one_param()
|
||||
|
||||
#? str()
|
||||
IndentIssues().with_param('')
|
||||
|
||||
|
||||
"""
|
||||
Just because there's a def keyword, doesn't mean it should not be able to
|
||||
complete to definition.
|
||||
"""
|
||||
definition = 0
|
||||
#? ['definition']
|
||||
str(def
|
||||
|
||||
|
||||
# It might be hard to determine the context
|
||||
class Foo(object):
|
||||
@property
|
||||
#? ['str']
|
||||
def bar(str
|
||||
@@ -0,0 +1,167 @@
|
||||
""" Pep-0484 type hinting """
|
||||
|
||||
# python >= 3.2
|
||||
|
||||
|
||||
class A():
|
||||
pass
|
||||
|
||||
|
||||
def function_parameters(a: A, b, c: str, d: int, e: str, f: str, g: int=4):
|
||||
"""
|
||||
:param e: if docstring and annotation agree, only one should be returned
|
||||
:type e: str
|
||||
:param f: if docstring and annotation disagree, both should be returned
|
||||
:type f: int
|
||||
"""
|
||||
#? A()
|
||||
a
|
||||
#?
|
||||
b
|
||||
#? str()
|
||||
c
|
||||
#? int()
|
||||
d
|
||||
#? str()
|
||||
e
|
||||
#? int() str()
|
||||
f
|
||||
# int()
|
||||
g
|
||||
|
||||
|
||||
def return_unspecified():
|
||||
pass
|
||||
|
||||
#?
|
||||
return_unspecified()
|
||||
|
||||
|
||||
def return_none() -> None:
|
||||
"""
|
||||
Return type None means the same as no return type as far as jedi
|
||||
is concerned
|
||||
"""
|
||||
pass
|
||||
|
||||
#?
|
||||
return_none()
|
||||
|
||||
|
||||
def return_str() -> str:
|
||||
pass
|
||||
|
||||
#? str()
|
||||
return_str()
|
||||
|
||||
|
||||
def return_custom_class() -> A:
|
||||
pass
|
||||
|
||||
#? A()
|
||||
return_custom_class()
|
||||
|
||||
|
||||
def return_annotation_and_docstring() -> str:
|
||||
"""
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
#? str() int()
|
||||
return_annotation_and_docstring()
|
||||
|
||||
|
||||
def return_annotation_and_docstring_different() -> str:
|
||||
"""
|
||||
:rtype: str
|
||||
"""
|
||||
pass
|
||||
|
||||
#? str()
|
||||
return_annotation_and_docstring_different()
|
||||
|
||||
|
||||
def annotation_forward_reference(b: "B") -> "B":
|
||||
#? B()
|
||||
b
|
||||
|
||||
#? ["test_element"]
|
||||
annotation_forward_reference(1).t
|
||||
|
||||
class B:
|
||||
test_element = 1
|
||||
pass
|
||||
|
||||
#? B()
|
||||
annotation_forward_reference(1)
|
||||
|
||||
|
||||
class SelfReference:
|
||||
test_element = 1
|
||||
def test_method(self, x: "SelfReference") -> "SelfReference":
|
||||
#? SelfReference()
|
||||
x
|
||||
#? ["test_element", "test_method"]
|
||||
self.t
|
||||
#? ["test_element", "test_method"]
|
||||
x.t
|
||||
#? ["test_element", "test_method"]
|
||||
self.test_method(1).t
|
||||
|
||||
#? SelfReference()
|
||||
SelfReference().test_method()
|
||||
|
||||
def function_with_non_pep_0484_annotation(
|
||||
x: "I can put anything here",
|
||||
xx: "",
|
||||
yy: "\r\n\0;+*&^564835(---^&*34",
|
||||
y: 3 + 3,
|
||||
zz: float) -> int("42"):
|
||||
# infers int from function call
|
||||
#? int()
|
||||
x
|
||||
# infers int from function call
|
||||
#? int()
|
||||
xx
|
||||
# infers int from function call
|
||||
#? int()
|
||||
yy
|
||||
# infers str from function call
|
||||
#? str()
|
||||
y
|
||||
#? float()
|
||||
zz
|
||||
#?
|
||||
function_with_non_pep_0484_annotation(1, 2, 3, "force string")
|
||||
|
||||
def function_forward_reference_dynamic(
|
||||
x: return_str_type(),
|
||||
y: "return_str_type()") -> None:
|
||||
#?
|
||||
x
|
||||
#? str()
|
||||
y
|
||||
|
||||
def return_str_type():
|
||||
return str
|
||||
|
||||
|
||||
X = str
|
||||
def function_with_assined_class_in_reference(x: X, y: "Y"):
|
||||
#? str()
|
||||
x
|
||||
#? int()
|
||||
y
|
||||
Y = int
|
||||
|
||||
def just_because_we_can(x: "flo" + "at"):
|
||||
#? float()
|
||||
x
|
||||
|
||||
|
||||
def keyword_only(a: str, *, b: str):
|
||||
#? ['startswith']
|
||||
a.startswi
|
||||
#? ['startswith']
|
||||
b.startswi
|
||||
@@ -0,0 +1,109 @@
|
||||
a = 3 # type: str
|
||||
#? str()
|
||||
a
|
||||
|
||||
b = 3 # type: str but I write more
|
||||
#? int()
|
||||
b
|
||||
|
||||
c = 3 # type: str # I comment more
|
||||
#? str()
|
||||
c
|
||||
|
||||
d = "It should not read comments from the next line"
|
||||
# type: int
|
||||
#? str()
|
||||
d
|
||||
|
||||
# type: int
|
||||
e = "It should not read comments from the previous line"
|
||||
#? str()
|
||||
e
|
||||
|
||||
class BB: pass
|
||||
|
||||
def test(a, b):
|
||||
a = a # type: BB
|
||||
c = a # type: str
|
||||
d = a
|
||||
# type: str
|
||||
e = a # type: str # Should ignore long whitespace
|
||||
|
||||
#? BB()
|
||||
a
|
||||
#? str()
|
||||
c
|
||||
#? BB()
|
||||
d
|
||||
#? str()
|
||||
e
|
||||
|
||||
a,b = 1, 2 # type: str, float
|
||||
#? str()
|
||||
a
|
||||
#? float()
|
||||
b
|
||||
|
||||
class Employee:
|
||||
pass
|
||||
|
||||
# The typing library is not installable for Python 2.6, therefore ignore the
|
||||
# following tests.
|
||||
# python >= 2.7
|
||||
|
||||
from typing import List
|
||||
x = [] # type: List[Employee]
|
||||
#? Employee()
|
||||
x[1]
|
||||
x, y, z = [], [], [] # type: List[int], List[int], List[str]
|
||||
#? int()
|
||||
y[2]
|
||||
x, y, z = [], [], [] # type: (List[float], List[float], List[BB])
|
||||
for zi in z:
|
||||
#? BB()
|
||||
zi
|
||||
|
||||
x = [
|
||||
1,
|
||||
2,
|
||||
] # type: List[str]
|
||||
|
||||
#? str()
|
||||
x[1]
|
||||
|
||||
|
||||
for bar in foo(): # type: str
|
||||
#? str()
|
||||
bar
|
||||
|
||||
for bar, baz in foo(): # type: int, float
|
||||
#? int()
|
||||
bar
|
||||
#? float()
|
||||
baz
|
||||
|
||||
for bar, baz in foo():
|
||||
# type: str, str
|
||||
""" type hinting on next line should not work """
|
||||
#?
|
||||
bar
|
||||
#?
|
||||
baz
|
||||
|
||||
with foo(): # type: int
|
||||
...
|
||||
|
||||
with foo() as f: # type: str
|
||||
#? str()
|
||||
f
|
||||
|
||||
with foo() as f:
|
||||
# type: str
|
||||
""" type hinting on next line should not work """
|
||||
#?
|
||||
f
|
||||
|
||||
aaa = some_extremely_long_function_name_that_doesnt_leave_room_for_hints() \
|
||||
# type: float # We should be able to put hints on the next line with a \
|
||||
#? float()
|
||||
aaa
|
||||
@@ -0,0 +1,263 @@
|
||||
"""
|
||||
Test the typing library, with docstrings. This is needed since annotations
|
||||
are not supported in python 2.7 else then annotating by comment (and this is
|
||||
still TODO at 2016-01-23)
|
||||
"""
|
||||
# There's no Python 2.6 typing module.
|
||||
# python >= 2.7
|
||||
import typing
|
||||
class B:
|
||||
pass
|
||||
|
||||
def we_can_has_sequence(p, q, r, s, t, u):
|
||||
"""
|
||||
:type p: typing.Sequence[int]
|
||||
:type q: typing.Sequence[B]
|
||||
:type r: typing.Sequence[int]
|
||||
:type s: typing.Sequence["int"]
|
||||
:type t: typing.MutableSequence[dict]
|
||||
:type u: typing.List[float]
|
||||
"""
|
||||
#? ["count"]
|
||||
p.c
|
||||
#? int()
|
||||
p[1]
|
||||
#? ["count"]
|
||||
q.c
|
||||
#? B()
|
||||
q[1]
|
||||
#? ["count"]
|
||||
r.c
|
||||
#? int()
|
||||
r[1]
|
||||
#? ["count"]
|
||||
s.c
|
||||
#? int()
|
||||
s[1]
|
||||
#? []
|
||||
s.a
|
||||
#? ["append"]
|
||||
t.a
|
||||
#? dict()
|
||||
t[1]
|
||||
#? ["append"]
|
||||
u.a
|
||||
#? float()
|
||||
u[1]
|
||||
|
||||
def iterators(ps, qs, rs, ts):
|
||||
"""
|
||||
:type ps: typing.Iterable[int]
|
||||
:type qs: typing.Iterator[str]
|
||||
:type rs: typing.Sequence["ForwardReference"]
|
||||
:type ts: typing.AbstractSet["float"]
|
||||
"""
|
||||
for p in ps:
|
||||
#? int()
|
||||
p
|
||||
#?
|
||||
next(ps)
|
||||
a, b = ps
|
||||
#? int()
|
||||
a
|
||||
##? int() --- TODO fix support for tuple assignment
|
||||
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
|
||||
# test below is just to make sure that in case it gets fixed by accident
|
||||
# these tests will be fixed as well the way they should be
|
||||
#?
|
||||
b
|
||||
|
||||
for q in qs:
|
||||
#? str()
|
||||
q
|
||||
#? str()
|
||||
next(qs)
|
||||
for r in rs:
|
||||
#? ForwardReference()
|
||||
r
|
||||
#?
|
||||
next(rs)
|
||||
for t in ts:
|
||||
#? float()
|
||||
t
|
||||
|
||||
def sets(p, q):
|
||||
"""
|
||||
:type p: typing.AbstractSet[int]
|
||||
:type q: typing.MutableSet[float]
|
||||
"""
|
||||
#? []
|
||||
p.a
|
||||
#? ["add"]
|
||||
q.a
|
||||
|
||||
def tuple(p, q, r):
|
||||
"""
|
||||
:type p: typing.Tuple[int]
|
||||
:type q: typing.Tuple[int, str, float]
|
||||
:type r: typing.Tuple[B, ...]
|
||||
"""
|
||||
#? int()
|
||||
p[0]
|
||||
#? int()
|
||||
q[0]
|
||||
#? str()
|
||||
q[1]
|
||||
#? float()
|
||||
q[2]
|
||||
#? B()
|
||||
r[0]
|
||||
#? B()
|
||||
r[1]
|
||||
#? B()
|
||||
r[2]
|
||||
#? B()
|
||||
r[10000]
|
||||
i, s, f = q
|
||||
#? int()
|
||||
i
|
||||
##? str() --- TODO fix support for tuple assignment
|
||||
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
|
||||
#?
|
||||
s
|
||||
##? float() --- TODO fix support for tuple assignment
|
||||
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
|
||||
#?
|
||||
f
|
||||
|
||||
class Key:
|
||||
pass
|
||||
|
||||
class Value:
|
||||
pass
|
||||
|
||||
def mapping(p, q, d, r, s, t):
|
||||
"""
|
||||
:type p: typing.Mapping[Key, Value]
|
||||
:type q: typing.MutableMapping[Key, Value]
|
||||
:type d: typing.Dict[Key, Value]
|
||||
:type r: typing.KeysView[Key]
|
||||
:type s: typing.ValuesView[Value]
|
||||
:type t: typing.ItemsView[Key, Value]
|
||||
"""
|
||||
#? []
|
||||
p.setd
|
||||
#? ["setdefault"]
|
||||
q.setd
|
||||
#? ["setdefault"]
|
||||
d.setd
|
||||
#? Value()
|
||||
p[1]
|
||||
for key in p:
|
||||
#? Key()
|
||||
key
|
||||
for key in p.keys():
|
||||
#? Key()
|
||||
key
|
||||
for value in p.values():
|
||||
#? Value()
|
||||
value
|
||||
for item in p.items():
|
||||
#? Key()
|
||||
item[0]
|
||||
#? Value()
|
||||
item[1]
|
||||
(key, value) = item
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key, value in p.items():
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key in r:
|
||||
#? Key()
|
||||
key
|
||||
for value in s:
|
||||
#? Value()
|
||||
value
|
||||
for key, value in t:
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
|
||||
def union(p, q, r, s, t):
|
||||
"""
|
||||
:type p: typing.Union[int]
|
||||
:type q: typing.Union[int, int]
|
||||
:type r: typing.Union[int, str, "int"]
|
||||
:type s: typing.Union[int, typing.Union[str, "typing.Union['float', 'dict']"]]
|
||||
:type t: typing.Union[int, None]
|
||||
"""
|
||||
#? int()
|
||||
p
|
||||
#? int()
|
||||
q
|
||||
#? int() str()
|
||||
r
|
||||
#? int() str() float() dict()
|
||||
s
|
||||
#? int()
|
||||
t
|
||||
|
||||
def optional(p):
|
||||
"""
|
||||
:type p: typing.Optional[int]
|
||||
Optional does not do anything special. However it should be recognised
|
||||
as being of that type. Jedi doesn't do anything with the extra into that
|
||||
it can be None as well
|
||||
"""
|
||||
#? int()
|
||||
p
|
||||
|
||||
class ForwardReference:
|
||||
pass
|
||||
|
||||
class TestDict(typing.Dict[str, int]):
|
||||
def setdud(self):
|
||||
pass
|
||||
|
||||
def testdict(x):
|
||||
"""
|
||||
:type x: TestDict
|
||||
"""
|
||||
#? ["setdud", "setdefault"]
|
||||
x.setd
|
||||
for key in x.keys():
|
||||
#? str()
|
||||
key
|
||||
for value in x.values():
|
||||
#? int()
|
||||
value
|
||||
|
||||
x = TestDict()
|
||||
#? ["setdud", "setdefault"]
|
||||
x.setd
|
||||
for key in x.keys():
|
||||
#? str()
|
||||
key
|
||||
for value in x.values():
|
||||
#? int()
|
||||
value
|
||||
# python >= 3.2
|
||||
"""
|
||||
docstrings have some auto-import, annotations can use all of Python's
|
||||
import logic
|
||||
"""
|
||||
import typing as t
|
||||
def union2(x: t.Union[int, str]):
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
from typing import Union
|
||||
def union3(x: Union[int, str]):
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
from typing import Union as U
|
||||
def union4(x: U[int, str]):
|
||||
#? int() str()
|
||||
x
|
||||
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
PEP 526 introduced a new way of using type annotations on variables. It was
|
||||
introduced in Python 3.6.
|
||||
"""
|
||||
# python >= 3.6
|
||||
|
||||
import typing
|
||||
|
||||
asdf = ''
|
||||
asdf: int
|
||||
# This is not necessarily correct, but for now this is ok (at least no error).
|
||||
#? int()
|
||||
asdf
|
||||
|
||||
|
||||
direct: int = NOT_DEFINED
|
||||
#? int()
|
||||
direct
|
||||
|
||||
with_typing_module: typing.List[float] = NOT_DEFINED
|
||||
#? float()
|
||||
with_typing_module[0]
|
||||
@@ -0,0 +1,138 @@
|
||||
"""
|
||||
Test Jedi's operation understanding. Jedi should understand simple additions,
|
||||
multiplications, etc.
|
||||
"""
|
||||
# -----------------
|
||||
# numbers
|
||||
# -----------------
|
||||
x = [1, 'a', 1.0]
|
||||
|
||||
#? int() str() float()
|
||||
x[12]
|
||||
|
||||
#? float()
|
||||
x[1 + 1]
|
||||
|
||||
index = 0 + 1
|
||||
|
||||
#? str()
|
||||
x[index]
|
||||
|
||||
#? int()
|
||||
x[1 + (-1)]
|
||||
|
||||
def calculate(number):
|
||||
return number + constant
|
||||
|
||||
constant = 1
|
||||
|
||||
#? float()
|
||||
x[calculate(1)]
|
||||
|
||||
def calculate(number):
|
||||
return number + constant
|
||||
|
||||
# -----------------
|
||||
# strings
|
||||
# -----------------
|
||||
|
||||
x = 'upp' + 'e'
|
||||
|
||||
#? str.upper
|
||||
getattr(str, x + 'r')
|
||||
|
||||
a = "a"*3
|
||||
#? str()
|
||||
a
|
||||
a = 3 * "a"
|
||||
#? str()
|
||||
a
|
||||
|
||||
a = 3 * "a"
|
||||
#? str()
|
||||
a
|
||||
|
||||
#? int()
|
||||
(3 ** 3)
|
||||
#? int() str()
|
||||
(3 ** 'a')
|
||||
|
||||
# -----------------
|
||||
# assignments
|
||||
# -----------------
|
||||
|
||||
x = [1, 'a', 1.0]
|
||||
|
||||
i = 0
|
||||
i += 1
|
||||
i += 1
|
||||
#? float()
|
||||
x[i]
|
||||
|
||||
i = 1
|
||||
i += 1
|
||||
i -= 3
|
||||
i += 1
|
||||
#? int()
|
||||
x[i]
|
||||
|
||||
# -----------------
|
||||
# in
|
||||
# -----------------
|
||||
|
||||
if 'X' in 'Y':
|
||||
a = 3
|
||||
else:
|
||||
a = ''
|
||||
# For now don't really check for truth values. So in should return both
|
||||
# results.
|
||||
#? str() int()
|
||||
a
|
||||
|
||||
# -----------------
|
||||
# for flow assignments
|
||||
# -----------------
|
||||
|
||||
class FooBar(object):
|
||||
fuu = 0.1
|
||||
raboof = 'fourtytwo'
|
||||
|
||||
# targets should be working
|
||||
target = ''
|
||||
for char in ['f', 'u', 'u']:
|
||||
target += char
|
||||
#? float()
|
||||
getattr(FooBar, target)
|
||||
|
||||
# github #24
|
||||
target = u''
|
||||
for char in reversed(['f', 'o', 'o', 'b', 'a', 'r']):
|
||||
target += char
|
||||
|
||||
#? str()
|
||||
getattr(FooBar, target)
|
||||
|
||||
|
||||
# -----------------
|
||||
# repetition problems -> could be very slow and memory expensive - shouldn't
|
||||
# be.
|
||||
# -----------------
|
||||
|
||||
b = [str(1)]
|
||||
l = list
|
||||
for x in [l(0), l(1), l(2), l(3), l(4), l(5), l(6), l(7), l(8), l(9), l(10),
|
||||
l(11), l(12), l(13), l(14), l(15), l(16), l(17), l(18), l(19), l(20),
|
||||
l(21), l(22), l(23), l(24), l(25), l(26), l(27), l(28), l(29)]:
|
||||
b += x
|
||||
|
||||
#? str()
|
||||
b[1]
|
||||
|
||||
|
||||
# -----------------
|
||||
# undefined names
|
||||
# -----------------
|
||||
a = foobarbaz + 'hello'
|
||||
|
||||
#? int() float()
|
||||
{'hello': 1, 'bar': 1.0}[a]
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Code that might cause recursion issues (or has caused in the past).
|
||||
"""
|
||||
|
||||
def Recursion():
|
||||
def recurse(self):
|
||||
self.a = self.a
|
||||
self.b = self.b.recurse()
|
||||
|
||||
#?
|
||||
Recursion().a
|
||||
|
||||
#?
|
||||
Recursion().b
|
||||
|
||||
|
||||
class X():
|
||||
def __init__(self):
|
||||
self.recursive = [1, 3]
|
||||
|
||||
def annoying(self):
|
||||
self.recursive = [self.recursive[0]]
|
||||
|
||||
def recurse(self):
|
||||
self.recursive = [self.recursive[1]]
|
||||
|
||||
#? int()
|
||||
X().recursive[0]
|
||||
|
||||
|
||||
def to_list(iterable):
|
||||
return list(set(iterable))
|
||||
|
||||
|
||||
def recursion1(foo):
|
||||
return to_list(to_list(foo)) + recursion1(foo)
|
||||
|
||||
#? int()
|
||||
recursion1([1,2])[0]
|
||||
|
||||
|
||||
class FooListComp():
|
||||
def __init__(self):
|
||||
self.recursive = [1]
|
||||
|
||||
def annoying(self):
|
||||
self.recursive = [x for x in self.recursive]
|
||||
|
||||
|
||||
#? int()
|
||||
FooListComp().recursive[0]
|
||||
|
||||
|
||||
class InstanceAttributeIfs:
|
||||
def b(self):
|
||||
self.a1 = 1
|
||||
self.a2 = 1
|
||||
|
||||
def c(self):
|
||||
self.a2 = ''
|
||||
|
||||
def x(self):
|
||||
self.b()
|
||||
|
||||
if self.a1 == 1:
|
||||
self.a1 = self.a1 + 1
|
||||
if self.a2 == UNDEFINED:
|
||||
self.a2 = self.a2 + 1
|
||||
|
||||
#? int()
|
||||
self.a1
|
||||
#? int() str()
|
||||
self.a2
|
||||
|
||||
#? int()
|
||||
InstanceAttributeIfs().a1
|
||||
#? int() str()
|
||||
InstanceAttributeIfs().a2
|
||||
@@ -0,0 +1,249 @@
|
||||
"""
|
||||
std library stuff
|
||||
"""
|
||||
|
||||
# -----------------
|
||||
# builtins
|
||||
# -----------------
|
||||
arr = ['']
|
||||
|
||||
#? str()
|
||||
sorted(arr)[0]
|
||||
|
||||
#? str()
|
||||
next(reversed(arr))
|
||||
next(reversed(arr))
|
||||
|
||||
# should not fail if there's no return value.
|
||||
def yielder():
|
||||
yield None
|
||||
|
||||
#? None
|
||||
next(reversed(yielder()))
|
||||
|
||||
# empty reversed should not raise an error
|
||||
#?
|
||||
next(reversed())
|
||||
|
||||
#? str()
|
||||
next(open(''))
|
||||
|
||||
#? int()
|
||||
{'a':2}.setdefault('a', 3)
|
||||
|
||||
# Compiled classes should have the meta class attributes.
|
||||
#? ['__itemsize__']
|
||||
tuple.__itemsize__
|
||||
|
||||
# -----------------
|
||||
# type() calls with one parameter
|
||||
# -----------------
|
||||
#? int
|
||||
type(1)
|
||||
#? int
|
||||
type(int())
|
||||
#? type
|
||||
type(int)
|
||||
#? type
|
||||
type(type)
|
||||
#? list
|
||||
type([])
|
||||
|
||||
def x():
|
||||
yield 1
|
||||
generator = type(x())
|
||||
#? generator
|
||||
type(x for x in [])
|
||||
#? type(x)
|
||||
type(lambda: x)
|
||||
|
||||
import math
|
||||
import os
|
||||
#? type(os)
|
||||
type(math)
|
||||
class X(): pass
|
||||
#? type
|
||||
type(X)
|
||||
|
||||
|
||||
with open('foo') as f:
|
||||
for line in f.readlines():
|
||||
#? str()
|
||||
line
|
||||
# -----------------
|
||||
# enumerate
|
||||
# -----------------
|
||||
for i, j in enumerate(["as", "ad"]):
|
||||
#? int()
|
||||
i
|
||||
#? str()
|
||||
j
|
||||
|
||||
# -----------------
|
||||
# re
|
||||
# -----------------
|
||||
import re
|
||||
c = re.compile(r'a')
|
||||
# re.compile should not return str -> issue #68
|
||||
#? []
|
||||
c.startswith
|
||||
#? int()
|
||||
c.match().start()
|
||||
|
||||
#? int()
|
||||
re.match(r'a', 'a').start()
|
||||
|
||||
for a in re.finditer('a', 'a'):
|
||||
#? int()
|
||||
a.start()
|
||||
|
||||
#? str()
|
||||
re.sub('a', 'a')
|
||||
|
||||
# -----------------
|
||||
# ref
|
||||
# -----------------
|
||||
import weakref
|
||||
|
||||
#? int()
|
||||
weakref.proxy(1)
|
||||
|
||||
#? weakref.ref()
|
||||
weakref.ref(1)
|
||||
#? int()
|
||||
weakref.ref(1)()
|
||||
|
||||
# -----------------
|
||||
# functools
|
||||
# -----------------
|
||||
import functools
|
||||
|
||||
basetwo = functools.partial(int, base=2)
|
||||
#? int()
|
||||
basetwo()
|
||||
|
||||
def function(a, b):
|
||||
return a, b
|
||||
a = functools.partial(function, 0)
|
||||
|
||||
#? int()
|
||||
a('')[0]
|
||||
#? str()
|
||||
a('')[1]
|
||||
|
||||
kw = functools.partial(function, b=1.0)
|
||||
tup = kw(1)
|
||||
#? int()
|
||||
tup[0]
|
||||
#? float()
|
||||
tup[1]
|
||||
|
||||
def my_decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
return f(*args, **kwds)
|
||||
return wrapper
|
||||
|
||||
@my_decorator
|
||||
def example(a):
|
||||
return a
|
||||
|
||||
#? str()
|
||||
example('')
|
||||
|
||||
|
||||
# -----------------
|
||||
# sqlite3 (#84)
|
||||
# -----------------
|
||||
|
||||
import sqlite3
|
||||
#? sqlite3.Connection()
|
||||
con = sqlite3.connect()
|
||||
#? sqlite3.Cursor()
|
||||
c = con.cursor()
|
||||
#? sqlite3.Row()
|
||||
row = c.fetchall()[0]
|
||||
#? str()
|
||||
row.keys()[0]
|
||||
|
||||
def huhu(db):
|
||||
"""
|
||||
:type db: sqlite3.Connection
|
||||
:param db: the db connection
|
||||
"""
|
||||
#? sqlite3.Connection()
|
||||
db
|
||||
|
||||
# -----------------
|
||||
# hashlib
|
||||
# -----------------
|
||||
|
||||
import hashlib
|
||||
|
||||
#? ['md5']
|
||||
hashlib.md5
|
||||
|
||||
# -----------------
|
||||
# copy
|
||||
# -----------------
|
||||
|
||||
import copy
|
||||
#? int()
|
||||
copy.deepcopy(1)
|
||||
|
||||
#?
|
||||
copy.copy()
|
||||
|
||||
# -----------------
|
||||
# json
|
||||
# -----------------
|
||||
|
||||
# We don't want any results for json, because it depends on IO.
|
||||
import json
|
||||
#?
|
||||
json.load('asdf')
|
||||
#?
|
||||
json.loads('[1]')
|
||||
|
||||
# -----------------
|
||||
# random
|
||||
# -----------------
|
||||
|
||||
import random
|
||||
class A(object):
|
||||
def say(self): pass
|
||||
class B(object):
|
||||
def shout(self): pass
|
||||
cls = random.choice([A, B])
|
||||
#? ['say', 'shout']
|
||||
cls().s
|
||||
|
||||
# -----------------
|
||||
# random
|
||||
# -----------------
|
||||
|
||||
import zipfile
|
||||
z = zipfile.ZipFile("foo")
|
||||
# It's too slow. So we don't run it at the moment.
|
||||
##? ['upper']
|
||||
z.read('name').upper
|
||||
|
||||
# -----------------
|
||||
# contextlib
|
||||
# -----------------
|
||||
|
||||
import contextlib
|
||||
with contextlib.closing('asd') as string:
|
||||
#? str()
|
||||
string
|
||||
|
||||
# -----------------
|
||||
# shlex
|
||||
# -----------------
|
||||
|
||||
# Github issue #929
|
||||
import shlex
|
||||
qsplit = shlex.split("foo, ferwerwerw werw werw e")
|
||||
for part in qsplit:
|
||||
#? str() None
|
||||
part
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
from os import dirname
|
||||
|
||||
sys.path.insert(0, '../../jedi')
|
||||
sys.path.append(dirname(os.path.abspath('thirdparty' + os.path.sep + 'asdf')))
|
||||
|
||||
# modifications, that should fail:
|
||||
# syntax err
|
||||
sys.path.append('a' +* '/thirdparty')
|
||||
|
||||
#? ['evaluate']
|
||||
import evaluate
|
||||
|
||||
#? ['evaluator_function_cache']
|
||||
evaluate.Evaluator_fu
|
||||
|
||||
# Those don't work because dirname and abspath are not properly understood.
|
||||
##? ['jedi_']
|
||||
import jedi_
|
||||
|
||||
##? ['el']
|
||||
jedi_.el
|
||||
19
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/PyQt4_.py
vendored
Normal file
19
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/PyQt4_.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
#? ['QActionGroup']
|
||||
QActionGroup
|
||||
|
||||
#? ['currentText']
|
||||
QStyleOptionComboBox().currentText
|
||||
|
||||
#? []
|
||||
QStyleOptionComboBox().currentText.
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
#? ['currentText']
|
||||
QtGui.QStyleOptionComboBox().currentText
|
||||
|
||||
#? []
|
||||
QtGui.QStyleOptionComboBox().currentText.
|
||||
11
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/django_.py
vendored
Normal file
11
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/django_.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#! ['class ObjectDoesNotExist']
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
import django
|
||||
|
||||
#? ['get_version']
|
||||
django.get_version
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
#? ['configured']
|
||||
settings.configured
|
||||
52
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/jedi_.py
vendored
Normal file
52
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/jedi_.py
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
from jedi import functions, evaluate, parsing
|
||||
|
||||
el = functions.completions()[0]
|
||||
#? ['description']
|
||||
el.description
|
||||
|
||||
#? str()
|
||||
el.description
|
||||
|
||||
|
||||
scopes, path, dot, like = \
|
||||
api._prepare_goto(source, row, column, path, True)
|
||||
|
||||
# has problems with that (sometimes) very deep nesting.
|
||||
#? set()
|
||||
el = scopes
|
||||
|
||||
# get_names_for_scope is also recursion stuff
|
||||
#? tuple()
|
||||
el = list(evaluate.get_names_for_scope())[0]
|
||||
|
||||
#? int() parsing.Module()
|
||||
el = list(evaluate.get_names_for_scope(1))[0][0]
|
||||
#? parsing.Module()
|
||||
el = list(evaluate.get_names_for_scope())[0][0]
|
||||
|
||||
#? list()
|
||||
el = list(evaluate.get_names_for_scope(1))[0][1]
|
||||
#? list()
|
||||
el = list(evaluate.get_names_for_scope())[0][1]
|
||||
|
||||
#? list()
|
||||
parsing.Scope((0,0)).get_set_vars()
|
||||
#? parsing.Import() parsing.Name()
|
||||
parsing.Scope((0,0)).get_set_vars()[0]
|
||||
# TODO access parent is not possible, because that is not set in the class
|
||||
## parsing.Class()
|
||||
parsing.Scope((0,0)).get_set_vars()[0].parent
|
||||
|
||||
#? parsing.Import() parsing.Name()
|
||||
el = list(evaluate.get_names_for_scope())[0][1][0]
|
||||
|
||||
#? evaluate.Array() evaluate.Class() evaluate.Function() evaluate.Instance()
|
||||
list(evaluate.follow_call())[0]
|
||||
|
||||
# With the right recursion settings, this should be possible (and maybe more):
|
||||
# Array Class Function Generator Instance Module
|
||||
# However, this was produced with the recursion settings 10/350/10000, and
|
||||
# lasted 18.5 seconds. So we just have to be content with the results.
|
||||
#? evaluate.Class() evaluate.Function()
|
||||
evaluate.get_scopes_for_name()[0]
|
||||
11
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/psycopg2_.py
vendored
Normal file
11
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/psycopg2_.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import psycopg2
|
||||
|
||||
conn = psycopg2.connect('dbname=test')
|
||||
|
||||
#? ['cursor']
|
||||
conn.cursor
|
||||
|
||||
cur = conn.cursor()
|
||||
|
||||
#? ['fetchall']
|
||||
cur.fetchall
|
||||
36
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/pylab_.py
vendored
Normal file
36
emacs/.emacs.d/anaconda-mode/0.1.9/jedi-0.11.1-py3.6.egg/test/completion/thirdparty/pylab_.py
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import pylab
|
||||
|
||||
# two gotos
|
||||
#! ['module numpy']
|
||||
import numpy
|
||||
|
||||
#! ['module random']
|
||||
import numpy.random
|
||||
|
||||
#? ['array2string']
|
||||
numpy.array2string
|
||||
|
||||
#? ['shape']
|
||||
numpy.matrix().shape
|
||||
|
||||
#? ['random_integers']
|
||||
pylab.random_integers
|
||||
|
||||
#? []
|
||||
numpy.random_integers
|
||||
|
||||
#? ['random_integers']
|
||||
numpy.random.random_integers
|
||||
#? ['sample']
|
||||
numpy.random.sample
|
||||
|
||||
import numpy
|
||||
na = numpy.array([1,2])
|
||||
#? ['shape']
|
||||
na.shape
|
||||
|
||||
# shouldn't raise an error #29, jedi-vim
|
||||
# doesn't return something, because matplotlib uses __import__
|
||||
fig = pylab.figure()
|
||||
#?
|
||||
fig.add_subplot
|
||||
@@ -0,0 +1,129 @@
|
||||
# -----------------
|
||||
# non array
|
||||
# -----------------
|
||||
|
||||
#? ['imag']
|
||||
int.imag
|
||||
|
||||
#? []
|
||||
int.is_integer
|
||||
|
||||
#? ['is_integer']
|
||||
float.is_int
|
||||
|
||||
#? ['is_integer']
|
||||
1.0.is_integer
|
||||
|
||||
#? ['upper']
|
||||
"".upper
|
||||
|
||||
#? ['upper']
|
||||
r"".upper
|
||||
|
||||
# strangely this didn't work, because the = is used for assignments
|
||||
#? ['upper']
|
||||
"=".upper
|
||||
a = "="
|
||||
#? ['upper']
|
||||
a.upper
|
||||
|
||||
|
||||
# -----------------
|
||||
# lists
|
||||
# -----------------
|
||||
arr = []
|
||||
#? ['append']
|
||||
arr.app
|
||||
|
||||
#? ['append']
|
||||
list().app
|
||||
#? ['append']
|
||||
[].append
|
||||
|
||||
arr2 = [1,2,3]
|
||||
#? ['append']
|
||||
arr2.app
|
||||
|
||||
#? int()
|
||||
arr.count(1)
|
||||
|
||||
x = []
|
||||
#?
|
||||
x.pop()
|
||||
x = [3]
|
||||
#? int()
|
||||
x.pop()
|
||||
x = []
|
||||
x.append(1.0)
|
||||
#? float()
|
||||
x.pop()
|
||||
|
||||
# -----------------
|
||||
# dicts
|
||||
# -----------------
|
||||
dic = {}
|
||||
|
||||
#? ['copy', 'clear']
|
||||
dic.c
|
||||
|
||||
dic2 = dict(a=1, b=2)
|
||||
#? ['pop', 'popitem']
|
||||
dic2.p
|
||||
#? ['popitem']
|
||||
{}.popitem
|
||||
|
||||
dic2 = {'asdf': 3}
|
||||
#? ['popitem']
|
||||
dic2.popitem
|
||||
|
||||
#? int()
|
||||
dic2['asdf']
|
||||
|
||||
d = {'a': 3, 1.0: list}
|
||||
|
||||
#? int() list
|
||||
d.values()[0]
|
||||
##? int() list
|
||||
dict(d).values()[0]
|
||||
|
||||
#? str()
|
||||
d.items()[0][0]
|
||||
#? int()
|
||||
d.items()[0][1]
|
||||
|
||||
# -----------------
|
||||
# tuples
|
||||
# -----------------
|
||||
tup = ('',2)
|
||||
|
||||
#? ['count']
|
||||
tup.c
|
||||
|
||||
tup2 = tuple()
|
||||
#? ['index']
|
||||
tup2.i
|
||||
#? ['index']
|
||||
().i
|
||||
|
||||
tup3 = 1,""
|
||||
#? ['index']
|
||||
tup3.index
|
||||
|
||||
tup4 = 1,""
|
||||
#? ['index']
|
||||
tup4.index
|
||||
|
||||
# -----------------
|
||||
# set
|
||||
# -----------------
|
||||
# Set literals are not valid in 2.6.
|
||||
# python >= 2.7
|
||||
set_t = {1,2}
|
||||
|
||||
#? ['clear', 'copy']
|
||||
set_t.c
|
||||
|
||||
set_t2 = set()
|
||||
|
||||
#? ['clear', 'copy']
|
||||
set_t2.c
|
||||
@@ -0,0 +1,316 @@
|
||||
"""
|
||||
Renaming tests. This means search for usages.
|
||||
I always leave a little bit of space to add room for additions, because the
|
||||
results always contain position informations.
|
||||
"""
|
||||
#< 4 (0,4), (3,0), (5,0), (17,0), (12,4), (14,5), (15,0)
|
||||
def abc(): pass
|
||||
|
||||
#< 0 (-3,4), (0,0), (2,0), (14,0), (9,4), (11,5), (12,0)
|
||||
abc.d.a.bsaasd.abc.d
|
||||
|
||||
abc
|
||||
# unicode chars shouldn't be a problem.
|
||||
x['smörbröd'].abc
|
||||
|
||||
# With the new parser these statements are not recognized as stateents, because
|
||||
# they are not valid Python.
|
||||
if 1:
|
||||
abc =
|
||||
else:
|
||||
(abc) =
|
||||
abc =
|
||||
#< (-17,4), (-14,0), (-12,0), (0,0), (-2,0), (-3,5), (-5,4)
|
||||
abc
|
||||
|
||||
abc = 5
|
||||
|
||||
|
||||
Abc = 3
|
||||
|
||||
#< 6 (0,6), (2,4), (5,8), (17,0)
|
||||
class Abc():
|
||||
#< (-2,6), (0,4), (3,8), (15,0)
|
||||
Abc
|
||||
|
||||
def Abc(self):
|
||||
Abc; self.c = 3
|
||||
|
||||
#< 17 (0,16), (2,8)
|
||||
def a(self, Abc):
|
||||
#< 10 (-2,16), (0,8)
|
||||
Abc
|
||||
|
||||
#< 19 (0,18), (2,8)
|
||||
def self_test(self):
|
||||
#< 12 (-2,18), (0,8)
|
||||
self.b
|
||||
|
||||
Abc.d.Abc
|
||||
|
||||
|
||||
#< 4 (0,4), (5,1)
|
||||
def blubi():
|
||||
pass
|
||||
|
||||
|
||||
#< (-5,4), (0,1)
|
||||
@blubi
|
||||
def a(): pass
|
||||
|
||||
|
||||
#< 0 (0,0), (1,0)
|
||||
set_object_var = object()
|
||||
set_object_var.var = 1
|
||||
|
||||
|
||||
response = 5
|
||||
#< 0 (0,0), (1,0), (2,0), (4,0)
|
||||
response = HttpResponse(mimetype='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename=%s.pdf' % id
|
||||
response.write(pdf)
|
||||
#< (-4,0), (-3,0), (-2,0), (0,0)
|
||||
response
|
||||
|
||||
|
||||
# -----------------
|
||||
# imports
|
||||
# -----------------
|
||||
#< (0,7), (3,0)
|
||||
import module_not_exists
|
||||
|
||||
#< (-3,7), (0,0)
|
||||
module_not_exists
|
||||
|
||||
|
||||
#< ('rename1', 1,0), (0,24), (3,0), (6,17), ('rename2', 4,5), (11,17), (14,17), ('imports', 72, 16)
|
||||
from import_tree import rename1
|
||||
|
||||
#< (0,8), ('rename1',3,0), ('rename2',4,20), ('rename2',6,0), (3,32), (8,32), (5,0)
|
||||
rename1.abc
|
||||
|
||||
#< (-3,8), ('rename1', 3,0), ('rename2', 4,20), ('rename2', 6,0), (0,32), (5,32), (2,0)
|
||||
from import_tree.rename1 import abc
|
||||
#< (-5,8), (-2,32), ('rename1', 3,0), ('rename2', 4,20), ('rename2', 6,0), (0,0), (3,32)
|
||||
abc
|
||||
|
||||
#< 20 ('rename1', 1,0), ('rename2', 4,5), (-11,24), (-8,0), (-5,17), (0,17), (3,17), ('imports', 72, 16)
|
||||
from import_tree.rename1 import abc
|
||||
|
||||
#< (0, 32),
|
||||
from import_tree.rename1 import not_existing
|
||||
|
||||
# Shouldn't raise an error or do anything weird.
|
||||
from not_existing import *
|
||||
|
||||
# -----------------
|
||||
# classes
|
||||
# -----------------
|
||||
|
||||
class TestMethods(object):
|
||||
#< 8 (0,8), (2,13)
|
||||
def a_method(self):
|
||||
#< 13 (-2,8), (0,13)
|
||||
self.a_method()
|
||||
#< 13 (2,8), (0,13), (3,13)
|
||||
self.b_method()
|
||||
|
||||
def b_method(self):
|
||||
self.b_method
|
||||
|
||||
|
||||
class TestClassVar(object):
|
||||
#< 4 (0,4), (5,13), (7,21)
|
||||
class_v = 1
|
||||
def a(self):
|
||||
class_v = 1
|
||||
|
||||
#< (-5,4), (0,13), (2,21)
|
||||
self.class_v
|
||||
#< (-7,4), (-2,13), (0,21)
|
||||
TestClassVar.class_v
|
||||
#< (0,8), (-7, 8)
|
||||
class_v
|
||||
|
||||
class TestInstanceVar():
|
||||
def a(self):
|
||||
#< 13 (4,13), (0,13)
|
||||
self._instance_var = 3
|
||||
|
||||
def b(self):
|
||||
#< (-4,13), (0,13)
|
||||
self._instance_var
|
||||
# A call to self used to trigger an error, because it's also a trailer
|
||||
# with two children.
|
||||
self()
|
||||
|
||||
|
||||
class NestedClass():
|
||||
def __getattr__(self, name):
|
||||
return self
|
||||
|
||||
# Shouldn't find a definition, because there's other `instance`.
|
||||
# TODO reenable that test
|
||||
##< (0, 14),
|
||||
NestedClass().instance
|
||||
|
||||
|
||||
# -----------------
|
||||
# inheritance
|
||||
# -----------------
|
||||
class Super(object):
|
||||
#< 4 (0,4), (23,18), (25,13)
|
||||
base_class = 1
|
||||
#< 4 (0,4),
|
||||
class_var = 1
|
||||
|
||||
#< 8 (0,8),
|
||||
def base_method(self):
|
||||
#< 13 (0,13), (20,13)
|
||||
self.base_var = 1
|
||||
#< 13 (0,13),
|
||||
self.instance_var = 1
|
||||
|
||||
#< 8 (0,8),
|
||||
def just_a_method(self): pass
|
||||
|
||||
|
||||
#< 20 (0,16), (-18,6)
|
||||
class TestClass(Super):
|
||||
#< 4 (0,4),
|
||||
class_var = 1
|
||||
|
||||
def x_method(self):
|
||||
|
||||
#< (0,18), (2,13), (-23,4)
|
||||
TestClass.base_class
|
||||
#< (-2,18), (0,13), (-25,4)
|
||||
self.base_class
|
||||
#< (-20,13), (0,13)
|
||||
self.base_var
|
||||
#< (0, 18),
|
||||
TestClass.base_var
|
||||
|
||||
|
||||
#< 13 (5,13), (0,13)
|
||||
self.instance_var = 3
|
||||
|
||||
#< 9 (0,8),
|
||||
def just_a_method(self):
|
||||
#< (-5,13), (0,13)
|
||||
self.instance_var
|
||||
|
||||
|
||||
# -----------------
|
||||
# properties
|
||||
# -----------------
|
||||
class TestProperty:
|
||||
|
||||
@property
|
||||
#< 10 (0,8), (5,13)
|
||||
def prop(self):
|
||||
return 1
|
||||
|
||||
def a(self):
|
||||
#< 13 (-5,8), (0,13)
|
||||
self.prop
|
||||
|
||||
@property
|
||||
#< 13 (0,8), (4,5)
|
||||
def rw_prop(self):
|
||||
return self._rw_prop
|
||||
|
||||
#< 8 (-4,8), (0,5)
|
||||
@rw_prop.setter
|
||||
#< 8 (0,8), (5,13)
|
||||
def rw_prop(self, value):
|
||||
self._rw_prop = value
|
||||
|
||||
def b(self):
|
||||
#< 13 (-5,8), (0,13)
|
||||
self.rw_prop
|
||||
|
||||
# -----------------
|
||||
# *args, **kwargs
|
||||
# -----------------
|
||||
#< 11 (1,11), (0,8)
|
||||
def f(**kwargs):
|
||||
return kwargs
|
||||
|
||||
|
||||
# -----------------
|
||||
# No result
|
||||
# -----------------
|
||||
if isinstance(j, int):
|
||||
#< (0, 4),
|
||||
j
|
||||
|
||||
# -----------------
|
||||
# Dynamic Param Search
|
||||
# -----------------
|
||||
|
||||
class DynamicParam():
|
||||
def foo(self):
|
||||
return
|
||||
|
||||
def check(instance):
|
||||
#< 13 (-5,8), (0,13)
|
||||
instance.foo()
|
||||
|
||||
check(DynamicParam())
|
||||
|
||||
# -----------------
|
||||
# Compiled Objects
|
||||
# -----------------
|
||||
|
||||
import _sre
|
||||
|
||||
#< 0 (-3,7), (0,0), ('_sre', None, None)
|
||||
_sre
|
||||
|
||||
# -----------------
|
||||
# on syntax
|
||||
# -----------------
|
||||
|
||||
#< 0
|
||||
import undefined
|
||||
|
||||
# -----------------
|
||||
# comprehensions
|
||||
# -----------------
|
||||
|
||||
#< 0 (0,0), (2,12)
|
||||
x = 32
|
||||
#< 12 (-2,0), (0,12)
|
||||
[x for x in x]
|
||||
|
||||
#< 0 (0,0), (2,1), (2,12)
|
||||
x = 32
|
||||
#< 12 (-2,0), (0,1), (0,12)
|
||||
[x for b in x]
|
||||
|
||||
|
||||
#< 1 (0,1), (0,7)
|
||||
[x for x in something]
|
||||
#< 7 (0,1), (0,7)
|
||||
[x for x in something]
|
||||
|
||||
x = 3
|
||||
# Not supported syntax in Python 2.6.
|
||||
# python >= 2.7
|
||||
#< 1 (0,1), (0,10)
|
||||
{x:1 for x in something}
|
||||
#< 10 (0,1), (0,10)
|
||||
{x:1 for x in something}
|
||||
|
||||
def x():
|
||||
zzz = 3
|
||||
if UNDEFINED:
|
||||
zzz = 5
|
||||
if UNDEFINED2:
|
||||
#< (3, 8), (4, 4), (0, 12), (-3, 8), (-5, 4)
|
||||
zzz
|
||||
else:
|
||||
#< (0, 8), (1, 4), (-3, 12), (-6, 8), (-8, 4)
|
||||
zzz
|
||||
zzz
|
||||
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
An import tree, for testing usages.
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from . import b
|
||||
|
||||
def foo():
|
||||
b.bar()
|
||||
@@ -0,0 +1,2 @@
|
||||
def bar():
|
||||
pass
|
||||
@@ -0,0 +1,5 @@
|
||||
from simple_import import module
|
||||
|
||||
|
||||
def in_function():
|
||||
from simple_import import module2
|
||||
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Test of keywords and ``jedi.keywords``
|
||||
"""
|
||||
from jedi import Script
|
||||
|
||||
|
||||
def test_issue436():
|
||||
code = "bar = 0\nbar += 'foo' + 4"
|
||||
errors = set(repr(e) for e in Script(code)._analysis())
|
||||
assert len(errors) == 2
|
||||
assert '<Error type-error-operation: None@2,4>' in errors
|
||||
assert '<Error type-error-operation: None@2,13>' in errors
|
||||
@@ -0,0 +1,224 @@
|
||||
"""
|
||||
Test all things related to the ``jedi.api`` module.
|
||||
"""
|
||||
|
||||
import os
|
||||
from textwrap import dedent
|
||||
|
||||
from jedi import api
|
||||
from jedi._compatibility import is_py3
|
||||
from pytest import raises
|
||||
from parso import cache
|
||||
|
||||
|
||||
def test_preload_modules():
|
||||
def check_loaded(*modules):
|
||||
# +1 for None module (currently used)
|
||||
grammar_cache = next(iter(cache.parser_cache.values()))
|
||||
assert len(grammar_cache) == len(modules) + 1
|
||||
for i in modules:
|
||||
assert [i in k for k in grammar_cache.keys() if k is not None]
|
||||
|
||||
old_cache = cache.parser_cache.copy()
|
||||
cache.parser_cache.clear()
|
||||
|
||||
try:
|
||||
api.preload_module('sys')
|
||||
check_loaded() # compiled (c_builtin) modules shouldn't be in the cache.
|
||||
api.preload_module('types', 'token')
|
||||
check_loaded('types', 'token')
|
||||
finally:
|
||||
cache.parser_cache.update(old_cache)
|
||||
|
||||
|
||||
def test_empty_script():
|
||||
assert api.Script('')
|
||||
|
||||
|
||||
def test_line_number_errors():
|
||||
"""
|
||||
Script should raise a ValueError if line/column numbers are not in a
|
||||
valid range.
|
||||
"""
|
||||
s = 'hello'
|
||||
# lines
|
||||
with raises(ValueError):
|
||||
api.Script(s, 2, 0)
|
||||
with raises(ValueError):
|
||||
api.Script(s, 0, 0)
|
||||
|
||||
# columns
|
||||
with raises(ValueError):
|
||||
api.Script(s, 1, len(s) + 1)
|
||||
with raises(ValueError):
|
||||
api.Script(s, 1, -1)
|
||||
|
||||
# ok
|
||||
api.Script(s, 1, 0)
|
||||
api.Script(s, 1, len(s))
|
||||
|
||||
|
||||
def _check_number(source, result='float'):
|
||||
completions = api.Script(source).completions()
|
||||
assert completions[0].parent().name == result
|
||||
|
||||
|
||||
def test_completion_on_number_literals():
|
||||
# No completions on an int literal (is a float).
|
||||
assert [c.name for c in api.Script('1.').completions()] \
|
||||
== ['and', 'if', 'in', 'is', 'not', 'or']
|
||||
|
||||
# Multiple points after an int literal basically mean that there's a float
|
||||
# and a call after that.
|
||||
_check_number('1..')
|
||||
_check_number('1.0.')
|
||||
|
||||
# power notation
|
||||
_check_number('1.e14.')
|
||||
_check_number('1.e-3.')
|
||||
_check_number('9e3.')
|
||||
assert api.Script('1.e3..').completions() == []
|
||||
assert api.Script('1.e-13..').completions() == []
|
||||
|
||||
|
||||
def test_completion_on_hex_literals():
|
||||
assert api.Script('0x1..').completions() == []
|
||||
_check_number('0x1.', 'int') # hexdecimal
|
||||
# Completing binary literals doesn't work if they are not actually binary
|
||||
# (invalid statements).
|
||||
assert api.Script('0b2.b').completions() == []
|
||||
_check_number('0b1.', 'int') # binary
|
||||
|
||||
_check_number('0x2e.', 'int')
|
||||
_check_number('0xE7.', 'int')
|
||||
_check_number('0xEa.', 'int')
|
||||
# theoretically, but people can just check for syntax errors:
|
||||
#assert api.Script('0x.').completions() == []
|
||||
|
||||
|
||||
def test_completion_on_complex_literals():
|
||||
assert api.Script('1j..').completions() == []
|
||||
_check_number('1j.', 'complex')
|
||||
_check_number('44.j.', 'complex')
|
||||
_check_number('4.0j.', 'complex')
|
||||
# No dot no completion - I thought, but 4j is actually a literall after
|
||||
# which a keyword like or is allowed. Good times, haha!
|
||||
assert (set([c.name for c in api.Script('4j').completions()]) ==
|
||||
set(['if', 'and', 'in', 'is', 'not', 'or']))
|
||||
|
||||
|
||||
def test_goto_assignments_on_non_name():
|
||||
assert api.Script('for').goto_assignments() == []
|
||||
|
||||
assert api.Script('assert').goto_assignments() == []
|
||||
if is_py3:
|
||||
assert api.Script('True').goto_assignments() == []
|
||||
else:
|
||||
# In Python 2.7 True is still a name.
|
||||
assert api.Script('True').goto_assignments()[0].description == 'instance True'
|
||||
|
||||
|
||||
def test_goto_definitions_on_non_name():
|
||||
assert api.Script('import x', column=0).goto_definitions() == []
|
||||
|
||||
|
||||
def test_goto_definitions_on_generator():
|
||||
def_, = api.Script('def x(): yield 1\ny=x()\ny').goto_definitions()
|
||||
assert def_.name == 'generator'
|
||||
|
||||
|
||||
def test_goto_definition_not_multiple():
|
||||
"""
|
||||
There should be only one Definition result if it leads back to the same
|
||||
origin (e.g. instance method)
|
||||
"""
|
||||
|
||||
s = dedent('''\
|
||||
import random
|
||||
class A():
|
||||
def __init__(self, a):
|
||||
self.a = 3
|
||||
|
||||
def foo(self):
|
||||
pass
|
||||
|
||||
if random.randint(0, 1):
|
||||
a = A(2)
|
||||
else:
|
||||
a = A(1)
|
||||
a''')
|
||||
assert len(api.Script(s).goto_definitions()) == 1
|
||||
|
||||
|
||||
def test_usage_description():
|
||||
descs = [u.description for u in api.Script("foo = ''; foo").usages()]
|
||||
assert set(descs) == set(["foo = ''", 'foo'])
|
||||
|
||||
|
||||
def test_get_line_code():
|
||||
def get_line_code(source, line=None, **kwargs):
|
||||
return api.Script(source, line=line).completions()[0].get_line_code(**kwargs)
|
||||
|
||||
# On builtin
|
||||
assert get_line_code('') == ''
|
||||
|
||||
# On custom code
|
||||
first_line = 'def foo():\n'
|
||||
line = ' foo'
|
||||
code = '%s%s' % (first_line, line)
|
||||
assert get_line_code(code) == first_line
|
||||
|
||||
# With before/after
|
||||
code = code + '\nother_line'
|
||||
assert get_line_code(code, line=2) == first_line
|
||||
assert get_line_code(code, line=2, after=1) == first_line + line + '\n'
|
||||
assert get_line_code(code, line=2, after=2, before=1) == code
|
||||
# Should just be the whole thing, since there are no more lines on both
|
||||
# sides.
|
||||
assert get_line_code(code, line=2, after=3, before=3) == code
|
||||
|
||||
|
||||
def test_goto_assignments_follow_imports():
|
||||
code = dedent("""
|
||||
import inspect
|
||||
inspect.isfunction""")
|
||||
definition, = api.Script(code, column=0).goto_assignments(follow_imports=True)
|
||||
assert 'inspect.py' in definition.module_path
|
||||
assert (definition.line, definition.column) == (1, 0)
|
||||
|
||||
definition, = api.Script(code).goto_assignments(follow_imports=True)
|
||||
assert 'inspect.py' in definition.module_path
|
||||
assert (definition.line, definition.column) > (1, 0)
|
||||
|
||||
code = '''def param(p): pass\nparam(1)'''
|
||||
start_pos = 1, len('def param(')
|
||||
|
||||
script = api.Script(code, *start_pos)
|
||||
definition, = script.goto_assignments(follow_imports=True)
|
||||
assert (definition.line, definition.column) == start_pos
|
||||
assert definition.name == 'p'
|
||||
result, = definition.goto_assignments()
|
||||
assert result.name == 'p'
|
||||
result, = definition._goto_definitions()
|
||||
assert result.name == 'int'
|
||||
result, = result._goto_definitions()
|
||||
assert result.name == 'int'
|
||||
|
||||
definition, = script.goto_assignments()
|
||||
assert (definition.line, definition.column) == start_pos
|
||||
|
||||
d, = api.Script('a = 1\na').goto_assignments(follow_imports=True)
|
||||
assert d.name == 'a'
|
||||
|
||||
|
||||
def test_goto_module():
|
||||
def check(line, expected):
|
||||
script = api.Script(path=path, line=line)
|
||||
module, = script.goto_assignments()
|
||||
assert module.module_path == expected
|
||||
|
||||
base_path = os.path.join(os.path.dirname(__file__), 'simple_import')
|
||||
path = os.path.join(base_path, '__init__.py')
|
||||
|
||||
check(1, os.path.join(base_path, 'module.py'))
|
||||
check(5, os.path.join(base_path, 'module2.py'))
|
||||
@@ -0,0 +1,62 @@
|
||||
from itertools import chain
|
||||
|
||||
import jedi
|
||||
from ..helpers import cwd_at
|
||||
|
||||
|
||||
def test_import_empty():
|
||||
""" github #340, return the full word. """
|
||||
completion = jedi.Script("import ").completions()[0]
|
||||
definition = completion.follow_definition()[0]
|
||||
assert definition
|
||||
|
||||
|
||||
def check_follow_definition_types(source):
|
||||
# nested import
|
||||
completions = jedi.Script(source, path='some_path.py').completions()
|
||||
defs = chain.from_iterable(c.follow_definition() for c in completions)
|
||||
return [d.type for d in defs]
|
||||
|
||||
|
||||
def test_follow_import_incomplete():
|
||||
"""
|
||||
Completion on incomplete imports should always take the full completion
|
||||
to do any evaluation.
|
||||
"""
|
||||
datetime = check_follow_definition_types("import itertool")
|
||||
assert datetime == ['module']
|
||||
|
||||
# empty `from * import` parts
|
||||
itert = jedi.Script("from itertools import ").completions()
|
||||
definitions = [d for d in itert if d.name == 'chain']
|
||||
assert len(definitions) == 1
|
||||
assert [d.type for d in definitions[0].follow_definition()] == ['class']
|
||||
|
||||
# incomplete `from * import` part
|
||||
datetime = check_follow_definition_types("from datetime import datetim")
|
||||
assert set(datetime) == set(['class', 'instance']) # py33: builtin and pure py version
|
||||
|
||||
# os.path check
|
||||
ospath = check_follow_definition_types("from os.path import abspat")
|
||||
assert ospath == ['function']
|
||||
|
||||
# alias
|
||||
alias = check_follow_definition_types("import io as abcd; abcd")
|
||||
assert alias == ['module']
|
||||
|
||||
|
||||
@cwd_at('test/completion/import_tree')
|
||||
def test_follow_definition_nested_import():
|
||||
types = check_follow_definition_types("import pkg.mod1; pkg")
|
||||
assert types == ['module']
|
||||
|
||||
types = check_follow_definition_types("import pkg.mod1; pkg.mod1")
|
||||
assert types == ['module']
|
||||
|
||||
types = check_follow_definition_types("import pkg.mod1; pkg.mod1.a")
|
||||
assert types == ['instance']
|
||||
|
||||
|
||||
def test_follow_definition_land_on_import():
|
||||
types = check_follow_definition_types("import datetime; datetim")
|
||||
assert types == ['module']
|
||||
@@ -0,0 +1,426 @@
|
||||
from textwrap import dedent
|
||||
import inspect
|
||||
import warnings
|
||||
|
||||
from ..helpers import TestCase
|
||||
from jedi import Script
|
||||
from jedi import cache
|
||||
from jedi._compatibility import is_py33
|
||||
|
||||
|
||||
def assert_signature(source, expected_name, expected_index=0, line=None, column=None):
|
||||
signatures = Script(source, line, column).call_signatures()
|
||||
|
||||
assert len(signatures) <= 1
|
||||
|
||||
if not signatures:
|
||||
assert expected_name is None, \
|
||||
'There are no signatures, but `%s` expected.' % expected_name
|
||||
else:
|
||||
assert signatures[0].name == expected_name
|
||||
assert signatures[0].index == expected_index
|
||||
return signatures[0]
|
||||
|
||||
|
||||
class TestCallSignatures(TestCase):
|
||||
def _run_simple(self, source, name, index=0, column=None, line=1):
|
||||
assert_signature(source, name, index, line, column)
|
||||
|
||||
def test_valid_call(self):
|
||||
assert_signature('str()', 'str', column=4)
|
||||
|
||||
def test_simple(self):
|
||||
run = self._run_simple
|
||||
|
||||
# simple
|
||||
s1 = "sorted(a, str("
|
||||
run(s1, 'sorted', 0, 7)
|
||||
run(s1, 'sorted', 1, 9)
|
||||
run(s1, 'sorted', 1, 10)
|
||||
run(s1, 'sorted', 1, 11)
|
||||
run(s1, 'str', 0, 14)
|
||||
|
||||
s2 = "abs(), "
|
||||
run(s2, 'abs', 0, 4)
|
||||
run(s2, None, column=5)
|
||||
run(s2, None)
|
||||
|
||||
s3 = "abs()."
|
||||
run(s3, None, column=5)
|
||||
run(s3, None)
|
||||
|
||||
def test_more_complicated(self):
|
||||
run = self._run_simple
|
||||
|
||||
s4 = 'abs(zip(), , set,'
|
||||
run(s4, None, column=3)
|
||||
run(s4, 'abs', 0, 4)
|
||||
run(s4, 'zip', 0, 8)
|
||||
run(s4, 'abs', 0, 9)
|
||||
run(s4, 'abs', None, 10)
|
||||
|
||||
s5 = "sorted(1,\nif 2:\n def a():"
|
||||
run(s5, 'sorted', 0, 7)
|
||||
run(s5, 'sorted', 1, 9)
|
||||
|
||||
s6 = "str().center("
|
||||
run(s6, 'center', 0)
|
||||
run(s6, 'str', 0, 4)
|
||||
|
||||
s7 = "str().upper().center("
|
||||
s8 = "str(int[zip("
|
||||
run(s7, 'center', 0)
|
||||
run(s8, 'zip', 0)
|
||||
run(s8, 'str', 0, 8)
|
||||
|
||||
run("import time; abc = time; abc.sleep(", 'sleep', 0)
|
||||
|
||||
def test_issue_57(self):
|
||||
# jedi #57
|
||||
s = "def func(alpha, beta): pass\n" \
|
||||
"func(alpha='101',"
|
||||
self._run_simple(s, 'func', 0, column=13, line=2)
|
||||
|
||||
def test_flows(self):
|
||||
# jedi-vim #9
|
||||
self._run_simple("with open(", 'open', 0)
|
||||
|
||||
# jedi-vim #11
|
||||
self._run_simple("for sorted(", 'sorted', 0)
|
||||
self._run_simple("for s in sorted(", 'sorted', 0)
|
||||
|
||||
def test_complex(self):
|
||||
s = """
|
||||
def abc(a,b):
|
||||
pass
|
||||
|
||||
def a(self):
|
||||
abc(
|
||||
|
||||
if 1:
|
||||
pass
|
||||
"""
|
||||
assert_signature(s, 'abc', 0, line=6, column=24)
|
||||
s = """
|
||||
import re
|
||||
def huhu(it):
|
||||
re.compile(
|
||||
return it * 2
|
||||
"""
|
||||
assert_signature(s, 'compile', 0, line=4, column=31)
|
||||
|
||||
# jedi-vim #70
|
||||
s = """def foo("""
|
||||
assert Script(s).call_signatures() == []
|
||||
|
||||
# jedi-vim #116
|
||||
s = """import itertools; test = getattr(itertools, 'chain'); test("""
|
||||
assert_signature(s, 'chain', 0)
|
||||
|
||||
def test_call_signature_on_module(self):
|
||||
"""github issue #240"""
|
||||
s = 'import datetime; datetime('
|
||||
# just don't throw an exception (if numpy doesn't exist, just ignore it)
|
||||
assert Script(s).call_signatures() == []
|
||||
|
||||
def test_call_signatures_empty_parentheses_pre_space(self):
|
||||
s = dedent("""\
|
||||
def f(a, b):
|
||||
pass
|
||||
f( )""")
|
||||
assert_signature(s, 'f', 0, line=3, column=3)
|
||||
|
||||
def test_multiple_signatures(self):
|
||||
s = dedent("""\
|
||||
if x:
|
||||
def f(a, b):
|
||||
pass
|
||||
else:
|
||||
def f(a, b):
|
||||
pass
|
||||
f(""")
|
||||
assert len(Script(s).call_signatures()) == 2
|
||||
|
||||
def test_call_signatures_whitespace(self):
|
||||
s = dedent("""\
|
||||
abs(
|
||||
def x():
|
||||
pass
|
||||
""")
|
||||
assert_signature(s, 'abs', 0, line=1, column=5)
|
||||
|
||||
def test_decorator_in_class(self):
|
||||
"""
|
||||
There's still an implicit param, with a decorator.
|
||||
Github issue #319.
|
||||
"""
|
||||
s = dedent("""\
|
||||
def static(func):
|
||||
def wrapped(obj, *args):
|
||||
return f(type(obj), *args)
|
||||
return wrapped
|
||||
|
||||
class C(object):
|
||||
@static
|
||||
def test(cls):
|
||||
return 10
|
||||
|
||||
C().test(""")
|
||||
|
||||
signatures = Script(s).call_signatures()
|
||||
assert len(signatures) == 1
|
||||
x = [p.description for p in signatures[0].params]
|
||||
assert x == ['param *args']
|
||||
|
||||
def test_additional_brackets(self):
|
||||
assert_signature('str((', 'str', 0)
|
||||
|
||||
def test_unterminated_strings(self):
|
||||
assert_signature('str(";', 'str', 0)
|
||||
|
||||
def test_whitespace_before_bracket(self):
|
||||
assert_signature('str (', 'str', 0)
|
||||
assert_signature('str (";', 'str', 0)
|
||||
assert_signature('str\n(', None)
|
||||
|
||||
def test_brackets_in_string_literals(self):
|
||||
assert_signature('str (" (', 'str', 0)
|
||||
assert_signature('str (" )', 'str', 0)
|
||||
|
||||
def test_function_definitions_should_break(self):
|
||||
"""
|
||||
Function definitions (and other tokens that cannot exist within call
|
||||
signatures) should break and not be able to return a call signature.
|
||||
"""
|
||||
assert_signature('str(\ndef x', 'str', 0)
|
||||
assert not Script('str(\ndef x(): pass').call_signatures()
|
||||
|
||||
def test_flow_call(self):
|
||||
assert not Script('if (1').call_signatures()
|
||||
|
||||
def test_chained_calls(self):
|
||||
source = dedent('''
|
||||
class B():
|
||||
def test2(self, arg):
|
||||
pass
|
||||
|
||||
class A():
|
||||
def test1(self):
|
||||
return B()
|
||||
|
||||
A().test1().test2(''')
|
||||
|
||||
assert_signature(source, 'test2', 0)
|
||||
|
||||
def test_return(self):
|
||||
source = dedent('''
|
||||
def foo():
|
||||
return '.'.join()''')
|
||||
|
||||
assert_signature(source, 'join', 0, column=len(" return '.'.join("))
|
||||
|
||||
|
||||
class TestParams(TestCase):
|
||||
def params(self, source, line=None, column=None):
|
||||
signatures = Script(source, line, column).call_signatures()
|
||||
assert len(signatures) == 1
|
||||
return signatures[0].params
|
||||
|
||||
def test_param_name(self):
|
||||
if not is_py33:
|
||||
p = self.params('''int(''')
|
||||
# int is defined as: `int(x[, base])`
|
||||
assert p[0].name == 'x'
|
||||
# `int` docstring has been redefined:
|
||||
# http://bugs.python.org/issue14783
|
||||
# TODO have multiple call signatures for int (like in the docstr)
|
||||
#assert p[1].name == 'base'
|
||||
|
||||
p = self.params('''open(something,''')
|
||||
assert p[0].name in ['file', 'name']
|
||||
assert p[1].name == 'mode'
|
||||
|
||||
def test_builtins(self):
|
||||
"""
|
||||
The self keyword should be visible even for builtins, if not
|
||||
instantiated.
|
||||
"""
|
||||
p = self.params('str.endswith(')
|
||||
assert p[0].name == 'self'
|
||||
assert p[1].name == 'suffix'
|
||||
p = self.params('str().endswith(')
|
||||
assert p[0].name == 'suffix'
|
||||
|
||||
|
||||
def test_signature_is_definition():
|
||||
"""
|
||||
Through inheritance, a call signature is a sub class of Definition.
|
||||
Check if the attributes match.
|
||||
"""
|
||||
s = """class Spam(): pass\nSpam"""
|
||||
signature = Script(s + '(').call_signatures()[0]
|
||||
definition = Script(s + '(', column=0).goto_definitions()[0]
|
||||
signature.line == 1
|
||||
signature.column == 6
|
||||
|
||||
# Now compare all the attributes that a CallSignature must also have.
|
||||
for attr_name in dir(definition):
|
||||
dont_scan = ['defined_names', 'parent', 'goto_assignments', 'params']
|
||||
if attr_name.startswith('_') or attr_name in dont_scan:
|
||||
continue
|
||||
|
||||
# Might trigger some deprecation warnings.
|
||||
with warnings.catch_warnings(record=True):
|
||||
attribute = getattr(definition, attr_name)
|
||||
signature_attribute = getattr(signature, attr_name)
|
||||
if inspect.ismethod(attribute):
|
||||
assert attribute() == signature_attribute()
|
||||
else:
|
||||
assert attribute == signature_attribute
|
||||
|
||||
|
||||
def test_no_signature():
|
||||
# str doesn't have a __call__ method
|
||||
assert Script('str()(').call_signatures() == []
|
||||
|
||||
s = dedent("""\
|
||||
class X():
|
||||
pass
|
||||
X()(""")
|
||||
assert Script(s).call_signatures() == []
|
||||
assert len(Script(s, column=2).call_signatures()) == 1
|
||||
assert Script('').call_signatures() == []
|
||||
|
||||
|
||||
def test_dict_literal_in_incomplete_call():
|
||||
source = """\
|
||||
import json
|
||||
|
||||
def foo():
|
||||
json.loads(
|
||||
|
||||
json.load.return_value = {'foo': [],
|
||||
'bar': True}
|
||||
|
||||
c = Foo()
|
||||
"""
|
||||
|
||||
script = Script(dedent(source), line=4, column=15)
|
||||
assert script.call_signatures()
|
||||
|
||||
|
||||
def test_completion_interference():
|
||||
"""Seems to cause problems, see also #396."""
|
||||
cache.parser_cache.pop(None, None)
|
||||
assert Script('open(').call_signatures()
|
||||
|
||||
# complete something usual, before doing the same call_signatures again.
|
||||
assert Script('from datetime import ').completions()
|
||||
|
||||
assert Script('open(').call_signatures()
|
||||
|
||||
|
||||
def test_keyword_argument_index():
|
||||
def get(source, column=None):
|
||||
return Script(source, column=column).call_signatures()[0]
|
||||
|
||||
assert get('sorted([], key=a').index == 2
|
||||
assert get('sorted([], key=').index == 2
|
||||
assert get('sorted([], no_key=a').index is None
|
||||
|
||||
kw_func = 'def foo(a, b): pass\nfoo(b=3, a=4)'
|
||||
assert get(kw_func, column=len('foo(b')).index == 0
|
||||
assert get(kw_func, column=len('foo(b=')).index == 1
|
||||
assert get(kw_func, column=len('foo(b=3, a=')).index == 0
|
||||
|
||||
kw_func_simple = 'def foo(a, b): pass\nfoo(b=4)'
|
||||
assert get(kw_func_simple, column=len('foo(b')).index == 0
|
||||
assert get(kw_func_simple, column=len('foo(b=')).index == 1
|
||||
|
||||
args_func = 'def foo(*kwargs): pass\n'
|
||||
assert get(args_func + 'foo(a').index == 0
|
||||
assert get(args_func + 'foo(a, b').index == 0
|
||||
|
||||
kwargs_func = 'def foo(**kwargs): pass\n'
|
||||
assert get(kwargs_func + 'foo(a=2').index == 0
|
||||
assert get(kwargs_func + 'foo(a=2, b=2').index == 0
|
||||
|
||||
both = 'def foo(*args, **kwargs): pass\n'
|
||||
assert get(both + 'foo(a=2').index == 1
|
||||
assert get(both + 'foo(a=2, b=2').index == 1
|
||||
assert get(both + 'foo(a=2, b=2)', column=len('foo(b=2, a=2')).index == 1
|
||||
assert get(both + 'foo(a, b, c').index == 0
|
||||
|
||||
|
||||
def test_bracket_start():
|
||||
def bracket_start(src):
|
||||
signatures = Script(src).call_signatures()
|
||||
assert len(signatures) == 1
|
||||
return signatures[0].bracket_start
|
||||
|
||||
assert bracket_start('str(') == (1, 3)
|
||||
|
||||
|
||||
def test_different_caller():
|
||||
"""
|
||||
It's possible to not use names, but another function result or an array
|
||||
index and then get the call signature of it.
|
||||
"""
|
||||
|
||||
assert_signature('[str][0](', 'str', 0)
|
||||
assert_signature('[str][0]()', 'str', 0, column=len('[str][0]('))
|
||||
|
||||
assert_signature('(str)(', 'str', 0)
|
||||
assert_signature('(str)()', 'str', 0, column=len('(str)('))
|
||||
|
||||
|
||||
def test_in_function():
|
||||
code = dedent('''\
|
||||
class X():
|
||||
@property
|
||||
def func(''')
|
||||
assert not Script(code).call_signatures()
|
||||
|
||||
|
||||
def test_lambda_params():
|
||||
code = dedent('''\
|
||||
my_lambda = lambda x: x+1
|
||||
my_lambda(1)''')
|
||||
sig, = Script(code, column=11).call_signatures()
|
||||
assert sig.index == 0
|
||||
assert sig.name == '<lambda>'
|
||||
assert [p.name for p in sig.params] == ['x']
|
||||
|
||||
|
||||
def test_class_creation():
|
||||
code = dedent('''\
|
||||
class X():
|
||||
def __init__(self, foo, bar):
|
||||
self.foo = foo
|
||||
''')
|
||||
sig, = Script(code + 'X(').call_signatures()
|
||||
assert sig.index == 0
|
||||
assert sig.name == 'X'
|
||||
assert [p.name for p in sig.params] == ['foo', 'bar']
|
||||
|
||||
sig, = Script(code + 'X.__init__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['self', 'foo', 'bar']
|
||||
sig, = Script(code + 'X().__init__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['foo', 'bar']
|
||||
|
||||
|
||||
def test_call_magic_method():
|
||||
code = dedent('''\
|
||||
class X():
|
||||
def __call__(self, baz):
|
||||
pass
|
||||
''')
|
||||
sig, = Script(code + 'X()(').call_signatures()
|
||||
assert sig.index == 0
|
||||
assert sig.name == 'X'
|
||||
assert [p.name for p in sig.params] == ['baz']
|
||||
|
||||
sig, = Script(code + 'X.__call__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['self', 'baz']
|
||||
sig, = Script(code + 'X().__call__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['baz']
|
||||
@@ -0,0 +1,393 @@
|
||||
""" Test all things related to the ``jedi.api_classes`` module.
|
||||
"""
|
||||
|
||||
from textwrap import dedent
|
||||
from inspect import cleandoc
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi import Script, __doc__ as jedi_doc, names
|
||||
from ..helpers import cwd_at
|
||||
from ..helpers import TestCase
|
||||
|
||||
|
||||
def test_is_keyword():
|
||||
#results = Script('import ', 1, 1, None).goto_definitions()
|
||||
#assert len(results) == 1 and results[0].is_keyword is True
|
||||
results = Script('str', 1, 1, None).goto_definitions()
|
||||
assert len(results) == 1 and results[0].is_keyword is False
|
||||
|
||||
|
||||
def make_definitions():
|
||||
"""
|
||||
Return a list of definitions for parametrized tests.
|
||||
|
||||
:rtype: [jedi.api_classes.BaseDefinition]
|
||||
"""
|
||||
source = dedent("""
|
||||
import sys
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
x = C()
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
def g():
|
||||
yield
|
||||
|
||||
h = lambda: None
|
||||
""")
|
||||
|
||||
definitions = []
|
||||
definitions += names(source)
|
||||
|
||||
source += dedent("""
|
||||
variable = sys or C or x or f or g or g() or h""")
|
||||
lines = source.splitlines()
|
||||
script = Script(source, len(lines), len('variable'), None)
|
||||
definitions += script.goto_definitions()
|
||||
|
||||
script2 = Script(source, 4, len('class C'), None)
|
||||
definitions += script2.usages()
|
||||
|
||||
source_param = "def f(a): return a"
|
||||
script_param = Script(source_param, 1, len(source_param), None)
|
||||
definitions += script_param.goto_assignments()
|
||||
|
||||
return definitions
|
||||
|
||||
|
||||
@pytest.mark.parametrize('definition', make_definitions())
|
||||
def test_basedefinition_type(definition):
|
||||
assert definition.type in ('module', 'class', 'instance', 'function',
|
||||
'generator', 'statement', 'import', 'param')
|
||||
|
||||
|
||||
def test_basedefinition_type_import():
|
||||
def get_types(source, **kwargs):
|
||||
return set([t.type for t in Script(source, **kwargs).completions()])
|
||||
|
||||
# import one level
|
||||
assert get_types('import t') == set(['module'])
|
||||
assert get_types('import ') == set(['module'])
|
||||
assert get_types('import datetime; datetime') == set(['module'])
|
||||
|
||||
# from
|
||||
assert get_types('from datetime import timedelta') == set(['class'])
|
||||
assert get_types('from datetime import timedelta; timedelta') == set(['class'])
|
||||
assert get_types('from json import tool') == set(['module'])
|
||||
assert get_types('from json import tool; tool') == set(['module'])
|
||||
|
||||
# import two levels
|
||||
assert get_types('import json.tool; json') == set(['module'])
|
||||
assert get_types('import json.tool; json.tool') == set(['module'])
|
||||
assert get_types('import json.tool; json.tool.main') == set(['function'])
|
||||
assert get_types('import json.tool') == set(['module'])
|
||||
assert get_types('import json.tool', column=9) == set(['module'])
|
||||
|
||||
|
||||
def test_function_call_signature_in_doc():
|
||||
defs = Script("""
|
||||
def f(x, y=1, z='a'):
|
||||
pass
|
||||
f""").goto_definitions()
|
||||
doc = defs[0].docstring()
|
||||
assert "f(x, y=1, z='a')" in str(doc)
|
||||
|
||||
|
||||
def test_class_call_signature():
|
||||
defs = Script("""
|
||||
class Foo:
|
||||
def __init__(self, x, y=1, z='a'):
|
||||
pass
|
||||
Foo""").goto_definitions()
|
||||
doc = defs[0].docstring()
|
||||
assert "Foo(self, x, y=1, z='a')" in str(doc)
|
||||
|
||||
|
||||
def test_position_none_if_builtin():
|
||||
gotos = Script('import sys; sys.path').goto_assignments()
|
||||
assert gotos[0].line is None
|
||||
assert gotos[0].column is None
|
||||
|
||||
|
||||
@cwd_at('.')
|
||||
def test_completion_docstring():
|
||||
"""
|
||||
Jedi should follow imports in certain conditions
|
||||
"""
|
||||
def docstr(src, result):
|
||||
c = Script(src).completions()[0]
|
||||
assert c.docstring(raw=True, fast=False) == cleandoc(result)
|
||||
|
||||
c = Script('import jedi\njed').completions()[0]
|
||||
assert c.docstring(fast=False) == cleandoc(jedi_doc)
|
||||
|
||||
docstr('import jedi\njedi.Scr', cleandoc(Script.__doc__))
|
||||
|
||||
docstr('abcd=3;abcd', '')
|
||||
docstr('"hello"\nabcd=3\nabcd', '')
|
||||
docstr(dedent('''
|
||||
def x():
|
||||
"hello"
|
||||
0
|
||||
x'''),
|
||||
'hello'
|
||||
)
|
||||
docstr(dedent('''
|
||||
def x():
|
||||
"hello";0
|
||||
x'''),
|
||||
'hello'
|
||||
)
|
||||
# Shouldn't work with a tuple.
|
||||
docstr(dedent('''
|
||||
def x():
|
||||
"hello",0
|
||||
x'''),
|
||||
''
|
||||
)
|
||||
# Should also not work if we rename something.
|
||||
docstr(dedent('''
|
||||
def x():
|
||||
"hello"
|
||||
y = x
|
||||
y'''),
|
||||
''
|
||||
)
|
||||
|
||||
|
||||
def test_completion_params():
|
||||
c = Script('import string; string.capwords').completions()[0]
|
||||
assert [p.name for p in c.params] == ['s', 'sep']
|
||||
|
||||
|
||||
def test_signature_params():
|
||||
def check(defs):
|
||||
params = defs[0].params
|
||||
assert len(params) == 1
|
||||
assert params[0].name == 'bar'
|
||||
|
||||
s = dedent('''
|
||||
def foo(bar):
|
||||
pass
|
||||
foo''')
|
||||
|
||||
check(Script(s).goto_definitions())
|
||||
|
||||
check(Script(s).goto_assignments())
|
||||
check(Script(s + '\nbar=foo\nbar').goto_assignments())
|
||||
|
||||
|
||||
def test_param_endings():
|
||||
"""
|
||||
Params should be represented without the comma and whitespace they have
|
||||
around them.
|
||||
"""
|
||||
sig = Script('def x(a, b=5, c=""): pass\n x(').call_signatures()[0]
|
||||
assert [p.description for p in sig.params] == ['param a', 'param b=5', 'param c=""']
|
||||
|
||||
|
||||
class TestIsDefinition(TestCase):
|
||||
def _def(self, source, index=-1):
|
||||
return names(dedent(source), references=True, all_scopes=True)[index]
|
||||
|
||||
def _bool_is_definitions(self, source):
|
||||
ns = names(dedent(source), references=True, all_scopes=True)
|
||||
# Assure that names are definitely sorted.
|
||||
ns = sorted(ns, key=lambda name: (name.line, name.column))
|
||||
return [name.is_definition() for name in ns]
|
||||
|
||||
def test_name(self):
|
||||
d = self._def('name')
|
||||
assert d.name == 'name'
|
||||
assert not d.is_definition()
|
||||
|
||||
def test_stmt(self):
|
||||
src = 'a = f(x)'
|
||||
d = self._def(src, 0)
|
||||
assert d.name == 'a'
|
||||
assert d.is_definition()
|
||||
d = self._def(src, 1)
|
||||
assert d.name == 'f'
|
||||
assert not d.is_definition()
|
||||
d = self._def(src)
|
||||
assert d.name == 'x'
|
||||
assert not d.is_definition()
|
||||
|
||||
def test_import(self):
|
||||
assert self._bool_is_definitions('import x as a') == [False, True]
|
||||
assert self._bool_is_definitions('from x import y') == [False, True]
|
||||
assert self._bool_is_definitions('from x.z import y') == [False, False, True]
|
||||
|
||||
|
||||
class TestParent(TestCase):
|
||||
def _parent(self, source, line=None, column=None):
|
||||
def_, = Script(dedent(source), line, column).goto_assignments()
|
||||
return def_.parent()
|
||||
|
||||
def test_parent(self):
|
||||
parent = self._parent('foo=1\nfoo')
|
||||
assert parent.type == 'module'
|
||||
|
||||
parent = self._parent('''
|
||||
def spam():
|
||||
if 1:
|
||||
y=1
|
||||
y''')
|
||||
assert parent.name == 'spam'
|
||||
assert parent.parent().type == 'module'
|
||||
|
||||
def test_on_function(self):
|
||||
parent = self._parent('''\
|
||||
def spam():
|
||||
pass''', 1, len('def spam'))
|
||||
assert parent.name == ''
|
||||
assert parent.type == 'module'
|
||||
|
||||
def test_parent_on_completion(self):
|
||||
parent = Script(dedent('''\
|
||||
class Foo():
|
||||
def bar(): pass
|
||||
Foo().bar''')).completions()[0].parent()
|
||||
assert parent.name == 'Foo'
|
||||
assert parent.type == 'class'
|
||||
|
||||
parent = Script('str.join').completions()[0].parent()
|
||||
assert parent.name == 'str'
|
||||
assert parent.type == 'class'
|
||||
|
||||
|
||||
def test_type():
|
||||
for c in Script('a = [str()]; a[0].').completions():
|
||||
if c.name == '__class__':
|
||||
assert c.type == 'class'
|
||||
else:
|
||||
assert c.type in ('function', 'instance')
|
||||
|
||||
# Github issue #397, type should never raise an error.
|
||||
for c in Script('import os; os.path.').completions():
|
||||
assert c.type
|
||||
|
||||
def test_type_II():
|
||||
"""
|
||||
GitHub Issue #833, `keyword`s are seen as `module`s
|
||||
"""
|
||||
for c in Script('f').completions():
|
||||
if c.name == 'for':
|
||||
assert c.type == 'keyword'
|
||||
|
||||
|
||||
class TestGotoAssignments(TestCase):
|
||||
"""
|
||||
This tests the BaseDefinition.goto_assignments function, not the jedi
|
||||
function. They are not really different in functionality, but really
|
||||
different as an implementation.
|
||||
"""
|
||||
def test_repetition(self):
|
||||
defs = names('a = 1; a', references=True, definitions=False)
|
||||
# Repeat on the same variable. Shouldn't change once we're on a
|
||||
# definition.
|
||||
for _ in range(3):
|
||||
assert len(defs) == 1
|
||||
ass = defs[0].goto_assignments()
|
||||
assert ass[0].description == 'a = 1'
|
||||
|
||||
def test_named_params(self):
|
||||
src = """\
|
||||
def foo(a=1, bar=2):
|
||||
pass
|
||||
foo(bar=1)
|
||||
"""
|
||||
bar = names(dedent(src), references=True)[-1]
|
||||
param = bar.goto_assignments()[0]
|
||||
assert (param.line, param.column) == (1, 13)
|
||||
assert param.type == 'param'
|
||||
|
||||
def test_class_call(self):
|
||||
src = 'from threading import Thread; Thread(group=1)'
|
||||
n = names(src, references=True)[-1]
|
||||
assert n.name == 'group'
|
||||
param_def = n.goto_assignments()[0]
|
||||
assert param_def.name == 'group'
|
||||
assert param_def.type == 'param'
|
||||
|
||||
def test_parentheses(self):
|
||||
n = names('("").upper', references=True)[-1]
|
||||
assert n.goto_assignments()[0].name == 'upper'
|
||||
|
||||
def test_import(self):
|
||||
nms = names('from json import load', references=True)
|
||||
assert nms[0].name == 'json'
|
||||
assert nms[0].type == 'module'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'json'
|
||||
assert n.type == 'module'
|
||||
|
||||
assert nms[1].name == 'load'
|
||||
assert nms[1].type == 'function'
|
||||
n = nms[1].goto_assignments()[0]
|
||||
assert n.name == 'load'
|
||||
assert n.type == 'function'
|
||||
|
||||
nms = names('import os; os.path', references=True)
|
||||
assert nms[0].name == 'os'
|
||||
assert nms[0].type == 'module'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'os'
|
||||
assert n.type == 'module'
|
||||
|
||||
n = nms[2].goto_assignments()[0]
|
||||
assert n.name == 'path'
|
||||
assert n.type == 'module'
|
||||
|
||||
nms = names('import os.path', references=True)
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'os'
|
||||
assert n.type == 'module'
|
||||
n = nms[1].goto_assignments()[0]
|
||||
# This is very special, normally the name doesn't chance, but since
|
||||
# os.path is a sys.modules hack, it does.
|
||||
assert n.name in ('ntpath', 'posixpath', 'os2emxpath')
|
||||
assert n.type == 'module'
|
||||
|
||||
def test_import_alias(self):
|
||||
nms = names('import json as foo', references=True)
|
||||
assert nms[0].name == 'json'
|
||||
assert nms[0].type == 'module'
|
||||
assert nms[0]._name.tree_name.parent.type == 'dotted_as_name'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'json'
|
||||
assert n.type == 'module'
|
||||
assert n._name._context.tree_node.type == 'file_input'
|
||||
|
||||
assert nms[1].name == 'foo'
|
||||
assert nms[1].type == 'module'
|
||||
assert nms[1]._name.tree_name.parent.type == 'dotted_as_name'
|
||||
ass = nms[1].goto_assignments()
|
||||
assert len(ass) == 1
|
||||
assert ass[0].name == 'json'
|
||||
assert ass[0].type == 'module'
|
||||
assert ass[0]._name._context.tree_node.type == 'file_input'
|
||||
|
||||
|
||||
def test_added_equals_to_params():
|
||||
def run(rest_source):
|
||||
source = dedent("""
|
||||
def foo(bar, baz):
|
||||
pass
|
||||
""")
|
||||
results = Script(source + rest_source).completions()
|
||||
assert len(results) == 1
|
||||
return results[0]
|
||||
|
||||
assert run('foo(bar').name_with_symbols == 'bar='
|
||||
assert run('foo(bar').complete == '='
|
||||
assert run('foo(bar, baz').complete == '='
|
||||
assert run(' bar').name_with_symbols == 'bar'
|
||||
assert run(' bar').complete == ''
|
||||
x = run('foo(bar=isins').name_with_symbols
|
||||
assert x == 'isinstance'
|
||||
@@ -0,0 +1,49 @@
|
||||
from textwrap import dedent
|
||||
from jedi import Script
|
||||
|
||||
|
||||
def test_in_whitespace():
|
||||
code = dedent('''
|
||||
def x():
|
||||
pass''')
|
||||
assert len(Script(code, column=2).completions()) > 20
|
||||
|
||||
|
||||
def test_empty_init():
|
||||
"""This was actually an issue."""
|
||||
code = dedent('''\
|
||||
class X(object): pass
|
||||
X(''')
|
||||
assert Script(code).completions()
|
||||
|
||||
|
||||
def test_in_empty_space():
|
||||
code = dedent('''\
|
||||
class X(object):
|
||||
def __init__(self):
|
||||
hello
|
||||
''')
|
||||
comps = Script(code, 3, 7).completions()
|
||||
self, = [c for c in comps if c.name == 'self']
|
||||
assert self.name == 'self'
|
||||
def_, = self._goto_definitions()
|
||||
assert def_.name == 'X'
|
||||
|
||||
|
||||
def test_indent_context():
|
||||
"""
|
||||
If an INDENT is the next supposed token, we should still be able to
|
||||
complete.
|
||||
"""
|
||||
code = 'if 1:\nisinstanc'
|
||||
comp, = Script(code).completions()
|
||||
assert comp.name == 'isinstance'
|
||||
|
||||
|
||||
def test_keyword_context():
|
||||
def get_names(*args, **kwargs):
|
||||
return [d.name for d in Script(*args, **kwargs).completions()]
|
||||
|
||||
names = get_names('if 1:\n pass\n')
|
||||
assert 'if' in names
|
||||
assert 'elif' in names
|
||||
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Tests for `api.defined_names`.
|
||||
"""
|
||||
|
||||
from textwrap import dedent
|
||||
|
||||
from jedi import names
|
||||
from ..helpers import TestCase
|
||||
|
||||
|
||||
class TestDefinedNames(TestCase):
|
||||
def assert_definition_names(self, definitions, names_):
|
||||
assert [d.name for d in definitions] == names_
|
||||
|
||||
def check_defined_names(self, source, names_):
|
||||
definitions = names(dedent(source))
|
||||
self.assert_definition_names(definitions, names_)
|
||||
return definitions
|
||||
|
||||
def test_get_definitions_flat(self):
|
||||
self.check_defined_names("""
|
||||
import module
|
||||
class Class:
|
||||
pass
|
||||
def func():
|
||||
pass
|
||||
data = None
|
||||
""", ['module', 'Class', 'func', 'data'])
|
||||
|
||||
def test_dotted_assignment(self):
|
||||
self.check_defined_names("""
|
||||
x = Class()
|
||||
x.y.z = None
|
||||
""", ['x', 'z']) # TODO is this behavior what we want?
|
||||
|
||||
def test_multiple_assignment(self):
|
||||
self.check_defined_names("""
|
||||
x = y = None
|
||||
""", ['x', 'y'])
|
||||
|
||||
def test_multiple_imports(self):
|
||||
self.check_defined_names("""
|
||||
from module import a, b
|
||||
from another_module import *
|
||||
""", ['a', 'b'])
|
||||
|
||||
def test_nested_definitions(self):
|
||||
definitions = self.check_defined_names("""
|
||||
class Class:
|
||||
def f():
|
||||
pass
|
||||
def g():
|
||||
pass
|
||||
""", ['Class'])
|
||||
subdefinitions = definitions[0].defined_names()
|
||||
self.assert_definition_names(subdefinitions, ['f', 'g'])
|
||||
self.assertEqual([d.full_name for d in subdefinitions],
|
||||
['__main__.Class.f', '__main__.Class.g'])
|
||||
|
||||
def test_nested_class(self):
|
||||
definitions = self.check_defined_names("""
|
||||
class L1:
|
||||
class L2:
|
||||
class L3:
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
""", ['L1', 'f'])
|
||||
subdefs = definitions[0].defined_names()
|
||||
subsubdefs = subdefs[0].defined_names()
|
||||
self.assert_definition_names(subdefs, ['L2', 'f'])
|
||||
self.assert_definition_names(subsubdefs, ['L3', 'f'])
|
||||
self.assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
||||
|
||||
|
||||
def test_follow_imports():
|
||||
# github issue #344
|
||||
imp = names('import datetime')[0]
|
||||
assert imp.name == 'datetime'
|
||||
datetime_names = [str(d.name) for d in imp.defined_names()]
|
||||
assert 'timedelta' in datetime_names
|
||||
|
||||
|
||||
def test_names_twice():
|
||||
source = dedent('''
|
||||
def lol():
|
||||
pass
|
||||
''')
|
||||
|
||||
defs = names(source=source)
|
||||
assert defs[0].defined_names() == []
|
||||
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
Tests for :attr:`.BaseDefinition.full_name`.
|
||||
|
||||
There are three kinds of test:
|
||||
|
||||
#. Test classes derived from :class:`MixinTestFullName`.
|
||||
Child class defines :attr:`.operation` to alter how
|
||||
the api definition instance is created.
|
||||
|
||||
#. :class:`TestFullDefinedName` is to test combination of
|
||||
``obj.full_name`` and ``jedi.defined_names``.
|
||||
|
||||
#. Misc single-function tests.
|
||||
"""
|
||||
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from ..helpers import TestCase
|
||||
|
||||
|
||||
class MixinTestFullName(object):
|
||||
operation = None
|
||||
|
||||
def check(self, source, desired):
|
||||
script = jedi.Script(textwrap.dedent(source))
|
||||
definitions = getattr(script, type(self).operation)()
|
||||
for d in definitions:
|
||||
self.assertEqual(d.full_name, desired)
|
||||
|
||||
def test_os_path_join(self):
|
||||
self.check('import os; os.path.join', 'os.path.join')
|
||||
|
||||
def test_builtin(self):
|
||||
self.check('TypeError', 'TypeError')
|
||||
|
||||
|
||||
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
|
||||
operation = 'goto_definitions'
|
||||
|
||||
@pytest.mark.skipif('sys.version_info[0] < 3', reason='Python 2 also yields None.')
|
||||
def test_tuple_mapping(self):
|
||||
self.check("""
|
||||
import re
|
||||
any_re = re.compile('.*')
|
||||
any_re""", '_sre.SRE_Pattern')
|
||||
|
||||
def test_from_import(self):
|
||||
self.check('from os import path', 'os.path')
|
||||
|
||||
|
||||
class TestFullNameWithCompletions(MixinTestFullName, TestCase):
|
||||
operation = 'completions'
|
||||
|
||||
|
||||
class TestFullDefinedName(TestCase):
|
||||
"""
|
||||
Test combination of ``obj.full_name`` and ``jedi.defined_names``.
|
||||
"""
|
||||
|
||||
def check(self, source, desired):
|
||||
definitions = jedi.names(textwrap.dedent(source))
|
||||
full_names = [d.full_name for d in definitions]
|
||||
self.assertEqual(full_names, desired)
|
||||
|
||||
def test_local_names(self):
|
||||
self.check("""
|
||||
def f(): pass
|
||||
class C: pass
|
||||
""", ['__main__.f', '__main__.C'])
|
||||
|
||||
def test_imports(self):
|
||||
self.check("""
|
||||
import os
|
||||
from os import path
|
||||
from os.path import join
|
||||
from os import path as opath
|
||||
""", ['os', 'os.path', 'os.path.join', 'os.path'])
|
||||
|
||||
|
||||
def test_sub_module():
|
||||
"""
|
||||
``full_name needs to check sys.path to actually find it's real path module
|
||||
path.
|
||||
"""
|
||||
defs = jedi.Script('from jedi.api import classes; classes').goto_definitions()
|
||||
assert [d.full_name for d in defs] == ['jedi.api.classes']
|
||||
defs = jedi.Script('import jedi.api; jedi.api').goto_definitions()
|
||||
assert [d.full_name for d in defs] == ['jedi.api']
|
||||
|
||||
|
||||
def test_os_path():
|
||||
d, = jedi.Script('from os.path import join').completions()
|
||||
assert d.full_name == 'os.path.join'
|
||||
d, = jedi.Script('import os.p').completions()
|
||||
assert d.full_name == 'os.path'
|
||||
|
||||
|
||||
def test_os_issues():
|
||||
"""Issue #873"""
|
||||
c, = jedi.Script('import os\nos.nt''').completions()
|
||||
assert c.full_name == 'nt'
|
||||
@@ -0,0 +1,300 @@
|
||||
"""
|
||||
Tests of ``jedi.api.Interpreter``.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from jedi._compatibility import is_py33, py_version
|
||||
from jedi.evaluate.compiled import mixed
|
||||
|
||||
|
||||
if py_version > 30:
|
||||
def exec_(source, global_map):
|
||||
exec(source, global_map)
|
||||
else:
|
||||
eval(compile("""def exec_(source, global_map):
|
||||
exec source in global_map """, 'blub', 'exec'))
|
||||
|
||||
|
||||
class _GlobalNameSpace():
|
||||
class SideEffectContainer():
|
||||
pass
|
||||
|
||||
|
||||
def get_completion(source, namespace):
|
||||
i = jedi.Interpreter(source, [namespace])
|
||||
completions = i.completions()
|
||||
assert len(completions) == 1
|
||||
return completions[0]
|
||||
|
||||
|
||||
def test_builtin_details():
|
||||
import keyword
|
||||
|
||||
class EmptyClass:
|
||||
pass
|
||||
|
||||
variable = EmptyClass()
|
||||
|
||||
def func():
|
||||
pass
|
||||
|
||||
cls = get_completion('EmptyClass', locals())
|
||||
var = get_completion('variable', locals())
|
||||
f = get_completion('func', locals())
|
||||
m = get_completion('keyword', locals())
|
||||
assert cls.type == 'class'
|
||||
assert var.type == 'instance'
|
||||
assert f.type == 'function'
|
||||
assert m.type == 'module'
|
||||
|
||||
|
||||
def test_numpy_like_non_zero():
|
||||
"""
|
||||
Numpy-like array can't be caster to bool and need to be compacre with
|
||||
`is`/`is not` and not `==`/`!=`
|
||||
"""
|
||||
|
||||
class NumpyNonZero:
|
||||
|
||||
def __zero__(self):
|
||||
raise ValueError('Numpy arrays would raise and tell you to use .any() or all()')
|
||||
def __bool__(self):
|
||||
raise ValueError('Numpy arrays would raise and tell you to use .any() or all()')
|
||||
|
||||
class NumpyLike:
|
||||
|
||||
def __eq__(self, other):
|
||||
return NumpyNonZero()
|
||||
|
||||
def something(self):
|
||||
pass
|
||||
|
||||
x = NumpyLike()
|
||||
d = {'a': x}
|
||||
|
||||
# just assert these do not raise. They (strangely) trigger different
|
||||
# codepath
|
||||
get_completion('d["a"].some', {'d':d})
|
||||
get_completion('x.some', {'x':x})
|
||||
|
||||
|
||||
def test_nested_resolve():
|
||||
class XX():
|
||||
def x():
|
||||
pass
|
||||
|
||||
cls = get_completion('XX', locals())
|
||||
func = get_completion('XX.x', locals())
|
||||
assert (func.line, func.column) == (cls.line + 1, 12)
|
||||
|
||||
|
||||
def test_side_effect_completion():
|
||||
"""
|
||||
In the repl it's possible to cause side effects that are not documented in
|
||||
Python code, however we want references to Python code as well. Therefore
|
||||
we need some mixed kind of magic for tests.
|
||||
"""
|
||||
_GlobalNameSpace.SideEffectContainer.foo = 1
|
||||
side_effect = get_completion('SideEffectContainer', _GlobalNameSpace.__dict__)
|
||||
|
||||
# It's a class that contains MixedObject.
|
||||
context, = side_effect._name.infer()
|
||||
assert isinstance(context, mixed.MixedObject)
|
||||
foo = get_completion('SideEffectContainer.foo', _GlobalNameSpace.__dict__)
|
||||
assert foo.name == 'foo'
|
||||
|
||||
|
||||
def _assert_interpreter_complete(source, namespace, completions,
|
||||
**kwds):
|
||||
script = jedi.Interpreter(source, [namespace], **kwds)
|
||||
cs = script.completions()
|
||||
actual = [c.name for c in cs]
|
||||
assert sorted(actual) == sorted(completions)
|
||||
|
||||
|
||||
def test_complete_raw_function():
|
||||
from os.path import join
|
||||
_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'])
|
||||
|
||||
|
||||
def test_complete_raw_module():
|
||||
import os
|
||||
_assert_interpreter_complete('os.path.join("a").up',
|
||||
locals(),
|
||||
['upper'])
|
||||
|
||||
|
||||
def test_complete_raw_instance():
|
||||
import datetime
|
||||
dt = datetime.datetime(2013, 1, 1)
|
||||
completions = ['time', 'timetz', 'timetuple']
|
||||
if is_py33:
|
||||
completions += ['timestamp']
|
||||
_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(),
|
||||
[])
|
||||
|
||||
# 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'])
|
||||
# inexistent index
|
||||
_assert_interpreter_complete('array[2].upper',
|
||||
locals(),
|
||||
['upper'])
|
||||
|
||||
|
||||
def test_slice():
|
||||
class Foo1():
|
||||
bar = []
|
||||
baz = 'xbarx'
|
||||
_assert_interpreter_complete('getattr(Foo1, baz[1:-1]).append',
|
||||
locals(),
|
||||
['append'])
|
||||
|
||||
|
||||
def test_getitem_side_effects():
|
||||
class Foo2():
|
||||
def __getitem__(self, index):
|
||||
# Possible side effects here, should therefore not call this.
|
||||
if True:
|
||||
raise NotImplementedError()
|
||||
return index
|
||||
|
||||
foo = Foo2()
|
||||
_assert_interpreter_complete('foo["asdf"].upper', locals(), ['upper'])
|
||||
|
||||
|
||||
def test_property_error_oldstyle():
|
||||
lst = []
|
||||
class Foo3():
|
||||
@property
|
||||
def bar(self):
|
||||
lst.append(1)
|
||||
raise ValueError
|
||||
|
||||
foo = Foo3()
|
||||
_assert_interpreter_complete('foo.bar', locals(), ['bar'])
|
||||
_assert_interpreter_complete('foo.bar.baz', locals(), [])
|
||||
|
||||
# There should not be side effects
|
||||
assert lst == []
|
||||
|
||||
|
||||
def test_property_error_newstyle():
|
||||
lst = []
|
||||
class Foo3(object):
|
||||
@property
|
||||
def bar(self):
|
||||
lst.append(1)
|
||||
raise ValueError
|
||||
|
||||
foo = Foo3()
|
||||
_assert_interpreter_complete('foo.bar', locals(), ['bar'])
|
||||
_assert_interpreter_complete('foo.bar.baz', locals(), [])
|
||||
|
||||
# There should not be side effects
|
||||
assert lst == []
|
||||
|
||||
|
||||
def test_param_completion():
|
||||
def foo(bar):
|
||||
pass
|
||||
|
||||
lambd = lambda xyz: 3
|
||||
|
||||
_assert_interpreter_complete('foo(bar', locals(), ['bar'])
|
||||
# TODO we're not yet using the Python3.5 inspect.signature, yet.
|
||||
assert not jedi.Interpreter('lambd(xyz', [locals()]).completions()
|
||||
|
||||
|
||||
def test_endless_yield():
|
||||
lst = [1] * 10000
|
||||
# If iterating over lists it should not be possible to take an extremely
|
||||
# long time.
|
||||
_assert_interpreter_complete('list(lst)[9000].rea', locals(), ['real'])
|
||||
|
||||
|
||||
@pytest.mark.skipif('py_version < 33', reason='inspect.signature was created in 3.3.')
|
||||
def test_completion_params():
|
||||
foo = lambda a, b=3: None
|
||||
|
||||
script = jedi.Interpreter('foo', [locals()])
|
||||
c, = script.completions()
|
||||
assert [p.name for p in c.params] == ['a', 'b']
|
||||
assert c.params[0]._goto_definitions() == []
|
||||
t, = c.params[1]._goto_definitions()
|
||||
assert t.name == 'int'
|
||||
|
||||
|
||||
@pytest.mark.skipif('py_version < 33', reason='inspect.signature was created in 3.3.')
|
||||
def test_completion_param_annotations():
|
||||
# Need to define this function not directly in Python. Otherwise Jedi is to
|
||||
# clever and uses the Python code instead of the signature object.
|
||||
code = 'def foo(a: 1, b: str, c: int = 1.0): pass'
|
||||
exec_(code, locals())
|
||||
script = jedi.Interpreter('foo', [locals()])
|
||||
c, = script.completions()
|
||||
a, b, c = c.params
|
||||
assert a._goto_definitions() == []
|
||||
assert [d.name for d in b._goto_definitions()] == ['str']
|
||||
assert set([d.name for d in c._goto_definitions()]) == set(['int', 'float'])
|
||||
|
||||
|
||||
def test_more_complex_instances():
|
||||
class Something:
|
||||
def foo(self, other):
|
||||
return self
|
||||
|
||||
class Base():
|
||||
def wow(self):
|
||||
return Something()
|
||||
|
||||
#script = jedi.Interpreter('Base().wow().foo', [locals()])
|
||||
#c, = script.completions()
|
||||
#assert c.name == 'foo'
|
||||
|
||||
x = Base()
|
||||
script = jedi.Interpreter('x.wow().foo', [locals()])
|
||||
c, = script.completions()
|
||||
assert c.name == 'foo'
|
||||
|
||||
|
||||
def test_repr_execution_issue():
|
||||
"""
|
||||
Anticipate inspect.getfile executing a __repr__ of all kinds of objects.
|
||||
See also #919.
|
||||
"""
|
||||
class ErrorRepr:
|
||||
def __repr__(self):
|
||||
raise Exception('xyz')
|
||||
|
||||
er = ErrorRepr()
|
||||
|
||||
script = jedi.Interpreter('er', [locals()])
|
||||
d, = script.goto_definitions()
|
||||
assert d.name == 'ErrorRepr'
|
||||
assert d.type == 'instance'
|
||||
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
All character set and unicode related tests.
|
||||
"""
|
||||
from jedi import Script
|
||||
from jedi._compatibility import u, unicode
|
||||
|
||||
|
||||
def test_unicode_script():
|
||||
""" normally no unicode objects are being used. (<=2.7) """
|
||||
s = unicode("import datetime; datetime.timedelta")
|
||||
completions = Script(s).completions()
|
||||
assert len(completions)
|
||||
assert type(completions[0].description) is unicode
|
||||
|
||||
s = u("author='öä'; author")
|
||||
completions = Script(s).completions()
|
||||
x = completions[0].description
|
||||
assert type(x) is unicode
|
||||
|
||||
s = u("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author")
|
||||
s = s.encode('latin-1')
|
||||
completions = Script(s).completions()
|
||||
assert type(completions[0].description) is unicode
|
||||
|
||||
|
||||
def test_unicode_attribute():
|
||||
""" github jedi-vim issue #94 """
|
||||
s1 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
|
||||
' name = "e"\n\nPerson().name.')
|
||||
completions1 = Script(s1).completions()
|
||||
assert 'strip' in [c.name for c in completions1]
|
||||
s2 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
|
||||
' name = "é"\n\nPerson().name.')
|
||||
completions2 = Script(s2).completions()
|
||||
assert 'strip' in [c.name for c in completions2]
|
||||
|
||||
|
||||
def test_multibyte_script():
|
||||
""" `jedi.Script` must accept multi-byte string source. """
|
||||
try:
|
||||
code = u("import datetime; datetime.d")
|
||||
comment = u("# multi-byte comment あいうえおä")
|
||||
s = (u('%s\n%s') % (code, comment)).encode('utf-8')
|
||||
except NameError:
|
||||
pass # python 3 has no unicode method
|
||||
else:
|
||||
assert len(Script(s, 1, len(code)).completions())
|
||||
|
||||
|
||||
def test_goto_definition_at_zero():
|
||||
"""At zero usually sometimes raises unicode issues."""
|
||||
assert Script("a", 1, 1).goto_definitions() == []
|
||||
s = Script("str", 1, 1).goto_definitions()
|
||||
assert len(s) == 1
|
||||
assert list(s)[0].description == 'class str'
|
||||
assert Script("", 1, 0).goto_definitions() == []
|
||||
|
||||
|
||||
def test_complete_at_zero():
|
||||
s = Script("str", 1, 3).completions()
|
||||
assert len(s) == 1
|
||||
assert list(s)[0].name == 'str'
|
||||
|
||||
s = Script("", 1, 0).completions()
|
||||
assert len(s) > 0
|
||||
@@ -0,0 +1,6 @@
|
||||
import jedi
|
||||
|
||||
|
||||
def test_import_usage():
|
||||
s = jedi.Script("from .. import foo", line=1, column=18, path="foo.py")
|
||||
assert [usage.line for usage in s.usages()] == [1]
|
||||
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
This is a module that imports the *standard library* unittest,
|
||||
despite there being a local "unittest" module. It specifies that it
|
||||
wants the stdlib one with the ``absolute_import`` __future__ import.
|
||||
|
||||
The twisted equivalent of this module is ``twisted.trial._synctest``.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class Assertions(unittest.TestCase):
|
||||
pass
|
||||
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
This is a module that shadows a builtin (intentionally).
|
||||
|
||||
It imports a local module, which in turn imports stdlib unittest (the
|
||||
name shadowed by this module). If that is properly resolved, there's
|
||||
no problem. However, if jedi doesn't understand absolute_imports, it
|
||||
will get this module again, causing infinite recursion.
|
||||
"""
|
||||
from local_module import Assertions
|
||||
|
||||
|
||||
class TestCase(Assertions):
|
||||
def test(self):
|
||||
self.assertT
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
sys.path[0:0] = [
|
||||
'/usr/lib/python3.4/site-packages',
|
||||
'/tmp/.buildout/eggs/important_package.egg'
|
||||
]
|
||||
|
||||
import important_package
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(important_package.main())
|
||||
@@ -0,0 +1 @@
|
||||
‰PNG
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Baz = 1
|
||||
@@ -0,0 +1,2 @@
|
||||
class Foo(object):
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
class Bar(object):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
Moo = 1
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns1_file!'
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns2_file!'
|
||||
@@ -0,0 +1 @@
|
||||
CONST = 1
|
||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
#include "Python.h"
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"init_extension_module",
|
||||
NULL,
|
||||
-1,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC PyInit_init_extension_module(void){
|
||||
PyObject *m = PyModule_Create(&module);
|
||||
PyModule_AddObject(m, "foo", Py_None);
|
||||
return m;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name='init_extension_module',
|
||||
version='0.0',
|
||||
description='',
|
||||
ext_modules=[
|
||||
Extension('init_extension_module.__init__',
|
||||
sources=['module.c'])
|
||||
]
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
foo = 'ns1!'
|
||||
|
||||
# this is a namespace package
|
||||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
__path__ = pkgutil.extend_path(__path__, __name__)
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns1_file!'
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns1_folder!'
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns2_file!'
|
||||
@@ -0,0 +1 @@
|
||||
foo = 'ns2_folder!'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user