forked from VimPlug/jedi
Merge branch 'master' into typeshed
This commit is contained in:
+1
-1
@@ -36,7 +36,7 @@ As you see Jedi is pretty simple and allows you to concentrate on writing a
|
||||
good text editor, while still having very good IDE features for Python.
|
||||
"""
|
||||
|
||||
__version__ = '0.13.2'
|
||||
__version__ = '0.13.3'
|
||||
|
||||
from jedi.api import Script, Interpreter, set_debug_function, \
|
||||
preload_module, names
|
||||
|
||||
@@ -348,6 +348,11 @@ try:
|
||||
except NameError:
|
||||
NotADirectoryError = IOError
|
||||
|
||||
try:
|
||||
PermissionError = PermissionError
|
||||
except NameError:
|
||||
PermissionError = IOError
|
||||
|
||||
|
||||
def no_unicode_pprint(dct):
|
||||
"""
|
||||
|
||||
+42
-4
@@ -153,9 +153,9 @@ def _get_virtual_env_from_var():
|
||||
variable is considered to be safe / controlled by the user solely.
|
||||
"""
|
||||
var = os.environ.get('VIRTUAL_ENV')
|
||||
if var is not None:
|
||||
if var:
|
||||
if var == sys.prefix:
|
||||
return SameEnvironment()
|
||||
return _try_get_same_env()
|
||||
|
||||
try:
|
||||
return create_environment(var, safe=False)
|
||||
@@ -184,9 +184,47 @@ def get_default_environment():
|
||||
if virtual_env is not None:
|
||||
return virtual_env
|
||||
|
||||
# If no VirtualEnv is found, use the environment we're already
|
||||
return _try_get_same_env()
|
||||
|
||||
|
||||
def _try_get_same_env():
|
||||
env = SameEnvironment()
|
||||
if not os.path.basename(env.executable).lower().startswith('python'):
|
||||
# This tries to counter issues with embedding. In some cases (e.g.
|
||||
# VIM's Python Mac/Windows, sys.executable is /foo/bar/vim. This
|
||||
# happens, because for Mac a function called `_NSGetExecutablePath` is
|
||||
# used and for Windows `GetModuleFileNameW`. These are both platform
|
||||
# specific functions. For all other systems sys.executable should be
|
||||
# alright. However here we try to generalize:
|
||||
#
|
||||
# 1. Check if the executable looks like python (heuristic)
|
||||
# 2. In case it's not try to find the executable
|
||||
# 3. In case we don't find it use an interpreter environment.
|
||||
#
|
||||
# The last option will always work, but leads to potential crashes of
|
||||
# Jedi - which is ok, because it happens very rarely and even less,
|
||||
# because the code below should work for most cases.
|
||||
if os.name == 'nt':
|
||||
# The first case would be a virtualenv and the second a normal
|
||||
# Python installation.
|
||||
checks = (r'Scripts\python.exe', 'python.exe')
|
||||
else:
|
||||
# For unix it looks like Python is always in a bin folder.
|
||||
checks = (
|
||||
'bin/python%s.%s' % (sys.version_info[0], sys.version[1]),
|
||||
'bin/python%s' % (sys.version_info[0]),
|
||||
'bin/python',
|
||||
)
|
||||
for check in checks:
|
||||
guess = os.path.join(sys.exec_prefix, check)
|
||||
if os.path.isfile(guess):
|
||||
# Bingo - We think we have our Python.
|
||||
return Environment(guess)
|
||||
# It looks like there is no reasonable Python to be found.
|
||||
return InterpreterEnvironment()
|
||||
# If no virtualenv is found, use the environment we're already
|
||||
# using.
|
||||
return SameEnvironment()
|
||||
return env
|
||||
|
||||
|
||||
def get_cached_default_environment():
|
||||
|
||||
+4
-1
@@ -130,7 +130,10 @@ def get_stack_at_position(grammar, code_lines, module_node, pos):
|
||||
p.parse(tokens=tokenize_without_endmarker(code))
|
||||
except EndMarkerReached:
|
||||
return p.stack
|
||||
raise SystemError("This really shouldn't happen. There's a bug in Jedi.")
|
||||
raise SystemError(
|
||||
"This really shouldn't happen. There's a bug in Jedi:\n%s"
|
||||
% list(tokenize_without_endmarker(code))
|
||||
)
|
||||
|
||||
|
||||
def evaluate_goto_definition(evaluator, context, leaf):
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import json
|
||||
|
||||
from jedi._compatibility import FileNotFoundError, NotADirectoryError
|
||||
from jedi._compatibility import FileNotFoundError, NotADirectoryError, PermissionError
|
||||
from jedi.api.environment import SameEnvironment, \
|
||||
get_cached_default_environment
|
||||
from jedi.api.exceptions import WrongVersion
|
||||
@@ -151,7 +151,7 @@ def _is_django_path(directory):
|
||||
try:
|
||||
with open(os.path.join(directory, 'manage.py'), 'rb') as f:
|
||||
return b"DJANGO_SETTINGS_MODULE" in f.read()
|
||||
except (FileNotFoundError, NotADirectoryError):
|
||||
except (FileNotFoundError, NotADirectoryError, PermissionError):
|
||||
return False
|
||||
|
||||
return False
|
||||
@@ -167,7 +167,7 @@ def get_default_project(path=None):
|
||||
for dir in traverse_parents(check, include_current=True):
|
||||
try:
|
||||
return Project.load(dir)
|
||||
except (FileNotFoundError, NotADirectoryError):
|
||||
except (FileNotFoundError, NotADirectoryError, PermissionError):
|
||||
pass
|
||||
|
||||
if first_no_init_file is None:
|
||||
|
||||
@@ -97,7 +97,7 @@ class MixedObjectFilter(compiled.CompiledObjectFilter):
|
||||
|
||||
@evaluator_function_cache()
|
||||
def _load_module(evaluator, path):
|
||||
module_node = evaluator.grammar.parse(
|
||||
module_node = evaluator.parse(
|
||||
path=path,
|
||||
cache=True,
|
||||
diff_cache=settings.fast_parser,
|
||||
|
||||
@@ -514,9 +514,10 @@ class SelfAttributeFilter(ClassFilter):
|
||||
for name in names:
|
||||
trailer = name.parent
|
||||
if trailer.type == 'trailer' \
|
||||
and len(trailer.children) == 2 \
|
||||
and len(trailer.parent.children) == 2 \
|
||||
and trailer.children[0] == '.':
|
||||
if name.is_definition() and self._access_possible(name):
|
||||
# TODO filter non-self assignments.
|
||||
yield name
|
||||
|
||||
def _convert_names(self, names):
|
||||
|
||||
@@ -172,7 +172,7 @@ def get_module_names(module, all_scopes):
|
||||
# parent_scope. There's None as a parent, because nodes in the module
|
||||
# node have the parent module and not suite as all the others.
|
||||
# Therefore it's important to catch that case.
|
||||
names = [n for n in names if get_parent_scope(n).parent in (module, None)]
|
||||
names = [n for n in names if get_parent_scope(n) == module]
|
||||
return names
|
||||
|
||||
|
||||
|
||||
@@ -572,7 +572,8 @@ def tree_name_to_contexts(evaluator, context, tree_name):
|
||||
filters = [next(filters)]
|
||||
return finder.find(filters, attribute_lookup=False)
|
||||
elif node.type not in ('import_from', 'import_name'):
|
||||
raise ValueError("Should not happen. type: %s", node.type)
|
||||
context = evaluator.create_context(context, tree_name)
|
||||
return eval_atom(context, tree_name)
|
||||
|
||||
typ = node.type
|
||||
if typ == 'for_stmt':
|
||||
@@ -612,6 +613,8 @@ def tree_name_to_contexts(evaluator, context, tree_name):
|
||||
# the static analysis report.
|
||||
exceptions = context.eval_node(tree_name.get_previous_sibling().get_previous_sibling())
|
||||
types = exceptions.execute_evaluated()
|
||||
elif node.type == 'param':
|
||||
types = NO_CONTEXTS
|
||||
else:
|
||||
raise ValueError("Should not happen. type: %s" % typ)
|
||||
return types
|
||||
|
||||
@@ -247,11 +247,16 @@ def get_parent_scope(node, include_flows=False):
|
||||
Returns the underlying scope.
|
||||
"""
|
||||
scope = node.parent
|
||||
while scope is not None:
|
||||
if include_flows and isinstance(scope, tree.Flow):
|
||||
if scope is None:
|
||||
return None # It's a module already.
|
||||
if scope.type in ('funcdef', 'classdef') and scope.name == node:
|
||||
scope = scope.parent
|
||||
if scope.parent is None: # The module scope.
|
||||
return scope
|
||||
|
||||
while True:
|
||||
if include_flows and isinstance(scope, tree.Flow) or is_scope(scope):
|
||||
return scope
|
||||
if is_scope(scope):
|
||||
break
|
||||
scope = scope.parent
|
||||
return scope
|
||||
|
||||
|
||||
Reference in New Issue
Block a user