spin 0.9__tar.gz → 0.11__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.
Files changed (29) hide show
  1. {spin-0.9/spin.egg-info → spin-0.11}/PKG-INFO +4 -7
  2. {spin-0.9 → spin-0.11}/README.md +2 -5
  3. {spin-0.9 → spin-0.11}/pyproject.toml +3 -1
  4. {spin-0.9 → spin-0.11}/spin/__init__.py +1 -1
  5. {spin-0.9 → spin-0.11}/spin/__main__.py +21 -2
  6. spin-0.11/spin/cmds/__init__.py +3 -0
  7. {spin-0.9 → spin-0.11}/spin/cmds/meson.py +87 -41
  8. {spin-0.9 → spin-0.11}/spin/cmds/pip.py +13 -9
  9. {spin-0.9 → spin-0.11}/spin/cmds/util.py +14 -2
  10. {spin-0.9 → spin-0.11}/spin/tests/conftest.py +7 -0
  11. {spin-0.9 → spin-0.11}/spin/tests/test_build_cmds.py +15 -11
  12. {spin-0.9 → spin-0.11}/spin/tests/test_editable.py +0 -10
  13. spin-0.11/spin/tests/test_test.py +29 -0
  14. {spin-0.9 → spin-0.11}/spin/tests/testutil.py +4 -0
  15. {spin-0.9 → spin-0.11/spin.egg-info}/PKG-INFO +4 -7
  16. {spin-0.9 → spin-0.11}/spin.egg-info/SOURCES.txt +1 -0
  17. {spin-0.9 → spin-0.11}/spin.egg-info/requires.txt +1 -1
  18. spin-0.9/spin/cmds/__init__.py +0 -8
  19. {spin-0.9 → spin-0.11}/LICENSE +0 -0
  20. {spin-0.9 → spin-0.11}/setup.cfg +0 -0
  21. {spin-0.9 → spin-0.11}/spin/cmds/build.py +0 -0
  22. {spin-0.9 → spin-0.11}/spin/color_format.py +0 -0
  23. {spin-0.9 → spin-0.11}/spin/containers.py +0 -0
  24. {spin-0.9 → spin-0.11}/spin/sectioned_help.py +0 -0
  25. {spin-0.9 → spin-0.11}/spin/tests/test_cli.py +0 -0
  26. {spin-0.9 → spin-0.11}/spin/tests/test_meson.py +0 -0
  27. {spin-0.9 → spin-0.11}/spin.egg-info/dependency_links.txt +0 -0
  28. {spin-0.9 → spin-0.11}/spin.egg-info/entry_points.txt +0 -0
  29. {spin-0.9 → spin-0.11}/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.9
3
+ Version: 0.11
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
@@ -55,7 +55,7 @@ Requires-Dist: tomli; python_version < "3.11"
55
55
  Requires-Dist: colorama; platform_system == "Windows"
56
56
  Requires-Dist: importlib_metadata>=7
57
57
  Provides-Extra: lint
58
- Requires-Dist: pre-commit==3.7.0; extra == "lint"
58
+ Requires-Dist: pre-commit==3.7.1; extra == "lint"
59
59
  Provides-Extra: dev
60
60
  Requires-Dist: changelist==0.5; extra == "dev"
61
61
 
@@ -120,7 +120,7 @@ These commands will then be rendered as:
120
120
 
121
121
  ```
122
122
  Build:
123
- build 🔧 Build package with Meson/ninja and install
123
+ build 🔧 Build package with Meson/ninja
124
124
  test 🔧 Run tests
125
125
 
126
126
  Environments:
@@ -147,7 +147,7 @@ python -m spin
147
147
  Available as `spin.cmds.meson.*`.
148
148
 
149
149
  ```
150
- build 🔧 Build package with Meson/ninja and install to `build-install`
150
+ build 🔧 Build package with Meson/ninja
151
151
  ipython 💻 Launch IPython shell with PYTHONPATH set
152
152
  python 🐍 Launch Python shell with PYTHONPATH set
153
153
  shell 💻 Launch shell with PYTHONPATH set
@@ -171,9 +171,6 @@ Available as `spin.cmds.build.*`:
171
171
  `pip` allows for editable installs, another common
172
172
  development workflow.
