Skip to content

Commit

Permalink
Upgrade to jedi==0.12.1 and parso==0.3.0 (#256)
Browse files Browse the repository at this point in the history
* Pass location by name every time

* Add locaiton as parameter by name when asking about "docstring"

* Upgrade to jedi==0.12.1 and parso==0.3.0
  • Loading branch information
edelvalle authored and srusskih committed Jul 10, 2018
1 parent 34b86b7 commit fd424a5
Show file tree
Hide file tree
Showing 41 changed files with 1,190 additions and 1,290 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dummy:
dependencies:
rm -rf dependencies/
mkdir dependencies/
$(call get_dependency,jedi,https://github.com/davidhalter/jedi,v0.12.0)
$(call get_dependency,parso,https://github.com/davidhalter/parso,v0.2.0)
$(call get_dependency,jedi,https://github.com/davidhalter/jedi,v0.12.1)
$(call get_dependency,parso,https://github.com/davidhalter/parso,v0.3.0)

clean:
find . -name '*.pyc' -delete
Expand Down
2 changes: 1 addition & 1 deletion dependencies/jedi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
good text editor, while still having very good IDE features for Python.
"""

__version__ = '0.12.0'
__version__ = '0.12.1'

from jedi.api import Script, Interpreter, set_debug_function, \
preload_module, names
Expand Down
147 changes: 103 additions & 44 deletions dependencies/jedi/_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
To ensure compatibility from Python ``2.7`` - ``3.x``, a module has been
created. Clearly there is huge need to use conforming syntax.
"""
import binascii
import errno
import sys
import os
Expand Down Expand Up @@ -381,8 +380,12 @@ def wrapper(self):
else:
import Queue as queue


import pickle
try:
# Attempt to load the C implementation of pickle on Python 2 as it is way
# faster.
import cPickle as pickle
except ImportError:
import pickle
if sys.version_info[:2] == (3, 3):
"""
Monkeypatch the unpickler in Python 3.3. This is needed, because the
Expand Down Expand Up @@ -443,53 +446,45 @@ def loads(s, fix_imports=True, encoding="ASCII", errors="strict"):
pickle.loads = loads


_PICKLE_PROTOCOL = 2
is_windows = sys.platform == 'win32'

# The Windows shell on Python 2 consumes all control characters (below 32) and expand on
# all Python versions \n to \r\n.
# pickle starting from protocol version 1 uses binary data, which could not be escaped by
# any normal unicode encoder. Therefore, the only bytes encoder which doesn't produce
# control characters is binascii.hexlify.


def pickle_load(file):
if is_windows:
try:
data = file.readline()
data = binascii.unhexlify(data.strip())
if is_py3:
return pickle.loads(data, encoding='bytes')
else:
return pickle.loads(data)
# Python on Windows don't throw EOF errors for pipes. So reraise them with
# the correct type, which is cought upwards.
except OSError:
raise EOFError()
else:
try:
if is_py3:
return pickle.load(file, encoding='bytes')
else:
return pickle.load(file)
return pickle.load(file)
# Python on Windows don't throw EOF errors for pipes. So reraise them with
# the correct type, which is caught upwards.
except OSError:
if sys.platform == 'win32':
raise EOFError()
raise


def pickle_dump(data, file):
if is_windows:
try:
data = pickle.dumps(data, protocol=_PICKLE_PROTOCOL)
data = binascii.hexlify(data)
file.write(data)
file.write(b'\n')
# On Python 3.3 flush throws sometimes an error even if the two file writes
# should done it already before. This could be also computer / speed depending.
file.flush()
# Python on Windows don't throw EPIPE errors for pipes. So reraise them with
# the correct type and error number.
except OSError:
raise IOError(errno.EPIPE, "Broken pipe")
else:
pickle.dump(data, file, protocol=_PICKLE_PROTOCOL)
def pickle_dump(data, file, protocol):
try:
pickle.dump(data, file, protocol)
# On Python 3.3 flush throws sometimes an error even though the writing
# operation should be completed.
file.flush()
# Python on Windows don't throw EPIPE errors for pipes. So reraise them with
# the correct type and error number.
except OSError:
if sys.platform == 'win32':
raise IOError(errno.EPIPE, "Broken pipe")
raise


# Determine the highest protocol version compatible for a given list of Python
# versions.
def highest_pickle_protocol(python_versions):
protocol = 4
for version in python_versions:
if version[0] == 2:
# The minimum protocol version for the versions of Python that we
# support (2.7 and 3.3+) is 2.
return 2
if version[1] < 4:
protocol = 3
return protocol


try:
Expand All @@ -513,3 +508,67 @@ def __init__(self, *args, **kwargs):
CREATE_NO_WINDOW = 0x08000000
kwargs['creationflags'] = CREATE_NO_WINDOW
super(GeneralizedPopen, self).__init__(*args, **kwargs)


# shutil.which is not available on Python 2.7.
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
"""Given a command, mode, and a PATH string, return the path which
conforms to the given mode on the PATH, or None if there is no such
file.
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
of os.environ.get("PATH"), or can be overridden with a custom search
path.
"""
# Check that a given file can be accessed with the correct mode.
# Additionally check that `file` is not a directory, as on Windows
# directories pass the os.access check.
def _access_check(fn, mode):
return (os.path.exists(fn) and os.access(fn, mode)
and not os.path.isdir(fn))

# If we're given a path with a directory part, look it up directly rather
# than referring to PATH directories. This includes checking relative to the
# current directory, e.g. ./script
if os.path.dirname(cmd):
if _access_check(cmd, mode):
return cmd
return None

if path is None:
path = os.environ.get("PATH", os.defpath)
if not path:
return None
path = path.split(os.pathsep)

if sys.platform == "win32":
# The current directory takes precedence on Windows.
if not os.curdir in path:
path.insert(0, os.curdir)

# PATHEXT is necessary to check on Windows.
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
# See if the given file matches any of the expected path extensions.
# This will allow us to short circuit when given "python.exe".
# If it does match, only test that one, otherwise we have to try
# others.
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
files = [cmd]
else:
files = [cmd + ext for ext in pathext]
else:
# On other platforms you don't have things like PATHEXT to tell you
# what file suffixes are executable, so just pass on cmd as-is.
files = [cmd]

seen = set()
for dir in path:
normdir = os.path.normcase(dir)
if not normdir in seen:
seen.add(normdir)
for thefile in files:
name = os.path.join(dir, thefile)
if _access_check(name, mode):
return name
return None
7 changes: 4 additions & 3 deletions dependencies/jedi/api/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def get_param_names(context):

followed = list(self._name.infer())
if not followed or not hasattr(followed[0], 'py__call__'):
raise AttributeError()
raise AttributeError('There are no params defined on this.')
context = followed[0] # only check the first one.

return [Definition(self._evaluator, n) for n in get_param_names(context)]
Expand Down Expand Up @@ -404,8 +404,9 @@ def _complete(self, like_name):
append = '('

if self._name.api_type == 'param' and self._stack is not None:
node_names = list(self._stack.get_node_names(self._evaluator.grammar._pgen_grammar))
if 'trailer' in node_names and 'argument' not in node_names:
nonterminals = [stack_node.nonterminal for stack_node in self._stack]
if 'trailer' in nonterminals and 'argument' not in nonterminals:
# TODO this doesn't work for nested calls.
append += '='

name = self._name.string_name
Expand Down
47 changes: 25 additions & 22 deletions dependencies/jedi/api/completion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from parso.python import token
from parso.python.token import PythonTokenTypes
from parso.python import tree
from parso.tree import search_ancestor, Leaf

Expand Down Expand Up @@ -57,7 +57,8 @@ def get_user_scope(module_context, position):
def scan(scope):
for s in scope.children:
if s.start_pos <= position <= s.end_pos:
if isinstance(s, (tree.Scope, tree.Flow)):
if isinstance(s, (tree.Scope, tree.Flow)) \
or s.type in ('async_stmt', 'async_funcdef'):
return scan(s) or s
elif s.type in ('suite', 'decorated'):
return scan(s)
Expand Down Expand Up @@ -121,11 +122,11 @@ def _get_context_completions(self):
grammar = self._evaluator.grammar

try:
self.stack = helpers.get_stack_at_position(
self.stack = stack = helpers.get_stack_at_position(
grammar, self._code_lines, self._module_node, self._position
)
except helpers.OnErrorLeaf as e:
self.stack = None
self.stack = stack = None
if e.error_leaf.value == '.':
# After ErrorLeaf's that are dots, we will not do any
# completions since this probably just confuses the user.
Expand All @@ -134,10 +135,10 @@ def _get_context_completions(self):

return self._global_completions()

allowed_keywords, allowed_tokens = \
helpers.get_possible_completion_types(grammar._pgen_grammar, self.stack)
allowed_transitions = \
list(stack._allowed_transition_names_and_token_types())

if 'if' in allowed_keywords:
if 'if' in allowed_transitions:
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
previous_leaf = leaf.get_previous_leaf()

Expand All @@ -163,50 +164,52 @@ def _get_context_completions(self):
# Compare indents
if stmt.start_pos[1] == indent:
if type_ == 'if_stmt':
allowed_keywords += ['elif', 'else']
allowed_transitions += ['elif', 'else']
elif type_ == 'try_stmt':
allowed_keywords += ['except', 'finally', 'else']
allowed_transitions += ['except', 'finally', 'else']
elif type_ == 'for_stmt':
allowed_keywords.append('else')
allowed_transitions.append('else')

completion_names = list(self._get_keyword_completion_names(allowed_keywords))
completion_names = list(self._get_keyword_completion_names(allowed_transitions))

if token.NAME in allowed_tokens or token.INDENT in allowed_tokens:
if any(t in allowed_transitions for t in (PythonTokenTypes.NAME,
PythonTokenTypes.INDENT)):
# This means that we actually have to do type inference.

symbol_names = list(self.stack.get_node_names(grammar._pgen_grammar))
nonterminals = [stack_node.nonterminal for stack_node in stack]

nodes = list(self.stack.get_nodes())
nodes = [node for stack_node in stack for node in stack_node.nodes]

if nodes and nodes[-1] in ('as', 'def', 'class'):
# No completions for ``with x as foo`` and ``import x as foo``.
# Also true for defining names as a class or function.
return list(self._get_class_context_completions(is_function=True))
elif "import_stmt" in symbol_names:
level, names = self._parse_dotted_names(nodes, "import_from" in symbol_names)
elif "import_stmt" in nonterminals:
level, names = self._parse_dotted_names(nodes, "import_from" in nonterminals)

only_modules = not ("import_from" in symbol_names and 'import' in nodes)
only_modules = not ("import_from" in nonterminals and 'import' in nodes)
completion_names += self._get_importer_names(
names,
level,
only_modules=only_modules,
)
elif symbol_names[-1] in ('trailer', 'dotted_name') and nodes[-1] == '.':
elif nonterminals[-1] in ('trailer', 'dotted_name') and nodes[-1] == '.':
dot = self._module_node.get_leaf_for_position(self._position)
completion_names += self._trailer_completions(dot.get_previous_leaf())
else:
completion_names += self._global_completions()
completion_names += self._get_class_context_completions(is_function=False)

if 'trailer' in symbol_names:
if 'trailer' in nonterminals:
call_signatures = self._call_signatures_method()
completion_names += get_call_signature_param_names(call_signatures)

return completion_names

def _get_keyword_completion_names(self, keywords_):
for k in keywords_:
yield keywords.KeywordName(self._evaluator, k)
def _get_keyword_completion_names(self, allowed_transitions):
for k in allowed_transitions:
if isinstance(k, str) and k.isalpha():
yield keywords.KeywordName(self._evaluator, k)

def _global_completions(self):
context = get_user_scope(self._module_context, self._position)
Expand Down
Loading

0 comments on commit fd424a5

Please sign in to comment.