From c05f400f288c4eee77a853f5bfdfd1b28ca94f78 2017-06-09 13:41:27 From: Thomas Kluyver Date: 2017-06-09 13:41:27 Subject: [PATCH] Merge pull request #10638 from adityausathe/master fix for #10327 : replacing support for get_ipython().magic() --- diff --git a/IPython/core/inputtransformer.py b/IPython/core/inputtransformer.py index 3fdc641..2b27566 100644 --- a/IPython/core/inputtransformer.py +++ b/IPython/core/inputtransformer.py @@ -198,11 +198,14 @@ def _make_help_call(target, esc, lspace, next_input=None): else 'psearch' if '*' in target \ else 'pinfo' arg = " ".join([method, target]) + #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) + t_magic_name, _, t_magic_arg_s = arg.partition(' ') + t_magic_name = t_magic_name.lstrip(ESC_MAGIC) if next_input is None: - return '%sget_ipython().magic(%r)' % (lspace, arg) + return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s) else: - return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \ - (lspace, next_input, arg) + return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \ + (lspace, next_input, t_magic_name, t_magic_arg_s) # These define the transformations for the different escape characters. def _tr_system(line_info): @@ -225,11 +228,14 @@ def _tr_help(line_info): def _tr_magic(line_info): "Translate lines escaped with: %" - tpl = '%sget_ipython().magic(%r)' + tpl = '%sget_ipython().run_line_magic(%r, %r)' if line_info.line.startswith(ESC_MAGIC2): return line_info.line cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip() - return tpl % (line_info.pre, cmd) + #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) + t_magic_name, _, t_magic_arg_s = cmd.partition(' ') + t_magic_name = t_magic_name.lstrip(ESC_MAGIC) + return tpl % (line_info.pre, t_magic_name, t_magic_arg_s) def _tr_quote(line_info): "Translate lines escaped with: ," @@ -514,12 +520,15 @@ def assign_from_system(line): return assign_system_template % m.group('lhs', 'cmd') assign_magic_re = re.compile(r'{}%\s*(?P.*)'.format(_assign_pat), re.VERBOSE) -assign_magic_template = '%s = get_ipython().magic(%r)' +assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)' @StatelessInputTransformer.wrap def assign_from_magic(line): """Transform assignment from magic commands (e.g. a = %who_ls)""" m = assign_magic_re.match(line) if m is None: return line - - return assign_magic_template % m.group('lhs', 'cmd') + #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) + m_lhs, m_cmd = m.group('lhs', 'cmd') + t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ') + t_magic_name = t_magic_name.lstrip(ESC_MAGIC) + return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s) diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 6afc2a6..3a3e885 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2036,7 +2036,7 @@ class InteractiveShell(SingletonConfigurable): # FIXME: Move the color initialization to the DisplayHook, which # should be split into a prompt manager and displayhook. We probably # even need a centralize colors management object. - self.magic('colors %s' % self.colors) + self.run_line_magic('colors', self.colors) # Defined here so that it's included in the documentation @functools.wraps(magic.MagicsManager.register_function) @@ -2044,7 +2044,7 @@ class InteractiveShell(SingletonConfigurable): self.magics_manager.register_function(func, magic_kind=magic_kind, magic_name=magic_name) - def run_line_magic(self, magic_name, line): + def run_line_magic(self, magic_name, line, _stack_depth=1): """Execute the given line magic. Parameters @@ -2054,6 +2054,10 @@ class InteractiveShell(SingletonConfigurable): line : str The rest of the input line as a single string. + + _stack_depth : int + If run_line_magic() is called from magic() then _stack_depth=2. + This is added to ensure backward compatibility for use of 'get_ipython().magic()' """ fn = self.find_line_magic(magic_name) if fn is None: @@ -2066,7 +2070,9 @@ class InteractiveShell(SingletonConfigurable): # Note: this is the distance in the stack to the user's frame. # This will need to be updated if the internal calling logic gets # refactored, or else we'll be expanding the wrong variables. - stack_depth = 2 + + # Determine stack_depth depending on where run_line_magic() has been called + stack_depth = _stack_depth magic_arg_s = self.var_expand(line, stack_depth) # Put magic args in a list so we can call with f(*a) syntax args = [magic_arg_s] @@ -2154,7 +2160,7 @@ class InteractiveShell(SingletonConfigurable): # TODO: should we issue a loud deprecation warning here? magic_name, _, magic_arg_s = arg_s.partition(' ') magic_name = magic_name.lstrip(prefilter.ESC_MAGIC) - return self.run_line_magic(magic_name, magic_arg_s) + return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2) #------------------------------------------------------------------------- # Things related to macros diff --git a/IPython/core/magics/history.py b/IPython/core/magics/history.py index 3a3c5c8..6f2138f 100644 --- a/IPython/core/magics/history.py +++ b/IPython/core/magics/history.py @@ -61,7 +61,7 @@ class HistoryMagics(Magics): source before executing it (things like magics or aliases are turned into function calls, for example). With this option, you'll see the native history instead of the user-entered version: '%%cd /' will be - seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'. + seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'. """) @argument( '-f', dest='filename', diff --git a/IPython/core/prefilter.py b/IPython/core/prefilter.py index 50ee071..c3109c7 100644 --- a/IPython/core/prefilter.py +++ b/IPython/core/prefilter.py @@ -589,8 +589,11 @@ class MagicHandler(PrefilterHandler): """Execute magic functions.""" ifun = line_info.ifun the_rest = line_info.the_rest - cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace, - (ifun + " " + the_rest)) + #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) + t_arg_s = ifun + " " + the_rest + t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ') + t_magic_name = t_magic_name.lstrip(ESC_MAGIC) + cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s) return cmd diff --git a/IPython/core/tests/test_handlers.py b/IPython/core/tests/test_handlers.py index 20f956a..45409d9 100644 --- a/IPython/core/tests/test_handlers.py +++ b/IPython/core/tests/test_handlers.py @@ -53,7 +53,7 @@ def test_handlers(): # line. run([(i,py3compat.u_format(o)) for i,o in \ [('"no change"', '"no change"'), # normal - (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic + (u"lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), # magic #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache ]]) diff --git a/IPython/core/tests/test_inputsplitter.py b/IPython/core/tests/test_inputsplitter.py index 54e85c0..d528078 100644 --- a/IPython/core/tests/test_inputsplitter.py +++ b/IPython/core/tests/test_inputsplitter.py @@ -479,11 +479,11 @@ class IPythonInputTestCase(InputSplitterTestCase): for raw, expected in [ ("a=5", "a=5#"), - ("%ls foo", "get_ipython().magic(%r)" % u'ls foo#'), - ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().magic(%r)" % ( - u'ls foo#', u'ls bar#' + ("%ls foo", "get_ipython().run_line_magic(%r, %r)" % (u'ls', u'foo#')), + ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().run_line_magic(%r, %r)" % ( + u'ls foo#', u'ls', u'bar#' )), - ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().magic(%r)\n4#\n5#" % u'ls foo#'), + ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().run_line_magic(%r, %r)\n4#\n5#" % (u'ls', u'foo#')), ]: out = isp.transform_cell(raw) self.assertEqual(out.rstrip(), expected.rstrip()) @@ -568,7 +568,7 @@ class CellMagicsCommon(object): def test_whole_cell(self): src = "%%cellm line\nbody\n" out = self.sp.transform_cell(src) - ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n" + ref = u"get_ipython().run_cell_magic('cellm', 'line', 'body')\n" nt.assert_equal(out, py3compat.u_format(ref)) def test_cellmagic_help(self): diff --git a/IPython/core/tests/test_inputtransformer.py b/IPython/core/tests/test_inputtransformer.py index 2aa0670..90a1d5a 100644 --- a/IPython/core/tests/test_inputtransformer.py +++ b/IPython/core/tests/test_inputtransformer.py @@ -39,16 +39,16 @@ def transform_checker(tests, transformer, **kwargs): syntax = \ dict(assign_system = [(i,py3compat.u_format(o)) for i,o in \ - [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"), - (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"), - (u'c= !ls', "c = get_ipython().getoutput({u}'ls')"), + [(u'a =! ls', "a = get_ipython().getoutput('ls')"), + (u'b = !ls', "b = get_ipython().getoutput('ls')"), + (u'c= !ls', "c = get_ipython().getoutput('ls')"), (u'd == !ls', u'd == !ls'), # Invalid syntax, but we leave == alone. ('x=1', 'x=1'), # normal input is unmodified (' ',' '), # blank lines are kept intact # Tuple unpacking - (u"a, b = !echo 'a\\nb'", u"a, b = get_ipython().getoutput({u}\"echo 'a\\\\nb'\")"), - (u"a,= !echo 'a'", u"a, = get_ipython().getoutput({u}\"echo 'a'\")"), - (u"a, *bc = !echo 'a\\nb\\nc'", u"a, *bc = get_ipython().getoutput({u}\"echo 'a\\\\nb\\\\nc'\")"), + (u"a, b = !echo 'a\\nb'", u"a, b = get_ipython().getoutput(\"echo 'a\\\\nb'\")"), + (u"a,= !echo 'a'", u"a, = get_ipython().getoutput(\"echo 'a'\")"), + (u"a, *bc = !echo 'a\\nb\\nc'", u"a, *bc = get_ipython().getoutput(\"echo 'a\\\\nb\\\\nc'\")"), # Tuple unpacking with regular Python expressions, not our syntax. (u"a, b = range(2)", u"a, b = range(2)"), (u"a, = range(1)", u"a, = range(1)"), @@ -57,13 +57,13 @@ syntax = \ assign_magic = [(i,py3compat.u_format(o)) for i,o in \ - [(u'a =% who', "a = get_ipython().magic({u}'who')"), - (u'b = %who', "b = get_ipython().magic({u}'who')"), - (u'c= %ls', "c = get_ipython().magic({u}'ls')"), + [(u'a =% who', "a = get_ipython().run_line_magic('who', '')"), + (u'b = %who', "b = get_ipython().run_line_magic('who', '')"), + (u'c= %ls', "c = get_ipython().run_line_magic('ls', '')"), (u'd == %ls', u'd == %ls'), # Invalid syntax, but we leave == alone. ('x=1', 'x=1'), # normal input is unmodified (' ',' '), # blank lines are kept intact - (u"a, b = %foo", u"a, b = get_ipython().magic({u}'foo')"), + (u"a, b = %foo", u"a, b = get_ipython().run_line_magic('foo', '')"), ]], classic_prompt = @@ -87,53 +87,53 @@ syntax = \ # System calls escaped_shell = [(i,py3compat.u_format(o)) for i,o in \ - [ (u'!ls', "get_ipython().system({u}'ls')"), + [ (u'!ls', "get_ipython().system('ls')"), # Double-escape shell, this means to capture the output of the # subprocess and return it - (u'!!ls', "get_ipython().getoutput({u}'ls')"), + (u'!!ls', "get_ipython().getoutput('ls')"), ]], # Help/object info escaped_help = [(i,py3compat.u_format(o)) for i,o in \ [ (u'?', 'get_ipython().show_usage()'), - (u'?x1', "get_ipython().magic({u}'pinfo x1')"), - (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"), - (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"), - (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"), - (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"), - (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"), + (u'?x1', "get_ipython().run_line_magic('pinfo', 'x1')"), + (u'??x2', "get_ipython().run_line_magic('pinfo2', 'x2')"), + (u'?a.*s', "get_ipython().run_line_magic('psearch', 'a.*s')"), + (u'?%hist1', "get_ipython().run_line_magic('pinfo', '%hist1')"), + (u'?%%hist2', "get_ipython().run_line_magic('pinfo', '%%hist2')"), + (u'?abc = qwe', "get_ipython().run_line_magic('pinfo', 'abc')"), ]], end_help = [(i,py3compat.u_format(o)) for i,o in \ - [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"), - (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"), - (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"), - (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"), - (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"), - (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"), - (u'f*?', "get_ipython().magic({u}'psearch f*')"), - (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"), - (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');" - "get_ipython().magic({u}'pinfo abc')"), - (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');" - "get_ipython().magic({u}'pinfo2 abc.qe')"), - (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');" - "get_ipython().magic({u}'psearch *.items')"), - (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');" - "get_ipython().magic({u}'pinfo a')"), + [ (u'x3?', "get_ipython().run_line_magic('pinfo', 'x3')"), + (u'x4??', "get_ipython().run_line_magic('pinfo2', 'x4')"), + (u'%hist1?', "get_ipython().run_line_magic('pinfo', '%hist1')"), + (u'%hist2??', "get_ipython().run_line_magic('pinfo2', '%hist2')"), + (u'%%hist3?', "get_ipython().run_line_magic('pinfo', '%%hist3')"), + (u'%%hist4??', "get_ipython().run_line_magic('pinfo2', '%%hist4')"), + (u'f*?', "get_ipython().run_line_magic('psearch', 'f*')"), + (u'ax.*aspe*?', "get_ipython().run_line_magic('psearch', 'ax.*aspe*')"), + (u'a = abc?', "get_ipython().set_next_input('a = abc');" + "get_ipython().run_line_magic('pinfo', 'abc')"), + (u'a = abc.qe??', "get_ipython().set_next_input('a = abc.qe');" + "get_ipython().run_line_magic('pinfo2', 'abc.qe')"), + (u'a = *.items?', "get_ipython().set_next_input('a = *.items');" + "get_ipython().run_line_magic('psearch', '*.items')"), + (u'plot(a?', "get_ipython().set_next_input('plot(a');" + "get_ipython().run_line_magic('pinfo', 'a')"), (u'a*2 #comment?', 'a*2 #comment?'), ]], # Explicit magic calls escaped_magic = [(i,py3compat.u_format(o)) for i,o in \ - [ (u'%cd', "get_ipython().magic({u}'cd')"), - (u'%cd /home', "get_ipython().magic({u}'cd /home')"), + [ (u'%cd', "get_ipython().run_line_magic('cd', '')"), + (u'%cd /home', "get_ipython().run_line_magic('cd', '/home')"), # Backslashes need to be escaped. - (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"), - (u' %magic', " get_ipython().magic({u}'magic')"), + (u'%cd C:\\User', "get_ipython().run_line_magic('cd', 'C:\\\\User')"), + (u' %magic', " get_ipython().run_line_magic('magic', '')"), ]], # Quoting with separate arguments @@ -163,11 +163,11 @@ syntax = \ # Check that we transform prompts before other transforms mixed = [(i,py3compat.u_format(o)) for i,o in \ - [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"), - (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"), - (u'In [2]: !ls', "get_ipython().system({u}'ls')"), - (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"), - (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"), + [ (u'In [1]: %lsmagic', "get_ipython().run_line_magic('lsmagic', '')"), + (u'>>> %lsmagic', "get_ipython().run_line_magic('lsmagic', '')"), + (u'In [2]: !ls', "get_ipython().system('ls')"), + (u'In [3]: abs?', "get_ipython().run_line_magic('pinfo', 'abs')"), + (u'In [4]: b = %who', "b = get_ipython().run_line_magic('who', '')"), ]], ) @@ -283,11 +283,11 @@ syntax_ml = \ cellmagic = [ [(u'%%foo a', None), - (None, u_fmt("get_ipython().run_cell_magic({u}'foo', {u}'a', {u}'')")), + (None, u_fmt("get_ipython().run_cell_magic('foo', 'a', '')")), ], [(u'%%bar 123', None), (u'hello', None), - (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")), + (None , u_fmt("get_ipython().run_cell_magic('bar', '123', 'hello')")), ], [(u'a=5', 'a=5'), (u'%%cellmagic', '%%cellmagic'), @@ -296,31 +296,31 @@ syntax_ml = \ escaped = [ [('%abc def \\', None), - ('ghi', u_fmt("get_ipython().magic({u}'abc def ghi')")), + ('ghi', u_fmt("get_ipython().run_line_magic('abc', 'def ghi')")), ], [('%abc def \\', None), ('ghi\\', None), - (None, u_fmt("get_ipython().magic({u}'abc def ghi')")), + (None, u_fmt("get_ipython().run_line_magic('abc', 'def ghi')")), ], ], assign_magic = [ [(u'a = %bc de \\', None), - (u'fg', u_fmt("a = get_ipython().magic({u}'bc de fg')")), + (u'fg', u_fmt("a = get_ipython().run_line_magic('bc', 'de fg')")), ], [(u'a = %bc de \\', None), (u'fg\\', None), - (None, u_fmt("a = get_ipython().magic({u}'bc de fg')")), + (None, u_fmt("a = get_ipython().run_line_magic('bc', 'de fg')")), ], ], assign_system = [ [(u'a = !bc de \\', None), - (u'fg', u_fmt("a = get_ipython().getoutput({u}'bc de fg')")), + (u'fg', u_fmt("a = get_ipython().getoutput('bc de fg')")), ], [(u'a = !bc de \\', None), (u'fg\\', None), - (None, u_fmt("a = get_ipython().getoutput({u}'bc de fg')")), + (None, u_fmt("a = get_ipython().getoutput('bc de fg')")), ], ], ) @@ -436,7 +436,7 @@ def test_cellmagic(): line_example = [(u'%%bar 123', None), (u'hello', None), - (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")), + (u'' , u_fmt("get_ipython().run_cell_magic('bar', '123', 'hello')")), ] transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True) @@ -474,16 +474,16 @@ def decistmt(tokens): def test_token_input_transformer(): - tests = [(u'1.2', u_fmt(u"Decimal ({u}'1.2')")), + tests = [(u'1.2', u_fmt(u"Decimal ('1.2')")), (u'"1.2"', u'"1.2"'), ] tt.check_pairs(transform_and_reset(decistmt), tests) ml_tests = \ [ [(u"a = 1.2; b = '''x", None), - (u"y'''", u_fmt(u"a =Decimal ({u}'1.2');b ='''x\ny'''")), + (u"y'''", u_fmt(u"a =Decimal ('1.2');b ='''x\ny'''")), ], [(u"a = [1.2,", None), - (u"3]", u_fmt(u"a =[Decimal ({u}'1.2'),\n3 ]")), + (u"3]", u_fmt(u"a =[Decimal ('1.2'),\n3 ]")), ], [(u"a = '''foo", None), # Test resetting when within a multi-line string (u"bar", None), diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 25a57a6..88dfa46 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -510,16 +510,16 @@ def doctest_precision(): In [1]: f = get_ipython().display_formatter.formatters['text/plain'] In [2]: %precision 5 - Out[2]: {u}'%.5f' + Out[2]: '%.5f' In [3]: f.float_format - Out[3]: {u}'%.5f' + Out[3]: '%.5f' In [4]: %precision %e - Out[4]: {u}'%e' + Out[4]: '%e' In [5]: f(3.1415927) - Out[5]: {u}'3.141593e+00' + Out[5]: '3.141593e+00' """ def test_psearch():