hatch-cpp 0.3.6__py3-none-any.whl → 0.4.0__py3-none-any.whl

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.
hatch_cpp/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.3.6"
1
+ __version__ = "0.4.0"
2
2
 
3
3
  from .config import *
4
4
  from .hooks import *
@@ -71,19 +71,11 @@ endif()
71
71
 
72
72
 
73
73
  find_package(Python ${CSP_PYTHON_VERSION} EXACT REQUIRED COMPONENTS Interpreter Development.Module)
74
- link_directories(${Python_LIBRARY_DIRS})
75
- include_directories(${Python_INCLUDE_DIRS})
76
-
77
- set(CMAKE_SHARED_LIBRARY_PREFIX "")
78
- if(NOT WIN32)
79
- set(CMAKE_SHARED_LIBRARY_SUFFIX .so)
80
- else()
81
- set(CMAKE_SHARED_LIBRARY_SUFFIX .pyd)
82
- endif()
83
74
 
84
75
  include_directories("${CMAKE_SOURCE_DIR}/cpp")
85
76
 
86
- add_library(extension SHARED cpp/project/basic.cpp)
77
+ python_add_library(extension MODULE WITH_SOABI cpp/project/basic.cpp)
78
+
87
79
  set_target_properties(extension PROPERTIES PUBLIC_HEADER cpp/project/basic.hpp)
88
80
  install(TARGETS extension
89
81
  PUBLIC_HEADER DESTINATION project/include/project
@@ -71,19 +71,11 @@ endif()
71
71
 
72
72
 
73
73
  find_package(Python ${CSP_PYTHON_VERSION} EXACT REQUIRED COMPONENTS Interpreter Development.Module)
74
- link_directories(${Python_LIBRARY_DIRS})
75
- include_directories(${Python_INCLUDE_DIRS})
76
-
77
- set(CMAKE_SHARED_LIBRARY_PREFIX "")
78
- if(NOT WIN32)
79
- set(CMAKE_SHARED_LIBRARY_SUFFIX .so)
80
- else()
81
- set(CMAKE_SHARED_LIBRARY_SUFFIX .pyd)
82
- endif()
83
74
 
84
75
  include_directories("${CMAKE_SOURCE_DIR}/cpp")
85
76
 
86
- add_library(extension SHARED cpp/project/basic.cpp)
77
+ python_add_library(extension MODULE WITH_SOABI cpp/project/basic.cpp)
78
+
87
79
  set_target_properties(extension PROPERTIES PUBLIC_HEADER cpp/project/basic.hpp)
88
80
  install(TARGETS extension
89
81
  PUBLIC_HEADER DESTINATION project/include/project
@@ -1,8 +1,9 @@
1
- from os import listdir
1
+ import contextlib
2
+ from os import listdir, remove
2
3
  from pathlib import Path
3
- from shutil import rmtree
4
4
  from subprocess import check_call
5
5
  from sys import modules, path, platform
6
+ from sysconfig import get_config_var
6
7
 
7
8
  import pytest
8
9
 
@@ -24,9 +25,17 @@ class TestProject:
24
25
  ],
25
26
  )
26
27
  def test_basic(self, project):
28
+
29
+ suffix_ext = get_config_var("EXT_SUFFIX")
30
+
27
31
  # cleanup
28
- rmtree(f"hatch_cpp/tests/{project}/project/extension.so", ignore_errors=True)
29
- rmtree(f"hatch_cpp/tests/{project}/project/extension.pyd", ignore_errors=True)
32
+ with contextlib.suppress(FileNotFoundError):
33
+ remove(f"hatch_cpp/tests/{project}/project/extension.so")
34
+ with contextlib.suppress(FileNotFoundError):
35
+ remove(f"hatch_cpp/tests/{project}/project/extension.pyd")
36
+ with contextlib.suppress(FileNotFoundError):
37
+ remove(f"hatch_cpp/tests/{project}/project/extension{suffix_ext}")
38
+
30
39
  modules.pop("project", None)
31
40
  modules.pop("project.extension", None)
32
41
 
@@ -40,14 +49,14 @@ class TestProject:
40
49
  )
41
50
 
42
51
  # assert built
43
-
52
+ project_dir_content = listdir(f"hatch_cpp/tests/{project}/project")
44
53
  if project == "test_project_limited_api" and platform != "win32":
45
- assert "extension.abi3.so" in listdir(f"hatch_cpp/tests/{project}/project")
54
+ assert "extension.abi3.so" in project_dir_content
46
55
  else:
47
56
  if platform == "win32":
