1
0
forked from VimPlug/jedi

Fix the first issues with the new typing module implementation

This commit is contained in:
Dave Halter
2018-08-21 01:28:55 +02:00
parent 6ddc242746
commit 9fe9bed1c9
6 changed files with 52 additions and 38 deletions

View File

@@ -273,6 +273,7 @@ class GeneratorComprehension(ComprehensionMixin, GeneratorBase):
class SequenceLiteralContext(Sequence): class SequenceLiteralContext(Sequence):
_TUPLE_LIKE = 'testlist_star_expr', 'testlist', 'subscriptlist'
mapping = {'(': u'tuple', mapping = {'(': u'tuple',
'[': u'list', '[': u'list',
'{': u'set'} '{': u'set'}
@@ -282,7 +283,7 @@ class SequenceLiteralContext(Sequence):
self.atom = atom self.atom = atom
self._defining_context = defining_context self._defining_context = defining_context
if self.atom.type in ('testlist_star_expr', 'testlist'): if self.atom.type in self._TUPLE_LIKE:
self.array_type = u'tuple' self.array_type = u'tuple'
else: else:
self.array_type = SequenceLiteralContext.mapping[atom.children[0]] self.array_type = SequenceLiteralContext.mapping[atom.children[0]]
@@ -336,7 +337,7 @@ class SequenceLiteralContext(Sequence):
def _items(self): def _items(self):
c = self.atom.children c = self.atom.children
if self.atom.type in ('testlist_star_expr', 'testlist'): if self.atom.type in self._TUPLE_LIKE:
return c[::2] return c[::2]
array_node = c[1] array_node = c[1]

View File

