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):
_TUPLE_LIKE = 'testlist_star_expr', 'testlist', 'subscriptlist'
mapping = {'(': u'tuple',
'[': u'list',
'{': u'set'}
@@ -282,7 +283,7 @@ class SequenceLiteralContext(Sequence):
self.atom = atom
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'
else:
self.array_type = SequenceLiteralContext.mapping[atom.children[0]]
@@ -336,7 +337,7 @@ class SequenceLiteralContext(Sequence):
def _items(self):
c = self.atom.children
if self.atom.type in ('testlist_star_expr', 'testlist'):
if self.atom.type in self._TUPLE_LIKE:
return c[::2]
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
contexts.
"""
from parso.python import tree
from jedi import debug
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()
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:
return TypingProxy(context)
return TypingProxy(name, context)
elif name in _TYPE_ALIAS_TYPES:
# TODO
raise NotImplementedError
@@ -45,31 +66,22 @@ def check(context, name):
return context
class _TypingBase(object):
def __init__(self, typing_context):
self._class_context = typing_context
class TypingProxy(_TypingBase):
py__simple_getitem__ = None
def __getattr__(self, name):
return getattr(self._class_context, name)
class TypingProxy(object):
def py__getitem__(self, index_context, contextualized_node):
return TypingProxyWithIndex(self._class_context, index_context)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._class_context)
return ContextSet(TypingProxyWithIndex(self._name, self._context, index_context))
class _WithIndexBase(_TypingBase):
def __init__(self, class_context, index_context):
super(_WithIndexBase, self).__init__(class_context)
def __init__(self, name, class_context, index_context):
super(_WithIndexBase, self).__init__(name, class_context)
self._index_context = index_context
def __repr__(self):
return '%s(%s, %s)' % (
self.__class__.__name__,
self._class_context,
self._context,
self._index_context
)
@@ -80,12 +92,8 @@ class _WithIndexBase(_TypingBase):
class TypingProxyWithIndex(_WithIndexBase):
def __init__(self, typing_context, index_context):
self._class_context = typing_context
self._index_context = index_context
def execute_annotation(self):
name = self._class_context.py__name__()
name = self._name
if name == 'Union':
# This is kind of a special case, because we have Unions (in Jedi
# ContextSets).
@@ -93,17 +101,17 @@ class TypingProxyWithIndex(_WithIndexBase):
elif name == 'Optional':
# Optional is basically just saying it's either None or the actual
# type.
return ContextSet(self._class_context) \
return ContextSet(self._context) \
| ContextSet(builtin_from_name(self.evaluator, u'None'))
elif name == 'Type':
# The type is actually already given in the index_context
return ContextSet(self._index_context)
elif name == 'ClassVar':
# 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]
return cls(self._class_context, self._index_context)
return ContextSet(cls(name, self._context, self._index_context))
def _iter_over_arguments(maybe_tuple_context):
@@ -146,14 +154,14 @@ class Tuple(_ContainerBase):
return self._get_getitem_contexts(0)
else:
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
def py__getitem__(self):
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()

View File

@@ -21,9 +21,9 @@ from textwrap import dedent
from parso import parse, ParserSyntaxError
from jedi._compatibility import u
from jedi import debug
from jedi.evaluate.utils import indent_block
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, \
NO_CONTEXTS
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
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
# don't need to conform with the current grammar.
debug.dbg('Parse docstring code %s', string, color='BLUE')
grammar = module_context.evaluator.latest_grammar
try:
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))
return {FakeSequence(evaluator, array.array_type, values)}
else:
return execute_evaluated(array)
return array.execute_annotation()
@evaluator_method_cache()
@@ -288,6 +289,7 @@ def infer_param(execution_context, param):
class_context = execution_context.var_args.instance.class_context
types |= eval_docstring(class_context.py__doc__())
debug.dbg('Found param types for docstring %s', types, color='BLUE')
return types

View File

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

View File

@@ -35,5 +35,5 @@ class _PluginCallbacks(object):
plugin_manager = _PluginManager([
StdlibPlugin,
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, \
TreeNameDefinition
from jedi.evaluate.context import ModuleContext, FunctionContext, ClassContext
from jedi.evaluate.context.typing import TypingModuleWrapper
from jedi.evaluate.compiled import CompiledObject
from jedi.evaluate.syntax_tree import tree_name_to_contexts
from jedi.evaluate.utils import to_list
@@ -133,7 +134,7 @@ class TypeshedPlugin(BasePlugin):
)
import_name = import_names[-1]
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)
elif isinstance(parent_module_context, StubModuleContext):
map_ = _merge_create_stub_map(parent_module_context.py__path__())
@@ -152,9 +153,10 @@ class TypeshedPlugin(BasePlugin):
stub_module_context = StubOnlyModuleContext(
context_set, evaluator, stub_module_node, path, code_lines=[]
)
return ContextSet.from_iterable(
_merge_modules(context_set, stub_module_context)
)
modules = _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.
return context_set
return wrapper