173
173
 
174
- Note that, for now, the meson commands above do not work with an
175
- editable install of the package. We're [working on changing that](https://github.com/scientific-python/spin/pull/141).
176
-
177
174
  Available as `spin.cmds.pip.*`:
178
175
 
179
176
  ```
@@ -59,7 +59,7 @@ These commands will then be rendered as:
59
59
 
60
60
  ```
61
61
  Build:
62
- build 🔧 Build package with Meson/ninja and install
62
+ build 🔧 Build package with Meson/ninja
63
63
  test 🔧 Run tests
64
64
 
65
65
  Environments:
@@ -86,7 +86,7 @@ python -m spin
86
86
  Available as `spin.cmds.meson.*`.
87
87
 
88
88
  ```
89
- build 🔧 Build package with Meson/ninja and install to `build-install`
89
+ build 🔧 Build package with Meson/ninja
90
90
  ipython 💻 Launch IPython shell with PYTHONPATH set
91
91
  python 🐍 Launch Python shell with PYTHONPATH set
92
92
  shell 💻 Launch shell with PYTHONPATH set
@@ -110,9 +110,6 @@ Available as `spin.cmds.build.*`:
110
110
  `pip` allows for editable installs, another common
111
111
  development workflow.
112
112
 
113
- Note that, for now, the meson commands above do not work with an
114
- editable install of the package. We're [working on changing that](https://github.com/scientific-python/spin/pull/141).
115
-
116
113
  Available as `spin.cmds.pip.*`:
117
114
 
118
115
  ```
@@ -34,7 +34,7 @@ dynamic = ['version']
34
34
  spin = "spin.__main__:main"
35
35
 
36
36
  [project.optional-dependencies]
37
- lint = ["pre-commit == 3.7.0"]
37
+ lint = ["pre-commit == 3.7.1"]
38
38
  dev = ["changelist == 0.5"]
39
39
 
40
40
  [project.urls]
