spin 0.17__tar.gz → 0.19__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 (32) hide show
  1. {spin-0.17/spin.egg-info → spin-0.19}/PKG-INFO +5 -34
  2. {spin-0.17 → spin-0.19}/pyproject.toml +9 -4
  3. {spin-0.17 → spin-0.19}/spin/__init__.py +1 -1
  4. {spin-0.17 → spin-0.19}/spin/__main__.py +5 -0
  5. {spin-0.17 → spin-0.19}/spin/cmds/meson.py +7 -1
  6. {spin-0.17 → spin-0.19}/spin/cmds/pip.py +3 -0
  7. {spin-0.17 → spin-0.19}/spin/tests/test_build_cmds.py +9 -0
  8. {spin-0.17 → spin-0.19}/spin/tests/test_meson.py +61 -0
  9. {spin-0.17 → spin-0.19/spin.egg-info}/PKG-INFO +5 -34
  10. {spin-0.17 → spin-0.19}/spin.egg-info/requires.txt +2 -2
  11. {spin-0.17 → spin-0.19}/LICENSE +0 -0
  12. {spin-0.17 → spin-0.19}/README.md +0 -0
  13. {spin-0.17 → spin-0.19}/setup.cfg +0 -0
  14. {spin-0.17 → spin-0.19}/spin/cmds/__init__.py +0 -0
  15. {spin-0.17 → spin-0.19}/spin/cmds/build.py +0 -0
  16. {spin-0.17 → spin-0.19}/spin/cmds/meta.py +0 -0
  17. {spin-0.17 → spin-0.19}/spin/cmds/util.py +0 -0
  18. {spin-0.17 → spin-0.19}/spin/color_format.py +0 -0
  19. {spin-0.17 → spin-0.19}/spin/containers.py +0 -0
  20. {spin-0.17 → spin-0.19}/spin/sectioned_help.py +0 -0
  21. {spin-0.17 → spin-0.19}/spin/tests/__init__.py +0 -0
  22. {spin-0.17 → spin-0.19}/spin/tests/conftest.py +0 -0
  23. {spin-0.17 → spin-0.19}/spin/tests/test_cli.py +0 -0
  24. {spin-0.17 → spin-0.19}/spin/tests/test_editable.py +0 -0
  25. {spin-0.17 → spin-0.19}/spin/tests/test_extend_command.py +0 -0
  26. {spin-0.17 → spin-0.19}/spin/tests/test_test.py +0 -0
  27. {spin-0.17 → spin-0.19}/spin/tests/test_util.py +0 -0
  28. {spin-0.17 → spin-0.19}/spin/tests/testutil.py +0 -0
  29. {spin-0.17 → spin-0.19}/spin.egg-info/SOURCES.txt +0 -0
  30. {spin-0.17 → spin-0.19}/spin.egg-info/dependency_links.txt +0 -0
  31. {spin-0.17 → spin-0.19}/spin.egg-info/entry_points.txt +0 -0
  32. {spin-0.17 → spin-0.19}/spin.egg-info/top_level.txt +0 -0
@@ -1,44 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spin
3
- Version: 0.17
3
+ Version: 0.19
4
4
  Summary: Developer tool for scientific Python libraries
5
5
  Maintainer-email: Scientific Python <spin@discuss.scientific-python.org>
6
- License: BSD 3-Clause License
7
-
8
- Copyright (c) 2021--2024, Scientific Python project
9
- All rights reserved.
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- 1. Redistributions of source code must retain the above copyright notice, this
15
- list of conditions and the following disclaimer.
16
-
17
- 2. Redistributions in binary form must reproduce the above copyright notice,
18
- this list of conditions and the following disclaimer in the documentation
19
- and/or other materials provided with the distribution.
20
-
21
- 3. Neither the name of the copyright holder nor the names of its
22
- contributors may be used to endorse or promote products derived from
23
- this software without specific prior written permission.
24
-
25
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
-
6
+ License-Expression: BSD-3-Clause
36
7
  Project-URL: homepage, https://github.com/scientific-python/spin
37
8
  Classifier: Development Status :: 4 - Beta
38
9
  Classifier: Programming Language :: Python
39
10
  Classifier: Intended Audience :: Developers
40
11
  Classifier: Intended Audience :: Science/Research
41
- Classifier: License :: OSI Approved :: BSD License
42
12
  Classifier: Operating System :: OS Independent
