From af23337c959f1038801880928c6b3c797f7e173a 2017-03-10 20:06:37 From: Matthias Bussonnier Date: 2017-03-10 20:06:37 Subject: [PATCH] Expand a bit the documentation about transformers. Mostly answering questions I had myself while trying to write some stuff and while trying to get a simple example working. --- diff --git a/IPython/core/inputsplitter.py b/IPython/core/inputsplitter.py index 267b73a..1196b0d 100644 --- a/IPython/core/inputsplitter.py +++ b/IPython/core/inputsplitter.py @@ -24,7 +24,6 @@ import sys import tokenize import warnings -from IPython.utils.py3compat import cast_unicode from IPython.core.inputtransformer import (leading_indent, classic_prompt, ipy_prompt, @@ -687,7 +686,6 @@ class IPythonInputSplitter(InputSplitter): """ # We must ensure all input is pure unicode - lines = cast_unicode(lines, self.encoding) # ''.splitlines() --> [], but we need to push the empty line to transformers lines_list = lines.splitlines() if not lines_list: diff --git a/docs/source/config/inputtransforms.rst b/docs/source/config/inputtransforms.rst index 581e3b2..aa04e7e 100644 --- a/docs/source/config/inputtransforms.rst +++ b/docs/source/config/inputtransforms.rst @@ -71,6 +71,32 @@ The decorator returns a factory function which will produce instances of :class:`~IPython.core.inputtransformer.StatelessInputTransformer` using your function. +Transforming a full block +------------------------- + +Transforming a full block of python code is possible by implementing a +:class:`~IPython.core.inputtransformer.Inputtransformer` and overwriting the +``push`` and ``reset`` methods. The reset method should send the full block of +transformed text. As an example a transformer the reversed the lines from last +to first. + + from IPython.core.inputtransformer import InputTransformer + + class ReverseLineTransformer(InputTransformer): + + def __init__(self): + self.acc = [] + + def push(self, line): + self.acc.append(line) + return None + + def reset(self): + ret = '\n'.join(self.acc[::-1]) + self.acc = [] + return ret + + Coroutine transformers ---------------------- @@ -79,9 +105,28 @@ sent each line in turn, followed by ``None`` to reset it. It can yield lines, or ``None`` if it is accumulating text to yield at a later point. When reset, it should give up any code it has accumulated. +You may use :meth:`CoroutineInputTransformer.wrap` to simplify the creation of +such a transformer. + +Here is a simple :class:`CoroutineInputTransformer` that can be though of be +being the identity:: + + @CoroutineInputTransformer.wrap + def noop(): + line = '' + while True: + line = (yield line) + + ip = get_ipython() + + ip.input_splitter.logical_line_transforms.append(noop()) + ip.input_transformer_manager.logical_line_transforms.append(noop()) + This code in IPython strips a constant amount of leading indentation from each line in a cell:: + from IPython.core.inputtransformer import CoroutineInputTransformer + @CoroutineInputTransformer.wrap def leading_indent(): """Remove leading indentation.