Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

#342: Try to recover as intelligently as possible if user calls magic(). #352

Closed
wants to merge 3 commits into from

2 participants

@dwf

This was annoying me from the perspective of force-of-habit typing quit() (system install at the lab of IPython 0.8.3 (!!!!!) requires it) but in general, people typing some_magic() with automagic on and expecting results might be awfully surprised by the NameError that results.

This attempts to address the problem in the following way:

  • Check if whatever precedes the first paren in line_info.ifun is a magic, and of course is not shadowed by something in the user namespace
  • Throw out everything after the first paren, as well as the contents of line_info.the_rest (trying to sensibly convert function call syntax to magic-calling syntax in a general way doesn't seem prudent or possible)
  • Visually rewrite as ----> %some_magic so that the user has some clue that what he typed was interpreted as a magic but that the subsequent parenthesized arguments were ignored.

The result looks something like this:

In [6]: quit(5, 4, 3)
------> %quit
dwf@strafe:~$ 

Ideally then, individual magics, if they require arguments, will complain about not receiving them, and in the process demonstrate their usage with the correct %foo bar baz way of calling them.

This pull request replaces #345.

@fperez
Owner

How is this pull related to #345?

@dwf

How is this pull related to #345?

It replaces it and solves the problem more generally. I meant to close the old pull request and in fact clicked the button to do so but was apparently the victim of a network hiccup. The Canadian inter-tubes are still thawing out from the winter, I guess...

@fperez
Owner

OK, looking at the code I think I understand better. But I'm not convinced we should add more input handling logic of this kind. Basically, I think if someone types foo(), then they mean a python call, not a magic. Granted, it may take a little bit to realize that ipython offers two overlapping systems, one for "commands" (magics) and one for pure python code, but anyone using a tool like ipython should figure that out pretty quickly.

Now, as for #342, I think we can address that one slightly differently, but I need to play with some ideas.

But I'm reluctant to add even more text input special-casing, as much of our code on that front is already fairly brittle. What do you think?

@fperez
Owner

BTW, I'm on IRC (freenode, #ipython) if you want to chat live on these two for a moment... That may be more efficient.

@dwf

I'm not entirely sure, either. @tk suggested that magic() ought to map to %magic for more than just %quit and %exit, and I went further with magic(...) mapping to %magic, but that last step might be too far.

I'll hop on IRC, just need to download a client on this machine. :)

@dwf

After discussing it with Fernando it was decided this was overkill, and #352 will be reopened.

@dwf dwf closed this
@damianavila damianavila referenced this pull request from a commit
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.
Showing with 16 additions and 2 deletions.
  1. +16 −2 IPython/core/prefilter.py
View
18 IPython/core/prefilter.py
@@ -688,14 +688,19 @@ def check(self, line_info):
check_esc_chars. This just checks for automagic. Also, before
triggering the magic handler, make sure that there is nothing in the
user namespace which could shadow it."""
- if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
+ ifun = line_info.ifun
+ # Try to recover if someone mistakenly tries to call quit(),
+ # exit(), Exit(), guiref()... magicname plus paren...
+ is_magic_w_paren = hasattr(self.shell, 'magic_' + ifun.split('(', 1)[0])
+ if not self.shell.automagic or (not hasattr(self.shell,'magic_'+ifun)
+ and not is_magic_w_paren):
return None
# We have a likely magic method. Make sure we should actually call it.
if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
return None
- head = line_info.ifun.split('.',1)[0]
+ head = ifun.split('(', 1)[0].split('.',1)[0]
if is_shadowed(head, self.shell):
return None
@@ -869,6 +874,15 @@ def handle(self, line_info):
"""Execute magic functions."""
ifun = line_info.ifun
the_rest = line_info.the_rest
+ # Try to accomodate magic calls with erroneous parens
+ if '(' in ifun:
+ ifun = ifun.split('(', 1)[0]
+ # Just ignore anything after the open paren. The auto_rewrite_input
+ # will make clear that the input was rewritten, and individual
+ # magics should print a useful error message that show how to call.
+ the_rest = ''
+ self.shell.auto_rewrite_input(ESC_MAGIC + ifun)
+
cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
make_quoted_expr(ifun + " " + the_rest))
return cmd
Something went wrong with that request. Please try again.