mirror of https://github.com/astral-sh/uv
Add docs
This commit is contained in:
parent
cf700dfe2c
commit
4ca8775372
|
|
@ -0,0 +1,105 @@
|
|||
# hookd
|
||||
|
||||
A daemon process for PEP 517 build hook requests.
|
||||
|
||||
|
||||
## Example
|
||||
```
|
||||
PYTHONPATH=scripts/hookd/backends ./scripts/hookd/hookd.py < scripts/hookd/example.in
|
||||
```
|
||||
|
||||
## Command line
|
||||
|
||||
|
||||
Build hooks should be run from the source tree of the project.
|
||||
|
||||
The script can either be invoked from the project source tree, or the source
|
||||
tree path can be provided as an argument e.g. `hookd.py /path/to/source`.
|
||||
|
||||
## Messages
|
||||
|
||||
The daemon communicates with bidirectional messages over STDIN and STDOUT.
|
||||
Each message is terminated with a newline.
|
||||
Newlines in values will be escaped as `\\n`.
|
||||
|
||||
``````
|
||||
READY
|
||||
|
||||
Signals that the daemon is ready to do work.
|
||||
Indicates that the daemon has finished running a hook.
|
||||
|
||||
EXPECT <name>
|
||||
|
||||
Signals the input kind that the daemon expects.
|
||||
The name MUST be one of:
|
||||
- action
|
||||
Either "run" or "shutdown" instruction to the daemon
|
||||
- build_backend
|
||||
A PEP 517 import path for the build backend
|
||||
- hook_name
|
||||
A PEP 517 hook function name
|
||||
- wheel_directory
|
||||
A path
|
||||
- sdist_directory
|
||||
A path
|
||||
- config_settings
|
||||
A JSON payload
|
||||
- metadata_directory
|
||||
A path
|
||||
|
||||
DEBUG <message>
|
||||
|
||||
A debugging message.
|
||||
|
||||
STDOUT <path>
|
||||
|
||||
Sent before a hook is imported.
|
||||
The path to a file the hook's stdout will be directed to.
|
||||
The caller SHOULD delete this file when done with it.
|
||||
|
||||
STDERR <path>
|
||||
|
||||
Sent before a hook is imported.
|
||||
The path to a file the hook's stderr will be directed to.
|
||||
The caller SHOULD delete this file when done with it.
|
||||
|
||||
OK <data>
|
||||
|
||||
Sent when a hook completes successfully.
|
||||
The return value of the hook should follow.
|
||||
|
||||
ERROR <kind> <message>
|
||||
|
||||
Sent when a hook fails.
|
||||
The error kind MUST be one of:
|
||||
- MissingBackendModule
|
||||
- MissingBackendAttribute
|
||||
- MalformedBackendName
|
||||
- BackendImportError
|
||||
- InvalidHookName
|
||||
- InvalidAction
|
||||
- UnsupportedHook
|
||||
- MalformedHookArgument
|
||||
- HookRuntimeError
|
||||
The message is a string describing the error.
|
||||
|
||||
FATAL <kind> <message>
|
||||
|
||||
Sent when the daemon crashes due to an unhandled error.
|
||||
|
||||
TRACEBACK <lines>
|
||||
|
||||
MAY be sent after a FATAL or ERROR message.
|
||||
Contains the traceback for the error.
|
||||
|
||||
SHUTDOWN
|
||||
|
||||
Signals that the daemon is exiting cleanly.
|
||||
```
|
||||
|
||||
## Caveats
|
||||
|
||||
The following caveats apply when using hookd:
|
||||
|
||||
- Imports are cached for the duration of the daemon. Changes to the build backend packages will not be detected without restart.
|
||||
- `BaseExceptions` raised during hook execution will be swallowed, unless from a SIGINT or SIGTERM.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
run
|
||||
ok_backend
|
||||
build_wheel
|
||||
foo
|
||||
|
||||
|
||||
shutdown
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
A daemon process for PEP 517 build hook requests.
|
||||
|
||||
See https://peps.python.org/pep-0517/
|
||||
See the `README` for details.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ from functools import cache
|
|||
from pathlib import Path
|
||||
from typing import Any, Literal, Self, TextIO
|
||||
|
||||
DEBUG_ON = os.getenv("DAEMON_DEBUG") is not None
|
||||
SOURCE_TREE = os.getenv("HOOKD_SOURCE_TREE")
|
||||
|
||||
# Arbitrary nesting is allowed, but all keys and terminal values are strings
|
||||
StringDict = dict[str, "str | StringDict"]
|
||||
|
|
@ -302,23 +303,6 @@ def parse_config_settings(buffer: TextIO) -> StringDict | None:
|
|||
raise MalformedHookArgument(data, HookArgument.config_settings) from exc
|
||||
|
||||
|
||||
@contextmanager
|
||||
def tmpchdir(path: str | Path) -> Path:
|
||||
"""
|
||||
Temporarily change the working directory for this process.
|
||||
|
||||
WARNING: This function is not safe to concurrent usage.
|
||||
"""
|
||||
path = Path(path).resolve()
|
||||
cwd = os.getcwd()
|
||||
|
||||
try:
|
||||
os.chdir(path)
|
||||
yield path
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def redirect_sys_stream(name: Literal["stdout", "stderr"]):
|
||||
"""
|
||||
|
|
@ -386,7 +370,7 @@ def write_safe(file: TextIO, *args: str):
|
|||
|
||||
|
||||
def send_expect(file: TextIO, name: str):
|
||||
write_safe(file, "EXPECT", name.replace("_", "-"))
|
||||
write_safe(file, "EXPECT", name)
|
||||
|
||||
|
||||
def send_ready(file: TextIO):
|
||||
|
|
@ -526,11 +510,26 @@ def main():
|
|||
send_fatal(stdout, exc)
|
||||
raise
|
||||
|
||||
# Do not run multiple iterations in debug mode
|
||||
# TODO(zanieb): Probably remove this after development is stable
|
||||
if DEBUG_ON:
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 2:
|
||||
print(
|
||||
"Invalid usage. Expected one argument specifying the path to the source tree.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
source_tree = Path(sys.argv[1]).resolve()
|
||||
os.chdir(source_tree)
|
||||
send_debug(sys.stdout, "changed working directory to", source_tree)
|
||||
except IndexError:
|
||||
pass
|
||||
except ValueError as exc:
|
||||
print(
|
||||
f"Invalid usage. Expected path argument but validation failed: {exc}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue