spin 0.12__tar.gz → 0.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spin-0.12/spin.egg-info → spin-0.13}/PKG-INFO +48 -38
- {spin-0.12 → spin-0.13}/README.md +45 -36
- {spin-0.12 → spin-0.13}/pyproject.toml +2 -1
- {spin-0.12 → spin-0.13}/spin/__init__.py +1 -1
- {spin-0.12 → spin-0.13}/spin/__main__.py +13 -5
- {spin-0.12 → spin-0.13}/spin/cmds/meson.py +76 -18
- {spin-0.12 → spin-0.13}/spin/cmds/meta.py +5 -1
- spin-0.13/spin/cmds/util.py +179 -0
- {spin-0.12 → spin-0.13}/spin/color_format.py +1 -1
- spin-0.13/spin/tests/__init__.py +0 -0
- {spin-0.12 → spin-0.13}/spin/tests/conftest.py +13 -4
- {spin-0.12 → spin-0.13}/spin/tests/test_build_cmds.py +24 -17
- {spin-0.12 → spin-0.13}/spin/tests/test_cli.py +4 -4
- {spin-0.12 → spin-0.13}/spin/tests/test_editable.py +3 -3
- spin-0.13/spin/tests/test_extend_command.py +83 -0
- spin-0.13/spin/tests/test_test.py +51 -0
- spin-0.13/spin/tests/test_util.py +10 -0
- {spin-0.12 → spin-0.13}/spin/tests/testutil.py +5 -0
- {spin-0.12 → spin-0.13/spin.egg-info}/PKG-INFO +48 -38
- {spin-0.12 → spin-0.13}/spin.egg-info/SOURCES.txt +3 -0
- {spin-0.12 → spin-0.13}/spin.egg-info/requires.txt +1 -1
- spin-0.12/spin/cmds/util.py +0 -96
- spin-0.12/spin/tests/test_test.py +0 -29
- {spin-0.12 → spin-0.13}/LICENSE +0 -0
- {spin-0.12 → spin-0.13}/setup.cfg +0 -0
- {spin-0.12 → spin-0.13}/spin/cmds/__init__.py +0 -0
- {spin-0.12 → spin-0.13}/spin/cmds/build.py +0 -0
- {spin-0.12 → spin-0.13}/spin/cmds/pip.py +0 -0
- {spin-0.12 → spin-0.13}/spin/containers.py +0 -0
- {spin-0.12 → spin-0.13}/spin/sectioned_help.py +0 -0
- {spin-0.12 → spin-0.13}/spin/tests/test_meson.py +0 -0
- {spin-0.12 → spin-0.13}/spin.egg-info/dependency_links.txt +0 -0
- {spin-0.12 → spin-0.13}/spin.egg-info/entry_points.txt +0 -0
- {spin-0.12 → spin-0.13}/spin.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: spin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13
|
|
4
4
|
Summary: Developer tool for scientific Python libraries
|
|
5
5
|
Maintainer-email: Scientific Python <spin@discuss.scientific-python.org>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -46,6 +46,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
46
46
|
Classifier: Programming Language :: Python :: 3.10
|
|
47
47
|
Classifier: Programming Language :: Python :: 3.11
|
|
48
48
|
Classifier: Programming Language :: Python :: 3.12
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
49
50
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
50
51
|
Requires-Python: >=3.8
|
|
51
52
|
Description-Content-Type: text/markdown
|
|
@@ -55,7 +56,7 @@ Requires-Dist: tomli; python_version < "3.11"
|
|
|
55
56
|
Requires-Dist: colorama; platform_system == "Windows"
|
|
56
57
|
Requires-Dist: importlib_metadata>=7
|
|
57
58
|
Provides-Extra: lint
|
|
58
|
-
Requires-Dist: pre-commit==
|
|
59
|
+
Requires-Dist: pre-commit==4.0.1; extra == "lint"
|
|
59
60
|
Provides-Extra: dev
|
|
60
61
|
Requires-Dist: changelist==0.5; extra == "dev"
|
|
61
62
|
|
|
@@ -75,6 +76,28 @@ When many of the build and installation commands changed, it made sense to abstr
|
|
|
75
76
|
_Note:_ We now have experimental builds for editable installs.
|
|
76
77
|
Most of the Meson commands listed below should work "out of the box" for those.
|
|
77
78
|
|
|
79
|
+
<!--TOC-->
|
|
80
|
+
|
|
81
|
+
- [Installation](#installation)
|
|
82
|
+
- [Configuration](#configuration)
|
|
83
|
+
- [Command sections](#command-sections)
|
|
84
|
+
- [Running](#running)
|
|
85
|
+
- [Built-in commands](#built-in-commands)
|
|
86
|
+
- [Meson](#meson)
|
|
87
|
+
- [Build (PEP 517 builder)](#build-pep-517-builder)
|
|
88
|
+
- [pip (Package Installer for Python)](#pip-package-installer-for-python)
|
|
89
|
+
- [Meta (commands that operate on commands)](#meta-commands-that-operate-on-commands)
|
|
90
|
+
- [🧪 Custom commands](#-custom-commands)
|
|
91
|
+
- [Configuration](#configuration-1)
|
|
92
|
+
- [Argument overrides](#argument-overrides)
|
|
93
|
+
- [Advanced: adding arguments to built-in commands](#advanced-adding-arguments-to-built-in-commands)
|
|
94
|
+
- [Advanced: override Meson CLI](#advanced-override-meson-cli)
|
|
95
|
+
- [FAQ](#faq)
|
|
96
|
+
- [For contributors](#for-contributors)
|
|
97
|
+
- [History](#history)
|
|
98
|
+
|
|
99
|
+
<!--TOC-->
|
|
100
|
+
|
|
78
101
|
## Installation
|
|
79
102
|
|
|
80
103
|
```
|
|
@@ -240,52 +263,39 @@ click options or function keywords:
|
|
|
240
263
|
|
|
241
264
|
### Advanced: adding arguments to built-in commands
|
|
242
265
|
|
|
243
|
-
Instead of rewriting a command from scratch, a project may want to add a flag to
|
|
244
|
-
For this, we
|
|
245
|
-
Fortunately, we don't need to know anything about contexts other than that they allow us to execute commands within commands.
|
|
266
|
+
Instead of rewriting a command from scratch, a project may simply want to add a flag to an existing `spin` command, or perhaps do some pre- or post-processing.
|
|
267
|
+
For this purpose, we provide the `spin.util.extend_cmd` decorator.
|
|
246
268
|
|
|
247
|
-
|
|
269
|
+
Here, we show how to add a `--extra` flag to the existing `build` function:
|
|
248
270
|
|
|
249
271
|
```python
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
# Take this from the built-in implementation, in `spin.cmds.meson.build`:
|
|
253
|
-
|
|
272
|
+
import spin
|
|
254
273
|
|
|
255
|
-
@click.command()
|
|
256
|
-
@click.argument("meson_args", nargs=-1)
|
|
257
|
-
@click.option("-j", "--jobs", help="Number of parallel tasks to launch", type=int)
|
|
258
|
-
@click.option("--clean", is_flag=True, help="Clean build directory before build")
|
|
259
|
-
@click.option(
|
|
260
|
-
"-v", "--verbose", is_flag=True, help="Print all build output, even installation"
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
# This is our new option
|
|
264
|
-
@click.option("--custom-arg/--no-custom-arg")
|
|
265
274
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
275
|
+
@click.option("-e", "--extra", help="Extra test flag")
|
|
276
|
+
@spin.util.extend_command(spin.cmds.meson.build)
|
|
277
|
+
def build_extend(*, parent_callback, extra=None, **kwargs):
|
|
278
|
+
"""
|
|
279
|
+
This version of build also provides the EXTRA flag, that can be used
|
|
280
|
+
to specify an extra integer argument.
|
|
281
|
+
"""
|
|
282
|
+
print(f"Preparing for build with {extra=}")
|
|
283
|
+
parent_callback(**kwargs)
|
|
284
|
+
print("Finalizing build...")
|
|
285
|
+
```
|
|
269
286
|
|
|
270
|
-
|
|
271
|
-
def build(ctx, meson_args, jobs=None, clean=False, verbose=False, custom_arg=False):
|
|
272
|
-
"""Docstring goes here. You may want to copy and customize the original."""
|
|
287
|
+
Note that `build_extend` receives the parent command callback (the function the `build` command would have executed) as its first argument.
|
|
273
288
|
|
|
274
|
-
|
|
275
|
-
print("The value of custom arg is:", custom_arg)
|
|
289
|
+
The matching entry in `pyproject.toml` is:
|
|
276
290
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
291
|
+
```
|
|
292
|
+
"Build" = [".spin/cmds.py:build_extend"]
|
|
293
|
+
```
|
|
280
294
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
ctx.forward(meson.build)
|
|
295
|
+
The `extend_cmd` decorator also accepts a `doc` argument, for setting the new command's `--help` description.
|
|
296
|
+
The function documentation ("This version of build...") is also appended.
|
|
284
297
|
|
|
285
|
-
|
|
286
|
-
# - https://click.palletsprojects.com/en/8.1.x/api/#click.Context.forward
|
|
287
|
-
# - https://click.palletsprojects.com/en/8.1.x/api/#click.Context.invoke
|
|
288
|
-
```
|
|
298
|
+
Finally, `remove_args` is a tuple of arguments that are not inherited from the original command.
|
|
289
299
|
|
|
290
300
|
### Advanced: override Meson CLI
|
|
291
301
|
|
|
@@ -14,6 +14,28 @@ When many of the build and installation commands changed, it made sense to abstr
|
|
|
14
14
|
_Note:_ We now have experimental builds for editable installs.
|
|
15
15
|
Most of the Meson commands listed below should work "out of the box" for those.
|
|
16
16
|
|
|
17
|
+
<!--TOC-->
|
|
18
|
+
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Configuration](#configuration)
|
|
21
|
+
- [Command sections](#command-sections)
|
|
22
|
+
- [Running](#running)
|
|
23
|
+
- [Built-in commands](#built-in-commands)
|
|
24
|
+
- [Meson](#meson)
|
|
25
|
+
- [Build (PEP 517 builder)](#build-pep-517-builder)
|
|
26
|
+
- [pip (Package Installer for Python)](#pip-package-installer-for-python)
|
|
27
|
+
- [Meta (commands that operate on commands)](#meta-commands-that-operate-on-commands)
|
|
28
|
+
- [🧪 Custom commands](#-custom-commands)
|
|
29
|
+
- [Configuration](#configuration-1)
|
|
30
|
+
- [Argument overrides](#argument-overrides)
|
|
31
|
+
- [Advanced: adding arguments to built-in commands](#advanced-adding-arguments-to-built-in-commands)
|
|
32
|
+
- [Advanced: override Meson CLI](#advanced-override-meson-cli)
|
|
33
|
+
- [FAQ](#faq)
|
|
34
|
+
- [For contributors](#for-contributors)
|
|
35
|
+
- [History](#history)
|
|
36
|
+
|
|
37
|
+
<!--TOC-->
|
|
38
|
+
|
|
17
39
|
## Installation
|
|
18
40
|
|
|
19
41
|
```
|
|
@@ -179,52 +201,39 @@ click options or function keywords:
|
|
|
179
201
|
|
|
180
202
|
### Advanced: adding arguments to built-in commands
|
|
181
203
|
|
|
182
|
-
Instead of rewriting a command from scratch, a project may want to add a flag to
|
|
183
|
-
For this, we
|
|
184
|
-
Fortunately, we don't need to know anything about contexts other than that they allow us to execute commands within commands.
|
|
204
|
+
Instead of rewriting a command from scratch, a project may simply want to add a flag to an existing `spin` command, or perhaps do some pre- or post-processing.
|
|
205
|
+
For this purpose, we provide the `spin.util.extend_cmd` decorator.
|
|
185
206
|
|
|
186
|
-
|
|
207
|
+
Here, we show how to add a `--extra` flag to the existing `build` function:
|
|
187
208
|
|
|
188
209
|
```python
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
# Take this from the built-in implementation, in `spin.cmds.meson.build`:
|
|
192
|
-
|
|
210
|
+
import spin
|
|
193
211
|
|
|
194
|
-
@click.command()
|
|
195
|
-
@click.argument("meson_args", nargs=-1)
|
|
196
|
-
@click.option("-j", "--jobs", help="Number of parallel tasks to launch", type=int)
|
|
197
|
-
@click.option("--clean", is_flag=True, help="Clean build directory before build")
|
|
198
|
-
@click.option(
|
|
199
|
-
"-v", "--verbose", is_flag=True, help="Print all build output, even installation"
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
# This is our new option
|
|
203
|
-
@click.option("--custom-arg/--no-custom-arg")
|
|
204
212
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
213
|
+
@click.option("-e", "--extra", help="Extra test flag")
|
|
214
|
+
@spin.util.extend_command(spin.cmds.meson.build)
|
|
215
|
+
def build_extend(*, parent_callback, extra=None, **kwargs):
|
|
216
|
+
"""
|
|
217
|
+
This version of build also provides the EXTRA flag, that can be used
|
|
218
|
+
to specify an extra integer argument.
|
|
219
|
+
"""
|
|
220
|
+
print(f"Preparing for build with {extra=}")
|
|
221
|
+
parent_callback(**kwargs)
|
|
222
|
+
print("Finalizing build...")
|
|
223
|
+
```
|
|
208
224
|
|
|
209
|
-
|
|
210
|
-
def build(ctx, meson_args, jobs=None, clean=False, verbose=False, custom_arg=False):
|
|
211
|
-
"""Docstring goes here. You may want to copy and customize the original."""
|
|
225
|
+
Note that `build_extend` receives the parent command callback (the function the `build` command would have executed) as its first argument.
|
|
212
226
|
|
|
213
|
-
|
|
214
|
-
print("The value of custom arg is:", custom_arg)
|
|
227
|
+
The matching entry in `pyproject.toml` is:
|
|
215
228
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
229
|
+
```
|
|
230
|
+
"Build" = [".spin/cmds.py:build_extend"]
|
|
231
|
+
```
|
|
219
232
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
ctx.forward(meson.build)
|
|
233
|
+
The `extend_cmd` decorator also accepts a `doc` argument, for setting the new command's `--help` description.
|
|
234
|
+
The function documentation ("This version of build...") is also appended.
|
|
223
235
|
|
|
224
|
-
|
|
225
|
-
# - https://click.palletsprojects.com/en/8.1.x/api/#click.Context.forward
|
|
226
|
-
# - https://click.palletsprojects.com/en/8.1.x/api/#click.Context.invoke
|
|
227
|
-
```
|
|
236
|
+
Finally, `remove_args` is a tuple of arguments that are not inherited from the original command.
|
|
228
237
|
|
|
229
238
|
### Advanced: override Meson CLI
|
|
230
239
|
|
|
@@ -20,6 +20,7 @@ classifiers = [
|
|
|
20
20
|
"Programming Language :: Python :: 3.10",
|
|
21
21
|
"Programming Language :: Python :: 3.11",
|
|
22
22
|
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
23
24
|
"Programming Language :: Python :: 3 :: Only",
|
|
24
25
|
]
|
|
25
26
|
dependencies = [
|
|
@@ -34,7 +35,7 @@ dynamic = ['version']
|
|
|
34
35
|
spin = "spin.__main__:main"
|
|
35
36
|
|
|
36
37
|
[project.optional-dependencies]
|
|
37
|
-
lint = ["pre-commit ==
|
|
38
|
+
lint = ["pre-commit == 4.0.1"]
|
|
38
39
|
dev = ["changelist == 0.5"]
|
|
39
40
|
|
|
40
41
|
[project.urls]
|
|
@@ -131,6 +131,8 @@ def main():
|
|
|
131
131
|
}
|
|
132
132
|
cmd_default_kwargs = toml_config.get("tool.spin.kwargs", {})
|
|
133
133
|
|
|
134
|
+
custom_module_cache = {}
|
|
135
|
+
|
|
134
136
|
for section, cmds in config_cmds.items():
|
|
135
137
|
for cmd in cmds:
|
|
136
138
|
if cmd not in commands:
|
|
@@ -147,11 +149,17 @@ def main():
|
|
|
147
149
|
else:
|
|
148
150
|
try:
|
|
149
151
|
path, func = cmd.split(":")
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
|
|
153
|
+
if path not in custom_module_cache:
|
|
154
|
+
spec = importlib.util.spec_from_file_location(
|
|
155
|
+
"custom_mod", path
|
|
156
|
+
)
|
|
157
|
+
mod = importlib.util.module_from_spec(spec)
|
|
158
|
+
spec.loader.exec_module(mod)
|
|
159
|
+
custom_module_cache[path] = mod
|
|
160
|
+
else:
|
|
161
|
+
mod = custom_module_cache[path]
|
|
162
|
+
|
|
155
163
|
except FileNotFoundError:
|
|
156
164
|
print(
|
|
157
165
|
f"!! Could not find file `{path}` to load custom command `{cmd}`.\n"
|
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import shutil
|
|
7
|
+
import signal
|
|
7
8
|
import sys
|
|
8
9
|
from enum import Enum
|
|
9
10
|
from pathlib import Path
|
|
@@ -230,18 +231,30 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat, build_dir
|
|
|
230
231
|
)
|
|
231
232
|
|
|
232
233
|
|
|
234
|
+
if sys.platform.startswith("win"):
|
|
235
|
+
DEFAULT_PREFIX = "C:/"
|
|
236
|
+
else:
|
|
237
|
+
DEFAULT_PREFIX = "/usr"
|
|
238
|
+
|
|
233
239
|
build_dir_option = click.option(
|
|
234
240
|
"-C",
|
|
235
241
|
"--build-dir",
|
|
236
242
|
default="build",
|
|
237
243
|
show_envvar=True,
|
|
244
|
+
metavar="BUILD_DIR",
|
|
238
245
|
envvar="SPIN_BUILD_DIR",
|
|
239
246
|
help="Meson build directory; package is installed into './{build-dir}-install'.",
|
|
240
247
|
)
|
|
241
248
|
|
|
242
249
|
|
|
243
250
|
@click.command()
|
|
244
|
-
@click.option(
|
|
251
|
+
@click.option(
|
|
252
|
+
"-j",
|
|
253
|
+
"--jobs",
|
|
254
|
+
metavar="N_JOBS",
|
|
255
|
+
help="Number of parallel tasks to launch",
|
|
256
|
+
type=int,
|
|
257
|
+
)
|
|
245
258
|
@click.option("--clean", is_flag=True, help="Clean build directory before build")
|
|
246
259
|
@click.option(
|
|
247
260
|
"-v", "--verbose", is_flag=True, help="Print detailed build and installation output"
|
|
@@ -251,6 +264,13 @@ build_dir_option = click.option(
|
|
|
251
264
|
is_flag=True,
|
|
252
265
|
help="Enable C code coverage using `gcov`. Use `spin test --gcov` to generate reports.",
|
|
253
266
|
)
|
|
267
|
+
@click.option(
|
|
268
|
+
"--prefix",
|
|
269
|
+
help="The build prefix, passed directly to meson.",
|
|
270
|
+
type=str,
|
|
271
|
+
metavar="PREFIX",
|
|
272
|
+
default=DEFAULT_PREFIX,
|
|
273
|
+
)
|
|
254
274
|
@click.argument("meson_args", nargs=-1)
|
|
255
275
|
@build_dir_option
|
|
256
276
|
def build(
|
|
@@ -262,6 +282,7 @@ def build(
|
|
|
262
282
|
gcov=False,
|
|
263
283
|
quiet=False,
|
|
264
284
|
build_dir=None,
|
|
285
|
+
prefix=None,
|
|
265
286
|
):
|
|
266
287
|
"""🔧 Build package with Meson/ninja
|
|
267
288
|
|
|
@@ -312,7 +333,7 @@ def build(
|
|
|
312
333
|
if gcov:
|
|
313
334
|
meson_args = meson_args + ["-Db_coverage=true"]
|
|
314
335
|
|
|
315
|
-
setup_cmd = _meson_cli() + ["setup", build_dir, "--prefix
|
|
336
|
+
setup_cmd = _meson_cli() + ["setup", build_dir, f"--prefix={prefix}"] + meson_args
|
|
316
337
|
|
|
317
338
|
if clean:
|
|
318
339
|
print(f"Removing `{build_dir}`")
|
|
@@ -480,18 +501,23 @@ def test(
|
|
|
480
501
|
|
|
481
502
|
package = cfg.get("tool.spin.package", None)
|
|
482
503
|
if package is None:
|
|
483
|
-
|
|
484
|
-
"Please specify `package = packagename` under `tool.spin` section of `pyproject.toml`"
|
|
504
|
+
click.secho(
|
|
505
|
+
"Please specify `package = packagename` under `tool.spin` section of `pyproject.toml`",
|
|
506
|
+
fg="bright_red",
|
|
485
507
|
)
|
|
486
508
|
raise SystemExit(1)
|
|
487
509
|
|
|
488
510
|
# User did not specify what to test, so we test
|
|
489
|
-
# the full package
|
|
511
|
+
# the full package, or the tests directory if that is present
|
|
490
512
|
if not (pytest_args or tests):
|
|
491
|
-
|
|
513
|
+
if os.path.isdir("./tests"):
|
|
514
|
+
# tests dir exists, presuming you are not shipping tests
|
|
515
|
+
# with your package, and prefer to run those instead
|
|
516
|
+
pytest_args = (os.path.abspath("./tests"),)
|
|
517
|
+
else:
|
|
518
|
+
pytest_args = ("--pyargs", package)
|
|
492
519
|
elif tests:
|
|
493
520
|
if (os.path.sep in tests) or ("/" in tests):
|
|
494
|
-
# Tests specified as file path
|
|
495
521
|
pytest_args = pytest_args + (tests,)
|
|
496
522
|
else:
|
|
497
523
|
# Otherwise tests given as modules
|
|
@@ -503,7 +529,7 @@ def test(
|
|
|
503
529
|
"Error: cannot generate coverage report for editable installs",
|
|
504
530
|
fg="bright_red",
|
|
505
531
|
)
|
|
506
|
-
raise SystemExit(
|
|
532
|
+
raise SystemExit(1)
|
|
507
533
|
|
|
508
534
|
build_cmd = _get_configured_command("build")
|
|
509
535
|
if build_cmd:
|
|
@@ -536,9 +562,6 @@ def test(
|
|
|
536
562
|
if (n_jobs != "1") and ("-n" not in pytest_args):
|
|
537
563
|
pytest_args = ("-n", str(n_jobs)) + pytest_args
|
|
538
564
|
|
|
539
|
-
if not any("--import-mode" in arg for arg in pytest_args):
|
|
540
|
-
pytest_args = ("--import-mode=importlib",) + pytest_args
|
|
541
|
-
|
|
542
565
|
if verbose:
|
|
543
566
|
pytest_args = ("-v",) + pytest_args
|
|
544
567
|
|
|
@@ -564,8 +587,11 @@ def test(
|
|
|
564
587
|
if not os.path.exists(install_dir):
|
|
565
588
|
os.mkdir(install_dir)
|
|
566
589
|
|
|
590
|
+
# Unless we have a src layout, we need to switch away from the current directory into build install to avoid importing ./package instead of the built package.
|
|
591
|
+
test_path = site_path if not os.path.isdir("./src") else None
|
|
592
|
+
|
|
567
593
|
cwd = os.getcwd()
|
|
568
|
-
pytest_p = _run(cmd + list(pytest_args), cwd=
|
|
594
|
+
pytest_p = _run(cmd + list(pytest_args), cwd=test_path)
|
|
569
595
|
os.chdir(cwd)
|
|
570
596
|
|
|
571
597
|
if gcov:
|
|
@@ -607,7 +633,9 @@ def test(
|
|
|
607
633
|
|
|
608
634
|
|
|
609
635
|
@click.command()
|
|
610
|
-
@click.option(
|
|
636
|
+
@click.option(
|
|
637
|
+
"--code", "-c", metavar="CODE", help="Python program passed in as a string"
|
|
638
|
+
)
|
|
611
639
|
@click.argument("gdb_args", nargs=-1)
|
|
612
640
|
@build_dir_option
|
|
613
641
|
@click.pass_context
|
|
@@ -664,7 +692,7 @@ def gdb(ctx, *, code, gdb_args, build_dir):
|
|
|
664
692
|
@click.argument("ipython_args", nargs=-1)
|
|
665
693
|
@build_dir_option
|
|
666
694
|
@click.pass_context
|
|
667
|
-
def ipython(ctx, *, ipython_args, build_dir):
|
|
695
|
+
def ipython(ctx, *, ipython_args, build_dir, pre_import=""):
|
|
668
696
|
"""💻 Launch IPython shell with PYTHONPATH set
|
|
669
697
|
|
|
670
698
|
IPYTHON_ARGS are passed through directly to IPython, e.g.:
|
|
@@ -674,13 +702,15 @@ def ipython(ctx, *, ipython_args, build_dir):
|
|
|
674
702
|
build_cmd = _get_configured_command("build")
|
|
675
703
|
if build_cmd:
|
|
676
704
|
click.secho(
|
|
677
|
-
"Invoking `build` prior to
|
|
705
|
+
"Invoking `build` prior to launching ipython:", bold=True, fg="bright_green"
|
|
678
706
|
)
|
|
679
707
|
ctx.invoke(build_cmd, build_dir=build_dir)
|
|
680
708
|
|
|
681
709
|
p = _set_pythonpath(build_dir)
|
|
682
710
|
if p:
|
|
683
711
|
print(f'💻 Launching IPython with PYTHONPATH="{p}"')
|
|
712
|
+
if pre_import:
|
|
713
|
+
ipython_args = (f"--TerminalIPythonApp.exec_lines={pre_import}",) + ipython_args
|
|
684
714
|
_run(["ipython", "--ignore-cwd"] + list(ipython_args), replace=True)
|
|
685
715
|
|
|
686
716
|
|
|
@@ -798,7 +828,27 @@ def run(ctx, *, args, build_dir=None):
|
|
|
798
828
|
cmd_args = ["bash", "-c", cmd_args]
|
|
799
829
|
|
|
800
830
|
_set_pythonpath(build_dir, quiet=True)
|
|
801
|
-
|
|
831
|
+
|
|
832
|
+
is_windows = sys.platform == "win32"
|
|
833
|
+
|
|
834
|
+
if not is_windows:
|
|
835
|
+
# Let the subprocess handle its own signals
|
|
836
|
+
# Except on Windows, where it already seems to work as intended,
|
|
837
|
+
# and `preexec_fn` is not supported
|
|
838
|
+
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
839
|
+
|
|
840
|
+
def attach_sigint():
|
|
841
|
+
# Reset SIGINT handler to default
|
|
842
|
+
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
843
|
+
|
|
844
|
+
# --- launch subprocess ---
|
|
845
|
+
p = _run(
|
|
846
|
+
cmd_args,
|
|
847
|
+
echo=False,
|
|
848
|
+
shell=shell,
|
|
849
|
+
sys_exit=False,
|
|
850
|
+
preexec_fn=None if is_windows else attach_sigint,
|
|
851
|
+
)
|
|
802
852
|
|
|
803
853
|
# Is the user trying to run a Python script, without calling the Python interpreter?
|
|
804
854
|
executable = args[0]
|
|
@@ -834,7 +884,13 @@ def run(ctx, *, args, build_dir=None):
|
|
|
834
884
|
default=True,
|
|
835
885
|
help="Sphinx gallery: enable/disable plots",
|
|
836
886
|
)
|
|
837
|
-
@click.option(
|
|
887
|
+
@click.option(
|
|
888
|
+
"--jobs",
|
|
889
|
+
"-j",
|
|
890
|
+
default="auto",
|
|
891
|
+
metavar="N_JOBS",
|
|
892
|
+
help="Number of parallel build jobs",
|
|
893
|
+
)
|
|
838
894
|
@build_dir_option
|
|
839
895
|
@click.pass_context
|
|
840
896
|
def docs(
|
|
@@ -937,7 +993,9 @@ def docs(
|
|
|
937
993
|
|
|
938
994
|
|
|
939
995
|
@click.command()
|
|
940
|
-
@click.option(
|
|
996
|
+
@click.option(
|
|
997
|
+
"--code", "-c", metavar="CODE", help="Python program passed in as a string"
|
|
998
|
+
)
|
|
941
999
|
@click.argument("lldb_args", nargs=-1)
|
|
942
1000
|
@build_dir_option
|
|
943
1001
|
@click.pass_context
|
|
@@ -29,7 +29,11 @@ def introspect(*, cmd):
|
|
|
29
29
|
|
|
30
30
|
cmd_func = cmds[cmd]
|
|
31
31
|
try:
|
|
32
|
-
|
|
32
|
+
if hasattr(cmd_func.callback, "_parent"):
|
|
33
|
+
# `util.extend_command` was used
|
|
34
|
+
code = inspect.getsource(cmd_func.callback._parent)
|
|
35
|
+
else:
|
|
36
|
+
code = inspect.getsource(cmd_func.callback)
|
|
33
37
|
except TypeError:
|
|
34
38
|
# Perhaps a partial, try again
|
|
35
39
|
code = inspect.getsource(cmd_func.callback.func)
|