@@ -3,6 +3,7 @@ We need to somehow work with the typing objects. Since the typing objects are
pretty bare we need to add all the Jedi customizations to make them work as pretty bare we need to add all the Jedi customizations to make them work as
contexts. contexts.
""" """
from parso.python import tree
from jedi import debug from jedi import debug
from jedi.evaluate.compiled import builtin_from_name from jedi.evaluate.compiled import builtin_from_name
@@ -13,10 +14,30 @@ _PROXY_TYPES = 'Optional Union Callable Type ClassVar Tuple Generic Protocol'.sp
_TYPE_ALIAS_TYPES = 'List Dict DefaultDict Set FrozenSet Counter Deque ChainMap'.split() _TYPE_ALIAS_TYPES = 'List Dict DefaultDict Set FrozenSet Counter Deque ChainMap'.split()
def check(context, name): class _TypingBase(object):
def __init__(self, name, typing_context):
self._name = name
self._context = typing_context
def __getattr__(self, name):
return getattr(self._context, name)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._context)
class TypingModuleWrapper(_TypingBase):
def py__getattribute__(self, name_or_str, *args, **kwargs):
result = self._context.py__getattribute__(name_or_str)
if kwargs.get('is_goto'):
return result
name = name_or_str.value if isinstance(name_or_str, tree.Name) else name_or_str
return ContextSet.from_iterable(_remap(c, name) for c in result)
def _remap(context, name):
if name in _PROXY_TYPES: if name in _PROXY_TYPES:
return TypingProxy(context) return TypingProxy(name, context)
elif name in _TYPE_ALIAS_TYPES: elif name in _TYPE_ALIAS_TYPES:
# TODO # TODO
raise NotImplementedError raise NotImplementedError
@@ -45,31 +66,22 @@ def check(context, name):
return context return context
class _TypingBase(object): class TypingProxy(_TypingBase):
def __init__(self, typing_context): py__simple_getitem__ = None
self._class_context = typing_context
def __getattr__(self, name):
return getattr(self._class_context, name)
class TypingProxy(object):
def py__getitem__(self, index_context, contextualized_node): def py__getitem__(self, index_context, contextualized_node):
return TypingProxyWithIndex(self._class_context, index_context) return ContextSet(TypingProxyWithIndex(self._name, self._context, index_context))
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._class_context)
class _WithIndexBase(_TypingBase): class _WithIndexBase(_TypingBase):
def __init__(self, class_context, index_context): def __init__(self, name, class_context, index_context):
super(_WithIndexBase, self).__init__(class_context) super(_WithIndexBase, self).__init__(name, class_context)
self._index_context = index_context self._index_context = index_context
def __repr__(self): def __repr__(self):
return '%s(%s, %s)' % ( return '%s(%s, %s)' % (
self.__class__.__name__, self.__class__.__name__,
self._class_context, self._context,
self._index_context self._index_context
) )
@@ -80,12 +92,8 @@ class _WithIndexBase(_TypingBase):
class TypingProxyWithIndex(_WithIndexBase): class TypingProxyWithIndex(_WithIndexBase):
def __init__(self, typing_context, index_context):
self._class_context = typing_context
self._index_context = index_context
def execute_annotation(self): def execute_annotation(self):
name = self._class_context.py__name__() name = self._name
if name == 'Union': if name == 'Union':
# This is kind of a special case, because we have Unions (in Jedi # This is kind of a special case, because we have Unions (in Jedi
# ContextSets). # ContextSets).
@@ -93,17 +101,17 @@ class TypingProxyWithIndex(_WithIndexBase):
elif name == 'Optional': elif name == 'Optional':
# Optional is basically just saying it's either None or the actual # Optional is basically just saying it's either None or the actual
# type. # type.
return ContextSet(self._class_context) \ return ContextSet(self._context) \
| ContextSet(builtin_from_name(self.evaluator, u'None')) | ContextSet(builtin_from_name(self.evaluator, u'None'))
elif name == 'Type': elif name == 'Type':
# The type is actually already given in the index_context # The type is actually already given in the index_context
return ContextSet(self._index_context) return ContextSet(self._index_context)
elif name == 'ClassVar': elif name == 'ClassVar':
# For now don't do anything here, ClassVars are always used. # For now don't do anything here, ClassVars are always used.
return self._class_context.execute_annotation() return self._context.execute_annotation()
cls = globals()[name] cls = globals()[name]
return cls(self._class_context, self._index_context) return ContextSet(cls(name, self._context, self._index_context))
def _iter_over_arguments(maybe_tuple_context): def _iter_over_arguments(maybe_tuple_context):
@@ -146,14 +154,14 @@ class Tuple(_ContainerBase):
return self._get_getitem_contexts(0) return self._get_getitem_contexts(0)
else: else:
if isinstance(index, int): if isinstance(index, int):
return self._get_getitem_contexts(index) return self._get_getitem_contexts(index).execute_annotation()
debug.dbg('The getitem is') debug.dbg('The getitem type on Tuple was %s' % index)
return NO_CONTEXTS return NO_CONTEXTS
def py__getitem__(self): def py__getitem__(self):
if self._is_homogenous(): if self._is_homogenous():
return self._get_getitem_contexts(0) return self._get_getitem_contexts(0).execute_annotation()
return self._execute_annotations_for_all_indexes() return self._execute_annotations_for_all_indexes()

View File

@@ -21,9 +21,9 @@ from textwrap import dedent
from parso import parse, ParserSyntaxError from parso import parse, ParserSyntaxError
from jedi._compatibility import u from jedi._compatibility import u
from jedi import debug
from jedi.evaluate.utils import indent_block from jedi.evaluate.utils import indent_block
from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.helpers import execute_evaluated
from jedi.evaluate.base_context import iterator_to_context_set, ContextSet, \ from jedi.evaluate.base_context import iterator_to_context_set, ContextSet, \
NO_CONTEXTS NO_CONTEXTS
from jedi.evaluate.lazy_context import LazyKnownContexts from jedi.evaluate.lazy_context import LazyKnownContexts
@@ -203,6 +203,7 @@ def _evaluate_for_statement_string(module_context, string):
# Take the default grammar here, if we load the Python 2.7 grammar here, it # Take the default grammar here, if we load the Python 2.7 grammar here, it
# will be impossible to use `...` (Ellipsis) as a token. Docstring types # will be impossible to use `...` (Ellipsis) as a token. Docstring types
# don't need to conform with the current grammar. # don't need to conform with the current grammar.
debug.dbg('Parse docstring code %s', string, color='BLUE')
grammar = module_context.evaluator.latest_grammar grammar = module_context.evaluator.latest_grammar
try: try:
module = grammar.parse(code.format(indent_block(string)), error_recovery=False) module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
@@ -262,7 +263,7 @@ def _execute_array_values(evaluator, array):
values.append(LazyKnownContexts(objects)) values.append(LazyKnownContexts(objects))
return {FakeSequence(evaluator, array.array_type, values)} return {FakeSequence(evaluator, array.array_type, values)}
else: else:
return execute_evaluated(array) return array.execute_annotation()
@evaluator_method_cache() @evaluator_method_cache()
@@ -288,6 +289,7 @@ def infer_param(execution_context, param):
class_context = execution_context.var_args.instance.class_context class_context = execution_context.var_args.instance.class_context
types |= eval_docstring(class_context.py__doc__()) types |= eval_docstring(class_context.py__doc__())
debug.dbg('Found param types for docstring %s', types, color='BLUE')
return types return types

