forked from VimPlug/jedi
Merge branch 'master' into pytest
This commit is contained in:
@@ -30,7 +30,7 @@ b = [6,7]
|
||||
#? int()
|
||||
b[8-7]
|
||||
# Something unreasonable:
|
||||
#?
|
||||
#? int()
|
||||
b['']
|
||||
|
||||
# -----------------
|
||||
@@ -45,7 +45,7 @@ b[int():]
|
||||
#? list()
|
||||
b[:]
|
||||
|
||||
#?
|
||||
#? int()
|
||||
b[:, 1]
|
||||
|
||||
class _StrangeSlice():
|
||||
@@ -161,7 +161,7 @@ def a(): return ''
|
||||
#? str()
|
||||
(a)()
|
||||
#? str()
|
||||
(a)().replace()
|
||||
(a)().title()
|
||||
#? int()
|
||||
(tuple).index()
|
||||
#? int()
|
||||
@@ -209,8 +209,7 @@ g
|
||||
dic2 = {'asdf': 3, 'b': 'str'}
|
||||
#? int()
|
||||
dic2['asdf']
|
||||
# TODO for now get doesn't work properly when used with a literal.
|
||||
#? None
|
||||
#? None int() str()
|
||||
dic2.get('asdf')
|
||||
|
||||
# string literal
|
||||
@@ -268,11 +267,12 @@ for x in {1: 3.0, '': 1j}:
|
||||
dict().values().__iter__
|
||||
|
||||
d = dict(a=3, b='')
|
||||
x, = d.values()
|
||||
#? int() str()
|
||||
x
|
||||
#? int() str()
|
||||
d.values()[0]
|
||||
#? int()
|
||||
d['a']
|
||||
#? int() None
|
||||
#? int() str() None
|
||||
d.get('a')
|
||||
|
||||
# -----------------
|
||||
@@ -437,7 +437,7 @@ def test_func():
|
||||
#? int()
|
||||
tuple({1})[0]
|
||||
|
||||
# python >= 3.3
|
||||
# python >= 3.4
|
||||
# -----------------
|
||||
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
||||
# -----------------
|
||||
@@ -445,7 +445,7 @@ tuple({1})[0]
|
||||
a, *b, c = [1, 'b', list, dict]
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
#?
|
||||
b
|
||||
#? list
|
||||
c
|
||||
@@ -454,12 +454,14 @@ c
|
||||
a, *b, *c = [1, 'd', list]
|
||||
#? int()
|
||||
a
|
||||
#? str()
|
||||
#?
|
||||
b
|
||||
#? list
|
||||
#?
|
||||
c
|
||||
|
||||
lc = [x for a, *x in [(1, '', 1.0)]]
|
||||
|
||||
#?
|
||||
lc[0][0]
|
||||
#?
|
||||
lc[0][1]
|
||||
|
||||
@@ -154,6 +154,9 @@ def global_define():
|
||||
#? int()
|
||||
global_var_in_func
|
||||
|
||||
#? ['global_var_in_func']
|
||||
global_var_in_f
|
||||
|
||||
|
||||
def funct1():
|
||||
# From issue #610
|
||||
@@ -175,6 +178,7 @@ def init_global_var_predefined():
|
||||
#? int() None
|
||||
global_var_predefined
|
||||
|
||||
|
||||
# -----------------
|
||||
# within docstrs
|
||||
# -----------------
|
||||
@@ -300,7 +304,7 @@ with open('') as f:
|
||||
#? ['closed']
|
||||
f.closed
|
||||
for line in f:
|
||||
#? str()
|
||||
#? str() bytes()
|
||||
line
|
||||
|
||||
with open('') as f1, open('') as f2:
|
||||
|
||||
@@ -36,6 +36,7 @@ class TestClass(object):
|
||||
self2.var_inst = first_param
|
||||
self2.second = second_param
|
||||
self2.first = first_param
|
||||
self2.first.var_on_argument = 5
|
||||
a = 3
|
||||
|
||||
def var_func(self):
|
||||
@@ -57,6 +58,8 @@ class TestClass(object):
|
||||
# should not know any class functions!
|
||||
#? []
|
||||
values
|
||||
#?
|
||||
values
|
||||
#? ['return']
|
||||
ret
|
||||
return a1
|
||||
@@ -417,6 +420,9 @@ class PrivateVar():
|
||||
def __private_func(self):
|
||||
return 1
|
||||
|
||||
#? int()
|
||||
__private_func()
|
||||
|
||||
def wrap_private(self):
|
||||
return self.__private_func()
|
||||
#? []
|
||||
@@ -425,6 +431,8 @@ PrivateVar().__var
|
||||
PrivateVar().__var
|
||||
#? []
|
||||
PrivateVar().__private_func
|
||||
#? []
|
||||
PrivateVar.__private_func
|
||||
#? int()
|
||||
PrivateVar().wrap_private()
|
||||
|
||||
@@ -571,3 +579,26 @@ class Foo(object):
|
||||
|
||||
#? int()
|
||||
Foo().b
|
||||
|
||||
# -----------------
|
||||
# default arguments
|
||||
# -----------------
|
||||
|
||||
default = ''
|
||||
class DefaultArg():
|
||||
default = 3
|
||||
def x(self, arg=default):
|
||||
#? str()
|
||||
default
|
||||
return arg
|
||||
def y(self):
|
||||
return default
|
||||
|
||||
#? int()
|
||||
DefaultArg().x()
|
||||
#? str()
|
||||
DefaultArg().y()
|
||||
#? int()
|
||||
DefaultArg.x()
|
||||
#? str()
|
||||
DefaultArg.y()
|
||||
|
||||
@@ -52,12 +52,12 @@ left
|
||||
[a for a in {1:'x'}][0]
|
||||
|
||||
# list comprehensions should also work in combination with functions
|
||||
def listen(arg):
|
||||
def _listen(arg):
|
||||
for x in arg:
|
||||
#? str()
|
||||
x
|
||||
|
||||
listen(['' for x in [1]])
|
||||
_listen(['' for x in [1]])
|
||||
#?
|
||||
([str for x in []])[0]
|
||||
|
||||
@@ -212,3 +212,14 @@ next(iter({a for a in range(10)}))
|
||||
|
||||
#? int()
|
||||
[a for a in {1, 2, 3}][0]
|
||||
|
||||
# -----------------
|
||||
# syntax errors
|
||||
# -----------------
|
||||
|
||||
# Issue #1146
|
||||
|
||||
#? ['list']
|
||||
[int(str(x.value) for x in list
|
||||
|
||||
def reset_missing_bracket(): pass
|
||||
|
||||
@@ -16,8 +16,18 @@ class Y(X):
|
||||
#? ['func']
|
||||
def f
|
||||
|
||||
#? ['__doc__']
|
||||
__doc__
|
||||
#? []
|
||||
def __doc__
|
||||
|
||||
# This might or might not be what we wanted, currently properties are also
|
||||
# used like this. IMO this is not wanted ~dave.
|
||||
#? ['__class__']
|
||||
def __class__
|
||||
#? []
|
||||
__class__
|
||||
|
||||
|
||||
#? ['__repr__']
|
||||
def __repr__
|
||||
|
||||
@@ -55,9 +55,10 @@ list(arr)[10]
|
||||
arr = [1.0]
|
||||
arr.extend([1,2,3])
|
||||
arr.extend([])
|
||||
arr.extend("") # should ignore
|
||||
arr.extend("")
|
||||
arr.extend(list) # should ignore
|
||||
|
||||
#? float() int()
|
||||
#? float() int() str()
|
||||
arr[100]
|
||||
|
||||
a = set(arr)
|
||||
@@ -94,7 +95,7 @@ arr2[0]
|
||||
lst = [1]
|
||||
lst.append(1.0)
|
||||
s = set(lst)
|
||||
s.add("")
|
||||
s.add("ahh")
|
||||
lst = list(s)
|
||||
lst.append({})
|
||||
|
||||
|
||||
@@ -25,3 +25,14 @@ Fr'sasdf'
|
||||
|
||||
#? 7 str()
|
||||
Fr'''sasdf''' + ''
|
||||
|
||||
#? ['upper']
|
||||
f'xyz'.uppe
|
||||
|
||||
|
||||
#? 3 []
|
||||
f'f'
|
||||
|
||||
# Github #1248
|
||||
#? int()
|
||||
{"foo": 1}[f"foo"]
|
||||
|
||||
@@ -319,6 +319,7 @@ exe['c']
|
||||
a = 'a'
|
||||
exe2 = kwargs_func(**{a:3,
|
||||
'b':4.0})
|
||||
|
||||
#? int()
|
||||
exe2['a']
|
||||
#? float()
|
||||
@@ -326,6 +327,19 @@ exe2['b']
|
||||
#? int() float()
|
||||
exe2['c']
|
||||
|
||||
exe3 = kwargs_func(**{k: v for k, v in [(a, 3), ('b', 4.0)]})
|
||||
|
||||
# Should resolve to the same as 2 but jedi is not smart enough yet
|
||||
# Here to make sure it doesn't result in crash though
|
||||
#?
|
||||
exe3['a']
|
||||
|
||||
#?
|
||||
exe3['b']
|
||||
|
||||
#?
|
||||
exe3['c']
|
||||
|
||||
# -----------------
|
||||
# *args / ** kwargs
|
||||
# -----------------
|
||||
|
||||
@@ -220,7 +220,7 @@ def x():
|
||||
# yield from
|
||||
# -----------------
|
||||
|
||||
# python >= 3.3
|
||||
# python >= 3.4
|
||||
|
||||
def yield_from():
|
||||
yield from iter([1])
|
||||
|
||||
@@ -120,6 +120,8 @@ import_tree.a
|
||||
|
||||
#! ['module mod1']
|
||||
import import_tree.mod1
|
||||
#! ['module mod1']
|
||||
from import_tree.mod1
|
||||
#! ['a = 1']
|
||||
import_tree.mod1.a
|
||||
|
||||
|
||||
@@ -114,6 +114,31 @@ def as_imports():
|
||||
bar.a
|
||||
|
||||
|
||||
def broken_import():
|
||||
import import_tree.mod1
|
||||
#? import_tree.mod1
|
||||
from import_tree.mod1
|
||||
|
||||
#? 25 import_tree.mod1
|
||||
import import_tree.mod1.
|
||||
#? 25 import_tree.mod1
|
||||
impo5t import_tree.mod1.foo
|
||||
#? 25 import_tree.mod1
|
||||
import import_tree.mod1.foo.
|
||||
#? 31 import_tree.mod1
|
||||
import json, import_tree.mod1.foo.
|
||||
|
||||
# Cases with ;
|
||||
mod1 = 3
|
||||
#? 25 int()
|
||||
import import_tree; mod1.
|
||||
#? 38 import_tree.mod1
|
||||
import_tree; import import_tree.mod1.
|
||||
|
||||
#! ['module json']
|
||||
from json
|
||||
|
||||
|
||||
def test_import_priorities():
|
||||
"""
|
||||
It's possible to overwrite import paths in an ``__init__.py`` file, by
|
||||
|
||||
@@ -143,12 +143,12 @@ a3[0]
|
||||
a = [for a in
|
||||
def break(): pass
|
||||
|
||||
#?
|
||||
#? str()
|
||||
a[0]
|
||||
|
||||
a = [a for a in [1,2]
|
||||
def break(): pass
|
||||
#?
|
||||
#? str()
|
||||
a[0]
|
||||
|
||||
#? []
|
||||
|
||||
@@ -18,13 +18,13 @@ b; continue
|
||||
b; continu
|
||||
|
||||
#? []
|
||||
c + brea
|
||||
c + pass
|
||||
|
||||
#? []
|
||||
a + break
|
||||
a + pass
|
||||
|
||||
#? ['break']
|
||||
b; break
|
||||
#? ['pass']
|
||||
b; pass
|
||||
|
||||
# -----------------
|
||||
# Keywords should not appear everywhere.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
""" Pep-0484 type hinting """
|
||||
|
||||
# python >= 3.2
|
||||
# python >= 3.4
|
||||
|
||||
|
||||
class A():
|
||||
@@ -68,7 +68,7 @@ def return_annotation_and_docstring() -> str:
|
||||
"""
|
||||
pass
|
||||
|
||||
#? str() int()
|
||||
#? str()
|
||||
return_annotation_and_docstring()
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ 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:
|
||||
#?
|
||||
#? str()
|
||||
x
|
||||
#? str()
|
||||
y
|
||||
|
||||
@@ -40,6 +40,8 @@ def we_can_has_sequence(p, q, r, s, t, u):
|
||||
t[1]
|
||||
#? ["append"]
|
||||
u.a
|
||||
#? float() list()
|
||||
u[1.0]
|
||||
#? float()
|
||||
u[1]
|
||||
|
||||
@@ -114,13 +116,9 @@ def tuple(p, q, r):
|
||||
i, s, f = q
|
||||
#? int()
|
||||
i
|
||||
##? str() --- TODO fix support for tuple assignment
|
||||
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
|
||||
#?
|
||||
#? str()
|
||||
s
|
||||
##? float() --- TODO fix support for tuple assignment
|
||||
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
|
||||
#?
|
||||
#? float()
|
||||
f
|
||||
|
||||
class Key:
|
||||
@@ -173,6 +171,21 @@ def mapping(p, q, d, dd, r, s, t):
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key, value in q.items():
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key, value in d.items():
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key, value in dd.items():
|
||||
#? Key()
|
||||
key
|
||||
#? Value()
|
||||
value
|
||||
for key in r:
|
||||
#? Key()
|
||||
key
|
||||
@@ -211,7 +224,7 @@ def optional(p):
|
||||
as being of that type. Jedi doesn't do anything with the extra into that
|
||||
it can be None as well
|
||||
"""
|
||||
#? int()
|
||||
#? int() None
|
||||
p
|
||||
|
||||
class ForwardReference:
|
||||
@@ -243,7 +256,7 @@ for key in x.keys():
|
||||
for value in x.values():
|
||||
#? int()
|
||||
value
|
||||
# python >= 3.2
|
||||
# python >= 3.4
|
||||
|
||||
class TestDefaultDict(typing.DefaultDict[str, int]):
|
||||
def setdud(self):
|
||||
@@ -271,7 +284,7 @@ for key in x.keys():
|
||||
for value in x.values():
|
||||
#? int()
|
||||
value
|
||||
# python >= 3.2
|
||||
# python >= 3.4
|
||||
|
||||
|
||||
"""
|
||||
@@ -292,3 +305,49 @@ from typing import Union as U
|
||||
def union4(x: U[int, str]):
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
|
||||
TYPE_VAR = typing.TypeVar('TYPE_VAR')
|
||||
# TODO there should at least be some results.
|
||||
#? []
|
||||
TYPE_VAR.
|
||||
#! ["TYPE_VAR = typing.TypeVar('TYPE_VAR')"]
|
||||
TYPE_VAR
|
||||
|
||||
|
||||
class WithTypeVar(typing.Generic[TYPE_VAR]):
|
||||
def lala(self) -> TYPE_VAR:
|
||||
...
|
||||
|
||||
|
||||
def maaan(p: WithTypeVar[int]):
|
||||
#? int()
|
||||
p.lala()
|
||||
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
with_type_checking = 1
|
||||
else:
|
||||
without_type_checking = 1.0
|
||||
#? int()
|
||||
with_type_checking
|
||||
#?
|
||||
without_type_checking
|
||||
|
||||
def foo(a: typing.List, b: typing.Dict, c: typing.MutableMapping) -> typing.Type[int]:
|
||||
#? ['append']
|
||||
a.appen
|
||||
#? list()
|
||||
a
|
||||
#?
|
||||
a[0]
|
||||
#? ['setdefault']
|
||||
b.setd
|
||||
#? ['setdefault']
|
||||
c.setd
|
||||
#? typing.MutableMapping()
|
||||
c
|
||||
#?
|
||||
c['asdf']
|
||||
#? int
|
||||
foo()
|
||||
|
||||
@@ -36,3 +36,18 @@ char: str
|
||||
for char in NOT_DEFINED:
|
||||
#? str()
|
||||
char
|
||||
|
||||
|
||||
class Foo():
|
||||
bar: int
|
||||
baz: typing.ClassVar[str]
|
||||
|
||||
|
||||
#? int()
|
||||
Foo.bar
|
||||
#? int()
|
||||
Foo().bar
|
||||
#? str()
|
||||
Foo.baz
|
||||
#? str()
|
||||
Foo().baz
|
||||
|
||||
@@ -57,6 +57,11 @@ a
|
||||
#? int() str()
|
||||
(3 ** 'a')
|
||||
|
||||
class X():
|
||||
foo = 2
|
||||
#? int()
|
||||
(X.foo ** 3)
|
||||
|
||||
# -----------------
|
||||
# assignments
|
||||
# -----------------
|
||||
|
||||
@@ -76,3 +76,18 @@ class InstanceAttributeIfs:
|
||||
InstanceAttributeIfs().a1
|
||||
#? int() str()
|
||||
InstanceAttributeIfs().a2
|
||||
|
||||
|
||||
|
||||
class A:
|
||||
def a(self, b):
|
||||
for x in [self.a(i) for i in b]:
|
||||
#?
|
||||
x
|
||||
|
||||
class B:
|
||||
def a(self, b):
|
||||
for i in b:
|
||||
for i in self.a(i):
|
||||
#?
|
||||
yield i
|
||||
|
||||
@@ -25,7 +25,7 @@ next(reversed(yielder()))
|
||||
#?
|
||||
next(reversed())
|
||||
|
||||
#? str()
|
||||
#? str() bytes()
|
||||
next(open(''))
|
||||
|
||||
#? int()
|
||||
@@ -34,6 +34,8 @@ next(open(''))
|
||||
# Compiled classes should have the meta class attributes.
|
||||
#? ['__itemsize__']
|
||||
tuple.__itemsize__
|
||||
#? []
|
||||
tuple().__itemsize__
|
||||
|
||||
# -----------------
|
||||
# type() calls with one parameter
|
||||
@@ -69,10 +71,15 @@ if os.path.isfile():
|
||||
#? ['abspath']
|
||||
fails = os.path.abspath
|
||||
|
||||
# The type vars and other underscored things from typeshed should not be
|
||||
# findable.
|
||||
#?
|
||||
os._T
|
||||
|
||||
|
||||
with open('foo') as f:
|
||||
for line in f.readlines():
|
||||
#? str()
|
||||
#? str() bytes()
|
||||
line
|
||||
# -----------------
|
||||
# enumerate
|
||||
@@ -101,9 +108,6 @@ for a in re.finditer('a', 'a'):
|
||||
#? int()
|
||||
a.start()
|
||||
|
||||
#? str()
|
||||
re.sub('a', 'a')
|
||||
|
||||
# -----------------
|
||||
# ref
|
||||
# -----------------
|
||||
@@ -114,7 +118,7 @@ weakref.proxy(1)
|
||||
|
||||
#? weakref.ref()
|
||||
weakref.ref(1)
|
||||
#? int()
|
||||
#? int() None
|
||||
weakref.ref(1)()
|
||||
|
||||
# -----------------
|
||||
@@ -165,10 +169,6 @@ import sqlite3
|
||||
con = sqlite3.connect()
|
||||
#? sqlite3.Cursor()
|
||||
c = con.cursor()
|
||||
#? sqlite3.Row()
|
||||
row = c.fetchall()[0]
|
||||
#? str()
|
||||
row.keys()[0]
|
||||
|
||||
def huhu(db):
|
||||
"""
|
||||
@@ -241,6 +241,31 @@ with contextlib.closing('asd') as string:
|
||||
#? str()
|
||||
string
|
||||
|
||||
# -----------------
|
||||
# operator
|
||||
# -----------------
|
||||
|
||||
import operator
|
||||
|
||||
f = operator.itemgetter(1)
|
||||
#? float()
|
||||
f([1.0])
|
||||
#? str()
|
||||
f([1, ''])
|
||||
|
||||
g = operator.itemgetter(1, 2)
|
||||
x1, x2 = g([1, 1.0, ''])
|
||||
#? float()
|
||||
x1
|
||||
#? str()
|
||||
x2
|
||||
|
||||
x1, x2 = g([1, ''])
|
||||
#? str()
|
||||
x1
|
||||
#? int() str()
|
||||
x2
|
||||
|
||||
# -----------------
|
||||
# shlex
|
||||
# -----------------
|
||||
@@ -249,5 +274,5 @@ with contextlib.closing('asd') as string:
|
||||
import shlex
|
||||
qsplit = shlex.split("foo, ferwerwerw werw werw e")
|
||||
for part in qsplit:
|
||||
#? str() None
|
||||
#? str()
|
||||
part
|
||||
|
||||
1
test/completion/stub_folder/stub_only.pyi
Normal file
1
test/completion/stub_folder/stub_only.pyi
Normal file
@@ -0,0 +1 @@
|
||||
in_stub_only: int
|
||||
@@ -0,0 +1 @@
|
||||
in_stub_only_folder: int
|
||||
@@ -0,0 +1 @@
|
||||
in_stub_only: int
|
||||
@@ -0,0 +1,2 @@
|
||||
in_python = ''
|
||||
in_both = ''
|
||||
@@ -0,0 +1,2 @@
|
||||
in_stub: int
|
||||
in_both: float
|
||||
@@ -0,0 +1 @@
|
||||
in_python = ''
|
||||
2
test/completion/stub_folder/with_stub.py
Normal file
2
test/completion/stub_folder/with_stub.py
Normal file
@@ -0,0 +1,2 @@
|
||||
in_with_stub_both = 5
|
||||
in_with_stub_python = 8
|
||||
2
test/completion/stub_folder/with_stub.pyi
Normal file
2
test/completion/stub_folder/with_stub.pyi
Normal file
@@ -0,0 +1,2 @@
|
||||
in_with_stub_both: str
|
||||
in_with_stub_stub: float
|
||||
2
test/completion/stub_folder/with_stub_folder/__init__.py
Normal file
2
test/completion/stub_folder/with_stub_folder/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
in_with_stub_both_folder = 5
|
||||
in_with_stub_python_folder = 8
|
||||
@@ -0,0 +1,2 @@
|
||||
in_with_stub_both_folder: str
|
||||
in_with_stub_stub_folder: float
|
||||
@@ -0,0 +1 @@
|
||||
in_stub_only: int
|
||||
@@ -0,0 +1,2 @@
|
||||
in_python = ''
|
||||
in_both = ''
|
||||
@@ -0,0 +1,2 @@
|
||||
in_stub: int
|
||||
in_both: float
|
||||
@@ -0,0 +1 @@
|
||||
in_python = ''
|
||||
104
test/completion/stubs.py
Normal file
104
test/completion/stubs.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# python >= 3.4
|
||||
from stub_folder import with_stub, stub_only, with_stub_folder, stub_only_folder
|
||||
|
||||
# -------------------------
|
||||
# Just files
|
||||
# -------------------------
|
||||
|
||||
#? int()
|
||||
stub_only.in_stub_only
|
||||
#? str()
|
||||
with_stub.in_with_stub_both
|
||||
#? int()
|
||||
with_stub.in_with_stub_python
|
||||
#? float()
|
||||
with_stub.in_with_stub_stub
|
||||
|
||||
#! ['in_stub_only: int']
|
||||
stub_only.in_stub_only
|
||||
#! ['in_with_stub_both = 5']
|
||||
with_stub.in_with_stub_both
|
||||
#! ['in_with_stub_python = 8']
|
||||
with_stub.in_with_stub_python
|
||||
#! ['in_with_stub_stub: float']
|
||||
with_stub.in_with_stub_stub
|
||||
|
||||
#? ['in_stub_only']
|
||||
stub_only.in_
|
||||
#? ['in_stub_only']
|
||||
from stub_folder.stub_only import in_
|
||||
#? ['in_with_stub_both', 'in_with_stub_python', 'in_with_stub_stub']
|
||||
with_stub.in_
|
||||
#? ['in_with_stub_both', 'in_with_stub_python', 'in_with_stub_stub']
|
||||
from stub_folder.with_stub import in_
|
||||
|
||||
#? ['with_stub', 'stub_only', 'with_stub_folder', 'stub_only_folder']
|
||||
from stub_folder.
|
||||
|
||||
# -------------------------
|
||||
# Folders
|
||||
# -------------------------
|
||||
|
||||
#? int()
|
||||
stub_only_folder.in_stub_only_folder
|
||||
#? str()
|
||||
with_stub_folder.in_with_stub_both_folder
|
||||
#? int()
|
||||
with_stub_folder.in_with_stub_python_folder
|
||||
#? float()
|
||||
with_stub_folder.in_with_stub_stub_folder
|
||||
|
||||
#? ['in_stub_only_folder']
|
||||
stub_only_folder.in_
|
||||
#? ['in_with_stub_both_folder', 'in_with_stub_python_folder', 'in_with_stub_stub_folder']
|
||||
with_stub_folder.in_
|
||||
|
||||
# -------------------------
|
||||
# Folders nested with stubs
|
||||
# -------------------------
|
||||
|
||||
from stub_folder.with_stub_folder import nested_stub_only, nested_with_stub, \
|
||||
python_only
|
||||
|
||||
#? int()
|
||||
nested_stub_only.in_stub_only
|
||||
#? float()
|
||||
nested_with_stub.in_both
|
||||
#? str()
|
||||
nested_with_stub.in_python
|
||||
#? int()
|
||||
nested_with_stub.in_stub
|
||||
#? str()
|
||||
python_only.in_python
|
||||
|
||||
#? ['in_stub_only_folder']
|
||||
stub_only_folder.in_
|
||||
#? ['in_with_stub_both_folder', 'in_with_stub_python_folder', 'in_with_stub_stub_folder']
|
||||
with_stub_folder.in_
|
||||
#? ['in_python']
|
||||
python_only.in_
|
||||
|
||||
# -------------------------
|
||||
# Folders nested with stubs
|
||||
# -------------------------
|
||||
|
||||
from stub_folder.stub_only_folder import nested_stub_only, nested_with_stub, \
|
||||
python_only
|
||||
|
||||
#? int()
|
||||
nested_stub_only.in_stub_only
|
||||
#? float()
|
||||
nested_with_stub.in_both
|
||||
#? str()
|
||||
nested_with_stub.in_python
|
||||
#? int()
|
||||
nested_with_stub.in_stub
|
||||
#? str()
|
||||
python_only.in_python
|
||||
|
||||
#? ['in_stub_only']
|
||||
nested_stub_only.in_
|
||||
#? ['in_both', 'in_python', 'in_stub']
|
||||
nested_with_stub.in_
|
||||
#? ['in_python']
|
||||
python_only.in_
|
||||
@@ -131,3 +131,58 @@ set_t2 = set()
|
||||
|
||||
#? ['clear', 'copy']
|
||||
set_t2.c
|
||||
|
||||
# -----------------
|
||||
# pep 448 unpacking generalizations
|
||||
# -----------------
|
||||
# python >= 3.5
|
||||
|
||||
d = {'a': 3}
|
||||
dc = {v: 3 for v in ['a']}
|
||||
|
||||
#? dict()
|
||||
{**d}
|
||||
|
||||
#? dict()
|
||||
{**dc}
|
||||
|
||||
#? str()
|
||||
{**d, "b": "b"}["b"]
|
||||
|
||||
#? str()
|
||||
{**dc, "b": "b"}["b"]
|
||||
|
||||
# Should resolve to int() but jedi is not smart enough yet
|
||||
# Here to make sure it doesn't result in crash though
|
||||
#?
|
||||
{**d}["a"]
|
||||
|
||||
# Should resolve to int() but jedi is not smart enough yet
|
||||
# Here to make sure it doesn't result in crash though
|
||||
#?
|
||||
{**dc}["a"]
|
||||
|
||||
s = {1, 2, 3}
|
||||
|
||||
#? set()
|
||||
{*s}
|
||||
|
||||
#? set()
|
||||
{*s, 4, *s}
|
||||
|
||||
s = {1, 2, 3}
|
||||
# Should resolve to int() but jedi is not smart enough yet
|
||||
# Here to make sure it doesn't result in crash though
|
||||
#?
|
||||
{*s}.pop()
|
||||
|
||||
#? int()
|
||||
{*s, 4}.pop()
|
||||
|
||||
# Should resolve to int() but jedi is not smart enough yet
|
||||
# Here to make sure it doesn't result in crash though
|
||||
#?
|
||||
[*s][0]
|
||||
|
||||
#? int()
|
||||
[*s, 4][0]
|
||||
|
||||
@@ -265,7 +265,10 @@ check(DynamicParam())
|
||||
|
||||
import _sre
|
||||
|
||||
#< 0 (-3,7), (0,0), ('_sre', None, None)
|
||||
# TODO reenable this, it's currently not working, because of 2/3
|
||||
# inconsistencies in typeshed (_sre exists in typeshed/2, but not in
|
||||
# typeshed/3).
|
||||
##< 0 (-3,7), (0,0), ('_sre', None, None)
|
||||
_sre
|
||||
|
||||
# -----------------
|
||||
|
||||
@@ -126,11 +126,12 @@ class StaticAnalysisCase(object):
|
||||
return "<%s: %s>" % (self.__class__.__name__, os.path.basename(self._path))
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def venv_path(tmpdir, environment):
|
||||
@pytest.fixture(scope='session')
|
||||
def venv_path(tmpdir_factory, environment):
|
||||
if environment.version_info.major < 3:
|
||||
pytest.skip("python -m venv does not exist in Python 2")
|
||||
|
||||
tmpdir = tmpdir_factory.mktemp('venv_path')
|
||||
dirname = os.path.join(tmpdir.dirname, 'venv')
|
||||
|
||||
# We cannot use the Python from tox because tox creates virtualenvs and
|
||||
|
||||
0
test/examples/issue1209/__init__.py
Normal file
0
test/examples/issue1209/__init__.py
Normal file
0
test/examples/issue1209/api/__init__.py
Normal file
0
test/examples/issue1209/api/__init__.py
Normal file
0
test/examples/issue1209/api/whatever/__init__.py
Normal file
0
test/examples/issue1209/api/whatever/__init__.py
Normal file
0
test/examples/issue1209/api/whatever/api_test1.py
Normal file
0
test/examples/issue1209/api/whatever/api_test1.py
Normal file
0
test/examples/issue1209/whatever/__init__.py
Normal file
0
test/examples/issue1209/whatever/__init__.py
Normal file
0
test/examples/issue1209/whatever/test.py
Normal file
0
test/examples/issue1209/whatever/test.py
Normal file
1
test/examples/namespace_package_relative_import/rel1.py
Normal file
1
test/examples/namespace_package_relative_import/rel1.py
Normal file
@@ -0,0 +1 @@
|
||||
from .rel2 import name
|
||||
1
test/examples/namespace_package_relative_import/rel2.py
Normal file
1
test/examples/namespace_package_relative_import/rel2.py
Normal file
@@ -0,0 +1 @@
|
||||
name = 1
|
||||
1
test/examples/stub_packages/no_python-stubs/__init__.pyi
Normal file
1
test/examples/stub_packages/no_python-stubs/__init__.pyi
Normal file
@@ -0,0 +1 @@
|
||||
foo: int
|
||||
@@ -0,0 +1,2 @@
|
||||
both: int
|
||||
stub_only: str
|
||||
1
test/examples/stub_packages/with_python-stubs/module.pyi
Normal file
1
test/examples/stub_packages/with_python-stubs/module.pyi
Normal file
@@ -0,0 +1 @@
|
||||
in_sub_module: int
|
||||
2
test/examples/stub_packages/with_python/__init__.py
Normal file
2
test/examples/stub_packages/with_python/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
python_only = 1
|
||||
both = ''
|
||||
1
test/examples/stub_packages/with_python/module.py
Normal file
1
test/examples/stub_packages/with_python/module.py
Normal file
@@ -0,0 +1 @@
|
||||
in_sub_module = ''
|
||||
15
test/run.py
15
test/run.py
@@ -126,6 +126,7 @@ from jedi.api.classes import Definition
|
||||
from jedi.api.completion import get_user_scope
|
||||
from jedi import parser_utils
|
||||
from jedi.api.environment import get_default_environment, get_system_environment
|
||||
from jedi.evaluate.gradual.conversion import try_stubs_to_actual_context_set
|
||||
|
||||
|
||||
TEST_COMPLETIONS = 0
|
||||
@@ -230,7 +231,10 @@ class IntegrationTestCase(object):
|
||||
if user_context.api_type == 'function':
|
||||
user_context = user_context.get_function_execution()
|
||||
element.parent = user_context.tree_node
|
||||
results = evaluator.eval_element(user_context, element)
|
||||
results = try_stubs_to_actual_context_set(
|
||||
evaluator.eval_element(user_context, element),
|
||||
prefer_stub_to_compiled=True
|
||||
)
|
||||
if not results:
|
||||
raise Exception('Could not resolve %s on line %s'
|
||||
% (match.string, self.line_nr - 1))
|
||||
@@ -412,7 +416,6 @@ if __name__ == '__main__':
|
||||
dir_ = os.path.dirname(os.path.realpath(__file__))
|
||||
completion_test_dir = os.path.join(dir_, '../test/completion')
|
||||
completion_test_dir = os.path.abspath(completion_test_dir)
|
||||
summary = []
|
||||
tests_fail = 0
|
||||
|
||||
# execute tests
|
||||
@@ -422,9 +425,11 @@ if __name__ == '__main__':
|
||||
cases += collect_dir_tests(completion_test_dir, test_files, True)
|
||||
|
||||
def file_change(current, tests, fails):
|
||||
if current is not None:
|
||||
if current is None:
|
||||
current = ''
|
||||
else:
|
||||
current = os.path.basename(current)
|
||||
print('%s \t\t %s tests and %s fails.' % (current, tests, fails))
|
||||
print('{:25} {} tests and {} fails.'.format(current, tests, fails))
|
||||
|
||||
def report(case, actual, desired):
|
||||
if actual == desired:
|
||||
@@ -470,8 +475,6 @@ if __name__ == '__main__':
|
||||
|
||||
print('\nSummary: (%s fails of %s tests) in %.3fs'
|
||||
% (tests_fail, len(cases), time.time() - t_start))
|
||||
for s in summary:
|
||||
print(s)
|
||||
|
||||
exit_code = 1 if tests_fail else 0
|
||||
sys.exit(exit_code)
|
||||
|
||||
@@ -111,9 +111,3 @@ import import_tree
|
||||
|
||||
import_tree.a
|
||||
import_tree.b
|
||||
|
||||
# This is something that raised an error, because it was using a complex
|
||||
# mixture of Jedi fakes and compiled objects.
|
||||
import _sre
|
||||
#! 15 attribute-error
|
||||
_sre.compile().not_existing
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
1 - '1'
|
||||
|
||||
-1 - - 1
|
||||
-1 - int()
|
||||
int() - float()
|
||||
# TODO uncomment
|
||||
#-1 - int()
|
||||
#int() - float()
|
||||
float() - 3.0
|
||||
|
||||
a = 3
|
||||
|
||||
@@ -87,3 +87,21 @@ else:
|
||||
str.upper
|
||||
#! 4 attribute-error
|
||||
str.undefined
|
||||
|
||||
# -----------------
|
||||
# arguments
|
||||
# -----------------
|
||||
|
||||
def i_see(r):
|
||||
return r
|
||||
|
||||
def lala():
|
||||
# This weird structure checks if the error is actually resolved in the
|
||||
# right place.
|
||||
a = TypeError
|
||||
try:
|
||||
i_see()
|
||||
except a:
|
||||
pass
|
||||
#! 5 type-error-too-few-arguments
|
||||
i_see()
|
||||
|
||||
@@ -5,17 +5,25 @@ Test all things related to the ``jedi.api`` module.
|
||||
import os
|
||||
from textwrap import dedent
|
||||
|
||||
from jedi import preload_module
|
||||
from jedi._compatibility import is_py3
|
||||
from pytest import raises
|
||||
from parso import cache
|
||||
|
||||
from jedi import preload_module
|
||||
from jedi.evaluate.gradual import typeshed
|
||||
|
||||
|
||||
def test_preload_modules():
|
||||
def check_loaded(*modules):
|
||||
for grammar_cache in cache.parser_cache.values():
|
||||
if None in grammar_cache:
|
||||
break
|
||||
# Filter the typeshed parser cache.
|
||||
typeshed_cache_count = sum(
|
||||
1 for path in grammar_cache
|
||||
if path is not None and path.startswith(typeshed.TYPESHED_PATH)
|
||||
)
|
||||
# +1 for None module (currently used)
|
||||
grammar_cache = next(iter(cache.parser_cache.values()))
|
||||
assert len(grammar_cache) == len(modules) + 1
|
||||
assert len(grammar_cache) - typeshed_cache_count == len(modules) + 1
|
||||
for i in modules:
|
||||
assert [i in k for k in grammar_cache.keys() if k is not None]
|
||||
|
||||
@@ -111,11 +119,7 @@ def test_goto_assignments_on_non_name(Script, environment):
|
||||
assert Script('for').goto_assignments() == []
|
||||
|
||||
assert Script('assert').goto_assignments() == []
|
||||
if environment.version_info.major == 2:
|
||||
# In Python 2.7 True is still a name.
|
||||
assert Script('True').goto_assignments()[0].description == 'instance True'
|
||||
else:
|
||||
assert Script('True').goto_assignments() == []
|
||||
assert Script('True').goto_assignments() == []
|
||||
|
||||
|
||||
def test_goto_definitions_on_non_name(Script):
|
||||
@@ -199,9 +203,9 @@ def test_goto_assignments_follow_imports(Script):
|
||||
assert definition.name == 'p'
|
||||
result, = definition.goto_assignments()
|
||||
assert result.name == 'p'
|
||||
result, = definition._goto_definitions()
|
||||
result, = definition.infer()
|
||||
assert result.name == 'int'
|
||||
result, = result._goto_definitions()
|
||||
result, = result.infer()
|
||||
assert result.name == 'int'
|
||||
|
||||
definition, = script.goto_assignments()
|
||||
@@ -285,3 +289,11 @@ def test_backslash_continuation_and_bracket(Script):
|
||||
column = lines[-1].index('(')
|
||||
def_, = Script(code, line=len(lines), column=column).goto_definitions()
|
||||
assert def_.name == 'int'
|
||||
|
||||
|
||||
def test_goto_follow_builtin_imports(Script):
|
||||
s = Script('import sys; sys')
|
||||
d, = s.goto_assignments(follow_imports=True)
|
||||
assert d.in_builtin_module() is True
|
||||
d, = s.goto_assignments(follow_imports=True, follow_builtin_imports=True)
|
||||
assert d.in_builtin_module() is True
|
||||
|
||||
@@ -18,7 +18,7 @@ def check_follow_definition_types(Script, source):
|
||||
return [d.type for d in defs]
|
||||
|
||||
|
||||
def test_follow_import_incomplete(Script):
|
||||
def test_follow_import_incomplete(Script, environment):
|
||||
"""
|
||||
Completion on incomplete imports should always take the full completion
|
||||
to do any evaluation.
|
||||
@@ -34,8 +34,10 @@ def test_follow_import_incomplete(Script):
|
||||
|
||||
# incomplete `from * import` part
|
||||
datetime = check_follow_definition_types(Script, "from datetime import datetim")
|
||||
assert set(datetime) == {'class', 'instance'} # py33: builtin and pure py version
|
||||
|
||||
if environment.version_info.major == 2:
|
||||
assert datetime == ['class']
|
||||
else:
|
||||
assert set(datetime) == {'class', 'instance'} # py3: builtin and pure py version
|
||||
# os.path check
|
||||
ospath = check_follow_definition_types(Script, "from os.path import abspat")
|
||||
assert ospath == ['function']
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytest
|
||||
|
||||
from ..helpers import TestCase
|
||||
from jedi import cache
|
||||
from jedi._compatibility import is_py33
|
||||
from jedi.parser_utils import get_call_signature
|
||||
|
||||
|
||||
def assert_signature(Script, source, expected_name, expected_index=0, line=None, column=None):
|
||||
@@ -24,7 +24,7 @@ def assert_signature(Script, source, expected_name, expected_index=0, line=None,
|
||||
|
||||
|
||||
def test_valid_call(Script):
|
||||
assert_signature(Script, 'str()', 'str', column=4)
|
||||
assert_signature(Script, 'bool()', 'bool', column=5)
|
||||
|
||||
|
||||
class TestCallSignatures(TestCase):
|
||||
@@ -39,12 +39,12 @@ class TestCallSignatures(TestCase):
|
||||
run = self._run_simple
|
||||
|
||||
# simple
|
||||
s1 = "sorted(a, str("
|
||||
s1 = "sorted(a, bool("
|
||||
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)
|
||||
run(s1, 'bool', 0, 15)
|
||||
|
||||
s2 = "abs(), "
|
||||
run(s2, 'abs', 0, 4)
|
||||
@@ -58,26 +58,26 @@ class TestCallSignatures(TestCase):
|
||||
def test_more_complicated(self):
|
||||
run = self._run_simple
|
||||
|
||||
s4 = 'abs(zip(), , set,'
|
||||
s4 = 'abs(bool(), , 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)
|
||||
run(s4, 'bool', 0, 9)
|
||||
run(s4, 'abs', 0, 10)
|
||||
run(s4, 'abs', None, 11)
|
||||
|
||||
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)
|
||||
s6 = "bool().__eq__("
|
||||
run(s6, '__eq__', 0)
|
||||
run(s6, 'bool', 0, 5)
|
||||
|
||||
s7 = "str().upper().center("
|
||||
s8 = "str(int[zip("
|
||||
s8 = "bool(int[abs("
|
||||
run(s7, 'center', 0)
|
||||
run(s8, 'zip', 0)
|
||||
run(s8, 'str', 0, 8)
|
||||
run(s8, 'abs', 0)
|
||||
run(s8, 'bool', 0, 10)
|
||||
|
||||
run("import time; abc = time; abc.sleep(", 'sleep', 0)
|
||||
|
||||
@@ -87,15 +87,19 @@ class TestCallSignatures(TestCase):
|
||||
"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)
|
||||
|
||||
def test_for(self):
|
||||
# jedi-vim #11
|
||||
self._run_simple("for sorted(", 'sorted', 0)
|
||||
self._run_simple("for s in sorted(", 'sorted', 0)
|
||||
|
||||
|
||||
def test_with(Script):
|
||||
# jedi-vim #9
|
||||
sigs = Script("with open(").call_signatures()
|
||||
assert sigs
|
||||
assert all(sig.name == 'open' for sig in sigs)
|
||||
|
||||
|
||||
def test_call_signatures_empty_parentheses_pre_space(Script):
|
||||
s = dedent("""\
|
||||
def f(a, b):
|
||||
@@ -150,22 +154,22 @@ def test_decorator_in_class(Script):
|
||||
|
||||
|
||||
def test_additional_brackets(Script):
|
||||
assert_signature(Script, 'str((', 'str', 0)
|
||||
assert_signature(Script, 'abs((', 'abs', 0)
|
||||
|
||||
|
||||
def test_unterminated_strings(Script):
|
||||
assert_signature(Script, 'str(";', 'str', 0)
|
||||
assert_signature(Script, 'abs(";', 'abs', 0)
|
||||
|
||||
|
||||
def test_whitespace_before_bracket(Script):
|
||||
assert_signature(Script, 'str (', 'str', 0)
|
||||
assert_signature(Script, 'str (";', 'str', 0)
|
||||
assert_signature(Script, 'str\n(', None)
|
||||
assert_signature(Script, 'abs (', 'abs', 0)
|
||||
assert_signature(Script, 'abs (";', 'abs', 0)
|
||||
assert_signature(Script, 'abs\n(', None)
|
||||
|
||||
|
||||
def test_brackets_in_string_literals(Script):
|
||||
assert_signature(Script, 'str (" (', 'str', 0)
|
||||
assert_signature(Script, 'str (" )', 'str', 0)
|
||||
assert_signature(Script, 'abs (" (', 'abs', 0)
|
||||
assert_signature(Script, 'abs (" )', 'abs', 0)
|
||||
|
||||
|
||||
def test_function_definitions_should_break(Script):
|
||||
@@ -173,8 +177,8 @@ def test_function_definitions_should_break(Script):
|
||||
Function definitions (and other tokens that cannot exist within call
|
||||
signatures) should break and not be able to return a call signature.
|
||||
"""
|
||||
assert_signature(Script, 'str(\ndef x', 'str', 0)
|
||||
assert not Script('str(\ndef x(): pass').call_signatures()
|
||||
assert_signature(Script, 'abs(\ndef x', 'abs', 0)
|
||||
assert not Script('abs(\ndef x(): pass').call_signatures()
|
||||
|
||||
|
||||
def test_flow_call(Script):
|
||||
@@ -211,7 +215,7 @@ def test_call_signature_on_module(Script):
|
||||
assert Script(s).call_signatures() == []
|
||||
|
||||
|
||||
def test_complex(Script):
|
||||
def test_complex(Script, environment):
|
||||
s = """
|
||||
def abc(a,b):
|
||||
pass
|
||||
@@ -229,7 +233,19 @@ def test_complex(Script):
|
||||
re.compile(
|
||||
return it * 2
|
||||
"""
|
||||
assert_signature(Script, s, 'compile', 0, line=4, column=27)
|
||||
sig1, sig2 = sorted(Script(s, line=4, column=27).call_signatures(), key=lambda s: s.line)
|
||||
assert sig1.name == sig2.name == 'compile'
|
||||
assert sig1.index == sig2.index == 0
|
||||
func1, = sig1._name.infer()
|
||||
func2, = sig2._name.infer()
|
||||
|
||||
if environment.version_info.major == 3:
|
||||
# Do these checks just for Python 3, I'm too lazy to deal with this
|
||||
# legacy stuff. ~ dave.
|
||||
assert get_call_signature(func1.tree_node) \
|
||||
== 'compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]'
|
||||
assert get_call_signature(func2.tree_node) \
|
||||
== 'compile(pattern: Pattern[AnyStr], flags: _FlagsType = ...) ->\nPattern[AnyStr]'
|
||||
|
||||
# jedi-vim #70
|
||||
s = """def foo("""
|
||||
@@ -246,19 +262,24 @@ def _params(Script, source, line=None, column=None):
|
||||
return signatures[0].params
|
||||
|
||||
|
||||
def test_param_name(Script):
|
||||
if not is_py33:
|
||||
p = _params(Script, '''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'
|
||||
def test_int_params(Script):
|
||||
sig1, sig2 = Script('int(').call_signatures()
|
||||
# int is defined as: `int(x[, base])`
|
||||
assert len(sig1.params) == 2
|
||||
assert sig1.params[0].name == 'x'
|
||||
assert sig1.params[1].name == 'base'
|
||||
assert len(sig2.params) == 1
|
||||
assert sig2.params[0].name == 'x'
|
||||
|
||||
p = _params(Script, '''open(something,''')
|
||||
assert p[0].name in ['file', 'name']
|
||||
assert p[1].name == 'mode'
|
||||
|
||||
def test_param_name(Script):
|
||||
sigs = Script('open(something,').call_signatures()
|
||||
for sig in sigs:
|
||||
# All of the signatures (in Python the function is overloaded),
|
||||
# contain the same param names.
|
||||
assert sig.params[0].name in ['file', 'name']
|
||||
assert sig.params[1].name == 'mode'
|
||||
assert sig.params[2].name == 'buffering'
|
||||
|
||||
|
||||
def test_builtins(Script):
|
||||
@@ -286,18 +307,16 @@ def test_signature_is_definition(Script):
|
||||
|
||||
# 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']
|
||||
dont_scan = ['defined_names', 'parent', 'goto_assignments', 'infer', '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
|
||||
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(Script):
|
||||
@@ -381,7 +400,7 @@ def test_bracket_start(Script):
|
||||
assert len(signatures) == 1
|
||||
return signatures[0].bracket_start
|
||||
|
||||
assert bracket_start('str(') == (1, 3)
|
||||
assert bracket_start('abs(') == (1, 3)
|
||||
|
||||
|
||||
def test_different_caller(Script):
|
||||
@@ -390,11 +409,11 @@ def test_different_caller(Script):
|
||||
index and then get the call signature of it.
|
||||
"""
|
||||
|
||||
assert_signature(Script, '[str][0](', 'str', 0)
|
||||
assert_signature(Script, '[str][0]()', 'str', 0, column=len('[str][0]('))
|
||||
assert_signature(Script, '[abs][0](', 'abs', 0)
|
||||
assert_signature(Script, '[abs][0]()', 'abs', 0, column=len('[abs][0]('))
|
||||
|
||||
assert_signature(Script, '(str)(', 'str', 0)
|
||||
assert_signature(Script, '(str)()', 'str', 0, column=len('(str)('))
|
||||
assert_signature(Script, '(abs)(', 'abs', 0)
|
||||
assert_signature(Script, '(abs)()', 'abs', 0, column=len('(abs)('))
|
||||
|
||||
|
||||
def test_in_function(Script):
|
||||
@@ -415,20 +434,28 @@ def test_lambda_params(Script):
|
||||
assert [p.name for p in sig.params] == ['x']
|
||||
|
||||
|
||||
CLASS_CODE = dedent('''\
|
||||
class X():
|
||||
def __init__(self, foo, bar):
|
||||
self.foo = foo
|
||||
''')
|
||||
|
||||
|
||||
def test_class_creation(Script):
|
||||
code = dedent('''\
|
||||
class X():
|
||||
def __init__(self, foo, bar):
|
||||
self.foo = foo
|
||||
''')
|
||||
sig, = Script(code + 'X(').call_signatures()
|
||||
|
||||
sig, = Script(CLASS_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()
|
||||
|
||||
def test_call_init_on_class(Script):
|
||||
sig, = Script(CLASS_CODE + 'X.__init__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['self', 'foo', 'bar']
|
||||
sig, = Script(code + 'X().__init__(').call_signatures()
|
||||
|
||||
|
||||
def test_call_init_on_instance(Script):
|
||||
sig, = Script(CLASS_CODE + 'X().__init__(').call_signatures()
|
||||
assert [p.name for p in sig.params] == ['foo', 'bar']
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import pytest
|
||||
|
||||
import jedi
|
||||
from jedi import __doc__ as jedi_doc, names
|
||||
from ..helpers import cwd_at
|
||||
from ..helpers import TestCase
|
||||
|
||||
|
||||
@@ -66,27 +65,31 @@ def test_basedefinition_type(Script, environment):
|
||||
'generator', 'statement', 'import', 'param')
|
||||
|
||||
|
||||
def test_basedefinition_type_import(Script):
|
||||
def get_types(source, **kwargs):
|
||||
return {t.type for t in Script(source, **kwargs).completions()}
|
||||
@pytest.mark.parametrize(
|
||||
('src', 'expected_result', 'column'), [
|
||||
# import one level
|
||||
('import t', 'module', None),
|
||||
('import ', 'module', None),
|
||||
('import datetime; datetime', 'module', None),
|
||||
|
||||
# import one level
|
||||
assert get_types('import t') == {'module'}
|
||||
assert get_types('import ') == {'module'}
|
||||
assert get_types('import datetime; datetime') == {'module'}
|
||||
# from
|
||||
('from datetime import timedelta', 'class', None),
|
||||
('from datetime import timedelta; timedelta', 'class', None),
|
||||
('from json import tool', 'module', None),
|
||||
('from json import tool; tool', 'module', None),
|
||||
|
||||
# from
|
||||
assert get_types('from datetime import timedelta') == {'class'}
|
||||
assert get_types('from datetime import timedelta; timedelta') == {'class'}
|
||||
assert get_types('from json import tool') == {'module'}
|
||||
assert get_types('from json import tool; tool') == {'module'}
|
||||
# import two levels
|
||||
('import json.tool; json', 'module', None),
|
||||
('import json.tool; json.tool', 'module', None),
|
||||
('import json.tool; json.tool.main', 'function', None),
|
||||
('import json.tool', 'module', None),
|
||||
('import json.tool', 'module', 9),
|
||||
]
|
||||
|
||||
# import two levels
|
||||
assert get_types('import json.tool; json') == {'module'}
|
||||
assert get_types('import json.tool; json.tool') == {'module'}
|
||||
assert get_types('import json.tool; json.tool.main') == {'function'}
|
||||
assert get_types('import json.tool') == {'module'}
|
||||
assert get_types('import json.tool', column=9) == {'module'}
|
||||
)
|
||||
def test_basedefinition_type_import(Script, src, expected_result, column):
|
||||
types = {t.type for t in Script(src, column=column).completions()}
|
||||
assert types == {expected_result}
|
||||
|
||||
|
||||
def test_function_call_signature_in_doc(Script):
|
||||
@@ -99,7 +102,7 @@ def test_function_call_signature_in_doc(Script):
|
||||
|
||||
|
||||
def test_param_docstring():
|
||||
param = jedi.names("def test(parameter): pass")[1]
|
||||
param = jedi.names("def test(parameter): pass", all_scopes=True)[1]
|
||||
assert param.name == 'parameter'
|
||||
assert param.docstring() == ''
|
||||
|
||||
@@ -111,13 +114,14 @@ def test_class_call_signature(Script):
|
||||
pass
|
||||
Foo""").goto_definitions()
|
||||
doc = defs[0].docstring()
|
||||
assert "Foo(self, x, y=1, z='a')" in str(doc)
|
||||
assert doc == "Foo(x, y=1, z='a')"
|
||||
|
||||
|
||||
def test_position_none_if_builtin(Script):
|
||||
gotos = Script('import sys; sys.path').goto_assignments()
|
||||
assert gotos[0].line is None
|
||||
assert gotos[0].column is None
|
||||
assert gotos[0].in_builtin_module()
|
||||
assert gotos[0].line is not None
|
||||
assert gotos[0].column is not None
|
||||
|
||||
|
||||
def test_completion_docstring(Script, jedi_path):
|
||||
@@ -174,9 +178,9 @@ def test_hashlib_params(Script, environment):
|
||||
if environment.version_info < (3,):
|
||||
pytest.skip()
|
||||
|
||||
script = Script(source='from hashlib import ', line=1, column=20)
|
||||
c = script.completions()
|
||||
assert c[2].params
|
||||
script = Script(source='from hashlib import sha256')
|
||||
c, = script.completions()
|
||||
assert [p.name for p in c.params] == ['arg']
|
||||
|
||||
|
||||
def test_signature_params(Script):
|
||||
@@ -291,10 +295,10 @@ def test_parent_on_completion(Script):
|
||||
|
||||
def test_type(Script):
|
||||
for c in Script('a = [str()]; a[0].').completions():
|
||||
if c.name == '__class__':
|
||||
if c.name == '__class__' and False: # TODO fix.
|
||||
assert c.type == 'class'
|
||||
else:
|
||||
assert c.type in ('function', 'instance')
|
||||
assert c.type in ('function', 'statement')
|
||||
|
||||
for c in Script('list.').completions():
|
||||
assert c.type
|
||||
|
||||
@@ -29,7 +29,7 @@ def test_in_empty_space(Script):
|
||||
comps = Script(code, 3, 7).completions()
|
||||
self, = [c for c in comps if c.name == 'self']
|
||||
assert self.name == 'self'
|
||||
def_, = self._goto_definitions()
|
||||
def_, = self.infer()
|
||||
assert def_.name == 'X'
|
||||
|
||||
|
||||
@@ -132,7 +132,6 @@ def test_async(Script, environment):
|
||||
hey = 3
|
||||
ho'''
|
||||
)
|
||||
print(code)
|
||||
comps = Script(code, column=4).completions()
|
||||
names = [c.name for c in comps]
|
||||
assert 'foo' in names
|
||||
|
||||
@@ -79,6 +79,59 @@ class TestDefinedNames(TestCase):
|
||||
self.assert_definition_names(subsubdefs, ['L3', 'f'])
|
||||
self.assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
||||
|
||||
def test_class_fields_with_all_scopes_false(self):
|
||||
definitions = self.check_defined_names("""
|
||||
from module import f
|
||||
g = f(f)
|
||||
class C:
|
||||
h = g
|
||||
|
||||
def foo(x=a):
|
||||
bar = x
|
||||
return bar
|
||||
""", ['f', 'g', 'C', 'foo'])
|
||||
C_subdefs = definitions[-2].defined_names()
|
||||
foo_subdefs = definitions[-1].defined_names()
|
||||
self.assert_definition_names(C_subdefs, ['h'])
|
||||
self.assert_definition_names(foo_subdefs, ['x', 'bar'])
|
||||
|
||||
def test_async_stmt_with_all_scopes_false(self):
|
||||
definitions = self.check_defined_names("""
|
||||
from module import f
|
||||
import asyncio
|
||||
|
||||
g = f(f)
|
||||
class C:
|
||||
h = g
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def __aenter__(self):
|
||||
pass
|
||||
|
||||
def foo(x=a):
|
||||
bar = x
|
||||
return bar
|
||||
|
||||
async def async_foo(duration):
|
||||
async def wait():
|
||||
await asyncio.sleep(100)
|
||||
for i in range(duration//100):
|
||||
await wait()
|
||||
return duration//100*100
|
||||
|
||||
async with C() as cinst:
|
||||
d = cinst
|
||||
""", ['f', 'asyncio', 'g', 'C', 'foo', 'async_foo', 'cinst', 'd'])
|
||||
C_subdefs = definitions[3].defined_names()
|
||||
foo_subdefs = definitions[4].defined_names()
|
||||
async_foo_subdefs = definitions[5].defined_names()
|
||||
cinst_subdefs = definitions[6].defined_names()
|
||||
self.assert_definition_names(C_subdefs, ['h', '__init__', '__aenter__'])
|
||||
self.assert_definition_names(foo_subdefs, ['x', 'bar'])
|
||||
self.assert_definition_names(async_foo_subdefs, ['duration', 'wait', 'i'])
|
||||
# We treat d as a name outside `async with` block
|
||||
self.assert_definition_names(cinst_subdefs, [])
|
||||
|
||||
def test_follow_imports(environment):
|
||||
# github issue #344
|
||||
@@ -96,3 +149,24 @@ def test_names_twice(environment):
|
||||
|
||||
defs = names(source=source, environment=environment)
|
||||
assert defs[0].defined_names() == []
|
||||
|
||||
|
||||
def test_simple_name(environment):
|
||||
defs = names('foo', references=True, environment=environment)
|
||||
assert not defs[0]._name.infer()
|
||||
|
||||
|
||||
def test_no_error(environment):
|
||||
code = dedent("""
|
||||
def foo(a, b):
|
||||
if a == 10:
|
||||
if b is None:
|
||||
print("foo")
|
||||
a = 20
|
||||
""")
|
||||
func_name, = names(code)
|
||||
a, b, a20 = func_name.defined_names()
|
||||
assert a.name == 'a'
|
||||
assert b.name == 'b'
|
||||
assert a20.name == 'a'
|
||||
assert a20.goto_assignments() == [a20]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -8,7 +7,8 @@ import jedi
|
||||
from jedi._compatibility import py_version
|
||||
from jedi.api.environment import get_default_environment, find_virtualenvs, \
|
||||
InvalidPythonEnvironment, find_system_environments, \
|
||||
get_system_environment, create_environment
|
||||
get_system_environment, create_environment, InterpreterEnvironment, \
|
||||
get_cached_default_environment
|
||||
|
||||
|
||||
def test_sys_path():
|
||||
@@ -44,7 +44,7 @@ def test_versions(version):
|
||||
|
||||
def test_load_module(evaluator):
|
||||
access_path = evaluator.compiled_subprocess.load_module(
|
||||
name=u'math',
|
||||
dotted_name=u'math',
|
||||
sys_path=evaluator.get_sys_path()
|
||||
)
|
||||
name, access_handle = access_path.accesses[0]
|
||||
@@ -55,7 +55,10 @@ def test_load_module(evaluator):
|
||||
access_handle.py__mro__()
|
||||
|
||||
|
||||
def test_error_in_environment(evaluator, Script):
|
||||
def test_error_in_environment(evaluator, Script, environment):
|
||||
if isinstance(environment, InterpreterEnvironment):
|
||||
pytest.skip("We don't catch these errors at the moment.")
|
||||
|
||||
# Provoke an error to show how Jedi can recover from it.
|
||||
with pytest.raises(jedi.InternalError):
|
||||
evaluator.compiled_subprocess._test_raise_error(KeyboardInterrupt)
|
||||
@@ -72,9 +75,11 @@ def test_stdout_in_subprocess(evaluator, Script):
|
||||
Script('1').goto_definitions()
|
||||
|
||||
|
||||
def test_killed_subprocess(evaluator, Script):
|
||||
def test_killed_subprocess(evaluator, Script, environment):
|
||||
if isinstance(environment, InterpreterEnvironment):
|
||||
pytest.skip("We cannot kill our own process")
|
||||
# Just kill the subprocess.
|
||||
evaluator.compiled_subprocess._compiled_subprocess._process.kill()
|
||||
evaluator.compiled_subprocess._compiled_subprocess._get_process().kill()
|
||||
# Since the process was terminated (and nobody knows about it) the first
|
||||
# Jedi call fails.
|
||||
with pytest.raises(jedi.InternalError):
|
||||
@@ -85,34 +90,22 @@ def test_killed_subprocess(evaluator, Script):
|
||||
assert def_.name == 'str'
|
||||
|
||||
|
||||
@contextmanager
|
||||
def set_environment_variable(name, value):
|
||||
tmp = os.environ.get(name)
|
||||
try:
|
||||
os.environ[name] = value
|
||||
yield
|
||||
finally:
|
||||
if tmp is None:
|
||||
del os.environ[name]
|
||||
else:
|
||||
os.environ[name] = tmp
|
||||
|
||||
|
||||
def test_not_existing_virtualenv():
|
||||
def test_not_existing_virtualenv(monkeypatch):
|
||||
"""Should not match the path that was given"""
|
||||
path = '/foo/bar/jedi_baz'
|
||||
with set_environment_variable('VIRTUAL_ENV', path):
|
||||
assert get_default_environment().executable != path
|
||||
monkeypatch.setenv('VIRTUAL_ENV', path)
|
||||
assert get_default_environment().executable != path
|
||||
|
||||
|
||||
def test_working_venv(venv_path):
|
||||
with set_environment_variable('VIRTUAL_ENV', venv_path):
|
||||
assert get_default_environment().path == venv_path
|
||||
def test_working_venv(venv_path, monkeypatch):
|
||||
monkeypatch.setenv('VIRTUAL_ENV', venv_path)
|
||||
assert get_default_environment().path == venv_path
|
||||
|
||||
|
||||
def test_scanning_venvs(venv_path):
|
||||
parent_dir = os.path.dirname(venv_path)
|
||||
assert any(venv.path == venv_path for venv in find_virtualenvs([parent_dir]))
|
||||
assert any(venv.path == venv_path
|
||||
for venv in find_virtualenvs([parent_dir]))
|
||||
|
||||
|
||||
def test_create_environment_venv_path(venv_path):
|
||||
@@ -123,3 +116,40 @@ def test_create_environment_venv_path(venv_path):
|
||||
def test_create_environment_executable():
|
||||
environment = create_environment(sys.executable)
|
||||
assert environment.executable == sys.executable
|
||||
|
||||
|
||||
def test_get_default_environment_from_env_does_not_use_safe(tmpdir, monkeypatch):
|
||||
fake_python = os.path.join(str(tmpdir), 'fake_python')
|
||||
with open(fake_python, 'w') as f:
|
||||
f.write('')
|
||||
|
||||
def _get_subprocess(self):
|
||||
if self._start_executable != fake_python:
|
||||
raise RuntimeError('Should not get called!')
|
||||
self.executable = fake_python
|
||||
self.path = 'fake'
|
||||
|
||||
monkeypatch.setattr('jedi.api.environment.Environment._get_subprocess',
|
||||
_get_subprocess)
|
||||
|
||||
monkeypatch.setenv('VIRTUAL_ENV', fake_python)
|
||||
env = get_default_environment()
|
||||
assert env.path == 'fake'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('virtualenv', ['', 'fufuuuuu', sys.prefix])
|
||||
def test_get_default_environment_when_embedded(monkeypatch, virtualenv):
|
||||
# When using Python embedded, sometimes the executable is not a Python
|
||||
# executable.
|
||||
executable_name = 'RANDOM_EXE'
|
||||
monkeypatch.setattr(sys, 'executable', executable_name)
|
||||
monkeypatch.setenv('VIRTUAL_ENV', virtualenv)
|
||||
env = get_default_environment()
|
||||
assert env.executable != executable_name
|
||||
|
||||
|
||||
def test_changing_venv(venv_path, monkeypatch):
|
||||
monkeypatch.setitem(os.environ, 'VIRTUAL_ENV', venv_path)
|
||||
get_cached_default_environment()
|
||||
monkeypatch.setitem(os.environ, 'VIRTUAL_ENV', sys.executable)
|
||||
assert get_cached_default_environment().executable == sys.executable
|
||||
|
||||
@@ -18,7 +18,7 @@ import textwrap
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from ..helpers import TestCase, cwd_at
|
||||
from ..helpers import TestCase
|
||||
|
||||
|
||||
class MixinTestFullName(object):
|
||||
@@ -52,7 +52,7 @@ class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
|
||||
self.check("""
|
||||
import re
|
||||
any_re = re.compile('.*')
|
||||
any_re""", '_sre.SRE_Pattern')
|
||||
any_re""", 'typing.Pattern')
|
||||
|
||||
def test_from_import(self):
|
||||
self.check('from os import path', 'os.path')
|
||||
@@ -111,5 +111,4 @@ def test_os_path(Script):
|
||||
|
||||
def test_os_issues(Script):
|
||||
"""Issue #873"""
|
||||
c, = Script('import os\nos.nt''').completions()
|
||||
assert c.full_name == 'nt'
|
||||
assert [c.name for c in Script('import os\nos.nt''').completions()] == ['nt']
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests of ``jedi.api.Interpreter``.
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from jedi._compatibility import is_py3, py_version, is_py35
|
||||
from jedi._compatibility import is_py3, py_version
|
||||
from jedi.evaluate.compiled import mixed
|
||||
|
||||
|
||||
@@ -244,8 +244,8 @@ def test_completion_params():
|
||||
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 c.params[0].infer() == []
|
||||
t, = c.params[1].infer()
|
||||
assert t.name == 'int'
|
||||
|
||||
|
||||
@@ -258,9 +258,9 @@ def test_completion_param_annotations():
|
||||
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 {d.name for d in c._goto_definitions()} == {'int', 'float'}
|
||||
assert a.infer() == []
|
||||
assert [d.name for d in b.infer()] == ['str']
|
||||
assert {d.name for d in c.infer()} == {'int', 'float'}
|
||||
|
||||
|
||||
def test_keyword_argument():
|
||||
@@ -340,7 +340,7 @@ def test_dir_magic_method():
|
||||
assert 'bar' in names
|
||||
|
||||
foo = [c for c in completions if c.name == 'foo'][0]
|
||||
assert foo._goto_definitions() == []
|
||||
assert foo.infer() == []
|
||||
|
||||
|
||||
def test_name_not_findable():
|
||||
@@ -356,3 +356,9 @@ def test_name_not_findable():
|
||||
setattr(X, 'NOT_FINDABLE', X.hidden)
|
||||
|
||||
assert jedi.Interpreter("X.NOT_FINDA", [locals()]).completions()
|
||||
|
||||
|
||||
def test_sys_path_docstring(): # Was an issue in #1298
|
||||
import jedi
|
||||
s = jedi.Interpreter("from sys import path\npath", line=2, column=4, namespaces=[locals()])
|
||||
s.completions()[0].docstring()
|
||||
|
||||
@@ -12,4 +12,4 @@ def test_django_default_project(Script):
|
||||
)
|
||||
c, = script.completions()
|
||||
assert c.name == "SomeModel"
|
||||
assert script._project._django is True
|
||||
assert script._evaluator.project._django is True
|
||||
|
||||
@@ -21,3 +21,14 @@ def test_add_dynamic_mods(Script):
|
||||
result = script.goto_definitions()
|
||||
assert len(result) == 1
|
||||
assert result[0].description == 'class int'
|
||||
|
||||
|
||||
def test_add_bracket_after_function(monkeypatch, Script):
|
||||
settings = api.settings
|
||||
monkeypatch.setattr(settings, 'add_bracket_after_function', True)
|
||||
script = Script('''\
|
||||
def foo():
|
||||
pass
|
||||
foo''')
|
||||
completions = script.completions()
|
||||
assert completions[0].complete == '('
|
||||
|
||||
@@ -72,3 +72,9 @@ def test_wrong_encoding(Script, tmpdir):
|
||||
|
||||
c, = Script('import x; x.foo', sys_path=[tmpdir.strpath]).completions()
|
||||
assert c.name == 'foobar'
|
||||
|
||||
|
||||
def test_encoding_parameter(Script):
|
||||
name = u('hö')
|
||||
s = Script(name.encode('latin-1'), encoding='latin-1')
|
||||
assert s._module_node.get_code() == name
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
def test_import_usage(Script):
|
||||
s = Script("from .. import foo", line=1, column=18, path="foo.py")
|
||||
assert [usage.line for usage in s.usages()] == [1]
|
||||
|
||||
|
||||
def test_exclude_builtin_modules(Script):
|
||||
def get(include):
|
||||
return [(d.line, d.column) for d in Script(source, column=8).usages(include_builtins=include)]
|
||||
source = '''import sys\nprint(sys.path)'''
|
||||
places = get(include=True)
|
||||
assert len(places) > 2 # Includes stubs
|
||||
|
||||
places = get(include=False)
|
||||
assert places == [(1, 7), (2, 6)]
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate.context import instance
|
||||
from jedi.evaluate.helpers import execute_evaluated
|
||||
from jedi.evaluate.gradual.conversion import stub_to_actual_context_set
|
||||
|
||||
|
||||
def test_simple(evaluator):
|
||||
def test_simple(evaluator, environment):
|
||||
obj = compiled.create_simple_object(evaluator, u'_str_')
|
||||
upper, = obj.py__getattribute__(u'upper')
|
||||
objs = list(upper.execute_evaluated())
|
||||
objs = list(execute_evaluated(upper))
|
||||
assert len(objs) == 1
|
||||
assert isinstance(objs[0], instance.CompiledInstance)
|
||||
if environment.version_info.major == 2:
|
||||
expected = 'unicode'
|
||||
else:
|
||||
expected = 'str'
|
||||
assert objs[0].name.string_name == expected
|
||||
|
||||
|
||||
def test_fake_loading(evaluator):
|
||||
builtin = compiled.get_special_object(evaluator, u'BUILTINS')
|
||||
string, = builtin.py__getattribute__(u'str')
|
||||
from_name = compiled.context.create_from_name(evaluator, string, u'__init__')
|
||||
def test_builtin_loading(evaluator):
|
||||
string, = evaluator.builtins_module.py__getattribute__(u'str')
|
||||
from_name, = string.py__getattribute__(u'__init__')
|
||||
assert from_name.tree_node
|
||||
assert not from_name.py__doc__() # It's a stub
|
||||
|
||||
|
||||
def test_fake_docstr(evaluator):
|
||||
def test_next_docstr(evaluator):
|
||||
next_ = compiled.builtin_from_name(evaluator, u'next')
|
||||
assert next_.py__doc__()
|
||||
assert next_.tree_node is not None
|
||||
assert next_.py__doc__() == next.__doc__
|
||||
assert next_.py__doc__() == '' # It's a stub
|
||||
for non_stub in stub_to_actual_context_set(next_):
|
||||
assert non_stub.py__doc__() == next.__doc__
|
||||
|
||||
|
||||
def test_parse_function_doc_illegal_docstr():
|
||||
@@ -42,7 +50,7 @@ def test_doc(evaluator):
|
||||
"""
|
||||
str_ = compiled.create_simple_object(evaluator, u'')
|
||||
# Equals `''.__getnewargs__`
|
||||
obj = compiled.create_from_name(evaluator, str_, u'__getnewargs__')
|
||||
obj, = str_.py__getattribute__(u'__getnewargs__')
|
||||
assert obj.py__doc__() == ''
|
||||
|
||||
|
||||
@@ -70,18 +78,26 @@ def test_method_completion(Script, environment):
|
||||
|
||||
foo = Foo()
|
||||
foo.bar.__func__''')
|
||||
if environment.version_info.major > 2:
|
||||
result = []
|
||||
else:
|
||||
result = ['__func__']
|
||||
assert [c.name for c in Script(code).completions()] == result
|
||||
assert [c.name for c in Script(code).completions()] == ['__func__']
|
||||
|
||||
|
||||
def test_time_docstring(Script):
|
||||
import time
|
||||
comp, = Script('import time\ntime.sleep').completions()
|
||||
assert comp.docstring() == time.sleep.__doc__
|
||||
assert comp.docstring(raw=True) == time.sleep.__doc__
|
||||
expected = 'sleep(secs: float) -> None\n\n' + time.sleep.__doc__
|
||||
assert comp.docstring() == expected
|
||||
|
||||
|
||||
def test_dict_values(Script):
|
||||
def test_dict_values(Script, environment):
|
||||
if environment.version_info.major == 2:
|
||||
# It looks like typeshed for Python 2 returns Any.
|
||||
pytest.skip()
|
||||
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').goto_definitions()
|
||||
|
||||
|
||||
def test_getitem_on_none(Script):
|
||||
script = Script('None[1j]')
|
||||
assert not script.goto_definitions()
|
||||
issue, = script._evaluator.analysis
|
||||
assert issue.name == 'type-error-not-subscriptable'
|
||||
|
||||
@@ -3,5 +3,5 @@ def test_module_attributes(Script):
|
||||
assert def_.name == '__name__'
|
||||
assert def_.line is None
|
||||
assert def_.column is None
|
||||
str_, = def_._goto_definitions()
|
||||
str_, = def_.infer()
|
||||
assert str_.name == 'str'
|
||||
|
||||
@@ -35,7 +35,20 @@ def test_class_doc(Script):
|
||||
class TestClass():
|
||||
'''Docstring of `TestClass`.'''
|
||||
TestClass""").goto_definitions()
|
||||
assert defs[0].docstring() == 'Docstring of `TestClass`.'
|
||||
|
||||
expected = 'Docstring of `TestClass`.'
|
||||
assert defs[0].docstring(raw=True) == expected
|
||||
assert defs[0].docstring() == 'TestClass()\n\n' + expected
|
||||
|
||||
|
||||
def test_class_doc_with_init(Script):
|
||||
d, = Script("""
|
||||
class TestClass():
|
||||
'''Docstring'''
|
||||
def __init__(self, foo, bar=3): pass
|
||||
TestClass""").goto_definitions()
|
||||
|
||||
assert d.docstring() == 'TestClass(foo, bar=3)\n\nDocstring'
|
||||
|
||||
|
||||
def test_instance_doc(Script):
|
||||
@@ -142,6 +155,16 @@ def test_docstring_keyword(Script):
|
||||
assert 'assert' in completions[0].docstring()
|
||||
|
||||
|
||||
def test_docstring_params_formatting(Script):
|
||||
defs = Script("""
|
||||
def func(param1,
|
||||
param2,
|
||||
param3):
|
||||
pass
|
||||
func""").goto_definitions()
|
||||
assert defs[0].docstring() == 'func(param1, param2, param3)'
|
||||
|
||||
|
||||
# ---- Numpy Style Tests ---
|
||||
|
||||
@pytest.mark.skipif(numpydoc_unavailable,
|
||||
@@ -349,7 +372,6 @@ def test_numpy_returns():
|
||||
x.d'''
|
||||
)
|
||||
names = [c.name for c in jedi.Script(s).completions()]
|
||||
print(names)
|
||||
assert 'diagonal' in names
|
||||
|
||||
|
||||
@@ -362,5 +384,4 @@ def test_numpy_comp_returns():
|
||||
x.d'''
|
||||
)
|
||||
names = [c.name for c in jedi.Script(s).completions()]
|
||||
print(names)
|
||||
assert 'diagonal' in names
|
||||
|
||||
27
test/test_evaluate/test_gradual/test_stub_loading.py
Normal file
27
test/test_evaluate/test_gradual/test_stub_loading.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from functools import partial
|
||||
from test.helpers import get_example_dir
|
||||
from jedi.api.project import Project
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ScriptInStubFolder(Script):
|
||||
path = get_example_dir('stub_packages')
|
||||
project = Project(path, sys_path=[path], smart_sys_path=False)
|
||||
return partial(Script, _project=project)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('code', 'expected'), [
|
||||
('from no_python import foo', ['int']),
|
||||
('from with_python import stub_only', ['str']),
|
||||
('from with_python import python_only', ['int']),
|
||||
('from with_python import both', ['int']),
|
||||
('from with_python import something_random', []),
|
||||
('from with_python.module import in_sub_module', ['int']),
|
||||
]
|
||||
)
|
||||
def test_find_stubs_infer(ScriptInStubFolder, code, expected):
|
||||
defs = ScriptInStubFolder(code).goto_definitions()
|
||||
assert [d.name for d in defs] == expected
|
||||
236
test/test_evaluate/test_gradual/test_typeshed.py
Normal file
236
test/test_evaluate/test_gradual/test_typeshed.py
Normal file
@@ -0,0 +1,236 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from parso.utils import PythonVersionInfo
|
||||
|
||||
from jedi.evaluate.gradual import typeshed, stub_context
|
||||
from jedi.evaluate.context import TreeInstance, BoundMethod, FunctionContext, \
|
||||
MethodContext, ClassContext
|
||||
|
||||
TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
|
||||
|
||||
|
||||
def test_get_typeshed_directories():
|
||||
def get_dirs(version_info):
|
||||
return {
|
||||
d.replace(typeshed.TYPESHED_PATH, '').lstrip(os.path.sep)
|
||||
for d in typeshed._get_typeshed_directories(version_info)
|
||||
}
|
||||
|
||||
def transform(set_):
|
||||
return {x.replace('/', os.path.sep) for x in set_}
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(2, 7))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/2', 'third_party/2and3', 'third_party/2'})
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(3, 4))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'third_party/2and3', 'third_party/3'})
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(3, 5))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'stdlib/3.5',
|
||||
'third_party/2and3', 'third_party/3', 'third_party/3.5'})
|
||||
|
||||
dirs = get_dirs(PythonVersionInfo(3, 6))
|
||||
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'stdlib/3.5',
|
||||
'stdlib/3.6', 'third_party/2and3',
|
||||
'third_party/3', 'third_party/3.5', 'third_party/3.6'})
|
||||
|
||||
|
||||
def test_get_stub_files():
|
||||
def get_map(version_info):
|
||||
return typeshed._create_stub_map(version_info)
|
||||
|
||||
map_ = typeshed._create_stub_map(TYPESHED_PYTHON3)
|
||||
assert map_['functools'] == os.path.join(TYPESHED_PYTHON3, 'functools.pyi')
|
||||
|
||||
|
||||
def test_function(Script, environment):
|
||||
code = 'import threading; threading.current_thread'
|
||||
def_, = Script(code).goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, FunctionContext), context
|
||||
|
||||
def_, = Script(code + '()').goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, TreeInstance)
|
||||
|
||||
def_, = Script('import threading; threading.Thread').goto_definitions()
|
||||
assert isinstance(def_._name._context, ClassContext), def_
|
||||
|
||||
|
||||
def test_keywords_variable(Script):
|
||||
code = 'import keyword; keyword.kwlist'
|
||||
for seq in Script(code).goto_definitions():
|
||||
assert seq.name == 'Sequence'
|
||||
# This points towards the typeshed implementation
|
||||
stub_seq, = seq.goto_stubs()
|
||||
assert typeshed.TYPESHED_PATH in stub_seq.module_path
|
||||
|
||||
|
||||
def test_class(Script):
|
||||
def_, = Script('import threading; threading.Thread').goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, ClassContext), context
|
||||
|
||||
|
||||
def test_instance(Script):
|
||||
def_, = Script('import threading; threading.Thread()').goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, TreeInstance)
|
||||
|
||||
|
||||
def test_class_function(Script):
|
||||
def_, = Script('import threading; threading.Thread.getName').goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, MethodContext), context
|
||||
|
||||
|
||||
def test_method(Script):
|
||||
code = 'import threading; threading.Thread().getName'
|
||||
def_, = Script(code).goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, BoundMethod), context
|
||||
assert isinstance(context._wrapped_context, MethodContext), context
|
||||
|
||||
def_, = Script(code + '()').goto_definitions()
|
||||
context = def_._name._context
|
||||
assert isinstance(context, TreeInstance)
|
||||
assert context.class_context.py__name__() == 'str'
|
||||
|
||||
|
||||
def test_sys_exc_info(Script):
|
||||
code = 'import sys; sys.exc_info()'
|
||||
none, def_ = Script(code + '[1]').goto_definitions()
|
||||
# It's an optional.
|
||||
assert def_.name == 'BaseException'
|
||||
assert def_.type == 'instance'
|
||||
assert none.name == 'NoneType'
|
||||
|
||||
none, def_ = Script(code + '[0]').goto_definitions()
|
||||
assert def_.name == 'BaseException'
|
||||
assert def_.type == 'class'
|
||||
|
||||
|
||||
def test_sys_getwindowsversion(Script, environment):
|
||||
# This should only exist on Windows, but type inference should happen
|
||||
# everywhere.
|
||||
definitions = Script('import sys; sys.getwindowsversion().major').goto_definitions()
|
||||
if environment.version_info.major == 2:
|
||||
assert not definitions
|
||||
else:
|
||||
def_, = definitions
|
||||
assert def_.name == 'int'
|
||||
|
||||
|
||||
def test_sys_hexversion(Script):
|
||||
script = Script('import sys; sys.hexversion')
|
||||
def_, = script.completions()
|
||||
assert isinstance(def_._name, stub_context._StubName), def_._name
|
||||
assert typeshed.TYPESHED_PATH in def_.module_path
|
||||
def_, = script.goto_definitions()
|
||||
assert def_.name == 'int'
|
||||
|
||||
|
||||
def test_math(Script):
|
||||
def_, = Script('import math; math.acos()').goto_definitions()
|
||||
assert def_.name == 'float'
|
||||
context = def_._name._context
|
||||
assert context
|
||||
|
||||
|
||||
def test_type_var(Script):
|
||||
def_, = Script('import typing; T = typing.TypeVar("T1")').goto_definitions()
|
||||
assert def_.name == 'TypeVar'
|
||||
assert def_.description == 'TypeVar = object()'
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'code, full_name', (
|
||||
('import math', 'math'),
|
||||
('from math import cos', 'math.cos')
|
||||
)
|
||||
)
|
||||
def test_math_is_stub(Script, code, full_name):
|
||||
s = Script(code)
|
||||
cos, = s.goto_definitions()
|
||||
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi')
|
||||
assert cos.module_path.endswith(wanted)
|
||||
assert cos.is_stub() is True
|
||||
assert cos.goto_stubs() == [cos]
|
||||
assert cos.full_name == full_name
|
||||
|
||||
cos, = s.goto_assignments()
|
||||
assert cos.module_path.endswith(wanted)
|
||||
assert cos.goto_stubs() == [cos]
|
||||
assert cos.is_stub() is True
|
||||
assert cos.full_name == full_name
|
||||
|
||||
|
||||
def test_goto_stubs(Script):
|
||||
s = Script('import os; os')
|
||||
os_module, = s.goto_definitions()
|
||||
assert os_module.full_name == 'os'
|
||||
assert os_module.is_stub() is False
|
||||
stub, = os_module.goto_stubs()
|
||||
assert stub.is_stub() is True
|
||||
|
||||
os_module, = s.goto_assignments()
|
||||
|
||||
|
||||
def _assert_is_same(d1, d2):
|
||||
assert d1.name == d2.name
|
||||
assert d1.module_path == d2.module_path
|
||||
assert d1.line == d2.line
|
||||
assert d1.column == d2.column
|
||||
|
||||
|
||||
@pytest.mark.parametrize('type_', ['goto', 'infer'])
|
||||
@pytest.mark.parametrize(
|
||||
'code', [
|
||||
'import os; os.walk',
|
||||
'from collections import Counter; Counter',
|
||||
'from collections import Counter; Counter()',
|
||||
'from collections import Counter; Counter.most_common',
|
||||
])
|
||||
def test_goto_stubs_on_itself(Script, code, type_):
|
||||
"""
|
||||
If goto_stubs is used on an identifier in e.g. the stdlib, we should goto
|
||||
the stub of it.
|
||||
"""
|
||||
s = Script(code)
|
||||
if type_ == 'infer':
|
||||
def_, = s.goto_definitions()
|
||||
else:
|
||||
def_, = s.goto_assignments(follow_imports=True)
|
||||
stub, = def_.goto_stubs()
|
||||
|
||||
script_on_source = Script(
|
||||
path=def_.module_path,
|
||||
line=def_.line,
|
||||
column=def_.column
|
||||
)
|
||||
if type_ == 'infer':
|
||||
definition, = script_on_source.goto_definitions()
|
||||
else:
|
||||
definition, = script_on_source.goto_assignments()
|
||||
same_stub, = definition.goto_stubs()
|
||||
_assert_is_same(same_stub, stub)
|
||||
_assert_is_same(definition, def_)
|
||||
assert same_stub.module_path != def_.module_path
|
||||
|
||||
# And the reverse.
|
||||
script_on_stub = Script(
|
||||
path=same_stub.module_path,
|
||||
line=same_stub.line,
|
||||
column=same_stub.column
|
||||
)
|
||||
|
||||
if type_ == 'infer':
|
||||
same_definition, = script_on_stub.goto_definitions()
|
||||
same_definition2, = same_stub.infer()
|
||||
else:
|
||||
same_definition, = script_on_stub.goto_assignments()
|
||||
same_definition2, = same_stub.goto_assignments()
|
||||
|
||||
_assert_is_same(same_definition, definition)
|
||||
_assert_is_same(same_definition, same_definition2)
|
||||
@@ -6,61 +6,106 @@ Tests".
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from parso.file_io import FileIO
|
||||
|
||||
from jedi._compatibility import find_module_py33, find_module
|
||||
from jedi.evaluate import compiled
|
||||
from ..helpers import cwd_at
|
||||
from jedi.evaluate import imports
|
||||
from jedi.api.project import Project
|
||||
from jedi.evaluate.gradual.conversion import stub_to_actual_context_set
|
||||
from ..helpers import cwd_at, get_example_dir, test_dir, root_dir
|
||||
|
||||
THIS_DIR = os.path.dirname(__file__)
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info < (3,3)')
|
||||
def test_find_module_py33():
|
||||
"""Needs to work like the old find_module."""
|
||||
assert find_module_py33('_io') == (None, '_io', False)
|
||||
assert find_module_py33('_io') == (None, False)
|
||||
with pytest.raises(ImportError):
|
||||
assert find_module_py33('_DOESNTEXIST_') == (None, None)
|
||||
|
||||
|
||||
def test_find_module_package():
|
||||
file, path, is_package = find_module('json')
|
||||
assert file is None
|
||||
assert path.endswith('json')
|
||||
file_io, is_package = find_module('json')
|
||||
assert file_io.path.endswith(os.path.join('json', '__init__.py'))
|
||||
assert is_package is True
|
||||
|
||||
|
||||
def test_find_module_not_package():
|
||||
file, path, is_package = find_module('io')
|
||||
assert file is not None
|
||||
assert path.endswith('io.py')
|
||||
file_io, is_package = find_module('io')
|
||||
assert file_io.path.endswith('io.py')
|
||||
assert is_package is False
|
||||
|
||||
|
||||
pkg_zip_path = os.path.join(os.path.dirname(__file__), 'zipped_imports/pkg.zip')
|
||||
|
||||
|
||||
def test_find_module_package_zipped(Script, evaluator, environment):
|
||||
path = os.path.join(os.path.dirname(__file__), 'zipped_imports/pkg.zip')
|
||||
sys_path = environment.get_sys_path() + [path]
|
||||
sys_path = environment.get_sys_path() + [pkg_zip_path]
|
||||
script = Script('import pkg; pkg.mod', sys_path=sys_path)
|
||||
assert len(script.completions()) == 1
|
||||
|
||||
code, path, is_package = evaluator.compiled_subprocess.get_module_info(
|
||||
file_io, is_package = evaluator.compiled_subprocess.get_module_info(
|
||||
sys_path=sys_path,
|
||||
string=u'pkg',
|
||||
full_name=u'pkg'
|
||||
)
|
||||
assert code is not None
|
||||
assert path.endswith('pkg.zip')
|
||||
assert file_io is not None
|
||||
assert file_io.path.endswith(os.path.join('pkg.zip', 'pkg', '__init__.py'))
|
||||
assert file_io._zip_path.endswith('pkg.zip')
|
||||
assert is_package is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'code, file, package, path', [
|
||||
('import pkg', '__init__.py', 'pkg', 'pkg'),
|
||||
('import pkg', '__init__.py', 'pkg', 'pkg'),
|
||||
|
||||
('from pkg import module', 'module.py', 'pkg', None),
|
||||
('from pkg.module', 'module.py', 'pkg', None),
|
||||
|
||||
('from pkg import nested', os.path.join('nested', '__init__.py'),
|
||||
'pkg.nested', os.path.join('pkg', 'nested')),
|
||||
('from pkg.nested', os.path.join('nested', '__init__.py'),
|
||||
'pkg.nested', os.path.join('pkg', 'nested')),
|
||||
|
||||
('from pkg.nested import nested_module',
|
||||
os.path.join('nested', 'nested_module.py'), 'pkg.nested', None),
|
||||
('from pkg.nested.nested_module',
|
||||
os.path.join('nested', 'nested_module.py'), 'pkg.nested', None),
|
||||
|
||||
('from pkg.namespace import namespace_module',
|
||||
os.path.join('namespace', 'namespace_module.py'), 'pkg.namespace', None),
|
||||
('from pkg.namespace.namespace_module',
|
||||
os.path.join('namespace', 'namespace_module.py'), 'pkg.namespace', None),
|
||||
]
|
||||
|
||||
)
|
||||
def test_correct_zip_package_behavior(Script, evaluator, environment, code,
|
||||
file, package, path, skip_python2):
|
||||
sys_path = environment.get_sys_path() + [pkg_zip_path]
|
||||
pkg, = Script(code, sys_path=sys_path).goto_definitions()
|
||||
context, = pkg._name.infer()
|
||||
assert context.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
|
||||
assert '.'.join(context.py__package__()) == package
|
||||
assert context.is_package is (path is not None)
|
||||
if path is not None:
|
||||
assert context.py__path__() == [os.path.join(pkg_zip_path, path)]
|
||||
|
||||
|
||||
def test_find_module_not_package_zipped(Script, evaluator, environment):
|
||||
path = os.path.join(os.path.dirname(__file__), 'zipped_imports/not_pkg.zip')
|
||||
sys_path = environment.get_sys_path() + [path]
|
||||
script = Script('import not_pkg; not_pkg.val', sys_path=sys_path)
|
||||
assert len(script.completions()) == 1
|
||||
|
||||
code, path, is_package = evaluator.compiled_subprocess.get_module_info(
|
||||
file_io, is_package = evaluator.compiled_subprocess.get_module_info(
|
||||
sys_path=sys_path,
|
||||
string=u'not_pkg',
|
||||
full_name=u'not_pkg'
|
||||
)
|
||||
assert code is not None
|
||||
assert path.endswith('not_pkg.zip')
|
||||
assert file_io.path.endswith(os.path.join('not_pkg.zip', 'not_pkg.py'))
|
||||
assert is_package is False
|
||||
|
||||
|
||||
@@ -87,10 +132,10 @@ def test_import_not_in_sys_path(Script):
|
||||
("from flask.ext.", "bar"),
|
||||
("from flask.ext.", "baz"),
|
||||
("from flask.ext.", "moo"),
|
||||
pytest.mark.xfail(("import flask.ext.foo; flask.ext.foo.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.bar; flask.ext.bar.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.baz; flask.ext.baz.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.moo; flask.ext.moo.", "Foo")),
|
||||
pytest.param("import flask.ext.foo; flask.ext.foo.", "Foo", marks=pytest.mark.xfail),
|
||||
pytest.param("import flask.ext.bar; flask.ext.bar.", "Foo", marks=pytest.mark.xfail),
|
||||
pytest.param("import flask.ext.baz; flask.ext.baz.", "Foo", marks=pytest.mark.xfail),
|
||||
pytest.param("import flask.ext.moo; flask.ext.moo.", "Foo", marks=pytest.mark.xfail),
|
||||
])
|
||||
def test_flask_ext(Script, code, name):
|
||||
"""flask.ext.foo is really imported from flaskext.foo or flask_foo.
|
||||
@@ -132,13 +177,13 @@ def test_cache_works_with_sys_path_param(Script, tmpdir):
|
||||
def test_import_completion_docstring(Script):
|
||||
import abc
|
||||
s = Script('"""test"""\nimport ab')
|
||||
completions = s.completions()
|
||||
assert len(completions) == 1
|
||||
assert completions[0].docstring(fast=False) == abc.__doc__
|
||||
abc_completions = [c for c in s.completions() if c.name == 'abc']
|
||||
assert len(abc_completions) == 1
|
||||
assert abc_completions[0].docstring(fast=False) == abc.__doc__
|
||||
|
||||
# However for performance reasons not all modules are loaded and the
|
||||
# docstring is empty in this case.
|
||||
assert completions[0].docstring() == ''
|
||||
assert abc_completions[0].docstring() == ''
|
||||
|
||||
|
||||
def test_goto_definition_on_import(Script):
|
||||
@@ -249,5 +294,146 @@ def test_compiled_import_none(monkeypatch, Script):
|
||||
"""
|
||||
Related to #1079. An import might somehow fail and return None.
|
||||
"""
|
||||
script = Script('import sys')
|
||||
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
|
||||
assert not Script('import sys').goto_definitions()
|
||||
def_, = script.goto_definitions()
|
||||
assert def_.type == 'module'
|
||||
context, = def_._name.infer()
|
||||
assert not stub_to_actual_context_set(context)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('path', 'is_package', 'goal'), [
|
||||
(os.path.join(THIS_DIR, 'test_docstring.py'), False, ('ok', 'lala', 'test_imports')),
|
||||
(os.path.join(THIS_DIR, '__init__.py'), True, ('ok', 'lala', 'x', 'test_imports')),
|
||||
]
|
||||
)
|
||||
def test_get_modules_containing_name(evaluator, path, goal, is_package):
|
||||
module = imports._load_python_module(
|
||||
evaluator,
|
||||
FileIO(path),
|
||||
import_names=('ok', 'lala', 'x'),
|
||||
is_package=is_package,
|
||||
)
|
||||
assert module
|
||||
input_module, found_module = imports.get_modules_containing_name(
|
||||
evaluator,
|
||||
[module],
|
||||
'string_that_only_exists_here'
|
||||
)
|
||||
assert input_module is module
|
||||
assert found_module.string_names == goal
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'path', ('api/whatever/test_this.py', 'api/whatever/file'))
|
||||
@pytest.mark.parametrize('empty_sys_path', (False, True))
|
||||
def test_relative_imports_with_multiple_similar_directories(Script, path, empty_sys_path):
|
||||
dir = get_example_dir('issue1209')
|
||||
if empty_sys_path:
|
||||
project = Project(dir, sys_path=(), smart_sys_path=False)
|
||||
else:
|
||||
project = Project(dir)
|
||||
script = Script(
|
||||
"from . ",
|
||||
path=os.path.join(dir, path),
|
||||
_project=project,
|
||||
)
|
||||
name, import_ = script.completions()
|
||||
assert import_.name == 'import'
|
||||
assert name.name == 'api_test1'
|
||||
|
||||
|
||||
def test_relative_imports_with_outside_paths(Script):
|
||||
dir = get_example_dir('issue1209')
|
||||
project = Project(dir, sys_path=[], smart_sys_path=False)
|
||||
script = Script(
|
||||
"from ...",
|
||||
path=os.path.join(dir, 'api/whatever/test_this.py'),
|
||||
_project=project,
|
||||
)
|
||||
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever']
|
||||
|
||||
script = Script(
|
||||
"from " + '.' * 100,
|
||||
path=os.path.join(dir, 'api/whatever/test_this.py'),
|
||||
_project=project,
|
||||
)
|
||||
assert [c.name for c in script.completions()] == ['import']
|
||||
|
||||
|
||||
@cwd_at('test/examples/issue1209/api/whatever/')
|
||||
def test_relative_imports_without_path(Script):
|
||||
project = Project('.', sys_path=[], smart_sys_path=False)
|
||||
script = Script("from . ", _project=project)
|
||||
assert [c.name for c in script.completions()] == ['api_test1', 'import']
|
||||
|
||||
script = Script("from .. ", _project=project)
|
||||
assert [c.name for c in script.completions()] == ['import', 'whatever']
|
||||
|
||||
script = Script("from ... ", _project=project)
|
||||
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever']
|
||||
|
||||
|
||||
def test_relative_import_out_of_file_system(Script):
|
||||
script = Script("from " + '.' * 100)
|
||||
import_, = script.completions()
|
||||
assert import_.name == 'import'
|
||||
|
||||
script = Script("from " + '.' * 100 + 'abc import ABCMeta')
|
||||
assert not script.goto_definitions()
|
||||
assert not script.completions()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'level, directory, project_path, result', [
|
||||
(1, '/a/b/c', '/a', (['b', 'c'], '/a')),
|
||||
(2, '/a/b/c', '/a', (['b'], '/a')),
|
||||
(3, '/a/b/c', '/a', ([], '/a')),
|
||||
(4, '/a/b/c', '/a', (None, '/')),
|
||||
(5, '/a/b/c', '/a', (None, None)),
|
||||
(1, '/', '/', ([], '/')),
|
||||
(2, '/', '/', (None, None)),
|
||||
(1, '/a/b', '/a/b/c', (None, '/a/b')),
|
||||
(2, '/a/b', '/a/b/c', (None, '/a')),
|
||||
(3, '/a/b', '/a/b/c', (None, '/')),
|
||||
]
|
||||
)
|
||||
def test_level_to_import_path(level, directory, project_path, result):
|
||||
assert imports._level_to_base_import_path(project_path, directory, level) == result
|
||||
|
||||
|
||||
def test_import_name_calculation(Script):
|
||||
s = Script(path=os.path.join(test_dir, 'completion', 'isinstance.py'))
|
||||
m = s._get_module()
|
||||
assert m.string_names == ('test', 'completion', 'isinstance')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name', ('builtins', 'typing'))
|
||||
def test_pre_defined_imports_module(Script, environment, name):
|
||||
if environment.version_info.major < 3 and name == 'builtins':
|
||||
name = '__builtin__'
|
||||
|
||||
path = os.path.join(root_dir, name + '.py')
|
||||
module = Script('', path=path)._get_module()
|
||||
assert module.string_names == (name,)
|
||||
|
||||
assert module.evaluator.builtins_module.py__file__() != path
|
||||
assert module.evaluator.typing_module.py__file__() != path
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name', ('builtins', 'typing'))
|
||||
def test_import_needed_modules_by_jedi(Script, environment, tmpdir, name):
|
||||
if environment.version_info.major < 3 and name == 'builtins':
|
||||
name = '__builtin__'
|
||||
|
||||
module_path = tmpdir.join(name + '.py')
|
||||
module_path.write('int = ...')
|
||||
script = Script(
|
||||
'import ' + name,
|
||||
path=tmpdir.join('something.py').strpath,
|
||||
sys_path=[tmpdir.strpath] + environment.get_sys_path(),
|
||||
)
|
||||
module, = script.goto_definitions()
|
||||
assert module._evaluator.builtins_module.py__file__() != module_path
|
||||
assert module._evaluator.typing_module.py__file__() != module_path
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import pytest
|
||||
from jedi.evaluate.context import CompiledInstance
|
||||
from jedi.evaluate.context import TreeInstance
|
||||
|
||||
|
||||
def _eval_literal(Script, code, is_fstring=False):
|
||||
def_, = Script(code).goto_definitions()
|
||||
if is_fstring:
|
||||
assert def_.name == 'str'
|
||||
assert isinstance(def_._name._context, CompiledInstance)
|
||||
assert isinstance(def_._name._context, TreeInstance)
|
||||
return ''
|
||||
else:
|
||||
return def_._name._context.get_safe_value()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from os.path import dirname, join
|
||||
|
||||
import pytest
|
||||
import py
|
||||
|
||||
from ..helpers import get_example_dir
|
||||
|
||||
|
||||
SYS_PATH = [join(dirname(__file__), d)
|
||||
@@ -72,3 +75,22 @@ def test_nested_namespace_package(Script):
|
||||
result = script.goto_definitions()
|
||||
|
||||
assert len(result) == 1
|
||||
|
||||
|
||||
def test_relative_import(Script, environment, tmpdir):
|
||||
"""
|
||||
Attempt a relative import in a very simple namespace package.
|
||||
"""
|
||||
if environment.version_info < (3, 4):
|
||||
pytest.skip()
|
||||
|
||||
directory = get_example_dir('namespace_package_relative_import')
|
||||
# Need to copy the content in a directory where there's no __init__.py.
|
||||
py.path.local(directory).copy(tmpdir)
|
||||
file_path = join(tmpdir.strpath, "rel1.py")
|
||||
script = Script(path=file_path, line=1)
|
||||
d, = script.goto_definitions()
|
||||
assert d.name == 'int'
|
||||
d, = script.goto_assignments()
|
||||
assert d.name == 'name'
|
||||
assert d.module_name == 'rel2'
|
||||
|
||||
@@ -4,9 +4,10 @@ import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize('source', [
|
||||
'1 == 1',
|
||||
'1.0 == 1',
|
||||
'... == ...'
|
||||
pytest.param('1 == 1'),
|
||||
pytest.param('1.0 == 1'),
|
||||
# Unfortunately for now not possible, because it's a typeshed object.
|
||||
pytest.param('... == ...', marks=pytest.mark.xfail),
|
||||
])
|
||||
def test_equals(Script, environment, source):
|
||||
if environment.version_info.major < 3:
|
||||
|
||||
@@ -10,8 +10,10 @@ import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from ..helpers import cwd_at
|
||||
from jedi.api.environment import SameEnvironment, InterpreterEnvironment
|
||||
|
||||
|
||||
SRC = """class Foo:
|
||||
@@ -22,35 +24,50 @@ class Bar:
|
||||
"""
|
||||
|
||||
|
||||
def generate_pyc():
|
||||
os.mkdir("dummy_package")
|
||||
with open("dummy_package/__init__.py", 'w'):
|
||||
@pytest.fixture
|
||||
def pyc_project_path(tmpdir):
|
||||
path = tmpdir.strpath
|
||||
dummy_package_path = os.path.join(path, "dummy_package")
|
||||
os.mkdir(dummy_package_path)
|
||||
with open(os.path.join(dummy_package_path, "__init__.py"), 'w'):
|
||||
pass
|
||||
with open("dummy_package/dummy.py", 'w') as f:
|
||||
|
||||
dummy_path = os.path.join(dummy_package_path, 'dummy.py')
|
||||
with open(dummy_path, 'w') as f:
|
||||
f.write(SRC)
|
||||
import compileall
|
||||
compileall.compile_file("dummy_package/dummy.py")
|
||||
os.remove("dummy_package/dummy.py")
|
||||
compileall.compile_file(dummy_path)
|
||||
os.remove(dummy_path)
|
||||
|
||||
if sys.version_info[0] == 3:
|
||||
if sys.version_info.major == 3:
|
||||
# Python3 specific:
|
||||
# To import pyc modules, we must move them out of the __pycache__
|
||||
# directory and rename them to remove ".cpython-%s%d"
|
||||
# see: http://stackoverflow.com/questions/11648440/python-does-not-detect-pyc-files
|
||||
for f in os.listdir("dummy_package/__pycache__"):
|
||||
pycache = os.path.join(dummy_package_path, "__pycache__")
|
||||
for f in os.listdir(pycache):
|
||||
dst = f.replace('.cpython-%s%s' % sys.version_info[:2], "")
|
||||
dst = os.path.join("dummy_package", dst)
|
||||
shutil.copy(os.path.join("dummy_package/__pycache__", f), dst)
|
||||
dst = os.path.join(dummy_package_path, dst)
|
||||
shutil.copy(os.path.join(pycache, f), dst)
|
||||
try:
|
||||
yield path
|
||||
finally:
|
||||
shutil.rmtree(path)
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate')
|
||||
def test_pyc(Script):
|
||||
def test_pyc(pyc_project_path, environment):
|
||||
"""
|
||||
The list of completion must be greater than 2.
|
||||
"""
|
||||
try:
|
||||
generate_pyc()
|
||||
s = jedi.Script("from dummy_package import dummy; dummy.", path='blub.py')
|
||||
assert len(s.completions()) >= 2
|
||||
finally:
|
||||
shutil.rmtree("dummy_package")
|
||||
path = os.path.join(pyc_project_path, 'blub.py')
|
||||
if not isinstance(environment, InterpreterEnvironment):
|
||||
# We are using the same version for pyc completions here, because it
|
||||
# was compiled in that version. However with interpreter environments
|
||||
# we also have the same version and it's easier to debug.
|
||||
environment = SameEnvironment()
|
||||
environment = environment
|
||||
s = jedi.Script(
|
||||
"from dummy_package import dummy; dummy.",
|
||||
path=path,
|
||||
environment=environment)
|
||||
assert len(s.completions()) >= 2
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from jedi.evaluate.helpers import execute_evaluated
|
||||
|
||||
|
||||
def get_definition_and_evaluator(Script, source):
|
||||
first, = Script(dedent(source)).goto_definitions()
|
||||
@@ -20,8 +22,8 @@ def test_function_execution(Script):
|
||||
# Now just use the internals of the result (easiest way to get a fully
|
||||
# usable function).
|
||||
# Should return the same result both times.
|
||||
assert len(func.execute_evaluated()) == 1
|
||||
assert len(func.execute_evaluated()) == 1
|
||||
assert len(execute_evaluated(func)) == 1
|
||||
assert len(execute_evaluated(func)) == 1
|
||||
|
||||
|
||||
def test_class_mro(Script):
|
||||
|
||||
@@ -7,14 +7,6 @@ from textwrap import dedent
|
||||
import pytest
|
||||
|
||||
|
||||
# The namedtuple is different for different Python2.7 versions. Some versions
|
||||
# are missing the attribute `_class_template`.
|
||||
@pytest.fixture(autouse=True)
|
||||
def skipping(environment):
|
||||
if environment.version_info.major < 3:
|
||||
pytest.skip()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['letter', 'expected'], [
|
||||
('n', ['name']),
|
||||
('s', ['smart']),
|
||||
@@ -86,3 +78,26 @@ def test_namedtuple_goto_definitions(Script):
|
||||
|
||||
assert d1.get_line_code() == "class Foo(tuple):\n"
|
||||
assert d1.module_path is None
|
||||
|
||||
|
||||
def test_re_sub(Script, environment):
|
||||
"""
|
||||
This whole test was taken out of completion/stdlib.py, because of the
|
||||
version differences.
|
||||
"""
|
||||
def run(code):
|
||||
defs = Script(code).goto_definitions()
|
||||
return {d.name for d in defs}
|
||||
|
||||
names = run("import re; re.sub('a', 'a', 'f')")
|
||||
if environment.version_info.major == 2:
|
||||
assert names == {'str', 'unicode'}
|
||||
else:
|
||||
assert names == {'str', 'bytes'}
|
||||
|
||||
# This param is missing because of overloading.
|
||||
names = run("import re; re.sub('a', 'a')")
|
||||
if environment.version_info.major == 2:
|
||||
assert names == {'str', 'unicode'}
|
||||
else:
|
||||
assert names == {'str', 'bytes'}
|
||||
|
||||
@@ -3,6 +3,8 @@ from glob import glob
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi.evaluate import sys_path
|
||||
from jedi.api.environment import create_environment
|
||||
|
||||
@@ -29,10 +31,8 @@ def test_paths_from_assignment(Script):
|
||||
def test_venv_and_pths(venv_path):
|
||||
pjoin = os.path.join
|
||||
|
||||
virtualenv = create_environment(venv_path)
|
||||
|
||||
CUR_DIR = os.path.dirname(__file__)
|
||||
site_pkg_path = pjoin(virtualenv.path, 'lib')
|
||||
site_pkg_path = pjoin(venv_path, 'lib')
|
||||
if os.name == 'nt':
|
||||
site_pkg_path = pjoin(site_pkg_path, 'site-packages')
|
||||
else:
|
||||
@@ -40,6 +40,7 @@ def test_venv_and_pths(venv_path):
|
||||
shutil.rmtree(site_pkg_path)
|
||||
shutil.copytree(pjoin(CUR_DIR, 'sample_venvs', 'pth_directory'), site_pkg_path)
|
||||
|
||||
virtualenv = create_environment(venv_path)
|
||||
venv_paths = virtualenv.get_sys_path()
|
||||
|
||||
ETALON = [
|
||||
@@ -60,3 +61,45 @@ def test_venv_and_pths(venv_path):
|
||||
|
||||
# Ensure that none of venv dirs leaked to the interpreter.
|
||||
assert not set(sys.path).intersection(ETALON)
|
||||
|
||||
|
||||
_s = ['/a', '/b', '/c/d/']
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'sys_path_, module_path, expected, is_package', [
|
||||
(_s, '/a/b', ('b',), False),
|
||||
(_s, '/a/b/c', ('b', 'c'), False),
|
||||
(_s, '/a/b.py', ('b',), False),
|
||||
(_s, '/a/b/c.py', ('b', 'c'), False),
|
||||
(_s, '/x/b.py', None, False),
|
||||
(_s, '/c/d/x.py', ('x',), False),
|
||||
(_s, '/c/d/x.py', ('x',), False),
|
||||
(_s, '/c/d/x/y.py', ('x', 'y'), False),
|
||||
# If dots are in there they also resolve. These are obviously illegal
|
||||
# in Python, but Jedi can handle them. Give the user a bit more freedom
|
||||
# that he will have to correct eventually.
|
||||
(_s, '/a/b.c.py', ('b.c',), False),
|
||||
(_s, '/a/b.d/foo.bar.py', ('b.d', 'foo.bar'), False),
|
||||
|
||||
(_s, '/a/.py', None, False),
|
||||
(_s, '/a/c/.py', None, False),
|
||||
|
||||
(['/foo'], '/foo/bar/__init__.py', ('bar',), True),
|
||||
(['/foo'], '/foo/bar/baz/__init__.py', ('bar', 'baz'), True),
|
||||
(['/foo'], '/foo/bar.so', ('bar',), False),
|
||||
(['/foo'], '/foo/bar/__init__.so', ('bar',), True),
|
||||
(['/foo'], '/x/bar.py', None, False),
|
||||
(['/foo'], '/foo/bar.xyz', ('bar.xyz',), False),
|
||||
|
||||
(['/foo', '/foo/bar'], '/foo/bar/baz', ('baz',), False),
|
||||
(['/foo/bar', '/foo'], '/foo/bar/baz', ('baz',), False),
|
||||
|
||||
(['/'], '/bar/baz.py', ('bar', 'baz',), False),
|
||||
])
|
||||
def test_transform_path_to_dotted(sys_path_, module_path, expected, is_package):
|
||||
# transform_path_to_dotted expects normalized absolute paths.
|
||||
sys_path_ = [os.path.abspath(path) for path in sys_path_]
|
||||
module_path = os.path.abspath(module_path)
|
||||
assert sys_path.transform_path_to_dotted(sys_path_, module_path) \
|
||||
== (expected, is_package)
|
||||
|
||||
Binary file not shown.
@@ -84,5 +84,3 @@ def test_get_call_signature(code, call_signature):
|
||||
if node.type == 'simple_stmt':
|
||||
node = node.children[0]
|
||||
assert parser_utils.get_call_signature(node) == call_signature
|
||||
|
||||
assert parser_utils.get_doc_with_call_signature(node) == (call_signature + '\n\n')
|
||||
|
||||
23
test/test_settings.py
Normal file
23
test/test_settings.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import pytest
|
||||
|
||||
from jedi import settings
|
||||
from jedi.evaluate.names import ContextName
|
||||
from jedi.evaluate.compiled import CompiledContextName
|
||||
from jedi.evaluate.gradual.typeshed import StubModuleContext
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def auto_import_json(monkeypatch):
|
||||
monkeypatch.setattr(settings, 'auto_import_modules', ['json'])
|
||||
|
||||
|
||||
def test_base_auto_import_modules(auto_import_json, Script):
|
||||
loads, = Script('import json; json.loads').goto_definitions()
|
||||
assert isinstance(loads._name, ContextName)
|
||||
context, = loads._name.infer()
|
||||
assert isinstance(context.parent_context, StubModuleContext)
|
||||
|
||||
|
||||
def test_auto_import_modules_imports(auto_import_json, Script):
|
||||
main, = Script('from json import tool; tool.main').goto_definitions()
|
||||
assert isinstance(main._name, CompiledContextName)
|
||||
@@ -30,7 +30,7 @@ def _check_speed(time_per_run, number=4, run_warm=True):
|
||||
return decorated
|
||||
|
||||
|
||||
@_check_speed(0.3)
|
||||
@_check_speed(0.5)
|
||||
def test_os_path_join(Script):
|
||||
s = "from posixpath import join; join('', '')."
|
||||
assert len(Script(s).completions()) > 10 # is a str completion
|
||||
|
||||
@@ -76,7 +76,11 @@ class TestSetupReadline(unittest.TestCase):
|
||||
goal = {s + el for el in dir(os)}
|
||||
# There are minor differences, e.g. the dir doesn't include deleted
|
||||
# items as well as items that are not only available on linux.
|
||||
assert len(set(self.completions(s)).symmetric_difference(goal)) < 20
|
||||
difference = set(self.completions(s)).symmetric_difference(goal)
|
||||
difference = {x for x in difference if not x.startswith('from os import _')}
|
||||
# There are quite a few differences, because both Windows and Linux
|
||||
# (posix and nt) libraries are included.
|
||||
assert len(difference) < 38
|
||||
|
||||
@cwd_at('test')
|
||||
def test_local_import(self):
|
||||
|
||||
Reference in New Issue
Block a user