import abc import re from IPython.core.splitinput import split_user_input, LineInfo from IPython.core.inputsplitter import (ESC_SHELL, ESC_SH_CAP, ESC_HELP, ESC_HELP2, ESC_MAGIC, ESC_MAGIC2, ESC_QUOTE, ESC_QUOTE2, ESC_PAREN) from IPython.core.inputsplitter import EscapedTransformer, _make_help_call, has_comment class InputTransformer(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def push(self, line): pass @abc.abstractmethod def reset(self): pass class StatelessInputTransformer(InputTransformer): """Decorator for a stateless input transformer implemented as a function.""" def __init__(self, func): self.func = func def push(self, line): return self.func(line) def reset(self): pass class CoroutineInputTransformer(InputTransformer): """Decorator for an input transformer implemented as a coroutine.""" def __init__(self, coro): # Prime it self.coro = coro() next(self.coro) def push(self, line): return self.coro.send(line) def reset(self): self.coro.send(None) @CoroutineInputTransformer def escaped_transformer(): et = EscapedTransformer() line = '' while True: line = (yield line) if not line or line.isspace(): continue lineinf = LineInfo(line) if lineinf.esc not in et.tr: continue parts = [] while line is not None: parts.append(line.rstrip('\\')) if not line.endswith('\\'): break line = (yield None) # Output lineinf = LineInfo(' '.join(parts)) line = et.tr[lineinf.esc](lineinf) _initial_space_re = re.compile(r'\s*') _help_end_re = re.compile(r"""(%{0,2} [a-zA-Z_*][\w*]* # Variable name (\.[a-zA-Z_*][\w*]*)* # .etc.etc ) (\?\??)$ # ? or ??""", re.VERBOSE) @StatelessInputTransformer def transform_help_end(line): """Translate lines with ?/?? at the end""" m = _help_end_re.search(line) if m is None or has_comment(line): return line target = m.group(1) esc = m.group(3) lspace = _initial_space_re.match(line).group(0) # If we're mid-command, put it back on the next prompt for the user. next_input = line.rstrip('?') if line.strip() != m.group(0) else None return _make_help_call(target, esc, lspace, next_input) @CoroutineInputTransformer def cellmagic(): tpl = 'get_ipython().run_cell_magic(%r, %r, %r)' line = '' while True: line = (yield line) if not line.startswith(ESC_MAGIC2): continue first = line body = [] line = (yield None) while (line is not None) and (line.strip() != ''): body.append(line) line = (yield None) # Output magic_name, _, first = first.partition(' ') magic_name = magic_name.lstrip(ESC_MAGIC2) line = tpl % (magic_name, first, '\n'.join(body))