@@ -54,6 +54,8 @@ filterwarnings = [
54
54
  [tool.ruff]
55
55
  line-length = 88
56
56
  target-version = "py38"
57
+
58
+ [tool.ruff.lint]
57
59
  select = [
58
60
  "C",
59
61
  "E",
@@ -6,7 +6,7 @@ For usage information see `python -m spin`.
6
6
  Read more at https://github.com/scientific-python/spin
7
7
  """
8
8
 
9
- __version__ = "0.9"
9
+ __version__ = "0.11"
10
10
 
11
11
  from .cmds import util
12
12
 
@@ -3,6 +3,8 @@ import importlib
3
3
  import importlib.util
4
4
  import os
5
5
  import sys
6
+ import textwrap
7
+ import traceback
6
8
 
7
9
  import click
8
10
 
@@ -152,8 +154,25 @@ def main():
152
154
 
153
155
  try:
154
156
  group()
155
- except Exception as e:
156
- print(f"Error: {e}; aborting.", file=sys.stderr)
157
+ except Exception:
158
+ click.secho("\n" + traceback.format_exc(limit=-3), fg="red", file=sys.stderr)
159
+ click.secho(
160
+ textwrap.dedent(
161
+ f"""\
162
+ An internal error has occurred. Please file a bug report at
163
+
164
+ https://github.com/scientific-python/spin
165
+
166
+ including the above traceback and the following information:
167
+
168
+ spin: {__version__}, package: {proj_name}
169
+
170
+ Aborting."""
171
+ ),
172
+ fg="red",
173
+ bold=True,
174
+ file=sys.stderr,
175
+ )
157
176
  sys.exit(1)
158
177
 
159
178
 
@@ -0,0 +1,3 @@
1
+ __all__ = ["meson"]
2
+
3
+ from . import meson
@@ -45,7 +45,12 @@ def _editable_install_path(distname):
45
45
  except importlib_metadata.PackageNotFoundError:
46
46
  return None
47
47
 
48
- if getattr(dist.origin.dir_info, "editable", False):
48
+ if dist.origin is None:
49
+ return None
50
+
51
+ if hasattr(dist.origin, "dir_info") and getattr(
52
+ dist.origin.dir_info, "editable", False
53
+ ):
49
54
  if sys.platform == "win32":
50
55
  return dist.origin.url.removeprefix("file:///")
51
56
  else:
@@ -213,9 +218,9 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat):
213
218
 
214
219
  # Verify the tools are installed prior to the build
215
220
  p = _run(["ninja", "-C", build_dir, "-t", "targets", "all"], output=False)
216
- if f"coverage-{coverage_type.value}" not in p.stdout.decode("ascii"):
221
+ if f"coverage-{coverage_type}" not in p.stdout.decode("ascii"):
217
222
  raise click.ClickException(
218
- f"coverage-{coverage_type.value} is not supported... "
223
+ f"coverage-{coverage_type} is not supported... "
219
224
  f"Ensure the following are installed: {', '.join(requirements[coverage_type])} "
220
225
  "and rerun `spin test --gcov`"
221
226
  )
@@ -233,15 +238,17 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat):
233
238
  help="Enable C code coverage using `gcov`. Use `spin test --gcov` to generate reports.",
234
239
  )
235
240
  @click.argument("meson_args", nargs=-1)
236
- def build(meson_args, jobs=None, clean=False, verbose=False, gcov=False, quiet=False):
237
- """🔧 Build package with Meson/ninja and install
241
+ def build(
242
+ *, meson_args, jobs=None, clean=False, verbose=False, gcov=False, quiet=False
243
+ ):
244
+ """🔧 Build package with Meson/ninja
245
+
246
+ The package is installed to `build-install`.
238
247
 
239
248
  MESON_ARGS are passed through e.g.:
240
249
 
241
250
  spin build -- -Dpkg_config_path=/lib64/pkgconfig
242
251
 
243
- The package is installed to build-install
244
-
245
252
  By default meson-python does release builds. To be able to use a debugger,
246
253
  tell meson to build in debug mode:
247
254
 
@@ -361,13 +368,14 @@ Which tests to run. Can be a module, function, class, or method:
361
368
  )
362
369
  @click.option(
363
370
  "--gcov-format",
364
- type=click.Choice(GcovReportFormat),
371
+ type=click.Choice([e.name for e in GcovReportFormat]),
365
372
  default="html",
366
373
  help=f"Format of the gcov report. Can be one of {', '.join(e.value for e in GcovReportFormat)}.",
367
374
  )
368
375
  @click.pass_context
369
376
  def test(
370
377
  ctx,
378
+ *,
371
379
  pytest_args,
372
380
  n_jobs,
373
381
  tests,
@@ -420,8 +428,35 @@ def test(
420
428
  """ # noqa: E501
421
429
  cfg = get_config()
422
430
  distname = cfg.get("project.name", None)
431
+ pytest_args = pytest_args or ()
432
+
433
+ # User specified tests without -t flag
434
+ # Rewrite arguments as though they specified using -t and proceed
435
+ if (len(pytest_args) == 1) and (not tests):
436
+ tests = pytest_args[0]
437
+ pytest_args = ()
438
+
439
+ package = cfg.get("tool.spin.package", None)
440
+ if package is None:
441
+ print(
442
+ "Please specify `package = packagename` under `tool.spin` section of `pyproject.toml`"
443
+ )
444
+ raise SystemExit(1)
445
+
446
+ # User did not specify what to test, so we test
447
+ # the full package
448
+ if not (pytest_args or tests):
449
+ pytest_args = ("--pyargs", package)
450
+ elif tests:
451
+ if (os.path.sep in tests) or ("/" in tests):
452
+ # Tests specified as file path
453
+ pytest_args = pytest_args + (tests,)
454
+ else:
455
+ # Otherwise tests given as modules
456
+ pytest_args = pytest_args + ("--pyargs", tests)
423
457
 
424
- if gcov and distname and _is_editable_install_of_same_source(distname):
458
+ is_editable_install = distname and _is_editable_install_of_same_source(distname)
459
+ if gcov and is_editable_install:
425
460
  click.secho(
426
461
  "Error: cannot generate coverage report for editable installs",
427
462
  fg="bright_red",
@@ -433,16 +468,10 @@ def test(
433
468
  click.secho(
434
469
  "Invoking `build` prior to running tests:", bold=True, fg="bright_green"
435
470
  )
436
- ctx.invoke(build_cmd, gcov=bool(gcov))
437
-
438
- package = cfg.get("tool.spin.package", None)
439
- if (not pytest_args) and (not tests):
440
- pytest_args = (package,)
441
- if pytest_args == (None,):
442
- print(
443
- "Please specify `package = packagename` under `tool.spin` section of `pyproject.toml`"
444
- )
445
- sys.exit(1)
471
+ if gcov is not None:
472
+ ctx.invoke(build_cmd, gcov=bool(gcov))
473
+ else:
474
+ ctx.invoke(build_cmd)
446
475
 
447
476
  site_path = _set_pythonpath()
448
477
  if site_path:
@@ -467,8 +496,8 @@ def test(
467
496
  if (n_jobs != "1") and ("-n" not in pytest_args):
468
497
  pytest_args = ("-n", str(n_jobs)) + pytest_args
469
498
 
470
- if tests and "--pyargs" not in pytest_args:
471
- pytest_args = ("--pyargs", tests) + pytest_args
499
+ if not any("--import-mode" in arg for arg in pytest_args):
500
+ pytest_args = ("--import-mode=importlib",) + pytest_args
472
501
 
473
502
  if verbose:
474
503
  pytest_args = ("-v",) + pytest_args
@@ -491,11 +520,11 @@ def test(
491
520
  else:
492
521
  cmd = ["pytest"]
493
522
 
523
+ if not os.path.exists(install_dir):
524
+ os.mkdir(install_dir)
525
+
494
526
  cwd = os.getcwd()
495
- pytest_p = _run(
496
- cmd + ([f"--rootdir={site_path}"] if site_path else []) + list(pytest_args),
497
- cwd=site_path,
498
- )
527
+ pytest_p = _run(cmd + list(pytest_args), cwd=site_path)
499
528
  os.chdir(cwd)
500
529
 
501
530
  if gcov:
@@ -509,7 +538,7 @@ def test(
509
538
 
510
539
  # Generate report
511
540
  click.secho(
512
- f"Generating {gcov_format.value} coverage report...",
541
+ f"Generating {gcov_format} coverage report...",
513
542
  bold=True,
514
543
  fg="bright_yellow",
515
544
  )
@@ -518,7 +547,7 @@ def test(
518
547
  "ninja",
519
548
  "-C",
520
549
  build_dir,
521
- f"coverage-{gcov_format.value.lower()}",
550
+ f"coverage-{gcov_format.lower()}",
522
551
  ],
523
552
  output=False,
524
553
  )
@@ -540,7 +569,7 @@ def test(
540
569
  @click.option("--code", "-c", help="Python program passed in as a string")
541
570
  @click.argument("gdb_args", nargs=-1)
542
571
  @click.pass_context
543
- def gdb(ctx, code, gdb_args):
572
+ def gdb(ctx, *, code, gdb_args):
544
573
  """👾 Execute code through GDB
545
574
 
546
575
  spin gdb -c 'import numpy as np; print(np.__version__)'
@@ -592,7 +621,7 @@ def gdb(ctx, code, gdb_args):
592
621
  @click.command()
593
622
  @click.argument("ipython_args", nargs=-1)
594
623
  @click.pass_context
595
- def ipython(ctx, ipython_args):
624
+ def ipython(ctx, *, ipython_args):
596
625
  """💻 Launch IPython shell with PYTHONPATH set
597
626
 
598
627
  IPYTHON_ARGS are passed through directly to IPython, e.g.:
@@ -646,7 +675,7 @@ def shell(ctx, shell_args=[]):
646
675
  @click.command()
647
676
  @click.argument("python_args", nargs=-1)
648
677
  @click.pass_context
649
- def python(ctx, python_args):
678
+ def python(ctx, *, python_args):
650
679
  """🐍 Launch Python shell with PYTHONPATH set
651
680
 
652
681
  PYTHON_ARGS are passed through directly to Python, e.g.:
@@ -687,7 +716,7 @@ def python(ctx, python_args):
687
716
  @click.command(context_settings={"ignore_unknown_options": True})
688
717
  @click.argument("args", nargs=-1)
689
718
  @click.pass_context
690
- def run(ctx, args):
719
+ def run(ctx, *, args):
691
720
  """🏁 Run a shell command with PYTHONPATH set
692
721
 
693
722
  \b
@@ -761,7 +790,16 @@ def run(ctx, args):
761
790
  )
762
791
  @click.option("--jobs", "-j", default="auto", help="Number of parallel build jobs")
763
792
  @click.pass_context
764
- def docs(ctx, sphinx_target, clean, first_build, jobs, sphinx_gallery_plot):
793
+ def docs(
794
+ ctx,
795
+ *,
796
+ sphinx_target,
797
+ clean,
798
+ first_build,
799
+ jobs,
800
+ sphinx_gallery_plot,
801
+ clean_dirs=None,
802
+ ):
765
803
  """📖 Build Sphinx documentation
766
804
 
767
805
  By default, SPHINXOPTS="-W", raising errors on warnings.
@@ -793,13 +831,18 @@ def docs(ctx, sphinx_target, clean, first_build, jobs, sphinx_gallery_plot):
793
831
  sphinx_target = "help"
794
832
 
795
833
  if clean:
796
- doc_dirs = [
797
- f"./{doc_dir}/build/",
798
- f"./{doc_dir}/source/api/",
799
- f"./{doc_dir}/source/auto_examples/",
800
- f"./{doc_dir}/source/jupyterlite_contents/",
801
- ]
802
- for target_dir in doc_dirs:
834
+ if clean_dirs is None:
835
+ clean_dirs = []
836
+ for prefix in ("", "_"):
837
+ clean_dirs += [
838
+ f"./{doc_dir}/{prefix}build/",
839
+ f"./{doc_dir}/{prefix}build/",
840
+ f"./{doc_dir}/{prefix}source/api/",
841
+ f"./{doc_dir}/{prefix}source/auto_examples/",
842
+ f"./{doc_dir}/{prefix}source/jupyterlite_contents/",
843
+ ]
844
+
845
+ for target_dir in clean_dirs:
803
846
  if os.path.isdir(target_dir):
804
847
  print(f"Removing {target_dir!r}")
805
848
  shutil.rmtree(target_dir)
@@ -837,14 +880,17 @@ def docs(ctx, sphinx_target, clean, first_build, jobs, sphinx_gallery_plot):
837
880
  bold=True,
838
881
  fg="bright_blue",
839
882
  )
840
- _run(["make", "-C", doc_dir, sphinx_target], replace=True)
883
+
884
+ make_bat_exists = (Path(doc_dir) / "make.bat").exists()
885
+ make_cmd = "make.bat" if sys.platform == "win32" and make_bat_exists else "make"
886
+ _run([make_cmd, sphinx_target], cwd=doc_dir, replace=True)
841
887
 
842
888
 
843
889
  @click.command()
844
890
  @click.option("--code", "-c", help="Python program passed in as a string")
845
891
  @click.argument("lldb_args", nargs=-1)
846
892
  @click.pass_context
847
- def lldb(ctx, code, lldb_args):
893
+ def lldb(ctx, *, code, lldb_args):
848
894
  """👾 Execute code through LLDB
849
895
 
850
896
  spin lldb -c 'import numpy as np; print(np.__version__)'
@@ -5,20 +5,19 @@ from .util import run as _run
5
5
 
6
6
  @click.command()
7
7
  @click.option(
8
- "-v",
9
- "--verbose",
10
- is_flag=True,
11
- default=False,
12
- help="Print detailed build and installation output",
8
+ "--editable/--no-editable",
9
+ default=True,
10
+ help="Install in editable mode.",
13
11
  )
12
+ @click.option("-v", "--verbose", is_flag=True, help="Print detailed build output.")
14
13
  @click.option(
15
- "--editable/--no-editable",
14
+ "--verbose-import/--no-verbose-import",
16
15
  is_flag=True,
17
16
  default=True,
18
- help="Install in editable mode",
17
+ help="Meson only: importing an editable install may trigger a build. This flag determines whether to print that build's output.",
19
18
  )
20
19
  @click.argument("pip_args", nargs=-1)
21
- def install(pip_args, verbose, editable):
20
+ def install(*, pip_args, editable, verbose, verbose_import):
22
21
  """💽 Build and install package using pip.
23
22
 
24
23
  By default, the package is installed in editable mode.
@@ -34,9 +33,14 @@ def install(pip_args, verbose, editable):
34
33
  pip_args = list(pip_args)
35
34
  pip_cmd = ["pip", "install"]
36
35
  pip_args += ["--no-build-isolation"]
36
+
37
37
  if editable:
38
38
  pip_args += ["--editable"]
39
39
 
40
- pip_args = (["-v"] if verbose else []) + pip_args
40
+ if verbose_import:
41
+ pip_args = ["--config-settings=editable-verbose=true"] + pip_args
42
+
43
+ if verbose:
44
+ pip_args = ["-v"] + pip_args
41
45
 
42
46
  _run(pip_cmd + pip_args + ["."], sys_exit=False, replace=True)
@@ -2,13 +2,21 @@ import os
2
2
  import shlex
3
3
  import subprocess
4
4
  import sys
5
+ from typing import Optional
5
6
 
6
7
  import click
7
8
 
8
9
 
9
10
  def run(
10
- cmd, cwd=None, replace=False, sys_exit=True, output=True, echo=True, *args, **kwargs
11
- ):
11
+ cmd: list[str],
12
+ cwd: Optional[str] = None, # in 3.10 and up: str | None
13
+ replace: bool = False,
14
+ sys_exit: bool = True,
15
+ output: bool = True,
16
+ echo: bool = True,
17
+ *args,
18
+ **kwargs,
19
+ ) -> subprocess.CompletedProcess:
12
20
  """Run a shell command.
13
21
 
14
22
  Parameters
@@ -33,6 +41,10 @@ def run(
33
41
 
34
42
  Other arguments and keywords are passed directly to `subprocess.run`.
35
43
 
44
+
45
+ Returns
46
+ -------
47
+ p : CompletedProcess
36
48
  """
37
49
  if cwd:
38
50
  if echo:
@@ -18,3 +18,10 @@ def pre_post_test():
18
18
  os.chdir(cwd)
19
19
  util.run(["git", "clean", "-xdf"], cwd="example_pkg")
20
20
  os.chdir(cwd)
21
+
22
+
23
+ @pytest.fixture
24
+ def editable_install():
25
+ util.run(["pip", "install", "--quiet", "--no-build-isolation", "-e", "."])
26
+ yield
27
+ util.run(["pip", "uninstall", "--quiet", "-y", "example_pkg"])
@@ -5,7 +5,7 @@ import tempfile
5
5
  from pathlib import Path
6
6
 
7
7
  import pytest
8
- from testutil import skip_on_windows, skip_unless_linux, spin, stdout
8
+ from testutil import skip_on_windows, skip_unless_linux, skip_unless_macos, spin, stdout
9
9
 
10
10
  from spin.cmds.util import run
11
11
 
@@ -88,16 +88,6 @@ def test_recommend_run_python():
88
88
  ), "Failed to recommend `python run python file.py`"
89
89
 
90
90
 
91
- def test_test():
92
- """Does the test command run?"""
93
- spin("test")
94
-
95
-
96
- def test_test_with_pythonpath():
97
- """Does `spin test` work when PYTHONPATH is set?"""
98
- spin("test", env={**os.environ, "PYTHONPATH": "/tmp"})
99
-
100
-
101
91
  def test_sdist():
102
92
  spin("sdist")
103
93
 
@@ -143,3 +133,17 @@ def test_gdb():
143
133
  "--batch",
144
134
  )
145
135
  assert "hi" in stdout(p)
136
+
137
+
138
+ @skip_unless_macos
139
+ def test_lldb():
140
+ p = spin(
141
+ "lldb",
142
+ "-c",
143
+ 'import example_pkg; example_pkg.echo("hi")',
144
+ "--",
145
+ "-o",
146
+ "run",
147
+ "--batch",
148
+ )
149
+ assert "hi" in stdout(p)
@@ -1,15 +1,5 @@
1
- import pytest
2
1
  from testutil import spin, stdout
3
2
 
4
- from spin.cmds.util import run
5
-
6
-
7
- @pytest.fixture
8
- def editable_install():
9
- run(["pip", "install", "--quiet", "--no-build-isolation", "-e", "."])
10
- yield
11
- run(["pip", "uninstall", "--quiet", "-y", "example_pkg"])
12
-
13
3
 
14
4
  def test_detect_editable(editable_install):
15
5
  assert "Editable install of same source detected" in stdout(
@@ -0,0 +1,29 @@
1
+ import os
2
+
3
+ from testutil import spin
4
+
5
+
6
+ def test_test():
7
+ """Does the test command run?"""
8
+ spin("test")
9
+
10
+
11
+ def test_test_with_pythonpath():
12
+ """Does `spin test` work when PYTHONPATH is set?"""
13
+ spin("test", env={**os.environ, "PYTHONPATH": "/tmp"})
14
+
15
+
16
+ def test_test_file_spec():
17
+ spin("test", "example_pkg/submodule/tests/test_submodule.py")
18
+
19
+
20
+ def test_test_module_spec():
21
+ spin("test", "example_pkg.submodule")
22
+
23
+
24
+ def test_test_editable_file_spec(editable_install):
25
+ spin("test", "example_pkg/submodule/tests/test_submodule.py")
26
+
27
+
28
+ def test_test_editable_module_spec(editable_install):
29
+ spin("test", "example_pkg.submodule")
@@ -13,6 +13,10 @@ skip_unless_linux = pytest.mark.skipif(
13
13
  not sys.platform.startswith("linux"), reason="Skipped; platform not Linux"
14
14
  )
15
15
 
16
+ skip_unless_macos = pytest.mark.skipif(
17
+ not sys.platform.startswith("darwin"), reason="Skipped; platform not macOS"
18
+ )
19
+
16
20
 
17
21
  def spin(*args, **user_kwargs):
18
22
  args = (str(el) for el in args)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spin
3
- Version: 0.9
3
+ Version: 0.11
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
@@ -55,7 +55,7 @@ Requires-Dist: tomli; python_version < "3.11"
55
55
  Requires-Dist: colorama; platform_system == "Windows"
56
56
  Requires-Dist: importlib_metadata>=7
57
57
  Provides-Extra: lint
58
- Requires-Dist: pre-commit==3.7.0; extra == "lint"
58
+ Requires-Dist: pre-commit==3.7.1; extra == "lint"
59
59
  Provides-Extra: dev
60
60
  Requires-Dist: changelist==0.5; extra == "dev"
61
61
 
@@ -120,7 +120,7 @@ These commands will then be rendered as:
120
120
 
121
121
  ```
122
122
  Build:
123
- build 🔧 Build package with Meson/ninja and install
123
+ build 🔧 Build package with Meson/ninja
124
124
  test 🔧 Run tests
125
125
 
126
126
  Environments:
@@ -147,7 +147,7 @@ python -m spin
147
147
  Available as `spin.cmds.meson.*`.
148
148
 
149
149
  ```
150
- build 🔧 Build package with Meson/ninja and install to `build-install`
150
+ build 🔧 Build package with Meson/ninja
151
151
  ipython 💻 Launch IPython shell with PYTHONPATH set
152
152
  python 🐍 Launch Python shell with PYTHONPATH set
153
153
  shell 💻 Launch shell with PYTHONPATH set
@@ -171,9 +171,6 @@ Available as `spin.cmds.build.*`:
171
171
  `pip` allows for editable installs, another common
172
172
  development workflow.
173
173
 
174
- Note that, for now, the meson commands above do not work with an
175
- editable install of the package. We're [working on changing that](https://github.com/scientific-python/spin/pull/141).
176
-
177
174
  Available as `spin.cmds.pip.*`:
178
175
 
179
176
  ```
@@ -22,4 +22,5 @@ spin/tests/test_build_cmds.py
22
22
  spin/tests/test_cli.py
23
23
  spin/tests/test_editable.py
24
24
  spin/tests/test_meson.py
25
+ spin/tests/test_test.py
25
26
  spin/tests/testutil.py
@@ -11,4 +11,4 @@ tomli
11
11
  changelist==0.5
12
12
 
13
13
  [lint]
14
- pre-commit==3.7.0
14
+ pre-commit==3.7.1
@@ -1,8 +0,0 @@
1
- from . import meson
2
-
3
- # Backward compatibility with older versions
4
- build = meson.build
5
- test = meson.test
6
- ipython = meson.ipython
7
- python = meson.python
8
- shell = meson.shell
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes