mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +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
|
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)
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user