A low-level library for calling build-backends in pyproject.toml-based project
npx @tessl/cli install tessl/pypi-pyproject-hooks@1.2.00
# pyproject-hooks
1
2
A low-level library for calling build-backends in pyproject.toml-based Python projects. This library provides the basic functionality to help write tooling that generates distribution files from Python projects, serving as the underlying piece for build frontends like pip, build, and other tools.
3
4
## Package Information
5
6
- **Package Name**: pyproject-hooks
7
- **Language**: Python
8
- **Installation**: `pip install pyproject-hooks`
9
- **Python Version**: >=3.7
10
11
## Core Imports
12
13
```python
14
from pyproject_hooks import BuildBackendHookCaller
15
```
16
17
For exception handling:
18
19
```python
20
from pyproject_hooks import (
21
BackendUnavailable,
22
HookMissing,
23
UnsupportedOperation
24
)
25
```
26
27
For subprocess runners:
28
29
```python
30
from pyproject_hooks import (
31
default_subprocess_runner,
32
quiet_subprocess_runner
33
)
34
```
35
36
## Basic Usage
37
38
```python
39
from pyproject_hooks import BuildBackendHookCaller
40
import tempfile
41
42
# Initialize the hook caller for a project
43
hook_caller = BuildBackendHookCaller(
44
source_dir="/path/to/project",
45
build_backend="setuptools.build_meta"
46
)
47
48
# Get wheel build dependencies
49
wheel_deps = hook_caller.get_requires_for_build_wheel()
50
print(f"Wheel dependencies: {wheel_deps}")
51
52
# Build a wheel
53
with tempfile.TemporaryDirectory() as temp_dir:
54
wheel_filename = hook_caller.build_wheel(temp_dir)
55
print(f"Built wheel: {wheel_filename}")
56
```
57
58
## Architecture
59
60
The library provides a subprocess-based isolation mechanism for calling build backends:
61
62
- **BuildBackendHookCaller**: Main class that manages backend communication
63
- **Subprocess Execution**: Isolates backend calls in subprocess to avoid import conflicts
64
- **Hook Protocol**: Implements PEP 517/518 build backend interface
65
- **Exception Handling**: Comprehensive error handling for backend failures
66
67
## Capabilities
68
69
### Build Backend Hook Caller
70
71
Main class for interfacing with build backends. Manages source directory, backend specification, and subprocess execution.
72
73
```python { .api }
74
class BuildBackendHookCaller:
75
def __init__(
76
self,
77
source_dir: str,
78
build_backend: str,
79
backend_path: Optional[Sequence[str]] = None,
80
runner: Optional[SubprocessRunner] = None,
81
python_executable: Optional[str] = None,
82
) -> None:
83
"""
84
Initialize the hook caller.
85
86
Parameters:
87
- source_dir: The source directory to invoke the build backend for
88
- build_backend: The build backend spec (e.g., "setuptools.build_meta")
89
- backend_path: Additional path entries for the build backend spec
90
- runner: The subprocess runner to use (defaults to default_subprocess_runner)
91
- python_executable: The Python executable used to invoke the build backend
92
"""
93
```
94
95
### Subprocess Runner Context Manager
96
97
Temporarily override the default subprocess runner for specific operations.
98
99
```python { .api }
100
def subprocess_runner(self, runner: SubprocessRunner) -> Iterator[None]:
101
"""
102
Context manager for temporarily overriding subprocess runner.
103
104
Parameters:
105
- runner: The new subprocess runner to use within the context
106
"""
107
```
108
109
### Wheel Build Operations
110
111
Operations for building wheels and managing wheel metadata.
112
113
```python { .api }
114
def get_requires_for_build_wheel(
115
self,
116
config_settings: Optional[Mapping[str, Any]] = None,
117
) -> Sequence[str]:
118
"""
119
Get additional dependencies required for building a wheel.
120
121
Parameters:
122
- config_settings: The configuration settings for the build backend
123
124
Returns:
125
A list of PEP 508 dependency specifiers.
126
127
Note: Returns empty list if backend doesn't define this hook.
128
"""
129
130
def prepare_metadata_for_build_wheel(
131
self,
132
metadata_directory: str,
133
config_settings: Optional[Mapping[str, Any]] = None,
134
_allow_fallback: bool = True,
135
) -> str:
136
"""
137
Prepare a *.dist-info folder with metadata for this project.
138
139
Parameters:
140
- metadata_directory: The directory to write the metadata to
141
- config_settings: The configuration settings for the build backend
142
- _allow_fallback: Whether to allow fallback to building wheel and extracting metadata
143
144
Returns:
145
Name of the newly created subfolder within metadata_directory containing the metadata.
146
147
Note: May fall back to building wheel and extracting metadata if hook not defined.
148
"""
149
150
def build_wheel(
151
self,
152
wheel_directory: str,
153
config_settings: Optional[Mapping[str, Any]] = None,
154
metadata_directory: Optional[str] = None,
155
) -> str:
156
"""
157
Build a wheel from this project.
158
159
Parameters:
160
- wheel_directory: The directory to write the wheel to
161
- config_settings: The configuration settings for the build backend
162
- metadata_directory: The directory to reuse existing metadata from
163
164
Returns:
165
The name of the newly created wheel within wheel_directory.
166
"""
167
```
168
169
### Editable Wheel Operations
170
171
Operations for building editable wheels, supporting PEP 660 editable installs.
172
173
```python { .api }
174
def get_requires_for_build_editable(
175
self,
176
config_settings: Optional[Mapping[str, Any]] = None,
177
) -> Sequence[str]:
178
"""
179
Get additional dependencies required for building an editable wheel.
180
181
Parameters:
182
- config_settings: The configuration settings for the build backend
183
184
Returns:
185
A list of PEP 508 dependency specifiers.
186
187
Note: Returns empty list if backend doesn't define this hook.
188
"""
189
190
def prepare_metadata_for_build_editable(
191
self,
192
metadata_directory: str,
193
config_settings: Optional[Mapping[str, Any]] = None,
194
_allow_fallback: bool = True,
195
) -> Optional[str]:
196
"""
197
Prepare a *.dist-info folder with metadata for editable installation.
198
199
Parameters:
200
- metadata_directory: The directory to write the metadata to
201
- config_settings: The configuration settings for the build backend
202
- _allow_fallback: Whether to allow fallback to building editable wheel and extracting metadata
203
204
Returns:
205
Name of the newly created subfolder within metadata_directory containing the metadata.
206
207
Note: May fall back to building editable wheel and extracting metadata if hook not defined.
208
"""
209
210
def build_editable(
211
self,
212
wheel_directory: str,
213
config_settings: Optional[Mapping[str, Any]] = None,
214
metadata_directory: Optional[str] = None,
215
) -> str:
216
"""
217
Build an editable wheel from this project.
218
219
Parameters:
220
- wheel_directory: The directory to write the wheel to
221
- config_settings: The configuration settings for the build backend
222
- metadata_directory: The directory to reuse existing metadata from
223
224
Returns:
225
The name of the newly created wheel within wheel_directory.
226
"""
227
```
228
229
### Source Distribution Operations
230
231
Operations for building source distributions (sdists).
232
233
```python { .api }
234
def get_requires_for_build_sdist(
235
self,
236
config_settings: Optional[Mapping[str, Any]] = None,
237
) -> Sequence[str]:
238
"""
239
Get additional dependencies required for building an sdist.
240
241
Parameters:
242
- config_settings: The configuration settings for the build backend
243
244
Returns:
245
A list of PEP 508 dependency specifiers.
246
"""
247
248
def build_sdist(
249
self,
250
sdist_directory: str,
251
config_settings: Optional[Mapping[str, Any]] = None,
252
) -> str:
253
"""
254
Build an sdist from this project.
255
256
Parameters:
257
- sdist_directory: The directory to write the sdist to
258
- config_settings: The configuration settings for the build backend
259
260
Returns:
261
The name of the newly created sdist within sdist_directory.
262
"""
263
```
264
265
### Exception Classes
266
267
Exception classes for handling various error conditions during build backend operations.
268
269
```python { .api }
270
class BackendUnavailable(Exception):
271
"""
272
Raised when the backend cannot be imported in the hook process.
273
274
Attributes:
275
- backend_name: The name of the backend that failed to import
276
- backend_path: The backend path that was used
277
- traceback: The traceback from the import failure
278
"""
279
def __init__(
280
self,
281
traceback: str,
282
message: Optional[str] = None,
283
backend_name: Optional[str] = None,
284
backend_path: Optional[Sequence[str]] = None,
285
) -> None: ...
286
287
class HookMissing(Exception):
288
"""
289
Raised on missing hooks when a fallback cannot be used.
290
291
Attributes:
292
- hook_name: The name of the missing hook
293
"""
294
def __init__(self, hook_name: str) -> None: ...
295
296
class UnsupportedOperation(Exception):
297
"""
298
Raised by build_sdist if the backend indicates that it cannot perform the operation.
299
300
Attributes:
301
- traceback: The traceback from the backend failure
302
"""
303
def __init__(self, traceback: str) -> None: ...
304
```
305
306
### Subprocess Runners
307
308
Functions for executing subprocess commands with different behaviors.
309
310
```python { .api }
311
def default_subprocess_runner(
312
cmd: Sequence[str],
313
cwd: Optional[str] = None,
314
extra_environ: Optional[Mapping[str, str]] = None,
315
) -> None:
316
"""
317
The default method of calling the wrapper subprocess.
318
319
Uses subprocess.check_call under the hood.
320
321
Parameters:
322
- cmd: The command to execute as a sequence of strings
323
- cwd: The working directory for the command
324
- extra_environ: Additional environment variables
325
"""
326
327
def quiet_subprocess_runner(
328
cmd: Sequence[str],
329
cwd: Optional[str] = None,
330
extra_environ: Optional[Mapping[str, str]] = None,
331
) -> None:
332
"""
333
Call the subprocess while suppressing output.
334
335
Uses subprocess.check_output under the hood.
336
337
Parameters:
338
- cmd: The command to execute as a sequence of strings
339
- cwd: The working directory for the command
340
- extra_environ: Additional environment variables
341
"""
342
```
343
344
## Types
345
346
```python { .api }
347
from typing import Protocol, Sequence, Optional, Mapping, Any
348
349
class SubprocessRunner(Protocol):
350
"""
351
Protocol for subprocess runner functions.
352
"""
353
def __call__(
354
self,
355
cmd: Sequence[str],
356
cwd: Optional[str] = None,
357
extra_environ: Optional[Mapping[str, str]] = None,
358
) -> None: ...
359
```
360
361
## Deprecated APIs
362
363
```python { .api }
364
# Deprecated alias for BackendUnavailable
365
BackendInvalid = BackendUnavailable
366
```
367
368
Note: `BackendInvalid` is a deprecated alias for `BackendUnavailable`. Use `BackendUnavailable` instead.