From 355e7ddbcf963816e6d2c1eda2bf0cb961b79fa0 2011-11-20 16:11:58 From: Thomas Kluyver Date: 2011-11-20 16:11:58 Subject: [PATCH] Copy EvalFormatter and FullEvalFormatter from prompt-manager branch. --- diff --git a/IPython/utils/text.py b/IPython/utils/text.py index cfec757..01d3d8d 100644 --- a/IPython/utils/text.py +++ b/IPython/utils/text.py @@ -597,33 +597,52 @@ def wrap_paragraphs(text, ncols=80): return out_ps - class EvalFormatter(Formatter): """A String Formatter that allows evaluation of simple expressions. - - Any time a format key is not found in the kwargs, - it will be tried as an expression in the kwargs namespace. - + + Note that this version interprets a : as specifying a format string (as per + standard string formatting), so if slicing is required, you must explicitly + create a slice. + This is to be used in templating cases, such as the parallel batch script templates, where simple arithmetic on arguments is useful. Examples -------- + + In [1]: f = EvalFormatter() + In [2]: f.format('{n//4}', n=8) + Out [2]: '2' + + In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello") + Out [3]: 'll' + """ + def get_field(self, name, args, kwargs): + v = eval(name, kwargs) + return v, name - In [1]: f = EvalFormatter() +class FullEvalFormatter(Formatter): + """A String Formatter that allows evaluation of simple expressions. + + Any time a format key is not found in the kwargs, + it will be tried as an expression in the kwargs namespace. + + Note that this version allows slicing using [1:2], so you cannot specify + a format string. Use :class:`EvalFormatter` to permit format strings. + + Examples + -------- + + In [1]: f = FullEvalFormatter() In [2]: f.format('{n//4}', n=8) Out[2]: '2' - - In [3]: f.format('{list(range(3))}') - Out[3]: '[0, 1, 2]' + + In [3]: f.format('{list(range(5))[2:4]}') + Out[3]: '[2, 3]' In [4]: f.format('{3*2}') Out[4]: '6' """ - - # should we allow slicing by disabling the format_spec feature? - allow_slicing = True - # copied from Formatter._vformat with minor changes to allow eval # and replace the format_spec code with slicing def _vformat(self, format_string, args, kwargs, used_args, recursion_depth): @@ -640,12 +659,11 @@ class EvalFormatter(Formatter): # if there's a field, output it if field_name is not None: # this is some markup, find the object and do - # the formatting + # the formatting - if self.allow_slicing and format_spec: + if format_spec: # override format spec, to allow slicing: field_name = ':'.join([field_name, format_spec]) - format_spec = '' # eval the contents of the field for the object # to be formatted @@ -654,12 +672,8 @@ class EvalFormatter(Formatter): # do any conversion on the resulting object obj = self.convert_field(obj, conversion) - # expand the format spec, if needed - format_spec = self._vformat(format_spec, args, kwargs, - used_args, recursion_depth-1) - # format the object and append to the result - result.append(self.format_field(obj, format_spec)) + result.append(self.format_field(obj, '')) return ''.join(result)