Skip to content
Closed
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
62 changes: 62 additions & 0 deletions .github/workflows/python-reference.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: python-reference

# Regenerate the Python SDK API reference with pdoc from the `lightpanda`
# package on PyPI and open a pull request when the output changed. The
# reference lives in public/python, which the static export copies verbatim,
# so the website serves it at lightpanda.io/docs/python/ once the submodule is
# bumped like any other docs change. The wheel bundles the generated tool
# methods, so no browser binary is needed here. Runs daily to pick up new
# package releases, or by hand.

on:
schedule:
- cron: "17 6 * * *"
workflow_dispatch:

permissions:
contents: write
pull-requests: write

concurrency:
group: python-reference
cancel-in-progress: true

jobs:
update:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v5

- name: Generate the reference with pdoc
id: generate
run: |
rm -rf public/python
uvx --from pdoc --with lightpanda pdoc lightpanda -o public/python --no-show-source
version=$(uv run --no-project --with lightpanda python -c \
'from importlib.metadata import version; print(version("lightpanda"))')
echo "version=$version" >> "$GITHUB_OUTPUT"
git status --short public/python

- name: Open a pull request if the reference changed
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.generate.outputs.version }}
run: |
if [ -z "$(git status --porcelain public/python)" ]; then
echo "reference already matches lightpanda $VERSION"
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 public/python
git commit -m "Update the Python SDK reference to lightpanda $VERSION"
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 reference to lightpanda $VERSION" \
--body "Regenerated \`public/python\` with pdoc from the \`lightpanda\` $VERSION package on PyPI. Served at https://lightpanda.io/docs/python/ after the website's submodule bump."
fi
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"files": {
"ignore": ["package.json", "node_modules", ".next", ".pnp.cjs", ".pnp.loader.mjs", "out"]
"ignore": ["package.json", "node_modules", ".next", ".pnp.cjs", ".pnp.loader.mjs", "out", "public"]
},
"organizeImports": {
"enabled": true
Expand Down
7 changes: 7 additions & 0 deletions public/python/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=./lightpanda.html"/>
</head>
</html>
2,203 changes: 2,203 additions & 0 deletions public/python/lightpanda.html

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions public/python/search.js

Large diffs are not rendered by default.

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 API reference at [lightpanda.io/lightpanda-python](https://lightpanda.io/lightpanda-python/).
Find every method's arguments in the [Python SDK reference](/reference/python), or browse the generated API reference at [lightpanda.io/docs/python](https://lightpanda.io/docs/python/).

## Replay a saved script

Expand Down
20 changes: 10 additions & 10 deletions src/content/reference/python.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ description: Reference of the classes and methods in the Lightpanda Python packa

# Python SDK

The [`lightpanda` package](https://pypi.org/project/lightpanda/) exposes `Browser`/`AsyncBrowser`, which spawn and manage the bundled binary, and `Session`/`AsyncSession`, with one method per browser action. See [Use the Python SDK](/guides/use-python) for practical documentation.
The [`lightpanda` package](https://pypi.org/project/lightpanda/) exposes `Browser`/`AsyncBrowser`, which spawn and manage the bundled binary, and `Session`/`AsyncSession`, with one method per browser action. See [Use the Python SDK](/guides/use-python) for practical documentation, and the [generated API reference](https://lightpanda.io/docs/python/) for every signature and docstring as shipped in the package.

## Browser

`Browser()` spawns the bundled binary when constructed. It is not fork-inheritable: create a fresh instance in a forked child.
[`Browser()`](https://lightpanda.io/docs/python/lightpanda.html#Browser) spawns the bundled binary when constructed. It is not fork-inheritable: create a fresh instance in a forked child.

| Argument | Default | Description |
|---|---|---|
Expand All @@ -29,7 +29,7 @@ The [`lightpanda` package](https://pypi.org/project/lightpanda/) exposes `Browse

## AsyncBrowser