48
- assert "extension.pyd" in listdir(f"hatch_cpp/tests/{project}/project")
57
+ assert "extension.pyd" in project_dir_content or f"extension{suffix_ext}" in project_dir_content
49
58
  else:
50
- assert "extension.so" in listdir(f"hatch_cpp/tests/{project}/project")
59
+ assert "extension.so" in project_dir_content or f"extension{suffix_ext}" in project_dir_content
51
60
 
52
61
  # import
53
62
  here = Path(__file__).parent / project
@@ -156,14 +156,66 @@ class TestVcpkgGenerate:
156
156
  def test_generate_skips_clone_when_vcpkg_root_exists(self, tmp_path, monkeypatch):
157
157
  monkeypatch.chdir(tmp_path)
158
158
  self._make_vcpkg_env(tmp_path)
159
- (tmp_path / "vcpkg").mkdir()
159
+ vcpkg_root = tmp_path / "vcpkg"
160
+ vcpkg_root.mkdir()
161
+ # Existing bootstrap script and executable mean no clone/bootstrap is needed.
162
+ (vcpkg_root / "bootstrap-vcpkg.sh").write_text("#!/bin/sh\nexit 0\n")
163
+ (vcpkg_root / "vcpkg").write_text("#!/bin/sh\nexit 0\n")
160
164
 
161
165
  cfg = HatchCppVcpkgConfiguration(vcpkg_ref="2024.01.12")
166
+ monkeypatch.setattr(cfg, "_is_vcpkg_working", lambda: True)
162
167
  commands = cfg.generate(None)
163
168
 
164
- # When vcpkg_root already exists, no clone or checkout happens
169
+ # When vcpkg_root already exists with a working executable, no clone or bootstrap happens.
165
170
  assert not any("git clone" in cmd for cmd in commands)
166
171
  assert not any("checkout" in cmd for cmd in commands)
172
+ assert not any("bootstrap-vcpkg" in cmd for cmd in commands)
173
+ assert any("vcpkg" in cmd and "install" in cmd for cmd in commands)
174
+
175
+ def test_generate_reclones_when_vcpkg_root_exists_but_empty(self, tmp_path, monkeypatch):
176
+ monkeypatch.chdir(tmp_path)
177
+ self._make_vcpkg_env(tmp_path)
178
+ (tmp_path / "vcpkg").mkdir()
179
+
180
+ cfg = HatchCppVcpkgConfiguration(vcpkg_ref="2024.01.12")
181
+ commands = cfg.generate(None)
182
+
183
+ assert any(cmd.startswith('rm -rf "vcpkg"') for cmd in commands)
184
+ assert any("git clone" in cmd for cmd in commands)
185
+ assert any("checkout 2024.01.12" in cmd for cmd in commands)
186
+ assert any("bootstrap-vcpkg" in cmd for cmd in commands)
187
+ assert any("vcpkg" in cmd and "install" in cmd for cmd in commands)
188
+
189
+ def test_generate_bootstraps_when_vcpkg_executable_missing(self, tmp_path, monkeypatch):
190
+ monkeypatch.chdir(tmp_path)
191
+ self._make_vcpkg_env(tmp_path)
192
+ vcpkg_root = tmp_path / "vcpkg"
193
+ vcpkg_root.mkdir()
194
+ (vcpkg_root / "bootstrap-vcpkg.sh").write_text("#!/bin/sh\nexit 0\n")
195
+
196
+ cfg = HatchCppVcpkgConfiguration(vcpkg_ref="2024.01.12")
197
+ commands = cfg.generate(None)
198
+
199
+ assert not any("git clone" in cmd for cmd in commands)
200
+ assert any("bootstrap-vcpkg" in cmd for cmd in commands)
201
+ assert any("vcpkg" in cmd and "install" in cmd for cmd in commands)
202
+
203
+ def test_generate_reclones_when_vcpkg_exists_but_not_working(self, tmp_path, monkeypatch):
204
+ monkeypatch.chdir(tmp_path)
205
+ self._make_vcpkg_env(tmp_path)
206
+ vcpkg_root = tmp_path / "vcpkg"
207
+ vcpkg_root.mkdir()
208
+ (vcpkg_root / "bootstrap-vcpkg.sh").write_text("#!/bin/sh\nexit 0\n")
209
+ (vcpkg_root / "vcpkg").write_text("#!/bin/sh\nexit 1\n")
210
+
211
+ cfg = HatchCppVcpkgConfiguration(vcpkg_ref="2024.01.12")
212
+ monkeypatch.setattr(cfg, "_is_vcpkg_working", lambda: False)
213
+ commands = cfg.generate(None)
214
+
215
+ assert any(cmd.startswith('rm -rf "vcpkg"') for cmd in commands)
216
+ assert any("git clone" in cmd for cmd in commands)
217
+ assert any("checkout 2024.01.12" in cmd for cmd in commands)
218
+ assert any("bootstrap-vcpkg" in cmd for cmd in commands)
167
219
  assert any("vcpkg" in cmd and "install" in cmd for cmd in commands)