43
13
  Classifier: Programming Language :: Python :: 3
44
14
  Classifier: Programming Language :: Python :: 3.10
@@ -46,16 +16,17 @@ Classifier: Programming Language :: Python :: 3.11
46
16
  Classifier: Programming Language :: Python :: 3.12
47
17
  Classifier: Programming Language :: Python :: 3.13
48
18
  Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
49
20
  Classifier: Programming Language :: Python :: 3 :: Only
50
21
  Requires-Python: >=3.10
51
22
  Description-Content-Type: text/markdown
52
23
  License-File: LICENSE
53
- Requires-Dist: click!=8.3.0,<8.4,>=8
24
+ Requires-Dist: click!=8.3.0,<8.6,>=8
54
25
  Requires-Dist: tomli; python_version < "3.11"
55
26
  Requires-Dist: colorama; platform_system == "Windows"
56
27
  Requires-Dist: importlib_metadata>=7
57
28
  Provides-Extra: lint
58
- Requires-Dist: pre-commit==4.3.0; extra == "lint"
29
+ Requires-Dist: pre-commit==4.6.2; extra == "lint"
59
30
  Provides-Extra: dev
60
31
  Requires-Dist: changelist==0.5; extra == "dev"
61
32
  Dynamic: license-file
@@ -1,9 +1,14 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
1
5
  [project]
2
6
  name = "spin"
3
7
  requires-python = ">=3.10" # Oldest non-EOL Python here
4
8
  description = "Developer tool for scientific Python libraries"
5
9
  readme = "README.md"
6
- license = {file = "LICENSE"}
10
+ license = "BSD-3-Clause"
11
+ license-files = ["LICENSE"]
7
12
  maintainers = [
8
13
  {name = "Scientific Python", email = "spin@discuss.scientific-python.org"}
9
14
  ]
