Browse files

Add quitter checker and handler for quit(), etc. calls. Closes gh-142.

After some discussion with Fernando it was decided that detecting calls
on all magics as in pull request #352 was probably overkill. Opted for
detecting with a regex possible calls to absent Quitter objects and
rewriting them (as before), with visual notification of this rewrite.
This is done with a QuitterChecker which has priority just below that
of AutoMagicChecker.

The only case where you will get a NameError now is if you input
newlines before the starting and closing paren, but that's sufficiently
crazy as to not be worth considering (it takes one, optional,
integer argument in the real Python shell, why you'd ever need
newlines...).

Also subclassed MagicHandler to avoid doing the regex check twice (once
in the Checker and once in the Handler) and factored out the creation of
the replacement command so as to avoid potential code rot.
  • Loading branch information...
1 parent 7403baf commit d0e797be8f93758497878a444c7de972b1037d8a @dwf dwf committed Apr 10, 2011
Showing with 41 additions and 2 deletions.
  1. +41 −2 IPython/core/prefilter.py
View
43 IPython/core/prefilter.py
@@ -702,6 +702,26 @@ def check(self, line_info):
return self.prefilter_manager.get_handler_by_name('magic')
+class QuitterChecker(PrefilterChecker):
+
+ priority = Int(701, config=True)
+
+ quitter_pattern = re.compile('([qQ]uit|[eE]xit)\([^\)]*\)')
+
+ def check(self, line_info):
+ # Pattern match against a small set of builtins that IPython removes
+ # related to quitting, in case user is call()ing them.
+ ifun = line_info.ifun
+ the_rest = line_info.the_rest
+ is_quitter = self.quitter_pattern.match(ifun + the_rest) is not None
+ if not is_quitter:
+ return None
+ head = ifun.split('(', 1)[0]
+ if is_shadowed(head, self.shell):
+ return None
+ else:
+ return self.prefilter_manager.get_handler_by_name('quitter')
+
class AliasChecker(PrefilterChecker):
priority = Int(800, config=True)
@@ -867,13 +887,30 @@ class MagicHandler(PrefilterHandler):
def handle(self, line_info):
"""Execute magic functions."""
- ifun = line_info.ifun
+ ifun = line_info.ifun
the_rest = line_info.the_rest
+ return self.magic_command(line_info, ifun + " " + the_rest)
+
+ def magic_command(self, line_info, magic_str):
+ # So that we don't duplicate code in derived class, just in case
+ # this ever changes.
cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
- make_quoted_expr(ifun + " " + the_rest))
+ make_quoted_expr(magic_str))
return cmd
+class QuitterHandler(MagicHandler):
+
+ handler_name = Str('quitter')
+ esc_strings = List([])
+
+ def handle(self, line_info):
+ """Execute magic function to quit."""
+ ifun = line_info.ifun.split('(', 1)[0]
+ self.shell.auto_rewrite_input(ESC_MAGIC + ifun)
+ return self.magic_command(line_info, ifun)
+
+
class AutoHandler(PrefilterHandler):
handler_name = Str('auto')
@@ -1008,6 +1045,7 @@ def handle(self, line_info):
EscCharsChecker,
AssignmentChecker,
AutoMagicChecker,
+ QuitterChecker,
AliasChecker,
PythonOpsChecker,
AutocallChecker
@@ -1019,6 +1057,7 @@ def handle(self, line_info):
ShellEscapeHandler,
MacroHandler,
MagicHandler,
+ QuitterHandler,
AutoHandler,
HelpHandler,
EmacsHandler

0 comments on commit d0e797b

Please sign in to comment.