diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py index fe60e27..0a549fc 100644 --- a/IPython/core/magics/execution.py +++ b/IPython/core/magics/execution.py @@ -11,6 +11,7 @@ import builtins as builtin_mod import gc import itertools import os +import shlex import sys import time import timeit @@ -617,6 +618,20 @@ python-profiler package from non-free.""") """ + # Logic to handle issue #3664 + # Add '--' after '-m ' to ignore additional args passed to a module. + if '-m' in parameter_s and '--' not in parameter_s: + argv = shlex.split(parameter_s, posix=(os.name == 'posix')) + for idx, arg in enumerate(argv): + if arg and arg.startswith('-') and arg != '-': + if arg == '-m': + argv.insert(idx + 2, '--') + break + else: + # Positional arg, break + break + parameter_s = ' '.join(shlex.quote(arg) for arg in argv) + # get arguments and set sys.argv for program to be run. opts, arg_lst = self.parse_options(parameter_s, 'nidtN:b:pD:l:rs:T:em:G', diff --git a/IPython/core/tests/test_run.py b/IPython/core/tests/test_run.py index a1ea35f..e089413 100644 --- a/IPython/core/tests/test_run.py +++ b/IPython/core/tests/test_run.py @@ -384,7 +384,14 @@ tclass.py: deleting object: C-third _ip.magic("run %s" % self.fname) nt.assert_equal(_ip.user_ns['answer'], 42) - + + def test_file_options(self): + src = ('import sys\n' + 'a = " ".join(sys.argv[1:])\n') + self.mktmp(src) + test_opts = '-x 3 --verbose' + _ip.run_line_magic("run", '{0} {1}'.format(self.fname, test_opts)) + nt.assert_equal(_ip.user_ns['a'], test_opts) class TestMagicRunWithPackage(unittest.TestCase): @@ -417,6 +424,10 @@ class TestMagicRunWithPackage(unittest.TestCase): self.writefile(os.path.join(package, 'absolute.py'), """ from {0}.sub import x """.format(package)) + self.writefile(os.path.join(package, 'args.py'), """ + import sys + a = " ".join(sys.argv[1:]) + """.format(package)) def tearDown(self): os.chdir(self.__orig_cwd) @@ -458,6 +469,18 @@ class TestMagicRunWithPackage(unittest.TestCase): def test_debug_run_submodule_with_relative_import(self): self.check_run_submodule('relative', '-d') + def test_module_options(self): + _ip.user_ns.pop('a', None) + test_opts = '-x abc -m test' + _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts)) + nt.assert_equal(_ip.user_ns['a'], test_opts) + + def test_module_options_with_separator(self): + _ip.user_ns.pop('a', None) + test_opts = '-x abc -m test' + _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts)) + nt.assert_equal(_ip.user_ns['a'], test_opts) + def test_run__name__(): with TemporaryDirectory() as td: path = pjoin(td, 'foo.py')