`AsyncBrowser` mirrors `Browser` for asyncio: every call runs on a browser-owned thread pool, so the event loop is never blocked.
[`AsyncBrowser`](https://lightpanda.io/docs/python/lightpanda.html#AsyncBrowser) mirrors `Browser` for asyncio: every call runs on a browser-owned thread pool, so the event loop is never blocked.

| Argument | Default | Description |
|---|---|---|
Expand All @@ -49,7 +49,7 @@ The [`lightpanda` package](https://pypi.org/project/lightpanda/) exposes `Browse

## Session and AsyncSession

`Browser.new_session()` and `AsyncBrowser.new_session()` are the only way to obtain a `Session` or `AsyncSession`; do not construct one directly.
`Browser.new_session()` and `AsyncBrowser.new_session()` are the only way to obtain a [`Session`](https://lightpanda.io/docs/python/lightpanda.html#Session) or [`AsyncSession`](https://lightpanda.io/docs/python/lightpanda.html#AsyncSession); do not construct one directly.

| Member | Description |
|---|---|
Expand All @@ -61,7 +61,7 @@ Sessions are context managers too: `with browser.new_session() as page:` closes

## Calling an action

Every browser action is a method on `Session`/`AsyncSession`, keyword-only, with the action and its arguments in snake_case: the `waitForSelector` action is `wait_for_selector`, and its `backendNodeId` argument is `backend_node_id`. The methods are generated from the bundled browser's action schemas, so the signatures and docstrings your IDE shows come straight from the binary. The generated reference for the latest release is published at [lightpanda.io/lightpanda-python](https://lightpanda.io/lightpanda-python/).
Every browser action is a method on `Session`/`AsyncSession`, keyword-only, with the action and its arguments in snake_case: the `waitForSelector` action is `wait_for_selector`, and its `backendNodeId` argument is `backend_node_id`. The methods are generated from the bundled browser's action schemas, so the signatures and docstrings your IDE shows come straight from the binary. The generated reference for the latest release is published at [lightpanda.io/docs/python](https://lightpanda.io/docs/python/); see [`Session`](https://lightpanda.io/docs/python/lightpanda.html#Session) and [`AsyncSession`](https://lightpanda.io/docs/python/lightpanda.html#AsyncSession) there for every method's exact signature and docstring.

A failed action raises `ToolError`.

Expand Down Expand Up @@ -149,7 +149,7 @@ These methods block until the page reaches a condition:

## Script replay

`run_script` and `run_script_async` (its awaitable variant, run in a worker thread) replay a saved [PandaScript](/reference/pandascript) with no LLM call, by running `lightpanda run <script>` and returning its stdout. Installing the package also puts the `lightpanda` binary itself on `PATH`.
[`run_script`](https://lightpanda.io/docs/python/lightpanda.html#run_script) and [`run_script_async`](https://lightpanda.io/docs/python/lightpanda.html#run_script_async) (its awaitable variant, run in a worker thread) replay a saved [PandaScript](/reference/pandascript) with no LLM call, by running `lightpanda run <script>` and returning its stdout. Installing the package also puts the `lightpanda` binary itself on `PATH`.

```python copy
from lightpanda import run_script
Expand All @@ -170,7 +170,7 @@ A non-zero exit raises `ScriptError`. Exceeding `timeout` raises `subprocess.Tim

| Error | Raised when |
|---|---|
| `LightpandaError` | Base class for every error the package raises. |
| `ProtocolError` | The connection to the browser process failed: a malformed request, a timeout, or an internal error. Carries a `code` attribute. |
| `ToolError` | A browser action reported failure, such as a bad selector, a JS exception inside `evaluate`, or a call on a closed session. |
| `ScriptError` | `run_script` or `run_script_async` exited with a non-zero status, or the script file doesn't exist (`returncode=-1`). Carries `returncode`, `stdout`, and `stderr` attributes. |
| [`LightpandaError`](https://lightpanda.io/docs/python/lightpanda.html#LightpandaError) | Base class for every error the package raises. |
| [`ProtocolError`](https://lightpanda.io/docs/python/lightpanda.html#ProtocolError) | The connection to the browser process failed: a malformed request, a timeout, or an internal error. Carries a `code` attribute. |
| [`ToolError`](https://lightpanda.io/docs/python/lightpanda.html#ToolError) | A browser action reported failure, such as a bad selector, a JS exception inside `evaluate`, or a call on a closed session. |
| [`ScriptError`](https://lightpanda.io/docs/python/lightpanda.html#ScriptError) | `run_script` or `run_script_async` exited with a non-zero status, or the script file doesn't exist (`returncode=-1`). Carries `returncode`, `stdout`, and `stderr` attributes. |
Loading