Skip to content

Jedi 0.11 parser + test fixes #777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 76 commits into from
Feb 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
7675901
Basic tokenizer
Dec 1, 2017
eb42669
Fixed property names
Dec 1, 2017
2756974
Tests, round I
Dec 1, 2017
c2c1ced
Tests, round II
Dec 2, 2017
a108c96
merge master
Dec 3, 2017
14864a5
tokenizer test
Dec 4, 2017
0ed51d6
Remove temorary change
Dec 4, 2017
51b544c
Fix merge issue
Dec 4, 2017
3cd11e6
Merge conflict
Dec 4, 2017
82e0ad1
Merge conflict
Dec 4, 2017
9295c1a
Completion test
Dec 4, 2017
06eb1a5
Fix last line
Dec 4, 2017
e9db8e0
Fix javascript math
Dec 4, 2017
d12ca03
Merge master
Dec 5, 2017
d8ab041
Make test await for results
Dec 5, 2017
db75cd0
Add license headers
Dec 5, 2017
9ab2c47
Rename definitions to types
Dec 5, 2017
d587485
License headers
Dec 5, 2017
1da5e0a
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 5, 2017
7668cee
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 11, 2017
1ac4932
Fix typo in completion details (typo)
Dec 11, 2017
2aa5a6c
Fix hover test
Dec 12, 2017
5db31bd
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 12, 2017
560d2af
Russian translations
Dec 13, 2017
c71024d
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 13, 2017
31aa087
Update to better translation
Dec 13, 2017
593ae05
Fix typo
Dec 13, 2017
e6d69bb
#70 How to get all parameter info when filling in a function param list
Dec 13, 2017
b5a23d3
Fix #70 How to get all parameter info when filling in a function para…
Dec 14, 2017
cd200f7
Clean up
Dec 14, 2017
7c33228
Clean imports
Dec 14, 2017
c4a6b90
CR feedback
Dec 14, 2017
f85b848
Trim whitespace for test stability
Dec 14, 2017
37c210b
More tests
Dec 15, 2017
61a5650
Better handle no-parameters documentation
Dec 15, 2017
a10305e
Better handle ellipsis and Python3
Dec 15, 2017
bfcae78
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 15, 2017
42a5f79
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 18, 2017
e4ba322
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Jan 8, 2018
7baec1a
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Jan 9, 2018
9cb43e7
#385 Auto-Indentation doesn't work after comment
Jan 9, 2018
5a9c3fd
#141 Auto indentation broken when return keyword involved
Jan 9, 2018
9800c4a
Undo changes
Jan 9, 2018
3205d33
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Jan 11, 2018
c1150d4
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Feb 1, 2018
30519c7
#627 Docstrings for builtin methods are not parsed correctly
Feb 5, 2018
96511cb
reStructuredText converter
Feb 5, 2018
c8670b9
Fix: period is not an operator
Feb 5, 2018
97f232f
Minor fixes
Feb 6, 2018
768bffe
Restructure
Feb 6, 2018
825f16b
Tests
Feb 6, 2018
eb36eef
Tests
Feb 6, 2018
bab4239
Code heuristics
Feb 6, 2018
2a30201
Baselines
Feb 6, 2018
e430ef8
HTML handling
Feb 6, 2018
1afa841
Lists
Feb 7, 2018
6bffb07
State machine
Feb 7, 2018
e436fde
Baselines
Feb 7, 2018
c03e619
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Feb 7, 2018
e52bcff
Squash
Feb 7, 2018
e6b8196
Merge branch 'master' of https://github.com/MikhailArkhipov/vscode-py…
Feb 7, 2018
3a0cfb1
no message
Feb 7, 2018
4616996
Merge branch 'master' of https://github.com/MikhailArkhipov/vscode-py…
Feb 7, 2018
35838b9
Whitespace difference
Feb 7, 2018
656a56b
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Feb 12, 2018
6a10786
Update Jedi to 0.11.1
Feb 12, 2018
d43f097
Enable Travis
Feb 12, 2018
f8db935
Test fixes
Feb 13, 2018
a8dc597
Undo change
Feb 13, 2018
3f5d492
Jedi 0.11 with parser
Feb 13, 2018
f93a0f4
Merge master
Feb 13, 2018
f8eaa93
Undo changes
Feb 13, 2018
e4372c6
Undo changes
Feb 13, 2018
469c8a7
Test fixes
Feb 13, 2018
609bbdd
More tests
Feb 15, 2018
7ea6fda
Tests
Feb 15, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@
"python.linting.enabled": false,
"python.unitTest.promptToConfigure": false,
"python.workspaceSymbols.enabled": false,
"python.formatting.provider": "none",
"files.insertFinalNewline": true
}
"python.formatting.provider": "none"
}
108 changes: 31 additions & 77 deletions pythonFiles/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self, new_stdout=None):

