Commit 628760c7 authored by Tzer-jen Wei's avatar Tzer-jen Wei

Experimental support for jedi 0.9.0

parent 19fa1c98
......@@ -6,9 +6,18 @@ from __future__ import absolute_import
from io import open
from collections import defaultdict
from jedi import Script
from jedi.parser.representation import Function, Module, Import
from itertools import chain
import re
import jedi
if list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) >= [0, 9, 0]:
__jedi_version__ = 9
from jedi.parser.tree import Module, Module as Import
from jedi.evaluate.representation import Function, Instance
else:
__jedi_version__ = 8
from jedi import Script
from jedi.parser.representation import Function, Module, Import
from Cython.Utils import open_source_file
......@@ -26,33 +35,54 @@ def analyse(source_path=None, code=None):
"""
if not source_path and code is None:
raise ValueError("Either 'source_path' or 'code' is required.")
script = Script(source=code, path=source_path)
evaluator = script._evaluator
scoped_names = {}
for statements in script._parser.module().used_names.values():
for statement in statements:
scope = statement.parent
if __jedi_version__ == 8:
script = Script(source=code, path=source_path)
evaluator = script._evaluator
statement_iter = chain.from_iterable(script._parser.module().used_names.values())
else:
statement_iter = jedi.names(source=code, path=source_path, all_scopes=True)
for statement in statement_iter:
if __jedi_version__ == 8:
parent = scope = statement.parent
while not isinstance(scope, (Function, Module)):
scope = scope.parent
parent = scope = scope.parent
# hack: work around current Jedi problem with global module variables
if not hasattr(scope, 'scope_names_generator'):
continue
statement_names = statement.get_defined_names()
if not statement_names:
continue
key = (None if isinstance(scope, Module) else str(scope.name), scope.start_pos)
try:
names = scoped_names[key]
except KeyError:
names = scoped_names[key] = defaultdict(set)
for name in statement_names:
for name_type in evaluator.find_types(scope, name):
if isinstance(name_type, Import):
else:
parent = statement.parent()
scope = parent._definition
evaluator = statement._evaluator
# original jedi-typer does not handle function definitions, so skip here as well
if isinstance(statement._definition, Function):
continue
statement_names = [statement.name]
key = (None if isinstance(scope, Module) else str(parent.name), scope.start_pos)
try:
names = scoped_names[key]
except KeyError:
names = scoped_names[key] = defaultdict(set)
for name in statement_names:
for name_type in evaluator.find_types(scope, name, search_global=True):
if isinstance(name_type, Import):
type_name = 'object'
else:
try:
if __jedi_version__ == 8:
type_name = name_type.name
else:
if isinstance(name_type, Instance):
type_name = name_type.base.obj.__name__
else:
type_name = type(name_type.obj).__name__
except AttributeError as error:
print(error)
type_name = 'object'
else:
type_name = name_type.name
names[str(name)].add(type_name)
names[str(name)].add(type_name)
return scoped_names
......@@ -72,13 +102,14 @@ def inject_types(source_path, types, type_map=default_type_map, mode='python'):
for line_no, line in enumerate(f, 1):
if line_no in col_and_types_by_line:
col, scope, types = col_and_types_by_line[line_no]
types = ', '.join("%s='%s'" % (name, type_map.get(type_name, type_name))
for name, type_name in types)
if scope is None:
type_decl = u'{indent}cython.declare({types})\n'
else:
type_decl = u'{indent}@cython.locals({types})\n'
lines.append(type_decl.format(indent=' '*col, types=types))
if types:
types = ', '.join("%s='%s'" % (name, type_map.get(type_name, type_name))
for name, type_name in types)
if scope is None:
type_decl = u'{indent}cython.declare({types})\n'
else:
type_decl = u'{indent}@cython.locals({types})\n'
lines.append(type_decl.format(indent=' '*col, types=types))
lines.append(line)
return lines
......
......@@ -1943,7 +1943,7 @@ def runtests(options, cmd_args, coverage=None):
try:
import jedi
if not ([0, 8, 1] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) < [0, 9]):
if not ([0, 8, 1] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) <= [0, 9, 0]):
raise ImportError
except (ImportError, AttributeError, TypeError):
exclude_selectors.append(RegExSelector('Jedi'))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment