mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
Merge with master
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
|
|
||||||
from jedi._compatibility import zip_longest
|
from jedi._compatibility import zip_longest
|
||||||
@@ -28,31 +30,82 @@ def try_iter_content(types, depth=0):
|
|||||||
try_iter_content(lazy_context.infer(), depth + 1)
|
try_iter_content(lazy_context.infer(), depth + 1)
|
||||||
|
|
||||||
|
|
||||||
class AbstractArguments(object):
|
def repack_with_argument_clinic(string, keep_arguments_param=False):
|
||||||
context = None
|
"""
|
||||||
argument_node = None
|
Transforms a function or method with arguments to the signature that is
|
||||||
trailer = None
|
given as an argument clinic notation.
|
||||||
|
|
||||||
def eval_argument_clinic(self, parameters):
|
Argument clinic is part of CPython and used for all the functions that are
|
||||||
|
implemented in C (Python 3.7):
|
||||||
|
|
||||||
|
str.split.__text_signature__
|
||||||
|
# Results in: '($self, /, sep=None, maxsplit=-1)'
|
||||||
|
"""
|
||||||
|
clinic_args = list(_parse_argument_clinic(string))
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if keep_arguments_param:
|
||||||
|
arguments = kwargs['arguments']
|
||||||
|
else:
|
||||||
|
arguments = kwargs.pop('arguments')
|
||||||
|
try:
|
||||||
|
args += tuple(_iterate_argument_clinic(arguments, clinic_args))
|
||||||
|
except ValueError:
|
||||||
|
return NO_CONTEXTS
|
||||||
|
else:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def _iterate_argument_clinic(arguments, parameters):
|
||||||
"""Uses a list with argument clinic information (see PEP 436)."""
|
"""Uses a list with argument clinic information (see PEP 436)."""
|
||||||
iterator = self.unpack()
|
iterator = arguments.unpack()
|
||||||
for i, (name, optional, allow_kwargs) in enumerate(parameters):
|
for i, (name, optional, allow_kwargs) in enumerate(parameters):
|
||||||
key, argument = next(iterator, (None, None))
|
key, argument = next(iterator, (None, None))
|
||||||
if key is not None:
|
if key is not None:
|
||||||
raise NotImplementedError
|
debug.warning('Keyword arguments in argument clinic are currently not supported.')
|
||||||
|
raise ValueError
|
||||||
if argument is None and not optional:
|
if argument is None and not optional:
|
||||||
debug.warning('TypeError: %s expected at least %s arguments, got %s',
|
debug.warning('TypeError: %s expected at least %s arguments, got %s',
|
||||||
name, len(parameters), i)
|
name, len(parameters), i)
|
||||||
raise ValueError
|
raise ValueError
|
||||||
values = NO_CONTEXTS if argument is None else argument.infer()
|
|
||||||
|
|
||||||
if not values and not optional:
|
context_set = NO_CONTEXTS if argument is None else argument.infer()
|
||||||
|
|
||||||
|
if not context_set and not optional:
|
||||||
# For the stdlib we always want values. If we don't get them,
|
# For the stdlib we always want values. If we don't get them,
|
||||||
# that's ok, maybe something is too hard to resolve, however,
|
# that's ok, maybe something is too hard to resolve, however,
|
||||||
# we will not proceed with the evaluation of that function.
|
# we will not proceed with the evaluation of that function.
|
||||||
debug.warning('argument_clinic "%s" not resolvable.', name)
|
debug.warning('argument_clinic "%s" not resolvable.', name)
|
||||||
raise ValueError
|
raise ValueError
|
||||||
yield values
|
yield context_set
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_argument_clinic(string):
|
||||||
|
allow_kwargs = False
|
||||||
|
optional = False
|
||||||
|
while string:
|
||||||
|
# Optional arguments have to begin with a bracket. And should always be
|
||||||
|
# at the end of the arguments. This is therefore not a proper argument
|
||||||
|
# clinic implementation. `range()` for exmple allows an optional start
|
||||||
|
# value at the beginning.
|
||||||
|
match = re.match('(?:(?:(\[),? ?|, ?|)(\w+)|, ?/)\]*', string)
|
||||||
|
string = string[len(match.group(0)):]
|
||||||
|
if not match.group(2): # A slash -> allow named arguments
|
||||||
|
allow_kwargs = True
|
||||||
|
continue
|
||||||
|
optional = optional or bool(match.group(1))
|
||||||
|
word = match.group(2)
|
||||||
|
yield (word, optional, allow_kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractArguments(object):
|
||||||
|
context = None
|
||||||
|
argument_node = None
|
||||||
|
trailer = None
|
||||||
|
|
||||||
def eval_all(self, funcdef=None):
|
def eval_all(self, funcdef=None):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ Note that this module exists only to implement very specific functionality in
|
|||||||
the standard library. The usual way to understand the standard library is the
|
the standard library. The usual way to understand the standard library is the
|
||||||
compiled module that returns the types for C-builtins.
|
compiled module that returns the types for C-builtins.
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
|
|
||||||
import parso
|
import parso
|
||||||
|
|
||||||
from jedi._compatibility import force_unicode
|
from jedi._compatibility import force_unicode
|
||||||
from jedi.plugins.base import BasePlugin
|
from jedi.plugins.base import BasePlugin
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.evaluate.arguments import ValuesArguments
|
from jedi.evaluate.arguments import ValuesArguments, repack_with_argument_clinic
|
||||||
from jedi.evaluate import analysis
|
from jedi.evaluate import analysis
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate.context.instance import \
|
from jedi.evaluate.context.instance import \
|
||||||
@@ -85,8 +83,6 @@ class StdlibPlugin(BasePlugin):
|
|||||||
if import_names == ('os', 'path'):
|
if import_names == ('os', 'path'):
|
||||||
return parent_module_context.py__getattribute__('path')
|
return parent_module_context.py__getattribute__('path')
|
||||||
return callback(evaluator, import_names, parent_module_context, sys_path)
|
return callback(evaluator, import_names, parent_module_context, sys_path)
|
||||||
|
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@@ -103,41 +99,21 @@ def argument_clinic(string, want_obj=False, want_context=False, want_arguments=F
|
|||||||
"""
|
"""
|
||||||
Works like Argument Clinic (PEP 436), to validate function params.
|
Works like Argument Clinic (PEP 436), to validate function params.
|
||||||
"""
|
"""
|
||||||
clinic_args = []
|
|
||||||
allow_kwargs = False
|
|
||||||
optional = False
|
|
||||||
while string:
|
|
||||||
# Optional arguments have to begin with a bracket. And should always be
|
|
||||||
# at the end of the arguments. This is therefore not a proper argument
|
|
||||||
# clinic implementation. `range()` for exmple allows an optional start
|
|
||||||
# value at the beginning.
|
|
||||||
match = re.match('(?:(?:(\[),? ?|, ?|)(\w+)|, ?/)\]*', string)
|
|
||||||
string = string[len(match.group(0)):]
|
|
||||||
if not match.group(2): # A slash -> allow named arguments
|
|
||||||
allow_kwargs = True
|
|
||||||
continue
|
|
||||||
optional = optional or bool(match.group(1))
|
|
||||||
word = match.group(2)
|
|
||||||
clinic_args.append((word, optional, allow_kwargs))
|
|
||||||
|
|
||||||
def f(func):
|
def f(func):
|
||||||
def wrapper(evaluator, obj, arguments):
|
@repack_with_argument_clinic(string, keep_arguments_param=True)
|
||||||
|
def wrapper(evaluator, obj, *args, **kwargs):
|
||||||
|
arguments = kwargs.pop('arguments')
|
||||||
|
assert not kwargs # Python 2...
|
||||||
debug.dbg('builtin start %s' % obj, color='MAGENTA')
|
debug.dbg('builtin start %s' % obj, color='MAGENTA')
|
||||||
result = NO_CONTEXTS
|
result = NO_CONTEXTS
|
||||||
try:
|
|
||||||
lst = list(arguments.eval_argument_clinic(clinic_args))
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
kwargs = {}
|
|
||||||
if want_context:
|
if want_context:
|
||||||
kwargs['context'] = arguments.context
|
kwargs['context'] = arguments.context
|
||||||
if want_obj:
|
if want_obj:
|
||||||
kwargs['obj'] = obj
|
kwargs['obj'] = obj
|
||||||
if want_arguments:
|
if want_arguments:
|
||||||
kwargs['arguments'] = arguments
|
kwargs['arguments'] = arguments
|
||||||
result = func(evaluator, *lst, **kwargs)
|
result = func(evaluator, *args, **kwargs)
|
||||||
finally:
|
|
||||||
debug.dbg('builtin end: %s', result, color='MAGENTA')
|
debug.dbg('builtin end: %s', result, color='MAGENTA')
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -349,8 +325,8 @@ _implemented = {
|
|||||||
'deepcopy': _return_first_param,
|
'deepcopy': _return_first_param,
|
||||||
},
|
},
|
||||||
'json': {
|
'json': {
|
||||||
'load': lambda *args: NO_CONTEXTS,
|
'load': lambda evaluator, obj, arguments: NO_CONTEXTS,
|
||||||
'loads': lambda *args: NO_CONTEXTS,
|
'loads': lambda evaluator, obj, arguments: NO_CONTEXTS,
|
||||||
},
|
},
|
||||||
'collections': {
|
'collections': {
|
||||||
'namedtuple': collections_namedtuple,
|
'namedtuple': collections_namedtuple,
|
||||||
|
|||||||
Reference in New Issue
Block a user