Repository: spyder-ide/spyder

Issue:
Auto-indent Incorrect following line starting with return as part of variable name.
## Description of your problem

Following an assignment to a variable starting with the string "return" as part of the variable name, e.g. "returns", in a function definition, the auto-indent for the following line is incorrectly set as if following a return statement.

**What steps will reproduce the problem?**

1. Create a python file containing the following code:

```
def some_func():
    returns = 10
```

2. Press enter with the cursor at the end of the second line.

**What is the expected output? What do you see instead?**
I expect the cursor to indent to the same level as the second line. Instead the cursor indents to same level as the first line.

## Versions and main components

* Spyder Version: 3.1.4
* Python Version: 3.6.0
* Qt Version: 5.6.2
* PyQt Version: 5.6.0
* Operating system: Windows 10 (Version 1703 OS Build 15063.296)

## Dependencies

Please go to the menu entry `Help > Optional Dependencies` (or
`Help > Dependencies`), press the button `Copy to clipboard`
and paste the contents below:
jedi >=0.9.0     :  0.9.0 (OK)
matplotlib >=1.0 :  2.0.0 (OK)
nbconvert >=4.0  :  4.2.0 (OK)
numpy >=1.7      :  1.11.3 (OK)
pandas >=0.13.1  :  0.20.1 (OK)
pep8 >=0.6       :  1.7.0 (OK)
pyflakes >=0.6.0 :  1.5.0 (OK)
pygments >=2.0   :  2.1.3 (OK)
pylint >=0.25    :  1.6.4 (OK)
qtconsole >=4.2.0:  4.2.1 (OK)
rope >=0.9.4     :  0.9.4-1 (OK)
sphinx >=0.6.6   :  1.5.1 (OK)
sympy >=0.7.3    :  1.0 (OK)



Discussion:

Resolving patch:
diff --git a/spyder/widgets/sourcecode/codeeditor.py b/spyder/widgets/sourcecode/codeeditor.py
--- a/spyder/widgets/sourcecode/codeeditor.py
+++ b/spyder/widgets/sourcecode/codeeditor.py
@@ -1929,7 +1929,7 @@ def fix_indent(self, forward=True, comment_or_string=False):
                not prevtext.strip().startswith('#') and prevtext) or
                prevtext):
 
-                if not prevtext.strip().startswith('return') and \
+                if not "return" in prevtext.strip().split()[:1] and \
                     (prevtext.strip().endswith(')') or
                      prevtext.strip().endswith(']') or
                      prevtext.strip().endswith('}')):
@@ -1978,7 +1978,7 @@ def fix_indent(self, forward=True, comment_or_string=False):
                 (prevtext.endswith('continue') or
                  prevtext.endswith('break') or
                  prevtext.endswith('pass') or
-                 (prevtext.strip().startswith("return") and
+                 ("return" in prevtext.strip().split()[:1] and
                   len(re.split(r'\(|\{|\[', prevtext)) ==
                   len(re.split(r'\)|\}|\]', prevtext)))):
                 # Unindent


Test patch:
diff --git a/spyder/widgets/sourcecode/tests/test_autoindent.py b/spyder/widgets/sourcecode/tests/test_autoindent.py
--- a/spyder/widgets/sourcecode/tests/test_autoindent.py
+++ b/spyder/widgets/sourcecode/tests/test_autoindent.py
@@ -156,6 +156,10 @@ def test_first_line():
         ("a = (a  #  some comment\n", "a = (a  #  some comment\n     ", "test_inline_comment"),
         ("len(a) == 1\n", "len(a) == 1\n", "test_balanced_brackets_not_ending_in_bracket"),
         ("x = f(\n", "x = f(\n      ", "test_short_open_bracket_not_hanging_indent"),
+        ("def some_func():\n    return 10\n", "def some_func():\n    return 10\n",
+         "test_return"),
+        ("def some_func():\n    returns = 10\n", "def some_func():\n    returns = 10\n    ",
+         "test_return_not_keyword"),
 
         pytest.mark.xfail(
             ("foo = 1  # Comment open parenthesis (\n",
@@ -194,6 +198,10 @@ def test_def_with_unindented_comment():
          "test_commented_brackets"),
         ("s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n", "s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n",
          "test_balanced_brackets"),
+        ("def some_func():\n\treturn 10\n", "def some_func():\n\treturn 10\n",
+         "test_return"),
+        ("def some_func():\n\treturns = 10\n", "def some_func():\n\treturns = 10\n\t",
+         "test_return_not_keyword"),
 
         # Failing test
         pytest.mark.xfail(