spack python: add -m option to run modules as scripts
It's often useful to run a module with `python -m`, e.g.: python -m pyinstrument script.py Running a python script this way was hard, though, as `spack python` did not have a similar `-m` option. This PR adds a `-m` option to `spack python` so that we can do things like this: spack python -m pyinstrument ./test.py This makes it easy to write a script that uses a small part of Spack and then profile it. Previously thee easiest way to do this was to write a custom Spack command, which is often overkill.
This commit is contained in:
parent
90f3635afd
commit
a7b43f1015
3 changed files with 32 additions and 2 deletions
|
@ -8,6 +8,9 @@
|
|||
import code
|
||||
import argparse
|
||||
import platform
|
||||
import runpy
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack
|
||||
|
||||
|
@ -19,12 +22,23 @@
|
|||
def setup_parser(subparser):
|
||||
subparser.add_argument(
|
||||
'-c', dest='python_command', help='command to execute')
|
||||
subparser.add_argument(
|
||||
'-m', dest='module', action='store',
|
||||
help='run library module as a script')
|
||||
subparser.add_argument(
|
||||
'python_args', nargs=argparse.REMAINDER,
|
||||
help="file to run plus arguments")
|
||||
|
||||
|
||||
def python(parser, args):
|
||||
def python(parser, args, unknown_args):
|
||||
if args.module:
|
||||
sys.argv = ['spack-python'] + unknown_args + args.python_args
|
||||
runpy.run_module(args.module, run_name="__main__", alter_sys=True)
|
||||
return
|
||||
|
||||
if unknown_args:
|
||||
tty.die("Unknown arguments:", " ".join(unknown_args))
|
||||
|
||||
# Fake a main python shell by setting __name__ to __main__.
|
||||
console = code.InteractiveConsole({'__name__': '__main__',
|
||||
'spack': spack})
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import pytest
|
||||
|
||||
import spack
|
||||
from spack.main import SpackCommand
|
||||
|
||||
|
@ -12,3 +14,17 @@
|
|||
def test_python():
|
||||
out = python('-c', 'import spack; print(spack.spack_version)')
|
||||
assert out.strip() == spack.spack_version
|
||||
|
||||
|
||||
def test_python_with_module():
|
||||
# pytest rewrites a lot of modules, which interferes with runpy, so
|
||||
# it's hard to test this. Trying to import a module like sys, that
|
||||
# has no code associated with it, raises an error reliably in python
|
||||
# 2 and 3, which indicates we successfully ran runpy.run_module.
|
||||
with pytest.raises(ImportError, match="No code object"):
|
||||
python('-m', 'sys')
|
||||
|
||||
|
||||
def test_python_raises():
|
||||
out = python('--foobar', fail_on_error=False)
|
||||
assert "Error: Unknown arguments" in out
|
||||
|
|
|
@ -1272,7 +1272,7 @@ _spack_pydoc() {
|
|||
_spack_python() {
|
||||
if $list_options
|
||||
then
|
||||
SPACK_COMPREPLY="-h --help -c"
|
||||
SPACK_COMPREPLY="-h --help -c -m"
|
||||
else
|
||||
SPACK_COMPREPLY=""
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue