From c97e1732eee6806dd85d99f592a6dbab811df5c8 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 27 Jul 2014 12:53:18 +0200 Subject: [PATCH] Operator statement wrapper was missing (fixes #436) --- jedi/evaluate/__init__.py | 9 ++++++--- jedi/evaluate/analysis.py | 2 +- jedi/parser/__init__.py | 1 - jedi/parser/representation.py | 11 +++++++---- test/test_integration_analysis.py | 12 ++++++++++++ 5 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 test/test_integration_analysis.py diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 944385c5..10e8411d 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -68,6 +68,7 @@ backtracking algorithm. .. todo:: nonlocal statement, needed or can be ignored? (py3k) """ +import copy import itertools from jedi._compatibility import next, hasattr, unicode @@ -133,9 +134,10 @@ class Evaluator(object): ass_details = stmt.assignment_details if ass_details and ass_details[0][1] != '=' and not isinstance(stmt, er.InstanceElement): # TODO don't check for this. - expr_list, operator = ass_details[0] + expr_list, _operator = ass_details[0] # `=` is always the last character in aug assignments -> -1 - operator = operator[:-1] + operator = copy.copy(_operator) + operator.string = operator.string[:-1] name = str(expr_list[0].name) parent = stmt.parent if isinstance(parent, (pr.SubModule, fast.Module)): @@ -333,7 +335,8 @@ class Evaluator(object): else: stmts = [] if obj.isinstance(er.Function): - stmts = er.FunctionExecution(self, obj, params).get_return_types(evaluate_generator) + stmts = er.FunctionExecution(self, obj, params) \ + .get_return_types(evaluate_generator) else: if hasattr(obj, 'execute_subscope_by_name'): try: diff --git a/jedi/evaluate/analysis.py b/jedi/evaluate/analysis.py index e036e9a3..64c457ce 100644 --- a/jedi/evaluate/analysis.py +++ b/jedi/evaluate/analysis.py @@ -63,7 +63,7 @@ class Error(object): return hash((self.path, self._start_pos, self.name)) def __repr__(self): - return '<%s %s: %s@%s,%s' % (self.__class__.__name__, + return '<%s %s: %s@%s,%s>' % (self.__class__.__name__, self.name, self.path, self._start_pos[0], self._start_pos[1]) diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index 86a31249..fbd1edac 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -322,7 +322,6 @@ class Parser(object): or tok.string in breaks and level <= 0 and not (in_lambda_param and tok.string in ',:')): try: - # print 'parse_stmt', tok, tokenize.tok_name[token_type] is_kw = tok.string in OPERATOR_KEYWORDS if tok.type == tokenize.OP or is_kw: tok_list.append( diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index b85f2fb3..41d6cc2f 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -113,13 +113,13 @@ class Base(object): @property def newline(self): """Returns the newline type for the current code.""" - #TODO: we need newline detection + # TODO: we need newline detection return "\n" @property def whitespace(self): """Returns the whitespace type for the current code: tab or space.""" - #TODO: we need tab detection + # TODO: we need tab detection return " " @Python3Method @@ -998,7 +998,7 @@ isinstance(c, tokenize.Token) else unicode(c) """ def is_assignment(tok): return isinstance(tok, Operator) and tok.string.endswith('=') \ - and not tok.string in ('>=', '<=', '==', '!=') + and tok.string not in ('>=', '<=', '==', '!=') def parse_array(token_iterator, array_type, start_pos, add_el=None): arr = Array(self._sub_module, start_pos, array_type, self) @@ -1164,7 +1164,7 @@ isinstance(c, tokenize.Token) else unicode(c) if is_assignment(tok): # This means, there is an assignment here. # Add assignments, which can be more than one - self._assignment_details.append((result, tok.string)) + self._assignment_details.append((result, tok)) result = [] is_chain = False continue @@ -1580,6 +1580,9 @@ class Operator(Simple): def __repr__(self): return "<%s: `%s`>" % (type(self).__name__, self.string) + def __str__(self): + return self.get_code() + def __eq__(self, other): """Make comparisons easy. Improves the readability of the parser.""" return self.string == other diff --git a/test/test_integration_analysis.py b/test/test_integration_analysis.py new file mode 100644 index 00000000..cfcd405d --- /dev/null +++ b/test/test_integration_analysis.py @@ -0,0 +1,12 @@ +""" +Test of keywords and ``jedi.keywords`` +""" +from jedi import Script + + +def test_issue436(): + code = "bar = 0\nbar += 'foo' + 4" + errors = set(repr(e) for e in Script(code)._analysis()) + assert len(errors) == 2 + assert '' in errors + assert '' in errors