@@ -12,7 +17,6 @@ classifiers = [
12
17
  "Programming Language :: Python",
13
18
  "Intended Audience :: Developers",
14
19
  "Intended Audience :: Science/Research",
15
- "License :: OSI Approved :: BSD License",
16
20
  "Operating System :: OS Independent",
17
21
  "Programming Language :: Python :: 3",
18
22
  "Programming Language :: Python :: 3.10",
@@ -20,10 +24,11 @@ classifiers = [
20
24
  "Programming Language :: Python :: 3.12",
21
25
  "Programming Language :: Python :: 3.13",
22
26
  "Programming Language :: Python :: 3.14",
27
+ "Programming Language :: Python :: 3.15",
23
28
  "Programming Language :: Python :: 3 :: Only",
24
29
  ]
25
30
  dependencies = [
26
- "click>=8,!=8.3.0,<8.4",
31
+ "click>=8,!=8.3.0,<8.6",
27
32
  "tomli; python_version < '3.11'",
28
33
  "colorama; platform_system == 'Windows'",
29
34
  "importlib_metadata >= 7"
@@ -34,7 +39,7 @@ dynamic = ['version']
34
39
  spin = "spin.__main__:main"
35
40
 
36
41
  [project.optional-dependencies]
37
- lint = ["pre-commit == 4.3.0"]
42
+ lint = ["pre-commit == 4.6.2"]
38
43
  dev = ["changelist == 0.5"]
39
44
 
40
45
  [project.urls]
@@ -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.17"
9
+ __version__ = "0.19"
10
10
 
11
11
  from .cmds import util
12
12
 
@@ -1,6 +1,7 @@
1
1
  import collections
2
2
  import importlib
3
3
  import importlib.util
4
+ import io
4
5
  import os
5
6
  import pathlib
6
7
  import sys
@@ -42,6 +43,10 @@ def _detect_config_dir(path: pathlib.Path) -> pathlib.Path | None:
42
43
 
43
44
 
44
45
  def main():
46
+ # Replace characters, such as emoji, that the stdout encoding cannot represent
47
+ if isinstance(sys.stdout, io.TextIOWrapper):
48
+ sys.stdout.reconfigure(errors="replace")
49
+
45
50
  # Alias `spin help` to `spin --help`
46
51
  if (len(sys.argv) == 2) and (sys.argv[1] == "help"):
47
52
  sys.argv[1] = "--help"
@@ -385,6 +385,8 @@ def build(
385
385
  if not (os.path.exists(build_dir) and _meson_version_configured(build_dir)):
386
386
  p = _run(setup_cmd, sys_exit=False, output=not quiet)
387
387
  if p.returncode != 0:
388
+ if quiet:
389
+ print(p.stdout.decode("utf-8"), end="")
388
390
  raise RuntimeError(
389
391
  "Meson configuration failed; please try `spin build` again with the `--clean` flag."
390
392
  )
@@ -417,6 +419,7 @@ def build(
417
419
  _meson_cli()
418
420
  + [
419
421
  "install",
422
+ "--no-rebuild",
420
423
  "--only-changed",
421
424
  "-C",
422
425
  build_dir,
@@ -765,7 +768,10 @@ def ipython(ctx, *, ipython_args, build=None, build_dir=None, pre_import=""):
765
768
  print(f'💻 Launching IPython with PYTHONPATH="{p}"')
766
769
  if pre_import:
767
770
  ipython_args = (f"--TerminalIPythonApp.exec_lines={pre_import}",) + ipython_args
768
- _run(["ipython", "--ignore-cwd"] + list(ipython_args), replace=True)
771
+ _run(
772
+ [sys.executable, "-P", "-m", "IPython", "--ignore-cwd"] + list(ipython_args),
773
+ replace=True,
774
+ )
769
775
 
770
776
 
771
777
  @click.command()
@@ -51,4 +51,7 @@ def install(*, pip_args, editable, verbose, verbose_import):
51
51
  if verbose:
52
52
  pip_args = ["-v"] + pip_args
53
53
 
54
+ if "." in pip_args:
55
+ pip_args.remove(".")
56
+
54
57
  _run(pip_cmd + pip_args + ["."], sys_exit=False, replace=True)
@@ -201,3 +201,12 @@ def test_parallel_builds(example_pkg):
201
201
  assert "build-install" in example_pkg_path
202
202
  assert "parallel/build-install" in example_pkg_parallel_path
203
203
  assert "parallel/build-install" not in example_pkg_path
204
+
205
+
206
+ @skip_py_lt_311 # python command does not run on older pythons
207
+ def test_unencodable_output(example_pkg):
208
+ # `spin python` prints an emoji, which ASCII cannot encode
209
+ p = spin(
210
+ "python", "--", "-c", "pass", env={**os.environ, "PYTHONIOENCODING": "ascii"}
211
+ )
212
+ assert p.returncode == 0
@@ -4,11 +4,72 @@ import tempfile
4
4
  from os.path import join as pjoin
5
5
  from os.path import normpath
6
6
 
7
+ import click
7
8
  import pytest
8
9
 
9
10
  from spin.cmds import meson
10
11
  from spin.containers import DotDict
11
12
 
13
+ # Fake meson: prints to stdout and stderr, and fails for subcommands in FAILING_CMDS
14
+ FAKE_MESON = """
15
+ import sys
16
+
17
+ FAILING_CMDS = {failing_cmds!r}
18
+
19
+ subcommand = sys.argv[1]
20
+ print("fake meson " + subcommand + ": stdout")
21
+ print("fake meson " + subcommand + ": stderr", file=sys.stderr)
22
+ sys.exit(1 if subcommand in FAILING_CMDS else 0)
23
+ """
24
+
25
+
26
+ @pytest.fixture
27
+ def fake_meson(tmp_path, monkeypatch):
28
+ """Return a factory that installs a fake meson and returns a build dir."""
29
+
30
+ def make(failing_cmds=()):
31
+ script = tmp_path / "meson.py"
32
+ script.write_text(FAKE_MESON.format(failing_cmds=list(failing_cmds)))
33
+ # Run the fake script in place of the meson binary
34
+ monkeypatch.setattr(meson, "_meson_cli", lambda: [sys.executable, str(script)])
35
+ monkeypatch.setattr(meson, "get_config", lambda: DotDict({}))
36
+ return str(tmp_path / "build")
37
+
38
+ return make
39
+
40
+
41
+ def test_quiet_configuration_failure_output(fake_meson, capfd):
42
+ build_dir = fake_meson(failing_cmds=["setup"])
43
+ with pytest.raises(RuntimeError, match="Meson configuration failed"):
44
+ meson.build.callback(
45
+ meson_args=(), build_dir=build_dir, prefix="/usr", quiet=True
46
+ )
47
+ captured = capfd.readouterr()
48
+ output = captured.out + captured.err
49
+ assert output.count("fake meson setup: stdout") == 1
50
+ assert output.count("fake meson setup: stderr") == 1
51
+
52
+
53
+ def test_run_configuration_failure_output(fake_meson, monkeypatch, capfd):
54
+ build_dir = fake_meson(failing_cmds=["setup"])
55
+ monkeypatch.setattr(meson, "_get_configured_command", lambda name: meson.build)
56
+ with (
57
+ click.Context(meson.run),
58
+ pytest.raises(RuntimeError, match="Meson configuration failed"),
59
+ ):
60
+ meson.run.callback(args=("unused-command",), build=True, build_dir=build_dir)
61
+ captured = capfd.readouterr()
62
+ assert "fake meson setup: stdout" in captured.err
63
+ assert "fake meson setup: stderr" in captured.err
64
+ assert "fake meson setup" not in captured.out
65
+
66
+
67
+ def test_successful_quiet_build_output(fake_meson, capfd):
68
+ build_dir = fake_meson()
69
+ meson.build.callback(meson_args=(), build_dir=build_dir, prefix="/usr", quiet=True)
70
+ captured = capfd.readouterr()
71
+ assert "fake meson" not in captured.out + captured.err
72
+
12
73
 
13
74
  def make_paths(root, paths):
14
75
  for p in paths:
@@ -1,44 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spin
3
- Version: 0.17
3
+ Version: 0.19
4
4
  Summary: Developer tool for scientific Python libraries
5
5
  Maintainer-email: Scientific Python <spin@discuss.scientific-python.org>
6
- License: BSD 3-Clause License
7
-
8
- Copyright (c) 2021--2024, Scientific Python project
9
- All rights reserved.
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- 1. Redistributions of source code must retain the above copyright notice, this
15
- list of conditions and the following disclaimer.
16
-
17
- 2. Redistributions in binary form must reproduce the above copyright notice,
18
- this list of conditions and the following disclaimer in the documentation
19
- and/or other materials provided with the distribution.
20
-
21
- 3. Neither the name of the copyright holder nor the names of its
22
- contributors may be used to endorse or promote products derived from
23
- this software without specific prior written permission.
24
-
25
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
-
6
+ License-Expression: BSD-3-Clause
36
7
  Project-URL: homepage, https://github.com/scientific-python/spin
37
8
  Classifier: Development Status :: 4 - Beta
38
9
  Classifier: Programming Language :: Python
39
10
  Classifier: Intended Audience :: Developers
40
11
  Classifier: Intended Audience :: Science/Research
41
- Classifier: License :: OSI Approved :: BSD License
42
12
  Classifier: Operating System :: OS Independent
43
13
  Classifier: Programming Language :: Python :: 3
44
14
  Classifier: Programming Language :: Python :: 3.10
@@ -46,16 +16,17 @@ Classifier: Programming Language :: Python :: 3.11
46
16
  Classifier: Programming Language :: Python :: 3.12
47
17
  Classifier: Programming Language :: Python :: 3.13
48
18
  Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
49
20
  Classifier: Programming Language :: Python :: 3 :: Only
50
21
  Requires-Python: >=3.10
51
22
  Description-Content-Type: text/markdown
52
23
  License-File: LICENSE
53
- Requires-Dist: click!=8.3.0,<8.4,>=8
24
+ Requires-Dist: click!=8.3.0,<8.6,>=8
54
25
  Requires-Dist: tomli; python_version < "3.11"
55
26
  Requires-Dist: colorama; platform_system == "Windows"
56
27
  Requires-Dist: importlib_metadata>=7
57
28
  Provides-Extra: lint
58
- Requires-Dist: pre-commit==4.3.0; extra == "lint"
29
+ Requires-Dist: pre-commit==4.6.2; extra == "lint"
59
30
  Provides-Extra: dev
60
31
  Requires-Dist: changelist==0.5; extra == "dev"
61
32
  Dynamic: license-file
@@ -1,4 +1,4 @@
1
- click!=8.3.0,<8.4,>=8
1
+ click!=8.3.0,<8.6,>=8
2
2
  importlib_metadata>=7
3
3
 
4
4
  [:platform_system == "Windows"]
@@ -11,4 +11,4 @@ tomli
11
11
  changelist==0.5
12
12
 
13
13
  [lint]
14
- pre-commit==4.3.0
14
+ pre-commit==4.6.2
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
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