forked from VimPlug/jedi
Cleanse the API from Python 2 stuff
This commit is contained in:
@@ -34,9 +34,7 @@ def _get_signature_param_names(signatures, positional_count, used_kwargs):
|
|||||||
# Add named params
|
# Add named params
|
||||||
for call_sig in signatures:
|
for call_sig in signatures:
|
||||||
for i, p in enumerate(call_sig.params):
|
for i, p in enumerate(call_sig.params):
|
||||||
# Allow protected access, because it's a public API.
|
kind = p.kind
|
||||||
# TODO reconsider with Python 2 drop
|
|
||||||
kind = p._name.get_kind()
|
|
||||||
if i < positional_count and kind == Parameter.POSITIONAL_OR_KEYWORD:
|
if i < positional_count and kind == Parameter.POSITIONAL_OR_KEYWORD:
|
||||||
continue
|
continue
|
||||||
if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) \
|
if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) \
|
||||||
@@ -51,8 +49,7 @@ def _must_be_kwarg(signatures, positional_count, used_kwargs):
|
|||||||
must_be_kwarg = True
|
must_be_kwarg = True
|
||||||
for signature in signatures:
|
for signature in signatures:
|
||||||
for i, p in enumerate(signature.params):
|
for i, p in enumerate(signature.params):
|
||||||
# TODO reconsider with Python 2 drop
|
kind = p.kind
|
||||||
kind = p._name.get_kind()
|
|
||||||
if kind is Parameter.VAR_POSITIONAL:
|
if kind is Parameter.VAR_POSITIONAL:
|
||||||
# In case there were not already kwargs, the next param can
|
# In case there were not already kwargs, the next param can
|
||||||
# always be a normal argument.
|
# always be a normal argument.
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ def _get_cached_default_environment():
|
|||||||
return InterpreterEnvironment()
|
return InterpreterEnvironment()
|
||||||
|
|
||||||
|
|
||||||
def find_virtualenvs(paths=None, **kwargs):
|
def find_virtualenvs(paths=None, *, safe=True, use_environment_vars=True):
|
||||||
"""
|
"""
|
||||||
:param paths: A list of paths in your file system to be scanned for
|
:param paths: A list of paths in your file system to be scanned for
|
||||||
Virtualenvs. It will search in these paths and potentially execute the
|
Virtualenvs. It will search in these paths and potentially execute the
|
||||||
@@ -274,47 +274,44 @@ def find_virtualenvs(paths=None, **kwargs):
|
|||||||
|
|
||||||
:yields: :class:`.Environment`
|
:yields: :class:`.Environment`
|
||||||
"""
|
"""
|
||||||
def py27_comp(paths=None, safe=True, use_environment_vars=True):
|
if paths is None:
|
||||||
if paths is None:
|
paths = []
|
||||||
paths = []
|
|
||||||
|
|
||||||
_used_paths = set()
|
_used_paths = set()
|
||||||
|
|
||||||
if use_environment_vars:
|
if use_environment_vars:
|
||||||
# Using this variable should be safe, because attackers might be
|
# Using this variable should be safe, because attackers might be
|
||||||
# able to drop files (via git) but not environment variables.
|
# able to drop files (via git) but not environment variables.
|
||||||
virtual_env = _get_virtual_env_from_var()
|
virtual_env = _get_virtual_env_from_var()
|
||||||
if virtual_env is not None:
|
if virtual_env is not None:
|
||||||
yield virtual_env
|
yield virtual_env
|
||||||
_used_paths.add(virtual_env.path)
|
_used_paths.add(virtual_env.path)
|
||||||
|
|
||||||
conda_env = _get_virtual_env_from_var(_CONDA_VAR)
|
conda_env = _get_virtual_env_from_var(_CONDA_VAR)
|
||||||
if conda_env is not None:
|
if conda_env is not None:
|
||||||
yield conda_env
|
yield conda_env
|
||||||
_used_paths.add(conda_env.path)
|
_used_paths.add(conda_env.path)
|
||||||
|
|
||||||
for directory in paths:
|
for directory in paths:
|
||||||
if not os.path.isdir(directory):
|
if not os.path.isdir(directory):
|
||||||
|
continue
|
||||||
|
|
||||||
|
directory = os.path.abspath(directory)
|
||||||
|
for path in os.listdir(directory):
|
||||||
|
path = os.path.join(directory, path)
|
||||||
|
if path in _used_paths:
|
||||||
|
# A path shouldn't be inferred twice.
|
||||||
continue
|
continue
|
||||||
|
_used_paths.add(path)
|
||||||
|
|
||||||
directory = os.path.abspath(directory)
|
try:
|
||||||
for path in os.listdir(directory):
|
executable = _get_executable_path(path, safe=safe)
|
||||||
path = os.path.join(directory, path)
|
yield Environment(executable)
|
||||||
if path in _used_paths:
|
except InvalidPythonEnvironment:
|
||||||
# A path shouldn't be inferred twice.
|
pass
|
||||||
continue
|
|
||||||
_used_paths.add(path)
|
|
||||||
|
|
||||||
try:
|
|
||||||
executable = _get_executable_path(path, safe=safe)
|
|
||||||
yield Environment(executable)
|
|
||||||
except InvalidPythonEnvironment:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return py27_comp(paths, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def find_system_environments(**kwargs):
|
def find_system_environments(*, env_vars={}):
|
||||||
"""
|
"""
|
||||||
Ignores virtualenvs and returns the Python versions that were installed on
|
Ignores virtualenvs and returns the Python versions that were installed on
|
||||||
your system. This might return nothing, if you're running Python e.g. from
|
your system. This might return nothing, if you're running Python e.g. from
|
||||||
@@ -326,14 +323,14 @@ def find_system_environments(**kwargs):
|
|||||||
"""
|
"""
|
||||||
for version_string in _SUPPORTED_PYTHONS:
|
for version_string in _SUPPORTED_PYTHONS:
|
||||||
try:
|
try:
|
||||||
yield get_system_environment(version_string, **kwargs)
|
yield get_system_environment(version_string, env_vars=env_vars)
|
||||||
except InvalidPythonEnvironment:
|
except InvalidPythonEnvironment:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# TODO: this function should probably return a list of environments since
|
# TODO: this function should probably return a list of environments since
|
||||||
# multiple Python installations can be found on a system for the same version.
|
# multiple Python installations can be found on a system for the same version.
|
||||||
def get_system_environment(version, **kwargs):
|
def get_system_environment(version, *, env_vars={}):
|
||||||
"""
|
"""
|
||||||
Return the first Python environment found for a string of the form 'X.Y'
|
Return the first Python environment found for a string of the form 'X.Y'
|
||||||
where X and Y are the major and minor versions of Python.
|
where X and Y are the major and minor versions of Python.
|
||||||
@@ -350,26 +347,20 @@ def get_system_environment(version, **kwargs):
|
|||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
for exe in _get_executables_from_windows_registry(version):
|
for exe in _get_executables_from_windows_registry(version):
|
||||||
try:
|
try:
|
||||||
return Environment(exe, **kwargs)
|
return Environment(exe, env_vars=env_vars)
|
||||||
except InvalidPythonEnvironment:
|
except InvalidPythonEnvironment:
|
||||||
pass
|
pass
|
||||||
raise InvalidPythonEnvironment("Cannot find executable python%s." % version)
|
raise InvalidPythonEnvironment("Cannot find executable python%s." % version)
|
||||||
|
|
||||||
|
|
||||||
def create_environment(path, safe=True, **kwargs):
|
def create_environment(path, *, safe=True, env_vars={}):
|
||||||
"""
|
"""
|
||||||
Make it possible to manually create an Environment object by specifying a
|
Make it possible to manually create an Environment object by specifying a
|
||||||
Virtualenv path or an executable path and optional environment variables.
|
Virtualenv path or an executable path and optional environment variables.
|
||||||
|
|
||||||
:raises: :exc:`.InvalidPythonEnvironment`
|
:raises: :exc:`.InvalidPythonEnvironment`
|
||||||
:returns: :class:`.Environment`
|
:returns: :class:`.Environment`
|
||||||
|
|
||||||
TODO: make env_vars a kwarg when Python 2 is dropped. For now, preserve API
|
|
||||||
"""
|
"""
|
||||||
return _create_environment(path, safe, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _create_environment(path, safe=True, env_vars={}):
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
_assert_safe(path, safe)
|
_assert_safe(path, safe)
|
||||||
return Environment(path, env_vars=env_vars)
|
return Environment(path, env_vars=env_vars)
|
||||||
@@ -393,11 +384,7 @@ def _get_executable_path(path, safe=True):
|
|||||||
|
|
||||||
|
|
||||||
def _get_executables_from_windows_registry(version):
|
def _get_executables_from_windows_registry(version):
|
||||||
# The winreg module is named _winreg on Python 2.
|
import winreg
|
||||||
try:
|
|
||||||
import winreg
|
|
||||||
except ImportError:
|
|
||||||
import _winreg as winreg
|
|
||||||
|
|
||||||
# TODO: support Python Anaconda.
|
# TODO: support Python Anaconda.
|
||||||
sub_keys = [
|
sub_keys = [
|
||||||
|
|||||||
@@ -295,8 +295,7 @@ def _iter_arguments(nodes, position):
|
|||||||
# Returns Generator[Tuple[star_count, Optional[key_start: str], had_equal]]
|
# Returns Generator[Tuple[star_count, Optional[key_start: str], had_equal]]
|
||||||
nodes_before = [c for c in nodes if c.start_pos < position]
|
nodes_before = [c for c in nodes if c.start_pos < position]
|
||||||
if nodes_before[-1].type == 'arglist':
|
if nodes_before[-1].type == 'arglist':
|
||||||
for x in _iter_arguments(nodes_before[-1].children, position):
|
yield from _iter_arguments(nodes_before[-1].children, position)
|
||||||
yield x # Python 2 :(
|
|
||||||
return
|
return
|
||||||
|
|
||||||
previous_node_yielded = False
|
previous_node_yielded = False
|
||||||
@@ -321,7 +320,7 @@ def _iter_arguments(nodes, position):
|
|||||||
else:
|
else:
|
||||||
yield 0, None, False
|
yield 0, None, False
|
||||||
stars_seen = 0
|
stars_seen = 0
|
||||||
elif node.type in ('testlist', 'testlist_star_expr'): # testlist is Python 2
|
elif node.type == 'testlist_star_expr':
|
||||||
for n in node.children[::2]:
|
for n in node.children[::2]:
|
||||||
if n.type == 'star_expr':
|
if n.type == 'star_expr':
|
||||||
stars_seen = 1
|
stars_seen = 1
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class Project(object):
|
|||||||
self._environment = get_cached_default_environment()
|
self._environment = get_cached_default_environment()
|
||||||
return self._environment
|
return self._environment
|
||||||
|
|
||||||
def search(self, string, **kwargs):
|
def search(self, string, *, all_scopes=False):
|
||||||
"""
|
"""
|
||||||
Searches a name in the whole project. If the project is very big,
|
Searches a name in the whole project. If the project is very big,
|
||||||
at some point Jedi will stop searching. However it's also very much
|
at some point Jedi will stop searching. However it's also very much
|
||||||
@@ -232,7 +232,7 @@ class Project(object):
|
|||||||
functions and classes.
|
functions and classes.
|
||||||
:yields: :class:`.Name`
|
:yields: :class:`.Name`
|
||||||
"""
|
"""
|
||||||
return self._search(string, **kwargs)
|
return self._search_func(string, all_scopes=all_scopes)
|
||||||
|
|
||||||
def complete_search(self, string, **kwargs):
|
def complete_search(self, string, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -246,9 +246,6 @@ class Project(object):
|
|||||||
"""
|
"""
|
||||||
return self._search_func(string, complete=True, **kwargs)
|
return self._search_func(string, complete=True, **kwargs)
|
||||||
|
|
||||||
def _search(self, string, all_scopes=False): # Python 2..
|
|
||||||
return self._search_func(string, all_scopes=all_scopes)
|
|
||||||
|
|
||||||
@_try_to_skip_duplicates
|
@_try_to_skip_duplicates
|
||||||
def _search_func(self, string, complete=False, all_scopes=False):
|
def _search_func(self, string, complete=False, all_scopes=False):
|
||||||
# Using a Script is they easiest way to get an empty module context.
|
# Using a Script is they easiest way to get an empty module context.
|
||||||
@@ -290,7 +287,7 @@ class Project(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
debug.dbg('Search of a specific module %s', m)
|
debug.dbg('Search of a specific module %s', m)
|
||||||
for x in search_in_module(
|
yield from search_in_module(
|
||||||
inference_state,
|
inference_state,
|
||||||
m,
|
m,
|
||||||
names=[m.name],
|
names=[m.name],
|
||||||
@@ -299,15 +296,14 @@ class Project(object):
|
|||||||
complete=complete,
|
complete=complete,
|
||||||
convert=True,
|
convert=True,
|
||||||
ignore_imports=True,
|
ignore_imports=True,
|
||||||
):
|
)
|
||||||
yield x # Python 2...
|
|
||||||
|
|
||||||
# 2. Search for identifiers in the project.
|
# 2. Search for identifiers in the project.
|
||||||
for module_context in search_in_file_ios(inference_state, file_ios, name):
|
for module_context in search_in_file_ios(inference_state, file_ios, name):
|
||||||
names = get_module_names(module_context.tree_node, all_scopes=all_scopes)
|
names = get_module_names(module_context.tree_node, all_scopes=all_scopes)
|
||||||
names = [module_context.create_name(n) for n in names]
|
names = [module_context.create_name(n) for n in names]
|
||||||
names = _remove_imports(names)
|
names = _remove_imports(names)
|
||||||
for x in search_in_module(
|
yield from search_in_module(
|
||||||
inference_state,
|
inference_state,
|
||||||
module_context,
|
module_context,
|
||||||
names=names,
|
names=names,
|
||||||
@@ -315,8 +311,7 @@ class Project(object):
|
|||||||
wanted_names=wanted_names,
|
wanted_names=wanted_names,
|
||||||
complete=complete,
|
complete=complete,
|
||||||
ignore_imports=True,
|
ignore_imports=True,
|
||||||
):
|
)
|
||||||
yield x # Python 2...
|
|
||||||
|
|
||||||
# 3. Search for modules on sys.path
|
# 3. Search for modules on sys.path
|
||||||
sys_path = [
|
sys_path = [
|
||||||
@@ -326,7 +321,7 @@ class Project(object):
|
|||||||
if not p.startswith(self._path)
|
if not p.startswith(self._path)
|
||||||
]
|
]
|
||||||
names = list(iter_module_names(inference_state, empty_module_context, sys_path))
|
names = list(iter_module_names(inference_state, empty_module_context, sys_path))
|
||||||
for x in search_in_module(
|
yield from search_in_module(
|
||||||
inference_state,
|
inference_state,
|
||||||
empty_module_context,
|
empty_module_context,
|
||||||
names=names,
|
names=names,
|
||||||
@@ -334,8 +329,7 @@ class Project(object):
|
|||||||
wanted_names=wanted_names,
|
wanted_names=wanted_names,
|
||||||
complete=complete,
|
complete=complete,
|
||||||
convert=True,
|
convert=True,
|
||||||
):
|
)
|
||||||
yield x # Python 2...
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self._path)
|
return '<%s: %s>' % (self.__class__.__name__, self._path)
|
||||||
|
|||||||
@@ -350,8 +350,7 @@ def _find_non_global_names(nodes):
|
|||||||
if node.type == 'trailer' and node.children[0] == '.':
|
if node.type == 'trailer' and node.children[0] == '.':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for x in _find_non_global_names(children): # Python 2...
|
yield from _find_non_global_names(children)
|
||||||
yield x
|
|
||||||
|
|
||||||
|
|
||||||
def _get_code_insertion_node(node, is_bound_method):
|
def _get_code_insertion_node(node, is_bound_method):
|
||||||
|
|||||||
@@ -97,10 +97,8 @@ def increase_indent_cm(title=None, color='MAGENTA'):
|
|||||||
dbg('End: ' + title, color=color)
|
dbg('End: ' + title, color=color)
|
||||||
|
|
||||||
|
|
||||||
def dbg(message, *args, **kwargs):
|
def dbg(message, *args, color='GREEN'):
|
||||||
""" Looks at the stack, to see if a debug message should be printed. """
|
""" Looks at the stack, to see if a debug message should be printed. """
|
||||||
# Python 2 compatibility, because it doesn't understand default args
|
|
||||||
color = kwargs.pop('color', 'GREEN')
|
|
||||||
assert color
|
assert color
|
||||||
|
|
||||||
if debug_function and enable_notice:
|
if debug_function and enable_notice:
|
||||||
|
|||||||
Reference in New Issue
Block a user