1
0
forked from VimPlug/jedi

Merge with the linter branch (especially the changes of pep484.

This commit is contained in:
Dave Halter
2016-06-07 13:51:25 +02:00
27 changed files with 883 additions and 108 deletions

View File

@@ -0,0 +1,105 @@
a = 3 # type: str
#? str()
a
b = 3 # type: str but I write more
#? int()
b
c = 3 # type: str # I comment more
#? str()
c
d = "It should not read comments from the next line"
# type: int
#? str()
d
# type: int
e = "It should not read comments from the previous line"
#? str()
e
class BB: pass
def test(a, b):
a = a # type: BB
c = a # type: str
d = a
# type: str
e = a # type: str # Should ignore long whitespace
#? BB()
a
#? str()
c
#? BB()
d
#? str()
e
a,b = 1, 2 # type: str, float
#? str()
a
#? float()
b
class Employee:
pass
from typing import List
x = [] # type: List[Employee]
#? Employee()
x[1]
x, y, z = [], [], [] # type: List[int], List[int], List[str]
#? int()
y[2]
x, y, z = [], [], [] # type: (List[float], List[float], List[BB])
for zi in z:
#? BB()
zi
x = [
1,
2,
] # type: List[str]
#? str()
x[1]
for bar in foo(): # type: str
#? str()
bar
for bar, baz in foo(): # type: int, float
#? int()
bar
#? float()
baz
for bar, baz in foo():
# type: str, str
""" type hinting on next line should not work """
#?
bar
#?
baz
with foo(): # type: int
...
with foo() as f: # type: str
#? str()
f
with foo() as f:
# type: str
""" type hinting on next line should not work """
#?
f
aaa = some_extremely_long_function_name_that_doesnt_leave_room_for_hints() \
# type: float # We should be able to put hints on the next line with a \
#? float()
aaa

View File

@@ -0,0 +1,263 @@
"""
Test the typing library, with docstrings. This is needed since annotations
are not supported in python 2.7 else then annotating by comment (and this is
still TODO at 2016-01-23)
"""
# There's no Python 2.6 typing module.
# python >= 2.7
import typing
class B:
pass
def we_can_has_sequence(p, q, r, s, t, u):
"""
:type p: typing.Sequence[int]
:type q: typing.Sequence[B]
:type r: typing.Sequence[int]
:type s: typing.Sequence["int"]
:type t: typing.MutableSequence[dict]
:type u: typing.List[float]
"""
#? ["count"]
p.c
#? int()
p[1]
#? ["count"]
q.c
#? B()
q[1]
#? ["count"]
r.c
#? int()
r[1]
#? ["count"]
s.c
#? int()
s[1]
#? []
s.a
#? ["append"]
t.a
#? dict()
t[1]
#? ["append"]
u.a
#? float()
u[1]
def iterators(ps, qs, rs, ts):
"""
:type ps: typing.Iterable[int]
:type qs: typing.Iterator[str]
:type rs: typing.Sequence["ForwardReference"]
:type ts: typing.AbstractSet["float"]
"""
for p in ps:
#? int()
p
#?
next(ps)
a, b = ps
#? int()
a
##? int() --- TODO fix support for tuple assignment
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
# test below is just to make sure that in case it gets fixed by accident
# these tests will be fixed as well the way they should be
#?
b
for q in qs:
#? str()
q
#? str()
next(qs)
for r in rs:
#? ForwardReference()
r
#?
next(rs)
for t in ts:
#? float()
t
def sets(p, q):
"""
:type p: typing.AbstractSet[int]
:type q: typing.MutableSet[float]
"""
#? []
p.a
#? ["add"]
q.a
def tuple(p, q, r):
"""
:type p: typing.Tuple[int]
:type q: typing.Tuple[int, str, float]
:type r: typing.Tuple[B, ...]
"""
#? int()
p[0]
#? int()
q[0]
#? str()
q[1]
#? float()
q[2]
#? B()
r[0]
#? B()
r[1]
#? B()
r[2]
#? B()
r[10000]
i, s, f = q
#? int()
i
##? str() --- TODO fix support for tuple assignment
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
#?
s
##? float() --- TODO fix support for tuple assignment
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
#?
f
class Key:
pass
class Value:
pass
def mapping(p, q, d, r, s, t):
"""
:type p: typing.Mapping[Key, Value]
:type q: typing.MutableMapping[Key, Value]
:type d: typing.Dict[Key, Value]
:type r: typing.KeysView[Key]
:type s: typing.ValuesView[Value]
:type t: typing.ItemsView[Key, Value]
"""
#? []
p.setd
#? ["setdefault"]
q.setd
#? ["setdefault"]
d.setd
#? Value()
p[1]
for key in p:
#? Key()
key
for key in p.keys():
#? Key()
key
for value in p.values():
#? Value()
value
for item in p.items():
#? Key()
item[0]
#? Value()
item[1]
(key, value) = item
#? Key()
key
#? Value()
value
for key, value in p.items():
#? Key()
key
#? Value()
value
for key in r:
#? Key()
key
for value in s:
#? Value()
value
for key, value in t:
#? Key()
key
#? Value()
value
def union(p, q, r, s, t):
"""
:type p: typing.Union[int]
:type q: typing.Union[int, int]
:type r: typing.Union[int, str, "int"]
:type s: typing.Union[int, typing.Union[str, "typing.Union['float', 'dict']"]]
:type t: typing.Union[int, None]
"""
#? int()
p
#? int()
q
#? int() str()
r
#? int() str() float() dict()
s
#? int()
t
def optional(p):
"""
:type p: typing.Optional[int]
Optional does not do anything special. However it should be recognised
as being of that type. Jedi doesn't do anything with the extra into that
it can be None as well
"""
#? int()
p
class ForwardReference:
pass
class TestDict(typing.Dict[str, int]):
def setdud(self):
pass
def testdict(x):
"""
:type x: TestDict
"""
#? ["setdud", "setdefault"]
x.setd
for key in x.keys():
#? str()
key
for value in x.values():
#? int()
value
x = TestDict()
#? ["setdud", "setdefault"]
x.setd
for key in x.keys():
#? str()
key
for value in x.values():
#? int()
value
# python >= 3.2
"""
docstrings have some auto-import, annotations can use all of Python's
import logic
"""
import typing as t
def union2(x: t.Union[int, str]):
#? int() str()
x
from typing import Union
def union3(x: Union[int, str]):
#? int() str()
x
from typing import Union as U
def union4(x: U[int, str]):
#? int() str()
x

View File

@@ -249,14 +249,16 @@ def skip_python_version(line):
map(int, match.group(2).split(".")))
operation = getattr(operator, comp_map[match.group(1)])
if not operation(sys.version_info, minimal_python_version):
return "Minimal python version %s" % match.group(1)
return "Minimal python version %s %s" % (match.group(1), match.group(2))
return None
def collect_file_tests(lines, lines_to_execute):
makecase = lambda t: IntegrationTestCase(t, correct, line_nr, column,
start, line, path=None, skip=skip)
def collect_file_tests(path, lines, lines_to_execute):
def makecase(t):
return IntegrationTestCase(t, correct, line_nr, column,
start, line, path=path, skip=skip)
start = None
correct = None
test_type = None
@@ -325,9 +327,8 @@ def collect_dir_tests(base_dir, test_files, check_thirdparty=False):
else:
source = unicode(open(path).read(), 'UTF-8')
for case in collect_file_tests(StringIO(source),
for case in collect_file_tests(path, StringIO(source),
lines_to_execute):
case.path = path
case.source = source
if skip:
case.skip = skip

View File

@@ -9,6 +9,7 @@ test_grammar.py files from both Python 2 and Python 3.
from textwrap import dedent
from jedi._compatibility import unicode
from jedi.parser import Parser, load_grammar, ParseError
import pytest
@@ -18,7 +19,7 @@ from test.helpers import TestCase
def parse(code, version='3.4'):
code = dedent(code) + "\n\n"
grammar = load_grammar(version=version)
return Parser(grammar, code, 'file_input').get_parsed_node()
return Parser(grammar, unicode(code), 'file_input').get_parsed_node()
class TestDriver(TestCase):
@@ -45,8 +46,8 @@ class GrammarTest(TestCase):
class TestMatrixMultiplication(GrammarTest):
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
def test_matrix_multiplication_operator(self):
parse("a @ b")
parse("a @= b")
parse("a @ b", "3.5")
parse("a @= b", "3.5")
class TestYieldFrom(GrammarTest):
@@ -61,7 +62,7 @@ class TestAsyncAwait(GrammarTest):
def test_await_expr(self):
parse("""async def foo():
await x
""")
""", "3.5")
parse("""async def foo():
@@ -70,46 +71,56 @@ class TestAsyncAwait(GrammarTest):
def foo(): pass
await x
""")
""", "3.5")
parse("""async def foo(): return await a""")
parse("""async def foo(): return await a""", "3.5")
parse("""def foo():
def foo(): pass
async def foo(): await x
""")
""", "3.5")
self.invalid_syntax("await x")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
@pytest.mark.xfail(reason="acting like python 3.7")
def test_await_expr_invalid(self):
self.invalid_syntax("await x", version="3.5")
self.invalid_syntax("""def foo():
await x""")
await x""", version="3.5")
self.invalid_syntax("""def foo():
def foo(): pass
async def foo(): pass
await x
""")
""", version="3.5")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
@pytest.mark.xfail(reason="acting like python 3.7")
def test_async_var(self):
parse("""async = 1""")
parse("""await = 1""")
parse("""def async(): pass""")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
def test_async_with(self):
parse("""async def foo():
async for a in b: pass""")
self.invalid_syntax("""def foo():
async for a in b: pass""")
parse("""async = 1""", "3.5")
parse("""await = 1""", "3.5")
parse("""def async(): pass""", "3.5")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
def test_async_for(self):
parse("""async def foo():
async with a: pass""")
async for a in b: pass""", "3.5")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
@pytest.mark.xfail(reason="acting like python 3.7")
def test_async_for_invalid(self):
self.invalid_syntax("""def foo():
async with a: pass""")
async for a in b: pass""", version="3.5")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
def test_async_with(self):
parse("""async def foo():
async with a: pass""", "3.5")
@pytest.mark.skipif('sys.version_info[:2] < (3, 5)')
@pytest.mark.xfail(reason="acting like python 3.7")
def test_async_with_invalid(self):
self.invalid_syntax("""def foo():
async with a: pass""", version="3.5")
class TestRaiseChanges(GrammarTest):
@@ -232,6 +243,9 @@ class TestParserIdempotency(TestCase):
class TestLiterals(GrammarTest):
# It's not possible to get the same result when using \xaa in Python 2/3,
# because it's treated differently.
@pytest.mark.skipif('sys.version_info[0] < 3')
def test_multiline_bytes_literals(self):
s = """
md5test(b"\xaa" * 80,
@@ -250,6 +264,7 @@ class TestLiterals(GrammarTest):
'''
parse(s)
@pytest.mark.skipif('sys.version_info[0] < 3')
def test_multiline_str_literals(self):
s = """
md5test("\xaa" * 80,