Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/python-reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: python-reference

# Regenerate the Python SDK API reference page from the lightpanda-python main
# branch and open a pull request when the output changed. The page is
# src/content/reference/python-api.mdx, written by
# src/content/reference/python.mdx, written by
# scripts/generate-python-reference.py with pdoc's Python API, so it renders
# like any other docs page and goes live at
# https://lightpanda.io/docs/reference/python-api once the website bumps its
# https://lightpanda.io/docs/reference/python once the website bumps its
# docs submodule like any other docs change. The package imports without a
# browser binary, so none is needed here. Runs daily to pick up new package
# changes, by hand, or as a smoke run when the generator itself changes.
Expand Down Expand Up @@ -44,26 +44,26 @@ jobs:
--with "git+https://github.com/lightpanda-io/lightpanda-python@$sha" \
python scripts/generate-python-reference.py
echo "sha=${sha::7}" >> "$GITHUB_OUTPUT"
git status --short src/content/reference/python-api.mdx
git status --short src/content/reference/python.mdx

- name: Open a pull request if the reference changed
if: github.event_name != 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ steps.generate.outputs.sha }}
run: |
if [ -z "$(git status --porcelain src/content/reference/python-api.mdx)" ]; then
if [ -z "$(git status --porcelain src/content/reference/python.mdx)" ]; then
echo "reference already matches lightpanda-python $SHA"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -B python-reference
git add src/content/reference/python-api.mdx
git add src/content/reference/python.mdx
git commit -m "Update the Python SDK API reference to lightpanda-python $SHA"
git push --force origin python-reference
if [ -z "$(gh pr list --head python-reference --state open --json number -q '.[].number')" ]; then
gh pr create --base main --head python-reference \
--title "Update the Python SDK API reference to lightpanda-python $SHA" \
--body "Regenerated \`src/content/reference/python-api.mdx\` from lightpanda-python $SHA. Served at https://lightpanda.io/docs/reference/python-api after the website's submodule bump."
--body "Regenerated \`src/content/reference/python.mdx\` from lightpanda-python $SHA. Served at https://lightpanda.io/docs/reference/python after the website's submodule bump."
fi
3 changes: 2 additions & 1 deletion redirects.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
export const basePath = '/docs'