168
220
 
169
221
  def test_generate_no_vcpkg_json(self, tmp_path, monkeypatch):
@@ -101,6 +101,9 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
101
101
  return value
102
102
 
103
103
  def get_qualified_name(self, platform):
104
+ if self.binding == "cpython" and not self.py_limited_api:
105
+ suffix = get_config_var("EXT_SUFFIX")
106
+ return f"{self.name}{suffix}"
104
107
  if platform == "win32":
105
108
  suffix = "dll" if self.binding == "generic" else "pyd"
106
109
  elif platform == "darwin":
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import configparser
4
+ import subprocess
4
5
  from pathlib import Path
5
6
  from platform import machine as platform_machine
6
7
  from sys import platform as sys_platform
@@ -78,6 +79,39 @@ class HatchCppVcpkgConfiguration(BaseModel):
78
79
  return self.vcpkg_ref
79
80
  return _read_vcpkg_ref_from_gitmodules(self.vcpkg_root)
80
81
 
82
+ def _bootstrap_script_path(self) -> Path:
83
+ return self.vcpkg_root / ("bootstrap-vcpkg.bat" if sys_platform == "win32" else "bootstrap-vcpkg.sh")
84
+
85
+ def _vcpkg_executable_path(self) -> Path:
86
+ if sys_platform == "win32":
87
+ return self.vcpkg_root / "vcpkg.exe"
88
+ return self.vcpkg_root / "vcpkg"
89
+
90
+ def _delete_dir_command(self, path: Path) -> str:
91
+ if sys_platform == "win32":
92
+ return f'rmdir /s /q "{path}"'
93
+ return f'rm -rf "{path}"'
94
+
95
+ def _is_vcpkg_working(self) -> bool:
96
+ vcpkg_executable = self._vcpkg_executable_path()
97
+ if not vcpkg_executable.exists():
98
+ return False
99
+ try:
100
+ result = subprocess.run([str(vcpkg_executable), "version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False)
101
+ return result.returncode == 0
102
+ except OSError:
103
+ return False
104
+
105
+ def _clone_checkout_bootstrap_commands(self) -> list[str]:
106
+ commands = [f"git clone {self.vcpkg_repo} {self.vcpkg_root}"]
107
+
108
+ ref = self._resolve_vcpkg_ref()
109
+ if ref is not None:
110
+ commands.append(f"git -C {self.vcpkg_root} checkout {ref}")
111
+
112
+ commands.append(f"./{self._bootstrap_script_path()}")
113
+ return commands
114
+
81
115
  def generate(self, config):
82
116
  commands = []
83
117
 
@@ -87,14 +121,24 @@ class HatchCppVcpkgConfiguration(BaseModel):
87
121
  raise ValueError(f"Could not determine vcpkg triplet for platform {sys_platform} and architecture {platform_machine()}")
88
122
 
89
123
  if self.vcpkg and Path(self.vcpkg).exists():
90
- if not Path(self.vcpkg_root).exists():
91
- commands.append(f"git clone {self.vcpkg_repo} {self.vcpkg_root}")
92
-
93
- ref = self._resolve_vcpkg_ref()
94
- if ref is not None:
95
- commands.append(f"git -C {self.vcpkg_root} checkout {ref}")
124
+ vcpkg_root = Path(self.vcpkg_root)
125
+ bootstrap_script = self._bootstrap_script_path()
126
+
127
+ if not vcpkg_root.exists():
128
+ commands.extend(self._clone_checkout_bootstrap_commands())
129
+ else:
130
+ is_empty_dir = vcpkg_root.is_dir() and not any(vcpkg_root.iterdir())
131
+ if is_empty_dir:
132
+ commands.append(self._delete_dir_command(vcpkg_root))
133
+ commands.extend(self._clone_checkout_bootstrap_commands())
134
+ else:
135
+ vcpkg_executable = self._vcpkg_executable_path()
136
+ if not vcpkg_executable.exists():
137
+ commands.append(f"./{bootstrap_script}")
138
+ elif not self._is_vcpkg_working():
139
+ commands.append(self._delete_dir_command(vcpkg_root))
140
+ commands.extend(self._clone_checkout_bootstrap_commands())
96
141
 
97
- commands.append(f"./{self.vcpkg_root / 'bootstrap-vcpkg.sh' if sys_platform != 'win32' else self.vcpkg_root / 'bootstrap-vcpkg.bat'}")
98
142
  commands.append(f"./{self.vcpkg_root / 'vcpkg'} install --triplet {self.vcpkg_triplet}")
99
143
 
100
144
  return commands
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hatch-cpp
3
- Version: 0.3.6
3
+ Version: 0.4.0
4
4
  Summary: Hatch plugin for C++ builds
5
5
  Project-URL: Repository, https://github.com/python-project-templates/hatch-cpp
6
6
  Project-URL: Homepage, https://github.com/python-project-templates/hatch-cpp
@@ -33,7 +33,7 @@ Requires-Dist: hatch-build>=0.3.2; extra == 'develop'
33
33
  Requires-Dist: hatchling; extra == 'develop'
34
34
  Requires-Dist: mdformat; extra == 'develop'
35
35
  Requires-Dist: mdformat-tables>=1; extra == 'develop'
36
- Requires-Dist: nanobind<2.13.0; extra == 'develop'
36
+ Requires-Dist: nanobind; extra == 'develop'
37
37
  Requires-Dist: pybind11; extra == 'develop'
38
38
  Requires-Dist: pytest; extra == 'develop'
39
39
  Requires-Dist: pytest-cov; extra == 'develop'
@@ -1,25 +1,25 @@
1
- hatch_cpp/__init__.py,sha256=xGDCEwGyCK-WHRtDPw6Bgp1xGbgIgA5VB0RayrIeETs,114
1
+ hatch_cpp/__init__.py,sha256=QnAS8UARqj-I35tzWD70JsB-xoePWVJxNMNgBt0Y_PU,114
2
2
  hatch_cpp/config.py,sha256=aRmcRyrPR7LsEOBjrF9pkOM3ldiykuYRmD73CB3k9MY,4512
3
3
  hatch_cpp/hooks.py,sha256=SQkF5WJIgzw-8rvlTzuQvBqdP6K3fHgnh6CZOZFag50,203
4
4
  hatch_cpp/plugin.py,sha256=NcIDi7c9KH-_RkPeeCgWKoH5InIjw2eECswazwvGl_c,4304
5
5
  hatch_cpp/utils.py,sha256=lxd3U3aMYsTS6DYMc1y17MR16LzgRzv92f_xh87LSg8,297
6
6
  hatch_cpp/tests/test_hatch_build.py,sha256=q2IKTFi3Pq99UsOyL84V-C9VtFUs3ZcA9UlA8lpRW54,1553
7
7
  hatch_cpp/tests/test_platform_specific.py,sha256=SRKAojh6PkwKZnEj8SjvfFa_Dy8NSKw4R82ol8O1TZs,20126
8
- hatch_cpp/tests/test_projects.py,sha256=vs-kHdiHM7pCqM3oGQsSryq5blRi0HyK5QFfHxlJDi8,1773
8
+ hatch_cpp/tests/test_projects.py,sha256=v05hZI9kfBCU6CpWXixyetNy92nC4Dajtxyj03lLjkQ,2168
9
9
  hatch_cpp/tests/test_structs.py,sha256=zmNtAV1bojvJM6gatjDtvqrAeUpKzpfmLrzgFTZLo8U,12028
10
- hatch_cpp/tests/test_vcpkg_ref.py,sha256=OEb4u3Ny-OYNYLanjGaG7-dL4WW48EYdbsxeDN0sqwM,7371
10
+ hatch_cpp/tests/test_vcpkg_ref.py,sha256=wcfbFp8Tc6E2hiQPlextdno0NYrA1yljRSRUIQEj0mM,9969
11
11
  hatch_cpp/tests/test_project_basic/pyproject.toml,sha256=eqM1UVpNmJWDfsuO18ZG_VOV9I4tAWgsM5Dhf49X8Nc,694
12
12
  hatch_cpp/tests/test_project_basic/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
13
13
  hatch_cpp/tests/test_project_basic/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
14
14
  hatch_cpp/tests/test_project_basic/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- hatch_cpp/tests/test_project_cmake/CMakeLists.txt,sha256=J6ijT9x9uSuisNEVIdFVgc_AstU9hbmIUbwvdjn_4GU,2795
15
+ hatch_cpp/tests/test_project_cmake/CMakeLists.txt,sha256=OvJT0L18qH6zRm3Uw8pO6085WLY1HMvBgq6zIcFuQvU,2580
16
16
  hatch_cpp/tests/test_project_cmake/Makefile,sha256=Vfr65pvnktWTUeuvpMWqIxDR-7V9MT4PQAyj-WHG_pI,4357
17
17
  hatch_cpp/tests/test_project_cmake/pyproject.toml,sha256=judDNJ0qYM6-ocGXtUEHQlUzyj8GsF5qoJ-jPDsIAdA,815
18
18
  hatch_cpp/tests/test_project_cmake/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
19
19
  hatch_cpp/tests/test_project_cmake/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
20
20
  hatch_cpp/tests/test_project_cmake/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  hatch_cpp/tests/test_project_cmake/project/include/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
22
- hatch_cpp/tests/test_project_cmake_vcpkg/CMakeLists.txt,sha256=J6ijT9x9uSuisNEVIdFVgc_AstU9hbmIUbwvdjn_4GU,2795
22
+ hatch_cpp/tests/test_project_cmake_vcpkg/CMakeLists.txt,sha256=OvJT0L18qH6zRm3Uw8pO6085WLY1HMvBgq6zIcFuQvU,2580
23
23
  hatch_cpp/tests/test_project_cmake_vcpkg/Makefile,sha256=Vfr65pvnktWTUeuvpMWqIxDR-7V9MT4PQAyj-WHG_pI,4357
24
24
  hatch_cpp/tests/test_project_cmake_vcpkg/pyproject.toml,sha256=pu9RWhm_FY7KlcdOg2nmp-obnStnPJ04jW-bxei704w,814
25
25
  hatch_cpp/tests/test_project_cmake_vcpkg/vcpkg.json,sha256=3D_Mm48_-srxYzbdHNCVO00eFLLGZfsFfL6IMcK0x3E,162
@@ -58,10 +58,10 @@ hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.hpp,sha256=LZSfCfhLY
58
58
  hatch_cpp/tests/test_project_pybind_vcpkg/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  hatch_cpp/toolchains/__init__.py,sha256=anza4tXKxauobWMOUrxX3sEO0qs7sp6VdLXhLae3vkY,64
60
60
  hatch_cpp/toolchains/cmake.py,sha256=yUMw6LzmasjRiJfxN98b-E9fDxUbM0-mz-RL0O7IVag,3748
61
- hatch_cpp/toolchains/common.py,sha256=wOu1d9bOWW962NH-Bt-cXLlfAjgCbLgq-lIXxSupCvc,20265
62
- hatch_cpp/toolchains/vcpkg.py,sha256=ku5NE4ihdzbxdReNUXsGx03fPG5FYdQC48mJhdpW-oo,3456
63
- hatch_cpp-0.3.6.dist-info/METADATA,sha256=lyNg7Xk0tL_pqvKFnNujLuxdC8_8tV1WiLvazo63ywQ,9896
64
- hatch_cpp-0.3.6.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
65
- hatch_cpp-0.3.6.dist-info/entry_points.txt,sha256=RgXfjpD4iwomJQK5n7FnPkXzb5fOnF5v3DI5hbkgVcw,30
66
- hatch_cpp-0.3.6.dist-info/licenses/LICENSE,sha256=FWyFTpd5xXEz50QpGDtsyIv6dgR2z_dHdoab_Nq_KMw,11452
67
- hatch_cpp-0.3.6.dist-info/RECORD,,
61
+ hatch_cpp/toolchains/common.py,sha256=O6eb5qoo9GArI4MB4cLL1z6UnA4rbWxQ5VUIHJmbHBQ,20423
62
+ hatch_cpp/toolchains/vcpkg.py,sha256=fBBModZOL49yJH8971zsOuuRPgTnmR2qvU_0AdT__DY,5233
63
+ hatch_cpp-0.4.0.dist-info/METADATA,sha256=puWLBhQOtranOGnNuD83YJl2li5CHAYaYmBaPm2iYd0,9889
64
+ hatch_cpp-0.4.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
65
+ hatch_cpp-0.4.0.dist-info/entry_points.txt,sha256=RgXfjpD4iwomJQK5n7FnPkXzb5fOnF5v3DI5hbkgVcw,30
66
+ hatch_cpp-0.4.0.dist-info/licenses/LICENSE,sha256=FWyFTpd5xXEz50QpGDtsyIv6dgR2z_dHdoab_Nq_KMw,11452
67
+ hatch_cpp-0.4.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.30.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any