def __enter__(self):
sys.stdout.flush()
oldstdout_fno = self.oldstdout_fno = os.dup(sys.stdout.fileno())
self.oldstdout_fno = os.dup(sys.stdout.fileno())
os.dup2(self._new_stdout.fileno(), 1)

def __exit__(self, exc_type, exc_value, traceback):
Expand Down Expand Up @@ -47,7 +47,6 @@ def __init__(self):
self.drive_mount = ''

def _get_definition_type(self, definition):
is_built_in = definition.in_builtin_module
# if definition.type not in ['import', 'keyword'] and is_built_in():
# return 'builtin'
try:
Expand Down Expand Up @@ -89,7 +88,7 @@ def _generate_signature(self, completion):
return ''
return '%s(%s)' % (
completion.name,
', '.join(p.description for p in completion.params if p))
', '.join(p.description[6:] for p in completion.params if p))

def _get_call_signatures(self, script):
"""Extract call signatures from jedi.api.Script object in failsafe way.
Expand All @@ -108,18 +107,28 @@ def _get_call_signatures(self, script):
for pos, param in enumerate(signature.params):
if not param.name:
continue

name = self._get_param_name(param)
if param.name == 'self' and pos == 0:
continue
try:
name, value = param.description.split('=')
except ValueError:
name = param.description
value = None
if name.startswith('*'):
continue

value = self._get_param_value(param)
_signatures.append((signature, name, value))
return _signatures

def _get_param_name(self, p):
if(p.name.startswith('param ')):
return p.name[6:] # drop leading 'param '
return p.name

def _get_param_value(self, p):
pair = p.description.split('=')
if(len(pair) > 1):
return pair[1]
return None

def _get_call_signatures_with_args(self, script):
"""Extract call signatures from jedi.api.Script object in failsafe way.

Expand Down Expand Up @@ -150,16 +159,12 @@ def _get_call_signatures_with_args(self, script):
for pos, param in enumerate(signature.params):
if not param.name:
continue

name = self._get_param_name(param)
if param.name == 'self' and pos == 0:
continue
try:
name, value = param.description.split('=')
except ValueError:
name = param.description
value = None
# if name.startswith('*'):
# continue
#_signatures.append((signature, name, value))

