prefilter.py
700 lines
| 24.9 KiB
| text/x-python
|
PythonLexer
|
r2244 | # encoding: utf-8 | |
|
r657 | """ | |
|
r2244 | Prefiltering components. | |
|
r2273 | Prefilters transform user input before it is exec'd by Python. These | |
transforms are used to implement additional syntax such as !ls and %magic. | |||
|
r657 | """ | |
|
r22340 | # Copyright (c) IPython Development Team. | |
# Distributed under the terms of the Modified BSD License. | |||
|
r2244 | ||
|
r12760 | from keyword import iskeyword | |
|
r657 | import re | |
|
r2244 | ||
|
r2205 | from IPython.core.autocall import IPyAutocall | |
|
r21253 | from traitlets.config.configurable import Configurable | |
|
r7437 | from IPython.core.inputsplitter import ( | |
ESC_MAGIC, | |||
ESC_QUOTE, | |||
ESC_QUOTE2, | |||
ESC_PAREN, | |||
) | |||
|
r3406 | from IPython.core.macro import Macro | |
|
r9399 | from IPython.core.splitinput import LineInfo | |
|
r2244 | ||
|
r21253 | from traitlets import ( | |
|
r22340 | List, Integer, Unicode, Bool, Instance, CRegExp | |
|
r6733 | ) | |
|
r2244 | ||
#----------------------------------------------------------------------------- | |||
# Global utilities, errors and constants | |||
#----------------------------------------------------------------------------- | |||
class PrefilterError(Exception): | |||
pass | |||
# RegExp to identify potential function names | |||
re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') | |||
# RegExp to exclude strings with this start from autocalling. In | |||
# particular, all binary operators should be excluded, so that if foo is | |||
# callable, foo OP bar doesn't become foo(OP bar), which is invalid. The | |||
# characters '!=()' don't need to be checked for, as the checkPythonChars | |||
# routine explicitely does so, to catch direct calls and rebindings of | |||
# existing names. | |||
# Warning: the '-' HAS TO BE AT THE END of the first group, otherwise | |||
# it affects the rest of the group in square brackets. | |||
re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' | |||
r'|^is |^not |^in |^and |^or ') | |||
# try to catch also methods for stuff in lists/tuples/dicts: off | |||
# (experimental). For this to work, the line_split regexp would need | |||
# to be modified so it wouldn't break things at '['. That line is | |||
# nasty enough that I shouldn't change it until I can test it _well_. | |||
#self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') | |||
# Handler Check Utilities | |||
def is_shadowed(identifier, ip): | |||
"""Is the given identifier defined in one of the namespaces which shadow | |||
the alias and magic namespaces? Note that an identifier is different | |||
than ifun, because it can not contain a '.' character.""" | |||
# This is much safer than calling ofind, which can change state | |||
return (identifier in ip.user_ns \ | |||
|
r5454 | or identifier in ip.user_global_ns \ | |
|
r12760 | or identifier in ip.ns_table['builtin']\ | |
or iskeyword(identifier)) | |||
|
r2244 | ||
#----------------------------------------------------------------------------- | |||
# Main Prefilter manager | |||
#----------------------------------------------------------------------------- | |||
|
r657 | ||
|
r2244 | ||
|
r2731 | class PrefilterManager(Configurable): | |
|
r2244 | """Main prefilter component. | |
The IPython prefilter is run on all user input before it is run. The | |||
|
r4872 | prefilter consumes lines of input and produces transformed lines of | |
|
r2273 | input. | |
The iplementation consists of two phases: | |||
1. Transformers | |||
2. Checkers and handlers | |||
Over time, we plan on deprecating the checkers and handlers and doing | |||
everything in the transformers. | |||
The transformers are instances of :class:`PrefilterTransformer` and have | |||
a single method :meth:`transform` that takes a line and returns a | |||
transformed line. The transformation can be accomplished using any | |||
|
r7273 | tool, but our current ones use regular expressions for speed. | |
|
r2273 | ||
After all the transformers have been run, the line is fed to the checkers, | |||
which are instances of :class:`PrefilterChecker`. The line is passed to | |||
|
r4872 | the :meth:`check` method, which either returns `None` or a | |
|
r2273 | :class:`PrefilterHandler` instance. If `None` is returned, the other | |
checkers are tried. If an :class:`PrefilterHandler` instance is returned, | |||
the line is passed to the :meth:`handle` method of the returned | |||
handler and no further checkers are tried. | |||
|
r4872 | ||
|
r2273 | Both transformers and checkers have a `priority` attribute, that determines | |
the order in which they are called. Smaller priorities are tried first. | |||
Both transformers and checkers also have `enabled` attribute, which is | |||
a boolean that determines if the instance is used. | |||
Users or developers can change the priority or enabled attribute of | |||
transformers or checkers, but they must call the :meth:`sort_checkers` | |||
|
r2277 | or :meth:`sort_transformers` method after changing the priority. | |
|
r657 | """ | |
|
r2244 | ||
|
r22340 | multi_line_specials = Bool(True).tag(config=True) | |
|
r20940 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) | |
|
r2244 | ||
|
r11064 | def __init__(self, shell=None, **kwargs): | |
super(PrefilterManager, self).__init__(shell=shell, **kwargs) | |||
|
r2731 | self.shell = shell | |
|
r2273 | self.init_transformers() | |
|
r2244 | self.init_handlers() | |
self.init_checkers() | |||
|
r2273 | #------------------------------------------------------------------------- | |
# API for managing transformers | |||
#------------------------------------------------------------------------- | |||
def init_transformers(self): | |||
"""Create the default transformers.""" | |||
self._transformers = [] | |||
for transformer_cls in _default_transformers: | |||
|
r2740 | transformer_cls( | |
|
r11064 | shell=self.shell, prefilter_manager=self, parent=self | |
|
r2740 | ) | |
|
r2273 | ||
def sort_transformers(self): | |||
"""Sort the transformers by priority. | |||
This must be called after the priority of a transformer is changed. | |||
The :meth:`register_transformer` method calls this automatically. | |||
""" | |||
|
r3108 | self._transformers.sort(key=lambda x: x.priority) | |
|
r2273 | ||
@property | |||
def transformers(self): | |||
"""Return a list of checkers, sorted by priority.""" | |||
return self._transformers | |||
def register_transformer(self, transformer): | |||
"""Register a transformer instance.""" | |||
if transformer not in self._transformers: | |||
self._transformers.append(transformer) | |||
self.sort_transformers() | |||
def unregister_transformer(self, transformer): | |||
"""Unregister a transformer instance.""" | |||
if transformer in self._transformers: | |||
self._transformers.remove(transformer) | |||
#------------------------------------------------------------------------- | |||
# API for managing checkers | |||
#------------------------------------------------------------------------- | |||
|
r2244 | def init_checkers(self): | |
|
r2273 | """Create the default checkers.""" | |
|
r2244 | self._checkers = [] | |
for checker in _default_checkers: | |||
|
r2740 | checker( | |
|
r11064 | shell=self.shell, prefilter_manager=self, parent=self | |
|
r2740 | ) | |
|
r2273 | ||
def sort_checkers(self): | |||
"""Sort the checkers by priority. | |||
This must be called after the priority of a checker is changed. | |||
The :meth:`register_checker` method calls this automatically. | |||
""" | |||
|
r3108 | self._checkers.sort(key=lambda x: x.priority) | |
|
r2273 | ||
@property | |||
def checkers(self): | |||
"""Return a list of checkers, sorted by priority.""" | |||
return self._checkers | |||
def register_checker(self, checker): | |||
"""Register a checker instance.""" | |||
if checker not in self._checkers: | |||
self._checkers.append(checker) | |||
self.sort_checkers() | |||
def unregister_checker(self, checker): | |||
"""Unregister a checker instance.""" | |||
if checker in self._checkers: | |||
self._checkers.remove(checker) | |||
#------------------------------------------------------------------------- | |||
|
r13905 | # API for managing handlers | |
|
r2273 | #------------------------------------------------------------------------- | |
|
r2244 | ||
def init_handlers(self): | |||
|
r2273 | """Create the default handlers.""" | |
|
r2244 | self._handlers = {} | |
self._esc_handlers = {} | |||
for handler in _default_handlers: | |||
|
r2740 | handler( | |
|
r11064 | shell=self.shell, prefilter_manager=self, parent=self | |
|
r2740 | ) | |
|
r2244 | ||
@property | |||
|
r2273 | def handlers(self): | |
"""Return a dict of all the handlers.""" | |||
return self._handlers | |||
|
r2244 | ||
def register_handler(self, name, handler, esc_strings): | |||
"""Register a handler instance by name with esc_strings.""" | |||
self._handlers[name] = handler | |||
for esc_str in esc_strings: | |||
self._esc_handlers[esc_str] = handler | |||
def unregister_handler(self, name, handler, esc_strings): | |||
"""Unregister a handler instance by name with esc_strings.""" | |||
|
r657 | try: | |
|
r2244 | del self._handlers[name] | |
except KeyError: | |||
pass | |||
for esc_str in esc_strings: | |||
h = self._esc_handlers.get(esc_str) | |||
if h is handler: | |||
del self._esc_handlers[esc_str] | |||
def get_handler_by_name(self, name): | |||
"""Get a handler by its name.""" | |||
return self._handlers.get(name) | |||
def get_handler_by_esc(self, esc_str): | |||
"""Get a handler by its escape string.""" | |||
return self._esc_handlers.get(esc_str) | |||
|
r2273 | #------------------------------------------------------------------------- | |
# Main prefiltering API | |||
#------------------------------------------------------------------------- | |||
|
r2244 | def prefilter_line_info(self, line_info): | |
|
r2273 | """Prefilter a line that has been converted to a LineInfo object. | |
This implements the checker/handler part of the prefilter pipe. | |||
""" | |||
|
r2256 | # print "prefilter_line_info: ", line_info | |
|
r2244 | handler = self.find_handler(line_info) | |
return handler.handle(line_info) | |||
def find_handler(self, line_info): | |||
"""Find a handler for the line_info by trying checkers.""" | |||
|
r2273 | for checker in self.checkers: | |
if checker.enabled: | |||
handler = checker.check(line_info) | |||
if handler: | |||
return handler | |||
|
r2244 | return self.get_handler_by_name('normal') | |
|
r2273 | def transform_line(self, line, continue_prompt): | |
"""Calls the enabled transformers in order of increasing priority.""" | |||
for transformer in self.transformers: | |||
if transformer.enabled: | |||
line = transformer.transform(line, continue_prompt) | |||
return line | |||
|
r2426 | def prefilter_line(self, line, continue_prompt=False): | |
|
r2273 | """Prefilter a single input line as text. | |
This method prefilters a single line of text by calling the | |||
transformers and then the checkers/handlers. | |||
""" | |||
|
r2244 | ||
|
r2256 | # print "prefilter_line: ", line, continue_prompt | |
|
r2244 | # All handlers *must* return a value, even if it's blank (''). | |
# save the line away in case we crash, so the post-mortem handler can | |||
|
r2256 | # record it | |
|
r2244 | self.shell._last_input_line = line | |
if not line: | |||
# Return immediately on purely empty lines, so that if the user | |||
# previously typed some whitespace that started a continuation | |||
# prompt, he can break out of that loop with just an empty line. | |||
# This is how the default python prompt works. | |||
return '' | |||
|
r2273 | ||
# At this point, we invoke our transformers. | |||
if not continue_prompt or (continue_prompt and self.multi_line_specials): | |||
line = self.transform_line(line, continue_prompt) | |||
# Now we compute line_info for the checkers and handlers | |||
|
r2244 | line_info = LineInfo(line, continue_prompt) | |
|
r4872 | ||
|
r2244 | # the input history needs to track even empty lines | |
stripped = line.strip() | |||
|
r657 | ||
|
r2273 | normal_handler = self.get_handler_by_name('normal') | |
|
r2244 | if not stripped: | |
|
r2245 | return normal_handler.handle(line_info) | |
|
r670 | ||
|
r2244 | # special handlers are only allowed for single line statements | |
if continue_prompt and not self.multi_line_specials: | |||
|
r2245 | return normal_handler.handle(line_info) | |
|
r670 | ||
|
r2256 | prefiltered = self.prefilter_line_info(line_info) | |
# print "prefiltered line: %r" % prefiltered | |||
return prefiltered | |||
|
r657 | ||
|
r2414 | def prefilter_lines(self, lines, continue_prompt=False): | |
|
r2244 | """Prefilter multiple input lines of text. | |
|
r670 | ||
|
r2273 | This is the main entry point for prefiltering multiple lines of | |
input. This simply calls :meth:`prefilter_line` for each line of | |||
input. | |||
This covers cases where there are multiple lines in the user entry, | |||
|
r2244 | which is the case when the user goes back to a multiline history | |
entry and presses enter. | |||
""" | |||
|
r2435 | llines = lines.rstrip('\n').split('\n') | |
# We can get multiple lines in one shot, where multiline input 'blends' | |||
# into one line, in cases like recalling from the readline history | |||
# buffer. We need to make sure that in such cases, we correctly | |||
# communicate downstream which line is first and which are continuation | |||
# ones. | |||
if len(llines) > 1: | |||
out = '\n'.join([self.prefilter_line(line, lnum>0) | |||
for lnum, line in enumerate(llines) ]) | |||
else: | |||
out = self.prefilter_line(llines[0], continue_prompt) | |||
|
r4872 | ||
|
r2435 | return out | |
|
r657 | ||
|
r2273 | #----------------------------------------------------------------------------- | |
# Prefilter transformers | |||
#----------------------------------------------------------------------------- | |||
|
r2731 | class PrefilterTransformer(Configurable): | |
|
r2273 | """Transform a line of user input.""" | |
|
r22330 | priority = Integer(100).tag(config=True) | |
|
r2731 | # Transformers don't currently use shell or prefilter_manager, but as we | |
# move away from checkers and handlers, they will need them. | |||
|
r20940 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) | |
prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) | |||
|
r22330 | enabled = Bool(True).tag(config=True) | |
|
r2273 | ||
|
r11064 | def __init__(self, shell=None, prefilter_manager=None, **kwargs): | |
|
r2740 | super(PrefilterTransformer, self).__init__( | |
|
r11064 | shell=shell, prefilter_manager=prefilter_manager, **kwargs | |
|
r2740 | ) | |
|
r2273 | self.prefilter_manager.register_transformer(self) | |
def transform(self, line, continue_prompt): | |||
"""Transform a line, returning the new one.""" | |||
return None | |||
def __repr__(self): | |||
return "<%s(priority=%r, enabled=%r)>" % ( | |||
self.__class__.__name__, self.priority, self.enabled) | |||
|
r2244 | #----------------------------------------------------------------------------- | |
# Prefilter checkers | |||
#----------------------------------------------------------------------------- | |||
|
r657 | ||
|
r2731 | class PrefilterChecker(Configurable): | |
|
r2244 | """Inspect an input line and return a handler for that line.""" | |
|
r657 | ||
|
r22330 | priority = Integer(100).tag(config=True) | |
|
r20940 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) | |
prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) | |||
|
r22330 | enabled = Bool(True).tag(config=True) | |
|
r657 | ||
|
r11064 | def __init__(self, shell=None, prefilter_manager=None, **kwargs): | |
|
r2740 | super(PrefilterChecker, self).__init__( | |
|
r11064 | shell=shell, prefilter_manager=prefilter_manager, **kwargs | |
|
r2740 | ) | |
|
r2273 | self.prefilter_manager.register_checker(self) | |
|
r657 | ||
|
r2244 | def check(self, line_info): | |
|
r2273 | """Inspect line_info and return a handler instance or None.""" | |
|
r657 | return None | |
|
r2273 | def __repr__(self): | |
return "<%s(priority=%r, enabled=%r)>" % ( | |||
self.__class__.__name__, self.priority, self.enabled) | |||
|
r2244 | ||
class EmacsChecker(PrefilterChecker): | |||
|
r22330 | priority = Integer(100).tag(config=True) | |
enabled = Bool(False).tag(config=True) | |||
|
r2244 | ||
def check(self, line_info): | |||
"Emacs ipython-mode tags certain input lines." | |||
if line_info.line.endswith('# PYTHON-MODE'): | |||
return self.prefilter_manager.get_handler_by_name('emacs') | |||
else: | |||
return None | |||
|
r3406 | class MacroChecker(PrefilterChecker): | |
|
r4872 | ||
|
r22330 | priority = Integer(250).tag(config=True) | |
|
r4872 | ||
|
r3406 | def check(self, line_info): | |
obj = self.shell.user_ns.get(line_info.ifun) | |||
if isinstance(obj, Macro): | |||
return self.prefilter_manager.get_handler_by_name('macro') | |||
else: | |||
return None | |||
|
r2244 | class IPyAutocallChecker(PrefilterChecker): | |
|
r22330 | priority = Integer(300).tag(config=True) | |
|
r2244 | ||
def check(self, line_info): | |||
"Instances of IPyAutocall in user_ns get autocalled immediately" | |||
obj = self.shell.user_ns.get(line_info.ifun, None) | |||
if isinstance(obj, IPyAutocall): | |||
obj.set_ip(self.shell) | |||
return self.prefilter_manager.get_handler_by_name('auto') | |||
else: | |||
return None | |||
class AssignmentChecker(PrefilterChecker): | |||
|
r22330 | priority = Integer(600).tag(config=True) | |
|
r2244 | ||
def check(self, line_info): | |||
"""Check to see if user is assigning to a var for the first time, in | |||
which case we want to avoid any sort of automagic / autocall games. | |||
|
r4872 | ||
|
r2244 | This allows users to assign to either alias or magic names true python | |
variables (the magic/alias systems always take second seat to true | |||
python code). E.g. ls='hi', or ls,that=1,2""" | |||
|
r2256 | if line_info.the_rest: | |
if line_info.the_rest[0] in '=,': | |||
return self.prefilter_manager.get_handler_by_name('normal') | |||
|
r2244 | else: | |
return None | |||
|
r657 | ||
|
r2244 | class AutoMagicChecker(PrefilterChecker): | |
|
r657 | ||
|
r22330 | priority = Integer(700).tag(config=True) | |
|
r657 | ||
|
r2244 | def check(self, line_info): | |
"""If the ifun is magic, and automagic is on, run it. Note: normal, | |||
non-auto magic would already have been triggered via '%' in | |||
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.""" | |||
|
r6908 | if not self.shell.automagic or not self.shell.find_magic(line_info.ifun): | |
|
r2244 | return None | |
# We have a likely magic method. Make sure we should actually call it. | |||
|
r2619 | if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials: | |
|
r2244 | return None | |
head = line_info.ifun.split('.',1)[0] | |||
if is_shadowed(head, self.shell): | |||
return None | |||
return self.prefilter_manager.get_handler_by_name('magic') | |||
class PythonOpsChecker(PrefilterChecker): | |||
|
r22330 | priority = Integer(900).tag(config=True) | |
|
r2244 | ||
def check(self, line_info): | |||
"""If the 'rest' of the line begins with a function call or pretty much | |||
any python operator, we should simply execute the line (regardless of | |||
whether or not there's a possible autocall expansion). This avoids | |||
spurious (and very confusing) geattr() accesses.""" | |||
if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': | |||
return self.prefilter_manager.get_handler_by_name('normal') | |||
else: | |||
return None | |||
class AutocallChecker(PrefilterChecker): | |||
|
r22330 | priority = Integer(1000).tag(config=True) | |
|
r2244 | ||
|
r22338 | function_name_regexp = CRegExp(re_fun_name, | |
help="RegExp to identify potential function names." | |||
).tag(config=True) | |||
exclude_regexp = CRegExp(re_exclude_auto, | |||
help="RegExp to exclude strings with this start from autocalling." | |||
).tag(config=True) | |||
|
r6733 | ||
|
r2244 | def check(self, line_info): | |
"Check if the initial word/function is callable and autocall is on." | |||
if not self.shell.autocall: | |||
return None | |||
oinfo = line_info.ofind(self.shell) # This can mutate state via getattr | |||
if not oinfo['found']: | |||
return None | |||
|
r4872 | ||
|
r2244 | if callable(oinfo['obj']) \ | |
|
r6733 | and (not self.exclude_regexp.match(line_info.the_rest)) \ | |
and self.function_name_regexp.match(line_info.ifun): | |||
|
r2244 | return self.prefilter_manager.get_handler_by_name('auto') | |
else: | |||
return None | |||
#----------------------------------------------------------------------------- | |||
# Prefilter handlers | |||
#----------------------------------------------------------------------------- | |||
|
r2731 | class PrefilterHandler(Configurable): | |
|
r2244 | ||
|
r4046 | handler_name = Unicode('normal') | |
|
r2244 | esc_strings = List([]) | |
|
r20940 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) | |
prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) | |||
|
r2244 | ||
|
r11064 | def __init__(self, shell=None, prefilter_manager=None, **kwargs): | |
|
r2740 | super(PrefilterHandler, self).__init__( | |
|
r11064 | shell=shell, prefilter_manager=prefilter_manager, **kwargs | |
|
r2740 | ) | |
|
r2244 | self.prefilter_manager.register_handler( | |
self.handler_name, | |||
self, | |||
self.esc_strings | |||
) | |||
def handle(self, line_info): | |||
|
r2256 | # print "normal: ", line_info | |
|
r2244 | """Handle normal input lines. Use as a template for handlers.""" | |
# With autoindent on, we need some way to exit the input loop, and I | |||
# don't want to force the user to have to backspace all the way to | |||
# clear the line. The rule will be in this case, that either two | |||
# lines of pure whitespace in a row, or a line of pure whitespace but | |||
# of a size different to the indent level, will exit the input loop. | |||
line = line_info.line | |||
continue_prompt = line_info.continue_prompt | |||
|
r2419 | if (continue_prompt and | |
self.shell.autoindent and | |||
line.isspace() and | |||
|
r3756 | 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2): | |
|
r2244 | line = '' | |
return line | |||
|
r2256 | def __str__(self): | |
return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) | |||
|
r2244 | ||
|
r3406 | class MacroHandler(PrefilterHandler): | |
|
r4046 | handler_name = Unicode("macro") | |
|
r4872 | ||
|
r3406 | def handle(self, line_info): | |
obj = self.shell.user_ns.get(line_info.ifun) | |||
pre_space = line_info.pre_whitespace | |||
line_sep = "\n" + pre_space | |||
return pre_space + line_sep.join(obj.value.splitlines()) | |||
|
r2244 | class MagicHandler(PrefilterHandler): | |
|
r4046 | handler_name = Unicode('magic') | |
|
r2245 | esc_strings = List([ESC_MAGIC]) | |
|
r2244 | ||
def handle(self, line_info): | |||
"""Execute magic functions.""" | |||
ifun = line_info.ifun | |||
the_rest = line_info.the_rest | |||
|
r5352 | cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace, | |
(ifun + " " + the_rest)) | |||
|
r2244 | return cmd | |
class AutoHandler(PrefilterHandler): | |||
|
r4046 | handler_name = Unicode('auto') | |
|
r2244 | esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) | |
def handle(self, line_info): | |||
|
r2731 | """Handle lines which can be auto-executed, quoting if requested.""" | |
|
r2244 | line = line_info.line | |
ifun = line_info.ifun | |||
the_rest = line_info.the_rest | |||
|
r4744 | esc = line_info.esc | |
|
r2244 | continue_prompt = line_info.continue_prompt | |
|
r6912 | obj = line_info.ofind(self.shell)['obj'] | |
|
r2244 | ||
# This should only be active for single-line input! | |||
if continue_prompt: | |||
return line | |||
force_auto = isinstance(obj, IPyAutocall) | |||
|
r5298 | ||
# User objects sometimes raise exceptions on attribute access other | |||
# than AttributeError (we've seen it in the past), so it's safest to be | |||
# ultra-conservative here and catch all. | |||
try: | |||
auto_rewrite = obj.rewrite | |||
except Exception: | |||
auto_rewrite = True | |||
|
r4872 | ||
|
r4744 | if esc == ESC_QUOTE: | |
|
r2244 | # Auto-quote splitting on whitespace | |
newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) | |||
|
r4744 | elif esc == ESC_QUOTE2: | |
|
r2244 | # Auto-quote whole string | |
newcmd = '%s("%s")' % (ifun,the_rest) | |||
|
r4744 | elif esc == ESC_PAREN: | |
|
r2244 | newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) | |
else: | |||
|
r5654 | # Auto-paren. | |
if force_auto: | |||
# Don't rewrite if it is already a call. | |||
do_rewrite = not the_rest.startswith('(') | |||
|
r2244 | else: | |
|
r5654 | 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 | |||
|
r2244 | else: | |
|
r5654 | do_rewrite = True |