##// END OF EJS Templates
Don't expand user variables in execution magics...
Min RK -
Show More
@@ -2276,6 +2276,10 b' class InteractiveShell(SingletonConfigurable):'
2276 2276
2277 2277 # Determine stack_depth depending on where run_line_magic() has been called
2278 2278 stack_depth = _stack_depth
2279 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2280 # magic has opted out of var_expand
2281 magic_arg_s = line
2282 else:
2279 2283 magic_arg_s = self.var_expand(line, stack_depth)
2280 2284 # Put magic args in a list so we can call with f(*a) syntax
2281 2285 args = [magic_arg_s]
@@ -2318,6 +2322,10 b' class InteractiveShell(SingletonConfigurable):'
2318 2322 # This will need to be updated if the internal calling logic gets
2319 2323 # refactored, or else we'll be expanding the wrong variables.
2320 2324 stack_depth = 2
2325 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2326 # magic has opted out of var_expand
2327 magic_arg_s = line
2328 else:
2321 2329 magic_arg_s = self.var_expand(line, stack_depth)
2322 2330 with self.builtin_trap:
2323 2331 result = fn(magic_arg_s, cell)
@@ -265,6 +265,25 b' def _function_magic_marker(magic_kind):'
265 265 return magic_deco
266 266
267 267
268 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
269
270
271 def no_var_expand(magic_func):
272 """Mark a magic function as not needing variable expansion
273
274 By default, IPython interprets `{a}` or `$a` in the line passed to magics
275 as variables that should be interpolated from the interactive namespace
276 before passing the line to the magic function.
277 This is not always desirable, e.g. when the magic executes Python code
278 (%timeit, %time, etc.).
279 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
280
281 .. versionadded:: 7.2
282 """
283 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
284 return magic_func
285
286
268 287 # Create the actual decorators for public use
269 288
270 289 # These three are used to decorate methods in class definitions
@@ -36,7 +36,8 b' from IPython.core import page'
36 36 from IPython.core.error import UsageError
37 37 from IPython.core.macro import Macro
38 38 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
39 line_cell_magic, on_off, needs_local_scope)
39 line_cell_magic, on_off, needs_local_scope,
40 no_var_expand)
40 41 from IPython.testing.skipdoctest import skip_doctest
41 42 from IPython.utils.contexts import preserve_keys
42 43 from IPython.utils.capture import capture_output
@@ -184,6 +185,7 b' python packages because of its non-free license. To use profiling, install the'
184 185 python-profiler package from non-free.""")
185 186
186 187 @skip_doctest
188 @no_var_expand
187 189 @line_cell_magic
188 190 def prun(self, parameter_s='', cell=None):
189 191
@@ -293,6 +295,11 b' python-profiler package from non-free.""")'
293 295 You can read the complete documentation for the profile module with::
294 296
295 297 In [1]: import profile; profile.help()
298
299 .. versionchanged:: 7.2
300 User variables are no longer expanded,
301 the magic line is always left unmodified.
302
296 303 """
297 304 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
298 305 list_all=True, posix=False)
@@ -422,6 +429,7 b' python-profiler package from non-free.""")'
422 429 You can omit this in cell magic mode.
423 430 """
424 431 )
432 @no_var_expand
425 433 @line_cell_magic
426 434 def debug(self, line='', cell=None):
427 435 """Activate the interactive debugger.
@@ -442,6 +450,11 b' python-profiler package from non-free.""")'
442 450
443 451 If you want IPython to automatically do this on every exception, see
444 452 the %pdb magic for more details.
453
454 .. versionchanged:: 7.2
455 When running code, user variables are no longer expanded,
456 the magic line is always left unmodified.
457
445 458 """
446 459 args = magic_arguments.parse_argstring(self.debug, line)
447 460
@@ -972,6 +985,7 b' python-profiler package from non-free.""")'
972 985 print("Wall time: %10.2f s." % (twall1 - twall0))
973 986
974 987 @skip_doctest
988 @no_var_expand
975 989 @line_cell_magic
976 990 @needs_local_scope
977 991 def timeit(self, line='', cell=None, local_ns=None):
@@ -1017,6 +1031,9 b' python-profiler package from non-free.""")'
1017 1031 -o: return a TimeitResult that can be stored in a variable to inspect
1018 1032 the result in more details.
1019 1033
1034 .. versionchanged:: 7.2
1035 User variables are no longer expanded,
1036 the magic line is always left unmodified.
1020 1037
1021 1038 Examples
1022 1039 --------
@@ -1161,6 +1178,7 b' python-profiler package from non-free.""")'
1161 1178 return timeit_result
1162 1179
1163 1180 @skip_doctest
1181 @no_var_expand
1164 1182 @needs_local_scope
1165 1183 @line_cell_magic
1166 1184 def time(self,line='', cell=None, local_ns=None):
@@ -1181,6 +1199,10 b' python-profiler package from non-free.""")'
1181 1199 This function provides very basic timing functionality. Use the timeit
1182 1200 magic for more control over the measurement.
1183 1201
1202 .. versionchanged:: 7.2
1203 User variables are no longer expanded,
1204 the magic line is always left unmodified.
1205
1184 1206 Examples
1185 1207 --------
1186 1208 ::
@@ -1088,6 +1088,7 b' def test_logging_magic_quiet_from_config():'
1088 1088 finally:
1089 1089 _ip.logger.logstop()
1090 1090
1091
1091 1092 def test_logging_magic_not_quiet():
1092 1093 _ip.config.LoggingMagics.quiet = False
1093 1094 lm = logging.LoggingMagics(shell=_ip)
@@ -1098,9 +1099,15 b' def test_logging_magic_not_quiet():'
1098 1099 finally:
1099 1100 _ip.logger.logstop()
1100 1101
1101 ##
1102
1103 def test_time_no_var_expand():
1104 _ip.user_ns['a'] = 5
1105 _ip.user_ns['b'] = []
1106 _ip.magic('time b.append("{a}")')
1107 assert _ip.user_ns['b'] == ['{a}']
1108
1109
1102 1110 # this is slow, put at the end for local testing.
1103 ##
1104 1111 def test_timeit_arguments():
1105 1112 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1106 1113 if sys.version_info < (3,7):
General Comments 0
You need to be logged in to leave comments. Login now