Skip to content
This repository

Don't transform function calls on IPyAutocall objects #1121

Merged
merged 4 commits into from over 2 years ago

4 participants

Thomas Kluyver Bradley M. Froehle Min RK Fernando Perez
Thomas Kluyver
Collaborator

Closes #1117.

Bradley M. Froehle

The lstrip isn't necessary.... or at least we don't use it later on in the_rest.startswith('[')

Collaborator

Good point.

Bradley M. Froehle
Collaborator

Anyway, looks fine to me. The logic in this section is terribly convoluted, the best I could do to disentangle it was something like

            if force_auto:
                # Don't rewrite if it is already a call.
                do_rewrite = not the_rest.startswith('(')
            else:
                if not the_rest:
                    # We only apply it to argument-less calls if the autocall
                    # parameter is set to 2.
                    do_rewrite = self.shell.autocall == 2
                elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
                    # Don't autocall in this case: item access for an object
                    # which is BOTH callable and implements __getitem__.
                    do_rewrite = False
                else:
                    do_rewrite = True

            # Figure out the rewritten command
            if do_rewrite:
                if the_rest.endswith(';'):
                    newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
                else:
                    newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
            else:
                newcmd = '%s %s' % (ifun,the_rest)

Thomas Kluyver
Collaborator

Thanks, Brad. I've tested that, and committed it here.

Bradley M. Froehle

Oops, not sure what happened here.

Bradley M. Froehle

Need to revert this change as well, as the tests expect 'autocallable ()'. My bad.

Collaborator

It's alright, it's a change I made (I should really have done a separate commit for it, but I wanted to go to bed).

The difference is that previously, if it decided not to rewrite the line, it simply used string formatting: newcmd = '%s %s' % (ifun,the_rest), which forced a single space in there. I've told it to use the default prefilter handler (normal_handler) instead. I think the new behaviour is better - when we're not rewriting it, I'd rather not change the input at all.

Min RK
Owner

I don't pretend to understand the slightly weird previous logic, but the replacement certainly looks clean and sensible, nice work!

Thomas Kluyver takluyver merged commit 7ea3e2f into from December 09, 2011
Thomas Kluyver takluyver closed this December 09, 2011
Thomas Kluyver
Collaborator

Merged, to keep the queue moving. Tests are passing - if you spot any issues with this, I'll do my best to respond to them quickly.

@fperez - tagged so you're aware of this.

Fernando Perez
Owner

Thanks, @takluyver. Good call on keeping the queue moving, otherwise we'll drown. I had a look and don't see any problems, and with the tests added we should be in good shape.

Brian E. Granger ellisonbg referenced this pull request from a commit January 10, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
44  IPython/core/prefilter.py
@@ -826,29 +826,33 @@ def handle(self, line_info):
826 826
         elif esc == ESC_PAREN:
827 827
             newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
828 828
         else:
829  
-            # Auto-paren.
830  
-            # We only apply it to argument-less calls if the autocall
831  
-            # parameter is set to 2.  We only need to check that autocall is <
832  
-            # 2, since this function isn't called unless it's at least 1.
833  
-            if not the_rest and (self.shell.autocall < 2) and not force_auto:
834  
-                newcmd = '%s %s' % (ifun,the_rest)
835  
-                auto_rewrite = False
  829
+            # Auto-paren.       
  830
+            if force_auto:
  831
+                # Don't rewrite if it is already a call.
  832
+                do_rewrite = not the_rest.startswith('(')
836 833
             else:
837  
-                if not force_auto and the_rest.startswith('['):
838  
-                    if hasattr(obj,'__getitem__'):
839  
-                        # Don't autocall in this case: item access for an object
840  
-                        # which is BOTH callable and implements __getitem__.
841  
-                        newcmd = '%s %s' % (ifun,the_rest)
842  
-                        auto_rewrite = False
843  
-                    else:
844  
-                        # if the object doesn't support [] access, go ahead and
845  
-                        # autocall
846  
-                        newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
847  
-                elif the_rest.endswith(';'):
848  
-                    newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
  834
+                if not the_rest:
  835
+                    # We only apply it to argument-less calls if the autocall
  836
+                    # parameter is set to 2.
  837
+                    do_rewrite = (self.shell.autocall >= 2)
  838
+                elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
  839
+                    # Don't autocall in this case: item access for an object
  840
+                    # which is BOTH callable and implements __getitem__.
  841
+                    do_rewrite = False
849 842
                 else:
850  
-                    newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
  843
+                    do_rewrite = True
851 844
 
  845
+            # Figure out the rewritten command
  846
+            if do_rewrite:
  847
+                if the_rest.endswith(';'):
  848
+                    newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
  849
+                else:
  850
+                    newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)                
  851
+            else:
  852
+                normal_handler = self.prefilter_manager.get_handler_by_name('normal')
  853
+                return normal_handler.handle(line_info)
  854
+        
  855
+        # Display the rewritten call
852 856
         if auto_rewrite:
853 857
             self.shell.auto_rewrite_input(newcmd)
854 858
 
4  IPython/core/tests/test_handlers.py
@@ -132,6 +132,8 @@ def test_handlers():
132 132
     run([
133 133
         ('len "abc"',       'len "abc"'),
134 134
         ('autocallable',    'autocallable()'),
  135
+        # Don't add extra brackets (gh-1117)
  136
+        ('autocallable()',    'autocallable()'),
135 137
         (",list 1 2 3",     'list("1", "2", "3")'),
136 138
         (";list 1 2 3",     'list("1 2 3")'),
137 139
         ("/len range(1,4)", 'len(range(1,4))'),
@@ -148,7 +150,7 @@ def test_handlers():
148 150
         ('len [1,2]', 'len([1,2])'),      # len doesn't support __getitem__...
149 151
         ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
150 152
         ('call_idx 1', 'call_idx(1)'),
151  
-        ('len', 'len '), # only at 2 does it auto-call on single args
  153
+        ('len', 'len'), # only at 2 does it auto-call on single args
152 154
         ])
153 155
     ip.magic('autocall 2')
154 156
     run([
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.