value = self._get_param_value(param)
paramDocstring = ''
try:
paramDocstring = param.docstring()
Expand Down Expand Up @@ -251,8 +256,7 @@ def _serialize_methods(self, script, identifier=None, prefix=''):
for completion in completions:
params = []
if hasattr(completion, 'params'):
params = [p.description for p in completion.params
if ARGUMENT_RE.match(p.description)]
params = [p.description for p in completion.params if p]
if completion.parent().type == 'class':
_methods.append({
'parent': completion.parent().name,
Expand Down Expand Up @@ -288,50 +292,8 @@ def _top_definition(self, definition):
return d
return definition

def _extract_range_jedi_0_9_0(self, definition):
from jedi import common
from jedi.parser.utils import load_parser
# get the scope range
try:
if definition.type in ['class', 'function'] and hasattr(definition, '_definition'):
scope = definition._definition
start_line = scope.start_pos[0] - 1
start_column = scope.start_pos[1]
end_line = scope.end_pos[0] - 1
end_column = scope.end_pos[1]
# get the lines
path = definition._definition.get_parent_until().path
parser = load_parser(path)
lines = common.splitlines(parser.source)
lines[end_line] = lines[end_line][:end_column]
# trim the lines
lines = lines[start_line:end_line + 1]
lines = '\n'.join(lines).rstrip().split('\n')
end_line = start_line + len(lines) - 1
end_column = len(lines[-1]) - 1
else:
symbol = definition._name
start_line = symbol.start_pos[0] - 1
start_column = symbol.start_pos[1]
end_line = symbol.end_pos[0] - 1
end_column = symbol.end_pos[1]
return {
'start_line': start_line,
'start_column': start_column,
'end_line': end_line,
'end_column': end_column
}
except Exception as e:
return {
'start_line': definition.line - 1,
'start_column': definition.column,
'end_line': definition.line - 1,
'end_column': definition.column
}

def _extract_range_jedi_0_10_1(self, definition):
from jedi import common
from jedi.parser.python import parse
def _extract_range_jedi_0_11_1(self, definition):
from parso.utils import split_lines
# get the scope range
try:
if definition.type in ['class', 'function']:
Expand All @@ -341,7 +303,7 @@ def _extract_range_jedi_0_10_1(self, definition):
start_column = scope.start_pos[1]
# get the lines
code = scope.get_code(include_prefix=False)
lines = common.splitlines(code)
lines = split_lines(code)
# trim the lines
lines = '\n'.join(lines).rstrip().split('\n')
end_line = start_line + len(lines) - 1
Expand Down Expand Up @@ -380,10 +342,7 @@ def _extract_range(self, definition):
last character of actual code. That's why we extract the lines that
make up our scope and trim the trailing whitespace.
"""
if jedi.__version__ in ('0.9.0', '0.10.0'):
return self._extract_range_jedi_0_9_0(definition)
else:
return self._extract_range_jedi_0_10_1(definition)
return self._extract_range_jedi_0_11_1(definition)

def _get_definitionsx(self, definitions, identifier=None, ignoreNoModulePath=False):
"""Serialize response to be read from VSCode.
Expand Down Expand Up @@ -680,22 +639,17 @@ def watch(self):
if __name__ == '__main__':
cachePrefix = 'v'
modulesToLoad = ''
if len(sys.argv) > 0 and sys.argv[1] == 'preview':
jediPath = os.path.join(os.path.dirname(__file__), 'preview')
jediPreview = True
if len(sys.argv) > 2:
modulesToLoad = sys.argv[2]
elif len(sys.argv) > 0 and sys.argv[1] == 'custom':
if len(sys.argv) > 2 and sys.argv[1] == 'custom':
jediPath = sys.argv[2]
jediPreview = True
cachePrefix = 'custom_v'
if len(sys.argv) > 3:
modulesToLoad = sys.argv[3]
else:
#std
jediPath = os.path.join(os.path.dirname(__file__), 'release')
if len(sys.argv) > 2:
modulesToLoad = sys.argv[2]
#release
jediPath = os.path.dirname(__file__)
if len(sys.argv) > 1:
modulesToLoad = sys.argv[1]

sys.path.insert(0, jediPath)
import jedi
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
58 changes: 58 additions & 0 deletions pythonFiles/parso/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
r"""
Parso is a Python parser that supports error recovery and round-trip parsing
for different Python versions (in multiple Python versions). Parso is also able
to list multiple syntax errors in your python file.

Parso has been battle-tested by jedi_. It was pulled out of jedi to be useful
for other projects as well.

Parso consists of a small API to parse Python and analyse the syntax tree.

.. _jedi: https://github.com/davidhalter/jedi

A simple example:

>>> import parso
>>> module = parso.parse('hello + 1', version="3.6")
>>> expr = module.children[0]
>>> expr
PythonNode(arith_expr, [<Name: hello@1,0>, <Operator: +>, <Number: 1>])
>>> print(expr.get_code())
hello + 1
>>> name = expr.children[0]
>>> name
<Name: hello@1,0>
>>> name.end_pos
(1, 5)
>>> expr.end_pos
(1, 9)

To list multiple issues:

>>> grammar = parso.load_grammar()
>>> module = grammar.parse('foo +\nbar\ncontinue')
>>> error1, error2 = grammar.iter_errors(module)
>>> error1.message
'SyntaxError: invalid syntax'
>>> error2.message
"SyntaxError: 'continue' not properly in loop"
"""

from parso.parser import ParserSyntaxError
from parso.grammar import Grammar, load_grammar
from parso.utils import split_lines, python_bytes_to_unicode


__version__ = '0.1.1'


def parse(code=None, **kwargs):
"""
A utility function to avoid loading grammars.
Params are documented in :py:meth:`parso.Grammar.parse`.

:param str version: The version used by :py:func:`parso.load_grammar`.
"""
version = kwargs.pop('version', None)
grammar = load_grammar(version=version)
return grammar.parse(code, **kwargs)
103 changes: 103 additions & 0 deletions pythonFiles/parso/_compatibility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""
To ensure compatibility from Python ``2.6`` - ``3.3``, a module has been
created. Clearly there is huge need to use conforming syntax.
"""
import sys
import platform

# Cannot use sys.version.major and minor names, because in Python 2.6 it's not
# a namedtuple.
py_version = int(str(sys.version_info[0]) + str(sys.version_info[1]))

# unicode function
try:
unicode = unicode
except NameError:
unicode = str

is_pypy = platform.python_implementation() == 'PyPy'


def use_metaclass(meta, *bases):
""" Create a class with a metaclass. """
if not bases:
bases = (object,)
return meta("HackClass", bases, {})


try:
encoding = sys.stdout.encoding
if encoding is None:
encoding = 'utf-8'
except AttributeError:
encoding = 'ascii'


def u(string):
"""Cast to unicode DAMMIT!
Written because Python2 repr always implicitly casts to a string, so we
have to cast back to a unicode (and we now that we always deal with valid
unicode, because we check that in the beginning).
"""
if py_version >= 30:
return str(string)

if not isinstance(string, unicode):
return unicode(str(string), 'UTF-8')
return string


try:
FileNotFoundError = FileNotFoundError
except NameError:
FileNotFoundError = IOError


def utf8_repr(func):
"""
``__repr__`` methods in Python 2 don't allow unicode objects to be
returned. Therefore cast them to utf-8 bytes in this decorator.
"""
def wrapper(self):
result = func(self)
if isinstance(result, unicode):
return result.encode('utf-8')
else:
return result

if py_version >= 30:
return func
else:
return wrapper


try:
from functools import total_ordering
except ImportError:
# Python 2.6
def total_ordering(cls):
"""Class decorator that fills in missing ordering methods"""
convert = {
'__lt__': [('__gt__', lambda self, other: not (self < other or self == other)),
('__le__', lambda self, other: self < other or self == other),
('__ge__', lambda self, other: not self < other)],
'__le__': [('__ge__', lambda self, other: not self <= other or self == other),
('__lt__', lambda self, other: self <= other and not self == other),
('__gt__', lambda self, other: not self <= other)],
'__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),
('__ge__', lambda self, other: self > other or self == other),
('__le__', lambda self, other: not self > other)],
'__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),
('__gt__', lambda self, other: self >= other and not self == other),
('__lt__', lambda self, other: not self >= other)]
}
roots = set(dir(cls)) & set(convert)
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in convert[root]:
if opname not in roots:
opfunc.__name__ = opname
opfunc.__doc__ = getattr(int, opname).__doc__
setattr(cls, opname, opfunc)
return cls
Loading