Skip to content

Commit 80b5e8b

Browse files
authored
Typeddict params v1 (#109)
1 parent 1555e59 commit 80b5e8b

89 files changed

Lines changed: 5643 additions & 818 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/quality.yml

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
name: Quality
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
merge_group:
9+
types: [checks_requested]
10+
workflow_dispatch:
11+
12+
concurrency:
13+
group: python-quality-${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
permissions:
17+
contents: read
18+
19+
jobs:
20+
lint:
21+
name: lint
22+
runs-on: ubuntu-24.04
23+
24+
steps:
25+
- name: Check out repository
26+
uses: actions/checkout@v6
27+
28+
- name: Set up Python
29+
uses: actions/setup-python@v6
30+
with:
31+
python-version: "3.12"
32+
cache: pip
33+
34+
- name: Install Ruff
35+
run: python -m pip install --upgrade pip ruff==0.3.7
36+
37+
- name: Run Ruff
38+
run: ruff check .
39+
40+
test:
41+
name: test (Python ${{ matrix.python-version }})
42+
runs-on: ubuntu-24.04
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
python-version:
47+
- "3.8"
48+
- "3.9"
49+
- "3.10"
50+
- "3.11"
51+
- "3.12"
52+
- "3.13"
53+
- "3.14"
54+
55+
steps:
56+
- name: Check out repository
57+
uses: actions/checkout@v6
58+
59+
- name: Set up Python
60+
uses: actions/setup-python@v6
61+
with:
62+
python-version: ${{ matrix.python-version }}
63+
cache: pip
64+
65+
- name: Install package and test dependencies
66+
shell: bash
67+
run: |
68+
python -m pip install --upgrade pip
69+
if [[ "${{ matrix.python-version }}" == "3.8" ]]; then
70+
pytest_version="8.3.5"
71+
else
72+
pytest_version="8.4.2"
73+
fi
74+
python -m pip install --editable . "pytest==$pytest_version"
75+
76+
- name: Run non-E2E tests
77+
run: |
78+
python -m pytest tests \
79+
--ignore=tests/sandbox/e2e \
80+
--ignore=tests/test_typing_contract.py
81+
82+
typing:
83+
name: typing
84+
runs-on: ubuntu-24.04
85+
86+
steps:
87+
- name: Check out repository
88+
uses: actions/checkout@v6
89+
90+
- name: Set up Python
91+
uses: actions/setup-python@v6
92+
with:
93+
python-version: "3.12"
94+
cache: pip
95+
96+
- name: Install package and typing dependencies
97+
run: |
98+
python -m pip install --upgrade pip
99+
python -m pip install \
100+
--editable . \
101+
mypy==1.14.1 \
102+
pyright==1.1.411 \
103+
pytest==8.3.5
104+
105+
- name: Verify public request types with mypy and Pyright
106+
run: |
107+
python -m pytest \
108+
tests/test_typed_request_surface.py \
109+
tests/test_typing_contract.py
110+
111+
package:
112+
name: package
113+
runs-on: ubuntu-24.04
114+
115+
steps:
116+
- name: Check out repository
117+
uses: actions/checkout@v6
118+
119+
- name: Set up Python
120+
uses: actions/setup-python@v6
121+
with:
122+
python-version: "3.12"
123+
cache: pip
124+
125+
- name: Install build tooling
126+
run: python -m pip install --upgrade build poetry==2.4.1 twine
127+
128+
- name: Check Poetry lock file
129+
run: poetry check --lock
130+
131+
- name: Build distributions
132+
run: python -m build
133+
134+
- name: Check distribution metadata
135+
run: python -m twine check dist/*
136+
137+
- name: Install wheel in an isolated environment
138+
shell: bash
139+
run: |
140+
python -m venv "$RUNNER_TEMP/wheel-smoke"
141+
"$RUNNER_TEMP/wheel-smoke/bin/python" -m pip install \
142+
dist/*.whl \
143+
mypy==1.14.1 \
144+
pyright==1.1.411
145+
146+
- name: Verify installed-wheel typing
147+
shell: bash
148+
run: |
149+
mkdir -p "$RUNNER_TEMP/typecheck"
150+
cp tests/typecheck/valid_requests.py "$RUNNER_TEMP/typecheck/"
151+
cp tests/typecheck/invalid_requests.py "$RUNNER_TEMP/typecheck/"
152+
cd "$RUNNER_TEMP/typecheck"
153+
154+
"$RUNNER_TEMP/wheel-smoke/bin/python" - <<'PY'
155+
from importlib.resources import files
156+
157+
assert files("hyperbrowser").joinpath("py.typed").is_file()
158+
PY
159+
160+
"$RUNNER_TEMP/wheel-smoke/bin/python" -m mypy \
161+
--follow-imports=silent \
162+
--ignore-missing-imports \
163+
--check-untyped-defs \
164+
--no-error-summary \
165+
--no-pretty \
166+
--no-incremental \
167+
valid_requests.py
168+
169+
if "$RUNNER_TEMP/wheel-smoke/bin/python" -m mypy \
170+
--follow-imports=silent \
171+
--ignore-missing-imports \
172+
--check-untyped-defs \
173+
--no-error-summary \
174+
--no-pretty \
175+
--no-incremental \
176+
invalid_requests.py; then
177+
echo "mypy unexpectedly accepted invalid installed-wheel requests"
178+
exit 1
179+
fi
180+
181+
"$RUNNER_TEMP/wheel-smoke/bin/python" -m pyright \
182+
--pythonpath "$RUNNER_TEMP/wheel-smoke/bin/python" \
183+
valid_requests.py
184+
185+
if "$RUNNER_TEMP/wheel-smoke/bin/python" -m pyright \
186+
--pythonpath "$RUNNER_TEMP/wheel-smoke/bin/python" \
187+
invalid_requests.py; then
188+
echo "Pyright unexpectedly accepted invalid installed-wheel requests"
189+
exit 1
190+
fi

AGENTS.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
11
# Repository Guidelines
22

33
## Project Structure & Module Organization
4-
- `hyperbrowser/` is the Python package. Key areas: `client/` (sync + async clients and managers), `models/` (Pydantic request/response types), `transport/` (HTTP transport), `tools/` (tool schemas for integrations), plus `config.py` and `exceptions.py`.
4+
- `hyperbrowser/` is the Python package. Key areas: `client/` (sync + async clients and managers), `types/` (TypedDict request types), `models/` (Pydantic responses and legacy-compatible request classes), `transport/` (HTTP transport), `tools/` (tool schemas for integrations), plus `config.py` and `exceptions.py`.
55
- `tests/` is reserved for test modules (currently minimal; add new tests here).
66
- `README.md` contains usage examples and API key setup.
77
- `pyproject.toml` defines packaging metadata and dev tooling.
88

99
## Build, Test, and Development Commands
10+
- Use Python 3.12 for the Poetry development environment; the runtime package is tested on Python 3.8 through 3.14.
1011
- `poetry install` — set up the virtualenv with runtime and dev dependencies.
1112
- `poetry build` — build source and wheel distributions.
12-
- `poetry run ruff check .` — run lint checks (ruff is the only configured dev tool).
13+
- `poetry run ruff check .` — run lint checks.
1314
- `poetry run ruff format .` — format code with ruff.
15+
- `poetry run pytest tests --ignore=tests/sandbox/e2e` — run the local non-E2E suite.
1416
- Example run: create a small script using the README snippets and run with `python path/to/script.py` after setting `HYPERBROWSER_API_KEY`.
1517

1618
## Coding Style & Naming Conventions
1719
- Python 3.8+ with 4‑space indentation.
1820
- Naming: `snake_case` for modules/functions, `CamelCase` for classes, `UPPER_SNAKE_CASE` for constants.
19-
- Prefer type hints and Pydantic models for request/response schemas.
21+
- Prefer TypedDicts for new request schemas and Pydantic models for responses. Preserve the legacy Pydantic request path when changing an existing API.
2022
- Use `ruff` for linting; keep code clean and import order consistent with ruff defaults.
2123

2224
## Testing Guidelines
2325
- Tests live in `tests/` and should follow `test_*.py` naming.
24-
- No test framework is wired in yet; if you add tests, include `pytest` in dev dependencies and document the command (e.g., `poetry run pytest`).
26+
- Add runtime compatibility coverage for both dictionaries and legacy Pydantic request objects when changing a request path.
27+
- Keep the mypy and Pyright fixtures under `tests/typecheck/` in sync with public request annotations.
2528

2629
## Commit & Pull Request Guidelines
2730
- Recent commit messages are short, imperative, and often include a PR reference like `(#45)`.
@@ -44,7 +47,7 @@
4447

4548
### Gotchas
4649

50+
- Use Python 3.12 for the Poetry environment. Runtime compatibility with other
51+
supported Python versions is exercised by CI.
4752
- Poetry must be on `PATH`. The Cloud Agent VM installs it via
4853
`pip3 install poetry`; the binary lands in `~/.local/bin`.
49-
- The baseline codebase has ~10 pre-existing ruff lint warnings (unused imports,
50-
bare `except`). These are not regressions.

CLAUDE.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ This is the Hyperbrowser Python SDK - a client library for interacting with the
88

99
## Development Commands
1010

11+
Use Python 3.12 for the Poetry development environment. CI exercises runtime
12+
compatibility from Python 3.8 through 3.14.
13+
1114
```bash
1215
# Install dependencies (uses Poetry)
1316
poetry install
@@ -17,6 +20,9 @@ poetry run ruff check .
1720

1821
# Format code with ruff
1922
poetry run ruff format .
23+
24+
# Run the non-E2E test suite
25+
poetry run pytest tests --ignore=tests/sandbox/e2e
2026
```
2127

2228
## Architecture
@@ -50,14 +56,16 @@ client.computer_action # Low-level computer actions
5056

5157
Each manager lives in `client/managers/sync_manager/` or `client/managers/async_manager/` with identical method signatures.
5258

53-
### Models
59+
### Request Types and Models
5460

55-
All Pydantic models are in `hyperbrowser/models/`:
56-
- Request params: `Start*Params`, `Create*Params`
57-
- Response types: `*Response`, `*StatusResponse`
58-
- Data models: `*Data`, `*TaskData`
61+
TypedDict request types are in `hyperbrowser/types/`. Pydantic response models
62+
and backwards-compatible request classes remain in `hyperbrowser/models/`.
63+
Managers accept either request dictionaries or the legacy request model and
64+
normalize both through the shared request serializer.
5965

60-
Models are re-exported from `hyperbrowser/models/__init__.py` for easy importing.
66+
Response and legacy models are re-exported from
67+
`hyperbrowser/models/__init__.py`; request TypedDicts are re-exported from
68+
`hyperbrowser/types/__init__.py`.
6169

6270
### Pre-built Tools
6371

0 commit comments

Comments
 (0)