|
1 | | -"""Generate the Python SDK API reference page from the lightpanda package. |
2 | | -
|
3 | | -The hand-written src/content/reference/python.mdx explains how the package fits |
4 | | -together; this script writes the exhaustive companion page, |
5 | | -src/content/reference/python-api.mdx, by walking the installed `lightpanda` |
6 | | -package with pdoc's Python API and emitting one MDX section per public class, |
7 | | -method, property, function and exception, with the signatures and docstrings |
8 | | -shipped in the code. Emitting MDX instead of pdoc's own HTML keeps the page |
| 1 | +"""Generate the Python SDK reference page from the lightpanda package. |
| 2 | +
|
| 3 | +This script writes src/content/reference/python.mdx by walking the installed |
| 4 | +`lightpanda` package with pdoc's Python API and emitting one MDX section per |
| 5 | +public class, method, property, function and exception, with the signatures |
| 6 | +and docstrings shipped in the code. Emitting MDX instead of pdoc's own HTML keeps the page |
9 | 7 | inside the Nextra site: sidebar, search, dark mode and deep links all work as |
10 | 8 | on any other page. |
11 | 9 |
|
|
34 | 32 | import lightpanda |
35 | 33 |
|
36 | 34 | ROOT = Path(__file__).resolve().parent.parent |
37 | | -DEFAULT_OUT = ROOT / "src" / "content" / "reference" / "python-api.mdx" |
| 35 | +DEFAULT_OUT = ROOT / "src" / "content" / "reference" / "python.mdx" |
38 | 36 |
|
39 | 37 | FRONTMATTER = """--- |
40 | 38 | title: Python SDK |
|
55 | 53 | "awaitable; the async sections below list only what the twin adds." |
56 | 54 | ) |
57 | 55 |
|
58 | | -CONVENTIONS = ( |
| 56 | +CONVENTIONS = [ |
59 | 57 | "Browser actions are keyword-only methods on [`Session`](#session) and " |
60 | 58 | "[`AsyncSession`](#asyncsession), named in snake_case after the browser's own action " |
61 | 59 | "names: the `waitForSelector` action is `wait_for_selector`, and its `backendNodeId` " |
62 | | - "argument is `backend_node_id`. Where a method accepts both `selector` and " |
63 | | - "`backend_node_id`, pass one of the two; `selector` is preferred for reproducibility and " |
64 | | - "wins when both are given, and `backend_node_id` takes the values returned by " |
65 | | - "[`tree`](#session-tree), [`links`](#session-links) or " |
66 | | - "[`find_element`](#session-find-element). [`Session.call`](#session-call) is the escape " |
67 | | - "hatch that takes the action and argument names exactly as the browser declares them. " |
68 | | - "A failed action raises [`ToolError`](#toolerror)." |
69 | | -) |
| 60 | + "argument is `backend_node_id`.", |
| 61 | + "Where a method accepts both `selector` and `backend_node_id`, pass one of the two. " |
| 62 | + "`selector` is preferred for reproducibility and wins when both are given; " |
| 63 | + "`backend_node_id` takes the values returned by [`tree`](#session-tree), " |
| 64 | + "[`links`](#session-links) or [`find_element`](#session-find-element).", |
| 65 | +] |
| 66 | + |
| 67 | +# Fixed paragraphs shown under a class heading, after its docstring. |
| 68 | +CLASS_NOTES = { |
| 69 | + "Session": ( |
| 70 | + "[`call`](#session-call) is the escape hatch that takes the action and argument " |
| 71 | + "names exactly as the browser declares them. A failed action raises " |
| 72 | + "[`ToolError`](#toolerror)." |
| 73 | + ), |
| 74 | +} |
70 | 75 |
|
71 | 76 | FENCE_RE = re.compile(r"^\s*```") |
72 | 77 | CODE_SPAN_RE = re.compile(r"(`+)(.+?)\1", re.DOTALL) |
@@ -301,6 +306,7 @@ def class_code(cls: pdoc.doc.Class) -> str: |
301 | 306 | def emit_class(page: Page, module: pdoc.doc.Module, cls: pdoc.doc.Class, links: dict[str, str]) -> None: |
302 | 307 | page.heading(2, cls.name, slug(cls.name)) |
303 | 308 | page.para(render_docstring(cls, links)) |
| 309 | + page.para(CLASS_NOTES.get(cls.name, "")) |
304 | 310 | page.fence(class_code(cls)) |
305 | 311 | init = cls.members.get("__init__") |
306 | 312 | if isinstance(init, pdoc.doc.Function) and "__init__" in vars(cls.obj): |
@@ -397,8 +403,8 @@ def generate() -> str: |
397 | 403 | page.lines.append("# Python SDK") |
398 | 404 | page.lines.append("") |
399 | 405 | page.para(INTRO) |
400 | | - page.para(CONVENTIONS) |
401 | | - page.para(render_docstring(module, links)) |
| 406 | + for paragraph in CONVENTIONS: |
| 407 | + page.para(paragraph) |
402 | 408 |
|
403 | 409 | exceptions: list[pdoc.doc.Class] = [] |
404 | 410 | for name in names: |
|
0 commit comments