From be25d3bb3a4e842361ac8508caca19d266375bdf Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Wed, 1 Jan 2025 12:55:27 +0100 Subject: [PATCH] docs: replace `tools/cli_usage.py` by mkdocs plugin (#2551) --- docs/deployment.md | 114 +------------------------------------------ docs/index.md | 113 +----------------------------------------- docs/plugins/main.py | 22 +++++++-- scripts/check | 1 - scripts/lint | 1 - tools/cli_usage.py | 70 -------------------------- 6 files changed, 23 insertions(+), 298 deletions(-) delete mode 100644 tools/cli_usage.py diff --git a/docs/deployment.md b/docs/deployment.md index d69fcf88e..5fa2a43f5 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -25,120 +25,10 @@ The `--reload` and `--workers` arguments are **mutually exclusive**. To see the complete set of available options, use `uvicorn --help`: - -``` -$ uvicorn --help -Usage: uvicorn [OPTIONS] APP - -Options: - --host TEXT Bind socket to this host. [default: - 127.0.0.1] - --port INTEGER Bind socket to this port. If 0, an available - port will be picked. [default: 8000] - --uds TEXT Bind to a UNIX domain socket. - --fd INTEGER Bind to socket from this file descriptor. - --reload Enable auto-reload. - --reload-dir PATH Set reload directories explicitly, instead - of using the current working directory. - --reload-include TEXT Set glob patterns to include while watching - for files. Includes '*.py' by default; these - defaults can be overridden with `--reload- - exclude`. This option has no effect unless - watchfiles is installed. - --reload-exclude TEXT Set glob patterns to exclude while watching - for files. Includes '.*, .py[cod], .sw.*, - ~*' by default; these defaults can be - overridden with `--reload-include`. This - option has no effect unless watchfiles is - installed. - --reload-delay FLOAT Delay between previous and next check if - application needs to be. Defaults to 0.25s. - [default: 0.25] - --workers INTEGER Number of worker processes. Defaults to the - $WEB_CONCURRENCY environment variable if - available, or 1. Not valid with --reload. - --loop [auto|asyncio|uvloop] Event loop implementation. [default: auto] - --http [auto|h11|httptools] HTTP protocol implementation. [default: - auto] - --ws [auto|none|websockets|wsproto] - WebSocket protocol implementation. - [default: auto] - --ws-max-size INTEGER WebSocket max size message in bytes - [default: 16777216] - --ws-max-queue INTEGER The maximum length of the WebSocket message - queue. [default: 32] - --ws-ping-interval FLOAT WebSocket ping interval in seconds. - [default: 20.0] - --ws-ping-timeout FLOAT WebSocket ping timeout in seconds. - [default: 20.0] - --ws-per-message-deflate BOOLEAN - WebSocket per-message-deflate compression - [default: True] - --lifespan [auto|on|off] Lifespan implementation. [default: auto] - --interface [auto|asgi3|asgi2|wsgi] - Select ASGI3, ASGI2, or WSGI as the - application interface. [default: auto] - --env-file PATH Environment configuration file. - --log-config PATH Logging configuration file. Supported - formats: .ini, .json, .yaml. - --log-level [critical|error|warning|info|debug|trace] - Log level. [default: info] - --access-log / --no-access-log Enable/Disable access log. - --use-colors / --no-use-colors Enable/Disable colorized logging. - --proxy-headers / --no-proxy-headers - Enable/Disable X-Forwarded-Proto, - X-Forwarded-For, X-Forwarded-Port to - populate remote address info. - --server-header / --no-server-header - Enable/Disable default Server header. - --date-header / --no-date-header - Enable/Disable default Date header. - --forwarded-allow-ips TEXT Comma separated list of IP Addresses, IP - Networks, or literals (e.g. UNIX Socket - path) to trust with proxy headers. Defaults - to the $FORWARDED_ALLOW_IPS environment - variable if available, or '127.0.0.1'. The - literal '*' means trust everything. - --root-path TEXT Set the ASGI 'root_path' for applications - submounted below a given URL path. - --limit-concurrency INTEGER Maximum number of concurrent connections or - tasks to allow, before issuing HTTP 503 - responses. - --backlog INTEGER Maximum number of connections to hold in - backlog - --limit-max-requests INTEGER Maximum number of requests to service before - terminating the process. - --timeout-keep-alive INTEGER Close Keep-Alive connections if no new data - is received within this timeout. [default: - 5] - --timeout-graceful-shutdown INTEGER - Maximum number of seconds to wait for - graceful shutdown. - --ssl-keyfile TEXT SSL key file - --ssl-certfile TEXT SSL certificate file - --ssl-keyfile-password TEXT SSL keyfile password - --ssl-version INTEGER SSL version to use (see stdlib ssl module's) - [default: 17] - --ssl-cert-reqs INTEGER Whether client certificate is required (see - stdlib ssl module's) [default: 0] - --ssl-ca-certs TEXT CA certificates file - --ssl-ciphers TEXT Ciphers to use (see stdlib ssl module's) - [default: TLSv1] - --header TEXT Specify custom default HTTP response headers - as a Name:Value pair - --version Display the uvicorn version and exit. - --app-dir TEXT Look for APP in the specified directory, by - adding this to the PYTHONPATH. Defaults to - the current working directory. - --h11-max-incomplete-event-size INTEGER - For h11, the maximum number of bytes to - buffer of an incomplete event. - --factory Treat APP as an application factory, i.e. a - () -> callable. - --help Show this message and exit. +```bash +{{ uvicorn_help }} ``` - See the [settings documentation](settings.md) for more details on the supported options for running uvicorn. ## Running programmatically diff --git a/docs/index.md b/docs/index.md index bb6fc321a..293361e37 100644 --- a/docs/index.md +++ b/docs/index.md @@ -95,117 +95,8 @@ The uvicorn command line tool is the easiest way to run your application. ### Command line options - -``` -$ uvicorn --help -Usage: uvicorn [OPTIONS] APP - -Options: - --host TEXT Bind socket to this host. [default: - 127.0.0.1] - --port INTEGER Bind socket to this port. If 0, an available - port will be picked. [default: 8000] - --uds TEXT Bind to a UNIX domain socket. - --fd INTEGER Bind to socket from this file descriptor. - --reload Enable auto-reload. - --reload-dir PATH Set reload directories explicitly, instead - of using the current working directory. - --reload-include TEXT Set glob patterns to include while watching - for files. Includes '*.py' by default; these - defaults can be overridden with `--reload- - exclude`. This option has no effect unless - watchfiles is installed. - --reload-exclude TEXT Set glob patterns to exclude while watching - for files. Includes '.*, .py[cod], .sw.*, - ~*' by default; these defaults can be - overridden with `--reload-include`. This - option has no effect unless watchfiles is - installed. - --reload-delay FLOAT Delay between previous and next check if - application needs to be. Defaults to 0.25s. - [default: 0.25] - --workers INTEGER Number of worker processes. Defaults to the - $WEB_CONCURRENCY environment variable if - available, or 1. Not valid with --reload. - --loop [auto|asyncio|uvloop] Event loop implementation. [default: auto] - --http [auto|h11|httptools] HTTP protocol implementation. [default: - auto] - --ws [auto|none|websockets|wsproto] - WebSocket protocol implementation. - [default: auto] - --ws-max-size INTEGER WebSocket max size message in bytes - [default: 16777216] - --ws-max-queue INTEGER The maximum length of the WebSocket message - queue. [default: 32] - --ws-ping-interval FLOAT WebSocket ping interval in seconds. - [default: 20.0] - --ws-ping-timeout FLOAT WebSocket ping timeout in seconds. - [default: 20.0] - --ws-per-message-deflate BOOLEAN - WebSocket per-message-deflate compression - [default: True] - --lifespan [auto|on|off] Lifespan implementation. [default: auto] - --interface [auto|asgi3|asgi2|wsgi] - Select ASGI3, ASGI2, or WSGI as the - application interface. [default: auto] - --env-file PATH Environment configuration file. - --log-config PATH Logging configuration file. Supported - formats: .ini, .json, .yaml. - --log-level [critical|error|warning|info|debug|trace] - Log level. [default: info] - --access-log / --no-access-log Enable/Disable access log. - --use-colors / --no-use-colors Enable/Disable colorized logging. - --proxy-headers / --no-proxy-headers - Enable/Disable X-Forwarded-Proto, - X-Forwarded-For, X-Forwarded-Port to - populate remote address info. - --server-header / --no-server-header - Enable/Disable default Server header. - --date-header / --no-date-header - Enable/Disable default Date header. - --forwarded-allow-ips TEXT Comma separated list of IP Addresses, IP - Networks, or literals (e.g. UNIX Socket - path) to trust with proxy headers. Defaults - to the $FORWARDED_ALLOW_IPS environment - variable if available, or '127.0.0.1'. The - literal '*' means trust everything. - --root-path TEXT Set the ASGI 'root_path' for applications - submounted below a given URL path. - --limit-concurrency INTEGER Maximum number of concurrent connections or - tasks to allow, before issuing HTTP 503 - responses. - --backlog INTEGER Maximum number of connections to hold in - backlog - --limit-max-requests INTEGER Maximum number of requests to service before - terminating the process. - --timeout-keep-alive INTEGER Close Keep-Alive connections if no new data - is received within this timeout. [default: - 5] - --timeout-graceful-shutdown INTEGER - Maximum number of seconds to wait for - graceful shutdown. - --ssl-keyfile TEXT SSL key file - --ssl-certfile TEXT SSL certificate file - --ssl-keyfile-password TEXT SSL keyfile password - --ssl-version INTEGER SSL version to use (see stdlib ssl module's) - [default: 17] - --ssl-cert-reqs INTEGER Whether client certificate is required (see - stdlib ssl module's) [default: 0] - --ssl-ca-certs TEXT CA certificates file - --ssl-ciphers TEXT Ciphers to use (see stdlib ssl module's) - [default: TLSv1] - --header TEXT Specify custom default HTTP response headers - as a Name:Value pair - --version Display the uvicorn version and exit. - --app-dir TEXT Look for APP in the specified directory, by - adding this to the PYTHONPATH. Defaults to - the current working directory. - --h11-max-incomplete-event-size INTEGER - For h11, the maximum number of bytes to - buffer of an incomplete event. - --factory Treat APP as an application factory, i.e. a - () -> callable. - --help Show this message and exit. +```bash +{{ uvicorn_help }} ``` For more information, see the [settings documentation](settings.md). diff --git a/docs/plugins/main.py b/docs/plugins/main.py index 12262c39f..ac7c1542e 100644 --- a/docs/plugins/main.py +++ b/docs/plugins/main.py @@ -1,6 +1,7 @@ from __future__ import annotations as _annotations import re +import subprocess from mkdocs.config import Config from mkdocs.structure.files import Files @@ -8,9 +9,7 @@ def on_page_content(html: str, page: Page, config: Config, files: Files) -> str: - """ - Called on each page after the markdown is converted to HTML. - """ + """Called on each page after the markdown is converted to HTML.""" html = add_hyperlink_to_pull_request(html, page, config, files) return html @@ -24,3 +23,20 @@ def add_hyperlink_to_pull_request(html: str, page: Page, config: Config, files: return html return re.sub(r"\(#(\d+)\)", r"(#\1)", html) + + +def on_page_markdown(markdown: str, page: Page, config: Config, files: Files) -> str: + """Called on each file after it is read and before it is converted to HTML.""" + markdown = uvicorn_print_help(markdown, page) + return markdown + + +def uvicorn_print_help(markdown: str, page: Page) -> str: + # if you don't filter to the specific route that needs this substitution, things will be very slow + print(page.file.src_uri) + if page.file.src_uri not in ("index.md", "deployment.md"): + return markdown + + output = subprocess.run(["uvicorn", "--help"], capture_output=True, check=True) + logfire_help = output.stdout.decode() + return re.sub(r"{{ *uvicorn_help *}}", logfire_help, markdown) diff --git a/scripts/check b/scripts/check index 15748a4e8..10e422cbf 100755 --- a/scripts/check +++ b/scripts/check @@ -13,4 +13,3 @@ set -x ${PREFIX}ruff format --check --diff $SOURCE_FILES ${PREFIX}mypy $SOURCE_FILES ${PREFIX}ruff check $SOURCE_FILES -${PREFIX}python -m tools.cli_usage --check diff --git a/scripts/lint b/scripts/lint index 1b04d208e..f22e77f95 100755 --- a/scripts/lint +++ b/scripts/lint @@ -11,4 +11,3 @@ set -x ${PREFIX}ruff format $SOURCE_FILES ${PREFIX}ruff check --fix $SOURCE_FILES -${PREFIX}python -m tools.cli_usage diff --git a/tools/cli_usage.py b/tools/cli_usage.py deleted file mode 100644 index 1cfa88672..000000000 --- a/tools/cli_usage.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Look for a marker comment in docs pages, and place the output of -`$ uvicorn --help` there. Pass `--check` to ensure the content is in sync. -""" - -from __future__ import annotations - -import argparse -import subprocess -import sys -from pathlib import Path - - -def _get_usage_lines() -> list[str]: - res = subprocess.run(["uvicorn", "--help"], stdout=subprocess.PIPE) - help_text = res.stdout.decode("utf-8") - return ["```", "$ uvicorn --help", *help_text.splitlines(), "```"] - - -def _find_next_codefence_lineno(lines: list[str], after: int) -> int: - return next(lineno for lineno, line in enumerate(lines[after:], after) if line == "```") - - -def _get_insert_location(lines: list[str]) -> tuple[int, int]: - marker = lines.index("") - start = marker + 1 - - if lines[start] == "```": - # Already generated. - # - # ``` <- start - # [...] - # ``` <- end - next_codefence = _find_next_codefence_lineno(lines, after=start + 1) - end = next_codefence + 1 - else: - # Not generated yet. - end = start - - return start, end - - -def _generate_cli_usage(path: Path, check: bool = False) -> int: - content = path.read_text() - - lines = content.splitlines() - usage_lines = _get_usage_lines() - start, end = _get_insert_location(lines) - lines = lines[:start] + usage_lines + lines[end:] - output = "\n".join(lines) + "\n" - - if check: - if content == output: - return 0 - print(f"ERROR: CLI usage in {path} is out of sync. Run scripts/lint to fix.") - return 1 - - path.write_text(output) - return 0 - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--check", action="store_true") - args = parser.parse_args() - paths = [Path("docs", "index.md"), Path("docs", "deployment.md")] - rv = 0 - for path in paths: - rv |= _generate_cli_usage(path, check=args.check) - sys.exit(rv)