1
0
forked from VimPlug/jedi

Merge branch 'dev' into get_code_fidelity

Conflicts:
	jedi/evaluate/docstrings.py
	jedi/parser/representation.py

Resolving merge problems:
* Introducing docstring for compiled.fake
* Partly fixing poor decision in TokenDocstring __init__
This commit is contained in:
Jean-Louis Fuchs
2014-01-28 00:37:06 +01:00
74 changed files with 4318 additions and 4322 deletions

View File

@@ -33,20 +33,23 @@ statements in this scope. Check this out:
See also :attr:`Scope.subscopes` and :attr:`Scope.statements`.
"""
from __future__ import with_statement
import os
import re
import tokenizer as tokenize
from inspect import cleandoc
from ast import literal_eval
from jedi._compatibility import next, Python3Method, encoding, unicode, is_py3k
from jedi._compatibility import next, Python3Method, encoding, unicode, is_py3
from jedi import common
from jedi import debug
from jedi import cache
from jedi.parser import tokenize
from jedi.parser import token as token_pr
SCOPE_CONTENTS = ['asserts', 'subscopes', 'imports', 'statements', 'returns']
class GetCodeState(object):
"""A helper class for passing the state of get_code in a thread-safe
manner"""
@@ -55,7 +58,6 @@ class GetCodeState(object):
def __init__(self):
self.last_pos = (0, 0)
class Base(object):
"""
This is just here to have an isinstance check, which is also used on
@@ -156,7 +158,7 @@ class Simple(Base):
def __repr__(self):
code = self.get_code().replace('\n', ' ')
if not is_py3k:
if not is_py3:
code = code.encode(encoding, 'replace')
return "<%s: %s@%s,%s>" % \
(type(self).__name__, code, self.start_pos[0], self.start_pos[1])
@@ -313,6 +315,10 @@ class Scope(Simple, IsScope):
if self.isinstance(Function):
checks += self.params + self.decorators
checks += [r for r in self.returns if r is not None]
if self.isinstance(Flow):
checks += self.inputs
if self.isinstance(ForFlow) and self.set_stmt is not None:
checks.append(self.set_stmt)
for s in checks:
if isinstance(s, Flow):
@@ -368,7 +374,6 @@ class SubModule(Scope, Module):
super(SubModule, self).__init__(self, start_pos)
self.path = path
self.global_vars = []
self._name = None
self.used_names = {}
self.temp_used_names = []
# this may be changed depending on fast_parser
@@ -394,25 +399,19 @@ class SubModule(Scope, Module):
return n
@property
@cache.underscore_memoization
def name(self):
""" This is used for the goto functions. """
if self._name is not None:
return self._name
if self.path is None:
string = '' # no path -> empty name
else:
sep = (re.escape(os.path.sep),) * 2
r = re.search(r'([^%s]*?)(%s__init__)?(\.py|\.so)?$' % sep,
self.path)
r = re.search(r'([^%s]*?)(%s__init__)?(\.py|\.so)?$' % sep, self.path)
# remove PEP 3149 names
string = re.sub('\.[a-z]+-\d{2}[mud]{0,3}$', '', r.group(1))
# positions are not real therefore choose (0, 0)
names = [(string, (0, 0))]
self._name = Name(self, names, (0, 0), (0, 0), self.use_as_parent)
return self._name
def is_builtin(self):
return not (self.path is None or self.path.endswith('.py'))
return Name(self, names, (0, 0), (0, 0), self.use_as_parent)
@property
def has_explicit_absolute_import(self):
@@ -525,7 +524,7 @@ class Function(Scope):
try:
n.append(p.get_name())
except IndexError:
debug.warning("multiple names in param %s" % n)
debug.warning("multiple names in param %s", n)
return n
def get_call_signature(self, width=72, funcname=None):
@@ -795,7 +794,7 @@ class Statement(Simple):
:type start_pos: 2-tuple of int
:param start_pos: Position (line, column) of the Statement.
"""
__slots__ = ('token_list', '_set_vars', 'as_names', '_commands',
__slots__ = ('token_list', '_set_vars', 'as_names', '_expression_list',
'_assignment_details', 'docstr', '_names_are_set_vars')
def __init__(self, module, token_list, start_pos, end_pos, parent=None,
@@ -817,7 +816,6 @@ class Statement(Simple):
self.as_names = list(as_names)
# cache
self._commands = None
self._assignment_details = []
# this is important for other scripts
@@ -834,7 +832,7 @@ class Statement(Simple):
return '%s %s ' % (''.join(pieces), assignment)
code = ''.join(assemble(*a) for a in self.assignment_details)
code += assemble(self.get_commands())
code += assemble(self.expression_list())
if self.docstr:
code += '\n"""%s"""' % self.docstr.as_string()
@@ -846,12 +844,12 @@ class Statement(Simple):
def get_set_vars(self):
""" Get the names for the statement. """
if self._set_vars is None:
self._set_vars = []
def search_calls(calls):
for call in calls:
if isinstance(call, Array):
for stmt in call:
search_calls(stmt.get_commands())
search_calls(stmt.expression_list())
elif isinstance(call, Call):
c = call
# Check if there's an execution in it, if so this is
@@ -865,12 +863,13 @@ class Statement(Simple):
continue
self._set_vars.append(call.name)
self._set_vars = []
for calls, operation in self.assignment_details:
search_calls(calls)
if not self.assignment_details and self._names_are_set_vars:
# In the case of Param, it's also a defining name without ``=``
search_calls(self.get_commands())
search_calls(self.expression_list())
return self._set_vars + self.as_names
def is_global(self):
@@ -889,17 +888,14 @@ class Statement(Simple):
would result in ``[(Name(x), '='), (Array([Name(y), Name(z)]), '=')]``.
"""
# parse statement which creates the assignment details.
self.get_commands()
self.expression_list()
return self._assignment_details
def get_commands(self):
if self._commands is None:
self._commands = ['time neeeeed'] # avoid recursions
self._commands = self._parse_statement()
return self._commands
def _parse_statement(self):
@cache.underscore_memoization
def expression_list(self):
"""
Parse a statement.
This is not done in the main parser, because it might be slow and
most of the statements won't need this data anyway. This is something
'like' a lazy execution.
@@ -966,10 +962,10 @@ class Statement(Simple):
# it's not possible to set it earlier
tok.parent = self
else:
tok = tok_temp.token
tok = tok_temp.token
start_tok_pos = tok_temp.start_pos
last_end_pos = end_pos
end_pos = tok_temp.end_pos
last_end_pos = end_pos
end_pos = tok_temp.end_pos
if first:
first = False
start_pos = start_tok_pos
@@ -1062,7 +1058,7 @@ class Statement(Simple):
stmt = Statement(self._sub_module, token_list,
start_pos, arr.end_pos)
arr.parent = stmt
stmt.token_list = stmt._commands = [arr]
stmt.token_list = stmt._expression_list = [arr]
else:
for t in stmt.token_list:
if isinstance(t, Name):
@@ -1075,12 +1071,12 @@ class Statement(Simple):
middle, tok = parse_stmt_or_arr(token_iterator, ['in'], True)
if tok != 'in' or middle is None:
debug.warning('list comprehension middle @%s' % str(start_pos))
debug.warning('list comprehension middle @%s', start_pos)
return None, tok
in_clause, tok = parse_stmt_or_arr(token_iterator)
if in_clause is None:
debug.warning('list comprehension in @%s' % str(start_pos))
debug.warning('list comprehension in @%s', start_pos)
return None, tok
return ListComprehension(st, middle, in_clause, self), tok
@@ -1101,9 +1097,9 @@ class Statement(Simple):
end_pos = tok.end_pos
else:
token_type = tok_temp.token_type
tok = tok_temp.token
start_pos = tok_temp.start_pos
end_pos = tok_temp.end_pos
tok = tok_temp.token
start_pos = tok_temp.start_pos
end_pos = tok_temp.end_pos
if is_assignment(tok):
# This means, there is an assignment here.
# Add assignments, which can be more than one
@@ -1126,9 +1122,7 @@ class Statement(Simple):
is_literal = token_type in [tokenize.STRING, tokenize.NUMBER]
if isinstance(tok, Name) or is_literal:
cls = Call
if is_literal:
cls = String if token_type == tokenize.STRING else Number
cls = Literal if is_literal else Call
call = cls(self._sub_module, tok, start_pos, end_pos, self)
if is_chain:
@@ -1149,7 +1143,7 @@ class Statement(Simple):
if result and isinstance(result[-1], StatementElement):
is_chain = True
elif tok == ',': # implies a tuple
# commands is now an array not a statement anymore
# expression is now an array not a statement anymore
t = result[0]
start_pos = t[2] if isinstance(t, tuple) else t.start_pos
@@ -1172,7 +1166,7 @@ class Statement(Simple):
self.parent,
set_name_parents=False
)
stmt._commands = result
stmt._expression_list = result
arr, break_tok = parse_array(token_iterator, Array.TUPLE,
stmt.start_pos, stmt)
result = [arr]
@@ -1213,7 +1207,7 @@ class Param(Statement):
""" get the name of the param """
n = self.get_set_vars()
if len(n) > 1:
debug.warning("Multiple param names (%s)." % n)
debug.warning("Multiple param names (%s).", n)
return n[0]
@@ -1292,25 +1286,14 @@ class Literal(StatementElement):
def get_code(self):
return self.literal + super(Literal, self).get_code()
def type_as_string(self):
return type(self.value).__name__
def __repr__(self):
if is_py3k:
if is_py3:
s = self.literal
else:
s = self.literal.encode('ascii', 'replace')
return "<%s: %s>" % (type(self).__name__, s)
class String(Literal):
pass
class Number(Literal):
pass
class Array(StatementElement):
"""
Describes the different python types for an array, but also empty