export const redirects = {
'/python': '/reference/python-api',
'/python': '/reference/python',
'/reference/python-api': '/reference/python',
'/quickstart/installation-and-setup': '/quickstart',
'/quickstart/your-first-test': '/quickstart',
'/quickstart/build-your-first-extraction-script': '/quickstart',
Expand Down
51 changes: 35 additions & 16 deletions scripts/generate-python-reference.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
"""Generate the Python SDK API reference page from the lightpanda package.

The hand-written src/content/reference/python.mdx explains how the package fits
together; this script writes the exhaustive companion page,
src/content/reference/python-api.mdx, by walking the installed `lightpanda`
package with pdoc's Python API and emitting one MDX section per public class,
method, property, function and exception, with the signatures and docstrings
shipped in the code. Emitting MDX instead of pdoc's own HTML keeps the page
"""Generate the Python SDK reference page from the lightpanda package.

This script writes src/content/reference/python.mdx by walking the installed
`lightpanda` package with pdoc's Python API and emitting one MDX section per
public class, method, property, function and exception, with the signatures
and docstrings shipped in the code. Emitting MDX instead of pdoc's own HTML keeps the page
inside the Nextra site: sidebar, search, dark mode and deep links all work as
on any other page.

Expand Down Expand Up @@ -34,11 +32,11 @@
import lightpanda

ROOT = Path(__file__).resolve().parent.parent
DEFAULT_OUT = ROOT / "src" / "content" / "reference" / "python-api.mdx"
DEFAULT_OUT = ROOT / "src" / "content" / "reference" / "python.mdx"

FRONTMATTER = """---
title: Python API
description: Generated reference of every public class, method, property and exception in the lightpanda Python package, with the signatures and docstrings shipped in the code.
title: Python SDK
description: Reference of every public class, method, property and exception in the lightpanda Python package, generated from the signatures and docstrings shipped in the code.
---
"""

Expand All @@ -50,12 +48,31 @@
INTRO = (
"Every public class, method, property and exception of the "
"[`lightpanda` package](https://pypi.org/project/lightpanda/), with the signatures and "
"docstrings shipped in the code. See [Python SDK](/reference/python) for a curated "
"overview of the same API and [Use the Python SDK](/guides/use-python) for practical "
"documentation. Every sync class has an asyncio twin with the same methods, "
"docstrings shipped in the code. See [Use the Python SDK](/guides/use-python) for a "
"practical walkthrough. Every sync class has an asyncio twin with the same methods, "
"awaitable; the async sections below list only what the twin adds."
)

CONVENTIONS = [
"Browser actions are keyword-only methods on [`Session`](#session) and "
"[`AsyncSession`](#asyncsession), named in snake_case after the browser's own action "
"names: the `waitForSelector` action is `wait_for_selector`, and its `backendNodeId` "
"argument is `backend_node_id`.",
"Where a method accepts both `selector` and `backend_node_id`, pass one of the two. "
"`selector` is preferred for reproducibility and wins when both are given; "
"`backend_node_id` takes the values returned by [`tree`](#session-tree), "
"[`links`](#session-links) or [`find_element`](#session-find-element).",
]

# Fixed paragraphs shown under a class heading, after its docstring.
CLASS_NOTES = {
"Session": (
"[`call`](#session-call) is the escape hatch that takes the action and argument "
"names exactly as the browser declares them. A failed action raises "
"[`ToolError`](#toolerror)."
),
}

FENCE_RE = re.compile(r"^\s*```")
CODE_SPAN_RE = re.compile(r"(`+)(.+?)\1", re.DOTALL)
MODULE_PREFIX_RE = re.compile(r"\blightpanda\.\w+\.")
Expand Down Expand Up @@ -289,6 +306,7 @@ def class_code(cls: pdoc.doc.Class) -> str:
def emit_class(page: Page, module: pdoc.doc.Module, cls: pdoc.doc.Class, links: dict[str, str]) -> None:
page.heading(2, cls.name, slug(cls.name))
page.para(render_docstring(cls, links))
page.para(CLASS_NOTES.get(cls.name, ""))
page.fence(class_code(cls))
init = cls.members.get("__init__")
if isinstance(init, pdoc.doc.Function) and "__init__" in vars(cls.obj):
Expand Down Expand Up @@ -382,10 +400,11 @@ def generate() -> str:
page.lines.append(FRONTMATTER.rstrip())
page.lines.append(BANNER)
page.lines.append("")
page.lines.append("# Python API")
page.lines.append("# Python SDK")
page.lines.append("")
page.para(INTRO)
page.para(render_docstring(module, links))
for paragraph in CONVENTIONS:
page.para(paragraph)

exceptions: list[pdoc.doc.Class] = []
for name in names:
Expand Down
2 changes: 1 addition & 1 deletion src/content/guides/use-python.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ asyncio.run(main())
Every browser action is a `Session` method, typed and documented in your IDE, with the action and its arguments in snake_case (`wait_for_selector`, `backend_node_id`).
</Callout>

Find every method's arguments in the [Python SDK reference](/reference/python), or browse the generated [Python API](/reference/python-api) reference.
Find every method's signature and docstring in the [Python SDK reference](/reference/python).

## Replay a saved script

Expand Down
1 change: 0 additions & 1 deletion src/content/reference/_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const meta: MetaRecord = {
'mcp-tools': 'MCP tools',
pandascript: 'PandaScript',
python: 'Python SDK',
'python-api': 'Python API',
}

export default meta
Loading
Loading