Skip to content

Commit 164d4a5

Browse files
authored
Add ability to switch pre-build on/off (#272)
* Add ability to switch pre-build on/off * Add test for --no-build * Show only --no-build flag
1 parent 43e85ee commit 164d4a5

File tree

2 files changed

+96
-60
lines changed

2 files changed

+96
-60
lines changed

spin/cmds/meson.py

Lines changed: 86 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat, build_dir
236236
else:
237237
DEFAULT_PREFIX = "/usr"
238238

239+
240+
build_option = click.option(
241+
"--no-build",
242+
"build",
243+
is_flag=True,
244+
callback=lambda ctx, param, value: not value, # store opposite value in `build` var
245+
default=False,
246+
help="Disable building before executing command",
247+
)
248+
239249
build_dir_option = click.option(
240250
"-C",
241251
"--build-dir",
@@ -447,6 +457,7 @@ def _get_configured_command(command_name):
447457
default="html",
448458
help=f"Format of the gcov report. Can be one of {', '.join(e.value for e in GcovReportFormat)}.",
449459
)
460+
@build_option
450461
@build_dir_option
451462
@click.pass_context
452463
def test(
@@ -459,6 +470,7 @@ def test(
459470
coverage=False,
460471
gcov=None,
461472
gcov_format=None,
473+
build=None,
462474
build_dir=None,
463475
):
464476
"""🔧 Run tests
@@ -541,15 +553,16 @@ def test(
541553
)
542554
raise SystemExit(1)
543555

544-
build_cmd = _get_configured_command("build")
545-
if build_cmd:
546-
click.secho(
547-
"Invoking `build` prior to running tests:", bold=True, fg="bright_green"
548-
)
549-
if gcov is not None:
550-
ctx.invoke(build_cmd, build_dir=build_dir, gcov=bool(gcov))
551-
else:
552-
ctx.invoke(build_cmd, build_dir=build_dir)
556+
if build:
557+
build_cmd = _get_configured_command("build")
558+
if build_cmd:
559+
click.secho(
560+
"Invoking `build` prior to running tests:", bold=True, fg="bright_green"
561+
)
562+
if gcov is not None:
563+
ctx.invoke(build_cmd, build_dir=build_dir, gcov=bool(gcov))
564+
else:
565+
ctx.invoke(build_cmd, build_dir=build_dir)
553566

554567
site_path = _set_pythonpath(build_dir)
555568

@@ -647,9 +660,10 @@ def test(
647660
"--code", "-c", metavar="CODE", help="Python program passed in as a string"
648661
)
649662
@click.argument("gdb_args", nargs=-1)
663+
@build_option
650664
@build_dir_option
651665
@click.pass_context
652-
def gdb(ctx, *, code, gdb_args, build_dir):
666+
def gdb(ctx, *, code, gdb_args, build=None, build_dir=None):
653667
"""👾 Execute code through GDB
654668
655669
spin gdb -c 'import numpy as np; print(np.__version__)'
@@ -670,12 +684,13 @@ def gdb(ctx, *, code, gdb_args, build_dir):
670684
spin gdb my_tests.py
671685
spin gdb -- my_tests.py --mytest-flag
672686
"""
673-
build_cmd = _get_configured_command("build")
674-
if build_cmd:
675-
click.secho(
676-
"Invoking `build` prior to invoking gdb:", bold=True, fg="bright_green"
677-
)
678-
ctx.invoke(build_cmd, build_dir=build_dir)
687+
if build:
688+
build_cmd = _get_configured_command("build")
689+
if build_cmd:
690+
click.secho(
691+
"Invoking `build` prior to invoking gdb:", bold=True, fg="bright_green"
692+
)
693+
ctx.invoke(build_cmd, build_dir=build_dir)
679694

680695
_set_pythonpath(build_dir)
681696
gdb_args = list(gdb_args)
@@ -700,21 +715,25 @@ def gdb(ctx, *, code, gdb_args, build_dir):
700715

701716
@click.command()
702717
@click.argument("ipython_args", nargs=-1)
718+
@build_option
703719
@build_dir_option
704720
@click.pass_context
705-
def ipython(ctx, *, ipython_args, build_dir, pre_import=""):
721+
def ipython(ctx, *, ipython_args, build=None, build_dir=None, pre_import=""):
706722
"""💻 Launch IPython shell with PYTHONPATH set
707723
708724
IPYTHON_ARGS are passed through directly to IPython, e.g.:
709725
710726
spin ipython -- -i myscript.py
711727
"""
712-
build_cmd = _get_configured_command("build")
713-
if build_cmd:
714-
click.secho(
715-
"Invoking `build` prior to launching ipython:", bold=True, fg="bright_green"
716-
)
717-
ctx.invoke(build_cmd, build_dir=build_dir)
728+
if build:
729+
build_cmd = _get_configured_command("build")
730+
if build_cmd:
731+
click.secho(
732+
"Invoking `build` prior to launching ipython:",
733+
bold=True,
734+
fg="bright_green",
735+
)
736+
ctx.invoke(build_cmd, build_dir=build_dir)
718737

719738
p = _set_pythonpath(build_dir)
720739
if p:
@@ -726,9 +745,10 @@ def ipython(ctx, *, ipython_args, build_dir, pre_import=""):
726745

727746
@click.command()
728747
@click.argument("shell_args", nargs=-1)
748+
@build_option
729749
@build_dir_option
730750
@click.pass_context
731-
def shell(ctx, shell_args=[], build_dir=None):
751+
def shell(ctx, shell_args=[], build=None, build_dir=None):
732752
"""💻 Launch shell with PYTHONPATH set
733753
734754
SHELL_ARGS are passed through directly to the shell, e.g.:
@@ -738,12 +758,15 @@ def shell(ctx, shell_args=[], build_dir=None):
738758
Ensure that your shell init file (e.g., ~/.zshrc) does not override
739759
the PYTHONPATH.
740760
"""
741-
build_cmd = _get_configured_command("build")
742-
if build_cmd:
743-
click.secho(
744-
"Invoking `build` prior to invoking shell:", bold=True, fg="bright_green"
745-
)
746-
ctx.invoke(build_cmd, build_dir=build_dir)
761+
if build:
762+
build_cmd = _get_configured_command("build")
763+
if build_cmd:
764+
click.secho(
765+
"Invoking `build` prior to invoking shell:",
766+
bold=True,
767+
fg="bright_green",
768+
)
769+
ctx.invoke(build_cmd, build_dir=build_dir)
747770

748771
p = _set_pythonpath(build_dir)
749772
if p:
@@ -758,21 +781,25 @@ def shell(ctx, shell_args=[], build_dir=None):
758781

759782
@click.command()
760783
@click.argument("python_args", nargs=-1)
784+
@build_option
761785
@build_dir_option
762786
@click.pass_context
763-
def python(ctx, *, python_args, build_dir):
787+
def python(ctx, *, python_args, build=None, build_dir=None):
764788
"""🐍 Launch Python shell with PYTHONPATH set
765789
766790
PYTHON_ARGS are passed through directly to Python, e.g.:
767791
768792
spin python -- -c 'import sys; print(sys.path)'
769793
"""
770-
build_cmd = _get_configured_command("build")
771-
if build_cmd:
772-
click.secho(
773-
"Invoking `build` prior to invoking Python:", bold=True, fg="bright_green"
774-
)
775-
ctx.invoke(build_cmd, build_dir=build_dir)
794+
if build:
795+
build_cmd = _get_configured_command("build")
796+
if build_cmd:
797+
click.secho(
798+
"Invoking `build` prior to invoking Python:",
799+
bold=True,
800+
fg="bright_green",
801+
)
802+
ctx.invoke(build_cmd, build_dir=build_dir)
776803

777804
p = _set_pythonpath(build_dir)
778805
if p:
@@ -799,10 +826,11 @@ def python(ctx, *, python_args, build_dir):
799826

800827

801828
@click.command(context_settings={"ignore_unknown_options": True})
829+
@build_option
802830
@build_dir_option
803831
@click.argument("args", nargs=-1)
804832
@click.pass_context
805-
def run(ctx, *, args, build_dir=None):
833+
def run(ctx, *, args, build=None, build_dir=None):
806834
"""🏁 Run a shell command with PYTHONPATH set
807835
808836
\b
@@ -821,12 +849,13 @@ def run(ctx, *, args, build_dir=None):
821849
if not len(args) > 0:
822850
raise RuntimeError("No command given")
823851

824-
build_cmd = _get_configured_command("build")
825-
if build_cmd:
826-
# Redirect spin generated output
827-
with contextlib.redirect_stdout(sys.stderr):
828-
# Also ask build to be quiet
829-
ctx.invoke(build_cmd, build_dir=build_dir, quiet=True)
852+
if build:
853+
build_cmd = _get_configured_command("build")
854+
if build_cmd:
855+
# Redirect spin generated output
856+
with contextlib.redirect_stdout(sys.stderr):
857+
# Also ask build to be quiet
858+
ctx.invoke(build_cmd, build_dir=build_dir, quiet=True)
830859

831860
is_posix = sys.platform in ("linux", "darwin")
832861
shell = len(args) == 1
@@ -882,12 +911,6 @@ def attach_sigint():
882911
default=False,
883912
help="Clean previously built docs before building",
884913
)
885-
@click.option(
886-
"--build/--no-build",
887-
"first_build",
888-
default=True,
889-
help="Build project before generating docs",
890-
)
891914
@click.option(
892915
"--plot/--no-plot",
893916
"sphinx_gallery_plot",
@@ -901,17 +924,18 @@ def attach_sigint():
901924
metavar="N_JOBS",
902925
help="Number of parallel build jobs",
903926
)
927+
@build_option
904928
@build_dir_option
905929
@click.pass_context
906930
def docs(
907931
ctx,
908932
*,
909933
sphinx_target,
910934
clean,
911-
first_build,
912935
jobs,
913936
sphinx_gallery_plot,
914937
clean_dirs=None,
938+
build=None,
915939
build_dir=None,
916940
):
917941
"""📖 Build Sphinx documentation
@@ -941,7 +965,7 @@ def docs(
941965

942966
if sphinx_target in ("targets", "help"):
943967
clean = False
944-
first_build = False
968+
build = False
945969
sphinx_target = "help"
946970

947971
if clean:
@@ -963,7 +987,7 @@ def docs(
963987

964988
build_cmd = _get_configured_command("build")
965989

966-
if build_cmd and first_build:
990+
if build_cmd and build:
967991
click.secho(
968992
"Invoking `build` prior to building docs:", bold=True, fg="bright_green"
969993
)
@@ -1007,9 +1031,10 @@ def docs(
10071031
"--code", "-c", metavar="CODE", help="Python program passed in as a string"
10081032
)
10091033
@click.argument("lldb_args", nargs=-1)
1034+
@build_option
10101035
@build_dir_option
10111036
@click.pass_context
1012-
def lldb(ctx, *, code, lldb_args, build_dir=None):
1037+
def lldb(ctx, *, code, lldb_args, build=None, build_dir=None):
10131038
"""👾 Execute code through LLDB
10141039
10151040
spin lldb -c 'import numpy as np; print(np.__version__)'
@@ -1032,12 +1057,13 @@ def lldb(ctx, *, code, lldb_args, build_dir=None):
10321057
spin lldb -- --arch x86_64 -- my_tests.py
10331058
spin lldb -c 'import numpy as np; print(np.__version__)' -- --arch x86_64
10341059
"""
1035-
build_cmd = _get_configured_command("build")
1036-
if build_cmd:
1037-
click.secho(
1038-
"Invoking `build` prior to invoking lldb:", bold=True, fg="bright_green"
1039-
)
1040-
ctx.invoke(build_cmd, build_dir=build_dir)
1060+
if build:
1061+
build_cmd = _get_configured_command("build")
1062+
if build_cmd:
1063+
click.secho(
1064+
"Invoking `build` prior to invoking lldb:", bold=True, fg="bright_green"
1065+
)
1066+
ctx.invoke(build_cmd, build_dir=build_dir)
10411067

10421068
_set_pythonpath(build_dir)
10431069
lldb_args = list(lldb_args)

spin/tests/test_build_cmds.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
skip_unless_linux,
1515
skip_unless_macos,
1616
spin,
17+
stderr,
1718
stdout,
1819
)
1920

@@ -90,6 +91,15 @@ def test_run_stdout(example_pkg):
9091
)
9192

9293

94+
def test_run_no_build(example_pkg):
95+
"""Does spin run ... --no-build correctly avoid building."""
96+
output = stderr(spin("run", "echo $PYTHONPATH"))
97+
assert "meson compile" in output
98+
99+
output = stderr(spin("run", "--no-build", "echo $PYTHONPATH"))
100+
assert "meson compile" not in output
101+
102+
93103
# Detecting whether a file is executable is not that easy on Windows,
94104
# as it seems to take into consideration whether that file is associated as an executable.
95105
@skip_on_windows

0 commit comments

Comments
 (0)