Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
e1f739f5
Commit
e1f739f5
authored
Jul 30, 2015
by
scoder
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #411 from tjwei/jedi_0.9
Experimental support for jedi 0.9.0
parents
e8521a59
5c848acb
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
137 additions
and
41 deletions
+137
-41
Cython/Tests/TestJediTyper.py
Cython/Tests/TestJediTyper.py
+88
-5
Tools/jedi-typer.py
Tools/jedi-typer.py
+48
-35
runtests.py
runtests.py
+1
-1
No files found.
Cython/Tests/TestJediTyper.py
View file @
e1f739f5
...
@@ -66,9 +66,6 @@ class TestJediTyper(TransformTest):
...
@@ -66,9 +66,6 @@ class TestJediTyper(TransformTest):
a = i + 1
a = i + 1
'''
'''
types
=
self
.
_test
(
code
)
types
=
self
.
_test
(
code
)
if
not
types
:
# old Jedi version
return
self
.
assertIn
((
None
,
(
1
,
0
)),
types
)
self
.
assertIn
((
None
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
None
,
(
1
,
0
)))
variables
=
types
.
pop
((
None
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertFalse
(
types
)
...
@@ -87,7 +84,7 @@ class TestJediTyper(TransformTest):
...
@@ -87,7 +84,7 @@ class TestJediTyper(TransformTest):
self
.
assertFalse
(
types
)
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'int'
]),
'i'
:
set
([
'int'
])},
variables
)
self
.
assertEqual
({
'a'
:
set
([
'int'
]),
'i'
:
set
([
'int'
])},
variables
)
def
_
test_conflicting_types_in_function
(
self
):
def
test_conflicting_types_in_function
(
self
):
code
=
'''
\
code
=
'''
\
def func(a, b):
def func(a, b):
print(a)
print(a)
...
@@ -102,7 +99,7 @@ class TestJediTyper(TransformTest):
...
@@ -102,7 +99,7 @@ class TestJediTyper(TransformTest):
self
.
assertIn
((
'func'
,
(
1
,
0
)),
types
)
self
.
assertIn
((
'func'
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
'func'
,
(
1
,
0
)))
variables
=
types
.
pop
((
'func'
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'
int'
,
'str'
]),
'i
'
:
set
([
'int'
])},
variables
)
self
.
assertEqual
({
'a'
:
set
([
'
float'
,
'int'
,
'str'
]),
'b
'
:
set
([
'int'
])},
variables
)
def
_test_typing_function_char_loop
(
self
):
def
_test_typing_function_char_loop
(
self
):
code
=
'''
\
code
=
'''
\
...
@@ -120,6 +117,92 @@ class TestJediTyper(TransformTest):
...
@@ -120,6 +117,92 @@ class TestJediTyper(TransformTest):
self
.
assertFalse
(
types
)
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'int'
]),
'i'
:
set
([
'int'
])},
variables
)
self
.
assertEqual
({
'a'
:
set
([
'int'
]),
'i'
:
set
([
'int'
])},
variables
)
def
test_typing_global_list
(
self
):
code
=
'''
\
a = [x for x in range(10)]
b = list(range(10))
c = a + b
d = [0]*10
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
None
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
None
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'list'
]),
'b'
:
set
([
'list'
]),
'c'
:
set
([
'list'
]),
'd'
:
set
([
'list'
])},
variables
)
def
test_typing_function_list
(
self
):
code
=
'''
\
def func(x):
a = [[], []]
b = [0]* 10 + a
c = a[0]
print(func([0]*100))
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
'func'
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
'func'
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'list'
]),
'b'
:
set
([
'list'
]),
'c'
:
set
([
'list'
]),
'x'
:
set
([
'list'
])},
variables
)
def
test_typing_global_dict
(
self
):
code
=
'''
\
a = dict()
b = {i: i**2 for i in range(10)}
c = a
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
None
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
None
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'dict'
]),
'b'
:
set
([
'dict'
]),
'c'
:
set
([
'dict'
])},
variables
)
def
test_typing_function_dict
(
self
):
code
=
'''
\
def func(x):
a = dict()
b = {i: i**2 for i in range(10)}
c = x
print(func({1:2, 'x':7}))
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
'func'
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
'func'
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'dict'
]),
'b'
:
set
([
'dict'
]),
'c'
:
set
([
'dict'
]),
'x'
:
set
([
'dict'
])},
variables
)
def
test_typing_global_set
(
self
):
code
=
'''
\
a = set()
# b = {i for i in range(10)} # jedi does not support set comprehension yet
c = a
d = {1,2,3}
e = a | b
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
None
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
None
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'set'
]),
'c'
:
set
([
'set'
]),
'd'
:
set
([
'set'
]),
'e'
:
set
([
'set'
])},
variables
)
def
test_typing_function_set
(
self
):
code
=
'''
\
def func(x):
a = set()
# b = {i for i in range(10)} # jedi does not support set comprehension yet
c = a
d = a | b
print(func({1,2,3}))
'''
types
=
self
.
_test
(
code
)
self
.
assertIn
((
'func'
,
(
1
,
0
)),
types
)
variables
=
types
.
pop
((
'func'
,
(
1
,
0
)))
self
.
assertFalse
(
types
)
self
.
assertEqual
({
'a'
:
set
([
'set'
]),
'c'
:
set
([
'set'
]),
'd'
:
set
([
'set'
]),
'x'
:
set
([
'set'
])},
variables
)
class
TestTypeInjection
(
TestJediTyper
):
class
TestTypeInjection
(
TestJediTyper
):
"""
"""
...
...
Tools/jedi-typer.py
View file @
e1f739f5
...
@@ -6,9 +6,12 @@ from __future__ import absolute_import
...
@@ -6,9 +6,12 @@ from __future__ import absolute_import
from
io
import
open
from
io
import
open
from
collections
import
defaultdict
from
collections
import
defaultdict
from
itertools
import
chain
from
jedi
import
Script
import
jedi
from
jedi.parser.representation
import
Function
,
Module
,
Import
from
jedi.parser.tree
import
Module
,
ImportName
from
jedi.evaluate.representation
import
Function
,
Instance
,
Class
from
jedi.evaluate.iterable
import
ArrayMixin
,
GeneratorComprehension
from
Cython.Utils
import
open_source_file
from
Cython.Utils
import
open_source_file
...
@@ -26,33 +29,42 @@ def analyse(source_path=None, code=None):
...
@@ -26,33 +29,42 @@ def analyse(source_path=None, code=None):
"""
"""
if
not
source_path
and
code
is
None
:
if
not
source_path
and
code
is
None
:
raise
ValueError
(
"Either 'source_path' or 'code' is required."
)
raise
ValueError
(
"Either 'source_path' or 'code' is required."
)
script
=
Script
(
source
=
code
,
path
=
source_path
)
evaluator
=
script
.
_evaluator
scoped_names
=
{}
scoped_names
=
{}
for
statements
in
script
.
_parser
.
module
().
used_names
.
values
():
statement_iter
=
jedi
.
names
(
source
=
code
,
path
=
source_path
,
all_scopes
=
True
)
for
statement
in
statements
:
scope
=
statement
.
parent
for
statement
in
statement_iter
:
while
not
isinstance
(
scope
,
(
Function
,
Module
)):
parent
=
statement
.
parent
()
scope
=
scope
.
parent
scope
=
parent
.
_definition
# hack: work around current Jedi problem with global module variables
evaluator
=
statement
.
_evaluator
if
not
hasattr
(
scope
,
'scope_names_generator'
):
continue
# skip function/generator definitions, class definitions, and module imports
statement_names
=
statement
.
get_defined_names
()
if
any
(
isinstance
(
statement
.
_definition
,
t
)
for
t
in
[
Function
,
Class
,
ImportName
]):
if
not
statement_names
:
continue
continue
key
=
(
None
if
isinstance
(
scope
,
Module
)
else
str
(
parent
.
name
),
scope
.
start_pos
)
key
=
(
None
if
isinstance
(
scope
,
Module
)
else
str
(
scope
.
name
),
scope
.
start_pos
)
try
:
try
:
names
=
scoped_names
[
key
]
names
=
scoped_names
[
key
]
except
KeyError
:
except
KeyError
:
names
=
scoped_names
[
key
]
=
defaultdict
(
set
)
names
=
scoped_names
[
key
]
=
defaultdict
(
set
)
for
name
in
statement_names
:
position
=
statement
.
start_pos
if
statement
.
name
in
names
else
None
for
name_type
in
evaluator
.
find_types
(
scope
,
name
):
if
isinstance
(
name_type
,
Import
):
for
name_type
in
evaluator
.
find_types
(
scope
,
statement
.
name
,
position
=
position
,
search_global
=
True
):
type_name
=
'object'
if
isinstance
(
name_type
,
Instance
):
else
:
if
isinstance
(
name_type
.
base
,
Class
):
type_name
=
name_type
.
name
type_name
=
'object'
names
[
str
(
name
)].
add
(
type_name
)
else
:
type_name
=
name_type
.
base
.
obj
.
__name__
elif
isinstance
(
name_type
,
ArrayMixin
):
type_name
=
name_type
.
type
elif
isinstance
(
name_type
,
GeneratorComprehension
):
type_name
=
None
else
:
try
:
type_name
=
type
(
name_type
.
obj
).
__name__
except
AttributeError
as
error
:
type_name
=
None
if
type_name
is
not
None
:
names
[
str
(
statement
.
name
)].
add
(
type_name
)
return
scoped_names
return
scoped_names
...
@@ -72,13 +84,14 @@ def inject_types(source_path, types, type_map=default_type_map, mode='python'):
...
@@ -72,13 +84,14 @@ def inject_types(source_path, types, type_map=default_type_map, mode='python'):
for
line_no
,
line
in
enumerate
(
f
,
1
):
for
line_no
,
line
in
enumerate
(
f
,
1
):
if
line_no
in
col_and_types_by_line
:
if
line_no
in
col_and_types_by_line
:
col
,
scope
,
types
=
col_and_types_by_line
[
line_no
]
col
,
scope
,
types
=
col_and_types_by_line
[
line_no
]
types
=
', '
.
join
(
"%s='%s'"
%
(
name
,
type_map
.
get
(
type_name
,
type_name
))
if
types
:
for
name
,
type_name
in
types
)
types
=
', '
.
join
(
"%s='%s'"
%
(
name
,
type_map
.
get
(
type_name
,
type_name
))
if
scope
is
None
:
for
name
,
type_name
in
types
)
type_decl
=
u'{indent}cython.declare({types})
\
n
'
if
scope
is
None
:
else
:
type_decl
=
u'{indent}cython.declare({types})
\
n
'
type_decl
=
u'{indent}@cython.locals({types})
\
n
'
else
:
lines
.
append
(
type_decl
.
format
(
indent
=
' '
*
col
,
types
=
types
))
type_decl
=
u'{indent}@cython.locals({types})
\
n
'
lines
.
append
(
type_decl
.
format
(
indent
=
' '
*
col
,
types
=
types
))
lines
.
append
(
line
)
lines
.
append
(
line
)
return
lines
return
lines
...
...
runtests.py
View file @
e1f739f5
...
@@ -1943,7 +1943,7 @@ def runtests(options, cmd_args, coverage=None):
...
@@ -1943,7 +1943,7 @@ def runtests(options, cmd_args, coverage=None):
try:
try:
import jedi
import jedi
if not ([0,
8, 1] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) < [0, 9]
):
if not ([0,
9] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0')))
):
raise ImportError
raise ImportError
except (ImportError, AttributeError, TypeError):
except (ImportError, AttributeError, TypeError):
exclude_selectors.append(RegExSelector('Jedi'))
exclude_selectors.append(RegExSelector('Jedi'))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment