Repository: ipython/ipython

Issue:
%autocall is conflicting with string literals
```
In [15]: name = 'foo'

In [16]: %autocall 0
Automatic calling is: OFF

In [17]: f'{name}'
Out[17]: 'foo'

In [18]: %autocall 1
Automatic calling is: Smart

In [19]: f'{name}'
-------> f('{name}')
sample function with ('{name}',), {}

In [20]: f '{name}'
-------> f('{name}')
sample function with ('{name}',), {}
```

```
→ ipython --version
5.2.2

→ python --version 
Python 3.7.0a0
```
%autocall is conflicting with string literals
```
In [15]: name = 'foo'

In [16]: %autocall 0
Automatic calling is: OFF

In [17]: f'{name}'
Out[17]: 'foo'

In [18]: %autocall 1
Automatic calling is: Smart

In [19]: f'{name}'
-------> f('{name}')
sample function with ('{name}',), {}

In [20]: f '{name}'
-------> f('{name}')
sample function with ('{name}',), {}
```

```
→ ipython --version
5.2.2

→ python --version 
Python 3.7.0a0
```


Discussion:
Hum, this is not totally correct, you must have something else in your namespace that conflicts. 
Yep, you have to define `f` as being a function or it behave fine:

```
In [1]: name = 'foo'

In [2]: f'{name}'
Out[2]: 'foo'

In [3]: autocall 1
Automatic calling is: Smart

In [4]: f'{name}'
Out[4]: 'foo'

In [5]: def f(*args):
   ...:     print('autocall conflict')
   ...:

In [6]: f'{name}'
------> f('{name}')
autocall conflict
```

Do you want to attempt writing a fix ? 
it affects u'', r'' ... as well if a function matching this name exists
Hum, this is not totally correct, you must have something else in your namespace that conflicts. 
Yep, you have to define `f` as being a function or it behave fine:

```
In [1]: name = 'foo'

In [2]: f'{name}'
Out[2]: 'foo'

In [3]: autocall 1
Automatic calling is: Smart

In [4]: f'{name}'
Out[4]: 'foo'

In [5]: def f(*args):
   ...:     print('autocall conflict')
   ...:

In [6]: f'{name}'
------> f('{name}')
autocall conflict
```

Do you want to attempt writing a fix ? 
it affects u'', r'' ... as well if a function matching this name exists

Resolving patch:
diff --git a/IPython/core/prefilter.py b/IPython/core/prefilter.py
--- a/IPython/core/prefilter.py
+++ b/IPython/core/prefilter.py
@@ -510,6 +510,12 @@ def check(self, line_info):
         if not oinfo['found']:
             return None
 
+        ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
+        ifun = line_info.ifun
+        line = line_info.line
+        if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
+            return None
+
         if callable(oinfo['obj']) \
                and (not self.exclude_regexp.match(line_info.the_rest)) \
                and self.function_name_regexp.match(line_info.ifun):
@@ -625,7 +631,7 @@ def handle(self, line_info):
         elif esc == ESC_PAREN:
             newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
         else:
-            # Auto-paren.       
+            # Auto-paren.
             if force_auto:
                 # Don't rewrite if it is already a call.
                 do_rewrite = not the_rest.startswith('(')
@@ -646,11 +652,11 @@ def handle(self, line_info):
                 if the_rest.endswith(';'):
                     newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
                 else:
-                    newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)                
+                    newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
             else:
                 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
                 return normal_handler.handle(line_info)
-        
+
         # Display the rewritten call
         if auto_rewrite:
             self.shell.auto_rewrite_input(newcmd)


Test patch:
diff --git a/IPython/core/tests/test_autocall.py b/IPython/core/tests/test_autocall.py
--- a/IPython/core/tests/test_autocall.py
+++ b/IPython/core/tests/test_autocall.py
@@ -5,41 +5,69 @@
 we do run the test, though ultimately this functionality should all be tested
 with better-isolated tests that don't rely on the global instance in iptest.
 """
+from IPython.core.splitinput import LineInfo
+from IPython.core.prefilter import AutocallChecker
 from IPython.utils import py3compat
+from IPython.testing.globalipapp import get_ipython
+
+
+ip = get_ipython()
+
 
 @py3compat.doctest_refactor_print
 def doctest_autocall():
     """
     In [1]: def f1(a,b,c):
        ...:     return a+b+c
-       ...: 
+       ...:
 
     In [2]: def f2(a):
        ...:     return a + a
-       ...:   
+       ...:
 
-    In [3]: ;f2 a b c
-    Out[3]: 'a b ca b c'
+    In [3]: def r(x):
+       ...:     return True
+       ...:
 
-    In [4]: assert _ == "a b ca b c"
+    In [4]: ;f2 a b c
+    Out[4]: 'a b ca b c'
 
-    In [5]: ,f1 a b c
-    Out[5]: 'abc'
+    In [5]: assert _ == "a b ca b c"
 
-    In [6]: assert _ == 'abc'
+    In [6]: ,f1 a b c
+    Out[6]: 'abc'
 
-    In [7]: print _
+    In [7]: assert _ == 'abc'
+
+    In [8]: print _
     abc
 
-    In [8]: /f1 1,2,3
-    Out[8]: 6
+    In [9]: /f1 1,2,3
+    Out[9]: 6
+
+    In [10]: assert _ == 6
 
-    In [9]: assert _ == 6
+    In [11]: /f2 4
+    Out[11]: 8
 
-    In [10]: /f2 4
-    Out[10]: 8
+    In [12]: assert _ == 8
 
-    In [11]: assert _ == 8
+    In [12]: del f1, f2
 
-    In [11]: del f1, f2
+    In [13]: ,r a
+    Out[13]: True
+
+    In [14]: assert _ == True
+
+    In [15]: r'a'
+    Out[15]: 'a'
+
+    In [16]: assert _ == 'a'
     """
+
+
+def test_autocall_should_ignore_raw_strings():
+    line_info = LineInfo("r'a'")
+    pm = ip.prefilter_manager
+    ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm, config=pm.config)
+    assert ac.check(line_info) is None