diff options
author | Tzer-jen Wei <tzerjen@gmail.com> | 2015-07-07 17:06:26 +0800 |
---|---|---|
committer | Tzer-jen Wei <tzerjen@gmail.com> | 2015-07-28 18:23:33 +0800 |
commit | 628760c739f1a84b9589b74f26f094e1354a6f11 (patch) | |
tree | 890e05f58ff6bc82c0f5f64c6c0364286ce95e39 /Tools | |
parent | 19fa1c9890c3c9ee7611de6339781d29f2b90db5 (diff) | |
download | cython-628760c739f1a84b9589b74f26f094e1354a6f11.tar.gz |
Experimental support for jedi 0.9.0
Diffstat (limited to 'Tools')
-rw-r--r-- | Tools/jedi-typer.py | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/Tools/jedi-typer.py b/Tools/jedi-typer.py index 576511726..668449305 100644 --- a/Tools/jedi-typer.py +++ b/Tools/jedi-typer.py @@ -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 |