View File

@@ -160,6 +160,7 @@ def eval_trailer(context, base_contexts, trailer):
# https://github.com/davidhalter/jedi/issues/663 # https://github.com/davidhalter/jedi/issues/663
result = ContextSet() result = ContextSet()
for typ in list(foo): for typ in list(foo):
continue
if isinstance(typ, (ClassContext, TreeInstance)): if isinstance(typ, (ClassContext, TreeInstance)):
typing_module_types = pep0484.py__simple_getitem__(context, typ, node) typing_module_types = pep0484.py__simple_getitem__(context, typ, node)
if typing_module_types is not None: if typing_module_types is not None:
@@ -678,7 +679,7 @@ def eval_subscript_list(evaluator, context, index):
return ContextSet(iterable.Slice(context, *result)) return ContextSet(iterable.Slice(context, *result))
elif index.type == 'subscriptlist': elif index.type == 'subscriptlist':
return NO_CONTEXTS return ContextSet(iterable.SequenceLiteralContext(evaluator, context, index))
# No slices # No slices
return context.eval_node(index) return context.eval_node(index)

View File

@@ -35,5 +35,5 @@ class _PluginCallbacks(object):
plugin_manager = _PluginManager([ plugin_manager = _PluginManager([
StdlibPlugin, StdlibPlugin,
FlaskPlugin, FlaskPlugin,
#TypeshedPlugin, TypeshedPlugin,
]) ])

View File

@@ -10,6 +10,7 @@ from jedi.evaluate.base_context import ContextSet, iterator_to_context_set
from jedi.evaluate.filters import AbstractTreeName, ParserTreeFilter, \ from jedi.evaluate.filters import AbstractTreeName, ParserTreeFilter, \
TreeNameDefinition TreeNameDefinition
from jedi.evaluate.context import ModuleContext, FunctionContext, ClassContext from jedi.evaluate.context import ModuleContext, FunctionContext, ClassContext
from jedi.evaluate.context.typing import TypingModuleWrapper
from jedi.evaluate.compiled import CompiledObject from jedi.evaluate.compiled import CompiledObject
from jedi.evaluate.syntax_tree import tree_name_to_contexts from jedi.evaluate.syntax_tree import tree_name_to_contexts
from jedi.evaluate.utils import to_list from jedi.evaluate.utils import to_list
@@ -133,7 +134,7 @@ class TypeshedPlugin(BasePlugin):
) )
import_name = import_names[-1] import_name = import_names[-1]
map_ = None map_ = None
if len(import_names) == 1 and import_name != 'typing': if len(import_names) == 1:
map_ = self._cache_stub_file_map(evaluator.grammar.version_info) map_ = self._cache_stub_file_map(evaluator.grammar.version_info)
elif isinstance(parent_module_context, StubModuleContext): elif isinstance(parent_module_context, StubModuleContext):
map_ = _merge_create_stub_map(parent_module_context.py__path__()) map_ = _merge_create_stub_map(parent_module_context.py__path__())
@@ -152,9 +153,10 @@ class TypeshedPlugin(BasePlugin):
stub_module_context = StubOnlyModuleContext( stub_module_context = StubOnlyModuleContext(
context_set, evaluator, stub_module_node, path, code_lines=[] context_set, evaluator, stub_module_node, path, code_lines=[]
) )
return ContextSet.from_iterable( modules = _merge_modules(context_set, stub_module_context)
_merge_modules(context_set, stub_module_context) if import_names == ('typing',):
) modules = [TypingModuleWrapper('typing', m) for m in modules]
return ContextSet.from_iterable(modules)
# If no stub is found, just return the default. # If no stub is found, just return the default.
return context_set return context_set
return wrapper return wrapper