mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 05:54:25 +08:00
Remove the old typing module support in favor of the new one
This commit is contained in:
@@ -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]
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from parso import ParserSyntaxError, parse, split_lines
|
||||
from parso.python import tree
|
||||
from parso import ParserSyntaxError, parse
|
||||
|
||||
from jedi._compatibility import unicode, force_unicode
|
||||
from jedi._compatibility import force_unicode
|
||||
from jedi.evaluate.cache import evaluator_method_cache
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate.base_context import NO_CONTEXTS, ContextSet
|
||||
from jedi.evaluate.lazy_context import LazyTreeContext
|
||||
from jedi.evaluate.context import ModuleContext, ClassContext
|
||||
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
|
||||
from jedi.evaluate.context import ClassContext
|
||||
from jedi.evaluate.context.typing import TypeVar, AnnotatedClass, \
|
||||
AnnotatedSubClass, AbstractAnnotatedClass
|
||||
from jedi.evaluate.helpers import is_string, execute_evaluated
|
||||
AbstractAnnotatedClass
|
||||
from jedi.evaluate.helpers import is_string
|
||||
from jedi import debug
|
||||
from jedi import parser_utils
|
||||
|
||||
@@ -356,91 +352,6 @@ def _infer_type_vars(annotation_context, context_set):
|
||||
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):
|
||||
return _find_type_from_comment_hint(context, node, node.children[1], name)
|
||||
|
||||
|
||||
@@ -117,8 +117,7 @@ class ExecutionRecursionDetector(object):
|
||||
|
||||
module = execution.get_root_context()
|
||||
|
||||
from jedi.evaluate.pep0484 import TypingModuleContext
|
||||
if module == self._evaluator.builtins_module or isinstance(module, TypingModuleContext):
|
||||
if module == self._evaluator.builtins_module:
|
||||
# We have control over builtins so we know they are not recursing
|
||||
# like crazy. Therefore we just let them execute always, because
|
||||
# they usually just help a lot with getting good results.
|
||||
|
||||
@@ -153,21 +153,7 @@ def eval_trailer(context, base_contexts, trailer):
|
||||
|
||||
if trailer_op == '[':
|
||||
trailer_op, node, _ = trailer.children
|
||||
|
||||
# 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(
|
||||
return base_contexts.get_item(
|
||||
eval_subscript_list(context.evaluator, context, node),
|
||||
ContextualizedNode(context, trailer)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user