Show More
@@ -73,7 +73,8 b' from IPython.utils.pickleshare import PickleShareDB' | |||||
73 | from IPython.utils.process import system, getoutput |
|
73 | from IPython.utils.process import system, getoutput | |
74 | from IPython.utils.strdispatch import StrDispatch |
|
74 | from IPython.utils.strdispatch import StrDispatch | |
75 | from IPython.utils.syspathcontext import prepended_to_syspath |
|
75 | from IPython.utils.syspathcontext import prepended_to_syspath | |
76 | from IPython.utils.text import num_ini_spaces, format_screen, LSString, SList |
|
76 | from IPython.utils.text import (num_ini_spaces, format_screen, LSString, SList, | |
|
77 | DollarFormatter) | |||
77 | from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum, |
|
78 | from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum, | |
78 | List, Unicode, Instance, Type) |
|
79 | List, Unicode, Instance, Type) | |
79 | from IPython.utils.warn import warn, error, fatal |
|
80 | from IPython.utils.warn import warn, error, fatal | |
@@ -2571,7 +2572,7 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||||
2571 | # Utilities |
|
2572 | # Utilities | |
2572 | #------------------------------------------------------------------------- |
|
2573 | #------------------------------------------------------------------------- | |
2573 |
|
2574 | |||
2574 | def var_expand(self,cmd,depth=0): |
|
2575 | def var_expand(self, cmd, depth=0, formatter=DollarFormatter()): | |
2575 | """Expand python variables in a string. |
|
2576 | """Expand python variables in a string. | |
2576 |
|
2577 | |||
2577 | The depth argument indicates how many frames above the caller should |
|
2578 | The depth argument indicates how many frames above the caller should | |
@@ -2580,11 +2581,10 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||||
2580 | The global namespace for expansion is always the user's interactive |
|
2581 | The global namespace for expansion is always the user's interactive | |
2581 | namespace. |
|
2582 | namespace. | |
2582 | """ |
|
2583 | """ | |
2583 |
|
|
2584 | ns = self.user_ns.copy() | |
2584 | # Skip our own frame in searching for locals: |
|
2585 | ns.update(sys._getframe(depth+1).f_locals) | |
2585 | sys._getframe(depth+1).f_locals # locals |
|
2586 | ns.pop('self', None) | |
2586 | ) |
|
2587 | return formatter.format(cmd, **ns) | |
2587 | return py3compat.str_to_unicode(str(res), res.codec) |
|
|||
2588 |
|
2588 | |||
2589 | def mktempfile(self, data=None, prefix='ipython_edit_'): |
|
2589 | def mktempfile(self, data=None, prefix='ipython_edit_'): | |
2590 | """Make a new tempfile and return its filename. |
|
2590 | """Make a new tempfile and return its filename. |
@@ -45,7 +45,7 b' def test_columnize_long():' | |||||
45 | nt.assert_equals(out, '\n'.join(items+[''])) |
|
45 | nt.assert_equals(out, '\n'.join(items+[''])) | |
46 |
|
46 | |||
47 | def eval_formatter_check(f): |
|
47 | def eval_formatter_check(f): | |
48 | ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) |
|
48 | ns = dict(n=12, pi=math.pi, stuff='hello there', os=os, u=u"cafΓ©", b="cafΓ©") | |
49 | s = f.format("{n} {n//4} {stuff.split()[0]}", **ns) |
|
49 | s = f.format("{n} {n//4} {stuff.split()[0]}", **ns) | |
50 | nt.assert_equals(s, "12 3 hello") |
|
50 | nt.assert_equals(s, "12 3 hello") | |
51 | s = f.format(' '.join(['{n//%i}'%i for i in range(1,8)]), **ns) |
|
51 | s = f.format(' '.join(['{n//%i}'%i for i in range(1,8)]), **ns) | |
@@ -57,6 +57,12 b' def eval_formatter_check(f):' | |||||
57 | s = f.format("{stuff!r}", **ns) |
|
57 | s = f.format("{stuff!r}", **ns) | |
58 | nt.assert_equals(s, repr(ns['stuff'])) |
|
58 | nt.assert_equals(s, repr(ns['stuff'])) | |
59 |
|
59 | |||
|
60 | # Check with unicode: | |||
|
61 | s = f.format("{u}", **ns) | |||
|
62 | nt.assert_equals(s, ns['u']) | |||
|
63 | # This decodes in a platform dependent manner, but it shouldn't error out | |||
|
64 | s = f.format("{b}", **ns) | |||
|
65 | ||||
60 | nt.assert_raises(NameError, f.format, '{dne}', **ns) |
|
66 | nt.assert_raises(NameError, f.format, '{dne}', **ns) | |
61 |
|
67 | |||
62 | def eval_formatter_slicing_check(f): |
|
68 | def eval_formatter_slicing_check(f): |
@@ -25,6 +25,7 b' import textwrap' | |||||
25 | from string import Formatter |
|
25 | from string import Formatter | |
26 |
|
26 | |||
27 | from IPython.external.path import path |
|
27 | from IPython.external.path import path | |
|
28 | from IPython.testing.skipdoctest import skip_doctest_py3 | |||
28 | from IPython.utils import py3compat |
|
29 | from IPython.utils import py3compat | |
29 | from IPython.utils.io import nlprint |
|
30 | from IPython.utils.io import nlprint | |
30 | from IPython.utils.data import flatten |
|
31 | from IPython.utils.data import flatten | |
@@ -621,6 +622,7 b' class EvalFormatter(Formatter):' | |||||
621 | v = eval(name, kwargs) |
|
622 | v = eval(name, kwargs) | |
622 | return v, name |
|
623 | return v, name | |
623 |
|
624 | |||
|
625 | @skip_doctest_py3 | |||
624 | class FullEvalFormatter(Formatter): |
|
626 | class FullEvalFormatter(Formatter): | |
625 | """A String Formatter that allows evaluation of simple expressions. |
|
627 | """A String Formatter that allows evaluation of simple expressions. | |
626 |
|
628 | |||
@@ -635,13 +637,13 b' class FullEvalFormatter(Formatter):' | |||||
635 |
|
637 | |||
636 | In [1]: f = FullEvalFormatter() |
|
638 | In [1]: f = FullEvalFormatter() | |
637 | In [2]: f.format('{n//4}', n=8) |
|
639 | In [2]: f.format('{n//4}', n=8) | |
638 | Out[2]: '2' |
|
640 | Out[2]: u'2' | |
639 |
|
641 | |||
640 | In [3]: f.format('{list(range(5))[2:4]}') |
|
642 | In [3]: f.format('{list(range(5))[2:4]}') | |
641 | Out[3]: '[2, 3]' |
|
643 | Out[3]: u'[2, 3]' | |
642 |
|
644 | |||
643 | In [4]: f.format('{3*2}') |
|
645 | In [4]: f.format('{3*2}') | |
644 | Out[4]: '6' |
|
646 | Out[4]: u'6' | |
645 | """ |
|
647 | """ | |
646 | # copied from Formatter._vformat with minor changes to allow eval |
|
648 | # copied from Formatter._vformat with minor changes to allow eval | |
647 | # and replace the format_spec code with slicing |
|
649 | # and replace the format_spec code with slicing | |
@@ -675,8 +677,9 b' class FullEvalFormatter(Formatter):' | |||||
675 | # format the object and append to the result |
|
677 | # format the object and append to the result | |
676 | result.append(self.format_field(obj, '')) |
|
678 | result.append(self.format_field(obj, '')) | |
677 |
|
679 | |||
678 | return ''.join(result) |
|
680 | return u''.join(py3compat.cast_unicode(s) for s in result) | |
679 |
|
681 | |||
|
682 | @skip_doctest_py3 | |||
680 | class DollarFormatter(FullEvalFormatter): |
|
683 | class DollarFormatter(FullEvalFormatter): | |
681 | """Formatter allowing Itpl style $foo replacement, for names and attribute |
|
684 | """Formatter allowing Itpl style $foo replacement, for names and attribute | |
682 | access only. Standard {foo} replacement also works, and allows full |
|
685 | access only. Standard {foo} replacement also works, and allows full | |
@@ -686,13 +689,13 b' class DollarFormatter(FullEvalFormatter):' | |||||
686 | -------- |
|
689 | -------- | |
687 | In [1]: f = DollarFormatter() |
|
690 | In [1]: f = DollarFormatter() | |
688 | In [2]: f.format('{n//4}', n=8) |
|
691 | In [2]: f.format('{n//4}', n=8) | |
689 | Out[2]: '2' |
|
692 | Out[2]: u'2' | |
690 |
|
693 | |||
691 | In [3]: f.format('23 * 76 is $result', result=23*76) |
|
694 | In [3]: f.format('23 * 76 is $result', result=23*76) | |
692 | Out[3]: '23 * 76 is 1748' |
|
695 | Out[3]: u'23 * 76 is 1748' | |
693 |
|
696 | |||
694 | In [4]: f.format('$a or {b}', a=1, b=2) |
|
697 | In [4]: f.format('$a or {b}', a=1, b=2) | |
695 | Out[4]: '1 or 2' |
|
698 | Out[4]: u'1 or 2' | |
696 | """ |
|
699 | """ | |
697 | _dollar_pattern = re.compile("(.*)\$([\w\.]+)") |
|
700 | _dollar_pattern = re.compile("(.*)\$([\w\.]+)") | |
698 | def parse(self, fmt_string): |
|
701 | def parse(self, fmt_string): | |
@@ -703,7 +706,7 b' class DollarFormatter(FullEvalFormatter):' | |||||
703 | continue_from = 0 |
|
706 | continue_from = 0 | |
704 | for m in self._dollar_pattern.finditer(literal_txt): |
|
707 | for m in self._dollar_pattern.finditer(literal_txt): | |
705 | new_txt, new_field = m.group(1,2) |
|
708 | new_txt, new_field = m.group(1,2) | |
706 |
yield (new_txt, new_field, "", |
|
709 | yield (new_txt, new_field, "", None) | |
707 | continue_from = m.end() |
|
710 | continue_from = m.end() | |
708 |
|
711 | |||
709 | # Re-yield the {foo} style pattern |
|
712 | # Re-yield the {foo} style pattern |
General Comments 0
You need to be logged in to leave comments.
Login now