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.
|
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
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
@ -19,7 +20,7 @@ from functools import cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Literal, Self, TextIO
|
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
|
# Arbitrary nesting is allowed, but all keys and terminal values are strings
|
||||||
StringDict = dict[str, "str | StringDict"]
|
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
|
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
|
@contextmanager
|
||||||
def redirect_sys_stream(name: Literal["stdout", "stderr"]):
|
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):
|
def send_expect(file: TextIO, name: str):
|
||||||
write_safe(file, "EXPECT", name.replace("_", "-"))
|
write_safe(file, "EXPECT", name)
|
||||||
|
|
||||||
|
|
||||||
def send_ready(file: TextIO):
|
def send_ready(file: TextIO):
|
||||||
|
|
@ -526,11 +510,26 @@ def main():
|
||||||
send_fatal(stdout, exc)
|
send_fatal(stdout, exc)
|
||||||
raise
|
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 __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()
|
main()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue