Remove the old typing module support in favor of the new one

This commit is contained in:
Dave Halter
2018-09-29 01:08:20 +02:00
parent 6539031d5a
commit d6bdb206c8
4 changed files with 8 additions and 216 deletions

View File

@@ -1,104 +0,0 @@
"""
This module is not intended to be used in jedi, rather it will be fed to the
jedi-parser to replace classes in the typing module
"""
try:
from collections import abc
except ImportError:
# python 2
import collections as abc
def factory(typing_name, indextypes):
class Iterable(abc.Iterable):
def __iter__(self):
while True:
yield indextypes[0]()
class Iterator(Iterable, abc.Iterator):
def next(self):
""" needed for python 2 """
return self.__next__()
def __next__(self):
return indextypes[0]()
class Sequence(abc.Sequence):
def __getitem__(self, index):
return indextypes[0]()
class MutableSequence(Sequence, abc.MutableSequence):
pass
class List(MutableSequence, list):
pass
class Tuple(Sequence, tuple):
def __getitem__(self, index):
if indextypes[1] == Ellipsis:
# https://www.python.org/dev/peps/pep-0484/#the-typing-module
# Tuple[int, ...] means a tuple of ints of indetermined length
return indextypes[0]()
else:
return indextypes[index]()
class AbstractSet(Iterable, abc.Set):
pass
class MutableSet(AbstractSet, abc.MutableSet):
pass
class KeysView(Iterable, abc.KeysView):
pass
class ValuesView(abc.ValuesView):
def __iter__(self):
while True:
yield indextypes[1]()
class ItemsView(abc.ItemsView):
def __iter__(self):
while True:
yield (indextypes[0](), indextypes[1]())
class Mapping(Iterable, abc.Mapping):
def __getitem__(self, item):
return indextypes[1]()
def keys(self):
return KeysView()
def values(self):
return ValuesView()
def items(self):
return ItemsView()
class MutableMapping(Mapping, abc.MutableMapping):
pass
class Dict(MutableMapping, dict):
pass
class DefaultDict(MutableMapping, dict):
pass
dct = {
"Sequence": Sequence,
"MutableSequence": MutableSequence,
"List": List,
"Iterable": Iterable,
"Iterator": Iterator,
"AbstractSet": AbstractSet,
"MutableSet": MutableSet,
"Mapping": Mapping,
"MutableMapping": MutableMapping,
"Tuple": Tuple,
"KeysView": KeysView,
"ItemsView": ItemsView,
"ValuesView": ValuesView,
"Dict": Dict,
"DefaultDict": DefaultDict,
}
return dct[typing_name]

View File

@@ -19,21 +19,17 @@ x support for type hint comments for functions, `# type: (int, str) -> int`.
See comment from Guido https://github.com/davidhalter/jedi/issues/662 See comment from Guido https://github.com/davidhalter/jedi/issues/662
""" """
import os
import re import re
from parso import ParserSyntaxError, parse, split_lines from parso import ParserSyntaxError, parse
from parso.python import tree
from jedi._compatibility import unicode, force_unicode from jedi._compatibility import force_unicode
from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate import compiled from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
from jedi.evaluate.base_context import NO_CONTEXTS, ContextSet from jedi.evaluate.context import ClassContext
from jedi.evaluate.lazy_context import LazyTreeContext
from jedi.evaluate.context import ModuleContext, ClassContext
from jedi.evaluate.context.typing import TypeVar, AnnotatedClass, \ from jedi.evaluate.context.typing import TypeVar, AnnotatedClass, \
AnnotatedSubClass, AbstractAnnotatedClass AbstractAnnotatedClass
from jedi.evaluate.helpers import is_string, execute_evaluated from jedi.evaluate.helpers import is_string
from jedi import debug from jedi import debug
from jedi import parser_utils from jedi import parser_utils
@@ -356,91 +352,6 @@ def _infer_type_vars(annotation_context, context_set):
return type_var_dict return type_var_dict
_typing_module = None
_typing_module_code_lines = None
class TypingModuleContext(ModuleContext):
"""
TODO this is currently used for recursion checks. We should just completely
refactor the typing module integration.
"""
pass
def _get_typing_replacement_module(grammar):
"""
The idea is to return our jedi replacement for the PEP-0484 typing module
as discussed at https://github.com/davidhalter/jedi/issues/663
"""
global _typing_module, _typing_module_code_lines
if _typing_module is None:
typing_path = \
os.path.abspath(os.path.join(__file__, "../jedi_typing.py"))
with open(typing_path) as f:
code = unicode(f.read())
_typing_module = grammar.parse(code)
_typing_module_code_lines = split_lines(code, keepends=True)
return _typing_module, _typing_module_code_lines
def py__simple_getitem__(context, typ, node):
if not typ.get_root_context().name.string_name == "typing":
return None
# we assume that any class using [] in a module called
# "typing" with a name for which we have a replacement
# should be replaced by that class. This is not 100%
# airtight but I don't have a better idea to check that it's
# actually the PEP-0484 typing module and not some other
if node.type == "subscriptlist":
nodes = node.children[::2] # skip the commas
else:
nodes = [node]
del node
nodes = [_fix_forward_reference(context, node) for node in nodes]
type_name = typ.name.string_name
# hacked in Union and Optional, since it's hard to do nicely in parsed code
if type_name in ("Union", '_Union'):
# In Python 3.6 it's still called typing.Union but it's an instance
# called _Union.
return ContextSet.from_sets(context.eval_node(node) for node in nodes)
if type_name in ("Optional", '_Optional'):
# Here we have the same issue like in Union. Therefore we also need to
# check for the instance typing._Optional (Python 3.6).
return context.eval_node(nodes[0])
module_node, code_lines = _get_typing_replacement_module(context.evaluator.latest_grammar)
typing = TypingModuleContext(
context.evaluator,
module_node=module_node,
path=None,
code_lines=code_lines,
)
factories = typing.py__getattribute__("factory")
assert len(factories) == 1
factory = list(factories)[0]
assert factory
function_body_nodes = factory.tree_node.children[4].children
valid_classnames = set(child.name.value
for child in function_body_nodes
if isinstance(child, tree.Class))
if type_name not in valid_classnames:
return None
compiled_classname = compiled.create_simple_object(context.evaluator, type_name)
from jedi.evaluate.context.iterable import FakeSequence
args = FakeSequence(
context.evaluator,
u'tuple',
[LazyTreeContext(context, n) for n in nodes]
)
result = execute_evaluated(factory, compiled_classname, args)
return result
def find_type_from_comment_hint_for(context, node, name): def find_type_from_comment_hint_for(context, node, name):
return _find_type_from_comment_hint(context, node, node.children[1], name) return _find_type_from_comment_hint(context, node, node.children[1], name)

View File

@@ -117,8 +117,7 @@ class ExecutionRecursionDetector(object):
module = execution.get_root_context() module = execution.get_root_context()
from jedi.evaluate.pep0484 import TypingModuleContext if module == self._evaluator.builtins_module:
if module == self._evaluator.builtins_module or isinstance(module, TypingModuleContext):
# We have control over builtins so we know they are not recursing # We have control over builtins so we know they are not recursing
# like crazy. Therefore we just let them execute always, because # like crazy. Therefore we just let them execute always, because
# they usually just help a lot with getting good results. # they usually just help a lot with getting good results.

View File

@@ -153,21 +153,7 @@ def eval_trailer(context, base_contexts, trailer):
if trailer_op == '[': if trailer_op == '[':
trailer_op, node, _ = trailer.children trailer_op, node, _ = trailer.children
return base_contexts.get_item(
# TODO It's kind of stupid to cast this from a context set to a set.
foo = set(base_contexts)
# special case: PEP0484 typing module, see
# https://github.com/davidhalter/jedi/issues/663
result = NO_CONTEXTS
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:
foo.remove(typ)
result |= typing_module_types
return result | base_contexts.get_item(
eval_subscript_list(context.evaluator, context, node), eval_subscript_list(context.evaluator, context, node),
ContextualizedNode(context, trailer) ContextualizedNode(context, trailer)
) )