Skip to content

Commit 6f27355

Browse files
committed
Add client documentation, typing, and code quality tooling
1 parent 3a77919 commit 6f27355

14 files changed

Lines changed: 630 additions & 132 deletions

File tree

‎.editorconfig‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
indent_style = space
9+
indent_size = 4
10+
11+
[*.{yml,yaml,toml}]
12+
indent_size = 2
13+
14+
[Makefile]
15+
indent_style = tab

‎.flake8‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[flake8]
2+
max-line-length = 100
3+
max-complexity = 35
4+
exclude = .git,__pycache__,.venv*,venv,build,dist,*.egg-info
5+
extend-ignore = E203,E501,W503
6+
# Enforce documentation for modules, classes, functions, methods, and constructors.
7+
docstring-convention = google

‎.gitattributes‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Normalize text to LF in the repository and on checkout, on every platform.
2+
# Git detects binary files and leaves their contents unchanged.
3+
* text=auto eol=lf

‎.github/workflows/lint.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Lint and type check
2+
3+
on: [push, pull_request]
4+
5+
permissions:
6+
contents: read
7+
8+
jobs:
9+
lint:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-python@v5
14+
with:
15+
python-version: '3.12'
16+
- run: python -m pip install --upgrade pip
17+
- run: python -m pip install -e '.[dev]'
18+
- run: make lint typecheck

‎.github/workflows/tests.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
runs-on: ubuntu-latest
88
strategy:
99
matrix:
10-
python: ['3.8', '3.10', '3.12', '3.13']
10+
python: ['3.8', '3.10', '3.12', '3.13', '3.14']
1111
steps:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-python@v5

‎.gitignore‎

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,51 @@
1+
# Python bytecode and compiled extensions
12
__pycache__/
23
*.py[cod]
3-
.pytest_cache/
4-
.venv*/
5-
.env
6-
.env.*
4+
*$py.class
5+
*.so
6+
7+
# Packaging and build output
78
build/
89
dist/
10+
.eggs/
911
*.egg-info/
12+
*.egg
13+
MANIFEST
14+
15+
# Virtual environments and local credentials
16+
.venv*/
17+
venv*/
18+
.env
19+
.env.*
20+
!.env.example
21+
!.env.*.example
22+
23+
# Test, coverage, type-checker, and linter caches
24+
.pytest_cache/
25+
.mypy_cache/
26+
.ruff_cache/
27+
.tox/
28+
.nox/
29+
.coverage
30+
.coverage.*
31+
htmlcov/
32+
coverage.xml
33+
junit.xml
34+
.hypothesis/
35+
36+
# Local scratch data and notebook checkpoints
37+
/tmp/
38+
/logs/
39+
.ipynb_checkpoints/
40+
41+
# Editor, OS, and agent-local settings
42+
.vscode/
43+
.idea/
44+
*.swp
45+
*.swo
46+
*~
47+
.DS_Store
48+
Thumbs.db
49+
Desktop.ini
50+
.codex/
51+
.agents/

‎Makefile‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
PYTHON ?= python
2+
3+
.PHONY: format lint typecheck test check build
4+
format:
5+
$(PYTHON) -m isort src tests
6+
$(PYTHON) -m black src tests
7+
8+
lint:
9+
$(PYTHON) -m black --check src tests
10+
$(PYTHON) -m isort --check-only src tests
11+
$(PYTHON) -m flake8 src tests
12+
13+
typecheck:
14+
$(PYTHON) -m mypy
15+
16+
test:
17+
$(PYTHON) -m pytest
18+
19+
check: lint typecheck test
20+
21+
build:
22+
$(PYTHON) -m build
23+
$(PYTHON) -m twine check dist/*

‎README.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,31 @@ phase, not a strict wall-clock deadline for the entire network exchange.
116116
The first scaffold is synchronous. Async support, rich response models, artifact
117117
streaming, idempotent write retries and worker support are not included. Mock HTTP
118118
tests do not certify any particular server deployment.
119+
120+
## Code quality
121+
122+
Install `.[dev]` to get the pinned development tools. Black 24.8.0, isort 5.13.2,
123+
and Flake8 7.1.1 follow the conventions used in the sibling envstack and pyseq
124+
projects: 100-column formatting, isort's Black profile, and a Python 3.8 target.
125+
The tool versions also support running locally under Python 3.8.
126+
127+
```bash
128+
make format # Sort imports and apply Black to src/ and tests/
129+
make lint # Check formatting, imports, Flake8 and Google-style docstrings
130+
make typecheck # Check annotated library code with mypy
131+
make test # Run the HTTP contract tests
132+
make check # Run lint, type checking and tests
133+
make build # Build distributions and check their metadata
134+
```
135+
136+
Activate your environment first, or specify it explicitly, for example:
137+
`make check PYTHON=.venv/bin/python`. The CI lint job uses the same commands.
138+
EditorConfig defines whitespace and newline conventions for supporting editors.
139+
140+
Add annotations and docstrings to new functions, methods and classes, including
141+
constructors and test helpers. Public docstrings should explain side effects,
142+
permissions, return values and failure behavior where useful. JSON dictionaries
143+
retain `Any` values because node parameters and server response fields are dynamic;
144+
this release does not pretend to provide complete generated response models.
145+
Mypy checks library signatures and bodies; Flake8 and formatting cover both the
146+
library and tests. Runtime tests continue to cover Python 3.8 in CI.

‎pyproject.toml‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,17 @@ classifiers = [
1818
]
1919

2020
[project.optional-dependencies]
21-
dev = ["pytest>=8,<10", "build>=1,<2", "twine>=6,<7"]
21+
dev = [
22+
"pytest>=8,<10",
23+
"build>=1,<2",
24+
"twine>=6,<7",
25+
"flake8==7.1.1",
26+
"flake8-docstrings==1.7.0",
27+
"mccabe==0.7.0",
28+
"isort==5.13.2",
29+
"black==24.8.0",
30+
"mypy==1.14.1",
31+
]
2232

2333
[tool.setuptools]
2434
license-files = ["LICENSE"]
@@ -31,3 +41,29 @@ subfork = ["py.typed"]
3141

3242
[tool.pytest.ini_options]
3343
testpaths = ["tests"]
44+
45+
[tool.isort]
46+
profile = "black"
47+
line_length = 100
48+
skip_gitignore = true
49+
50+
[tool.black]
51+
line-length = 100
52+
target-version = ["py38"]
53+
extend-exclude = '/\.venv[^/]*/'
54+
55+
[tool.mypy]
56+
python_version = "3.8"
57+
files = ["src/subfork"]
58+
disallow_untyped_defs = true
59+
check_untyped_defs = true
60+
no_implicit_optional = true
61+
warn_unused_ignores = true
62+
warn_redundant_casts = true
63+
show_error_codes = true
64+
65+
# Newer environments install CLI/async dependency internals with newer syntax.
66+
# Skip those internals while retaining HTTPX's client types and our 3.8 target.
67+
[[tool.mypy.overrides]]
68+
module = ["httpx._main", "anyio", "anyio.*"]
69+
follow_imports = "skip"

‎src/subfork/__init__.py‎

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
11
"""Subfork's Python API client. BYO worker support is a separate distribution."""
2+
23
from .client import Subfork
3-
from .errors import APIError, AuthenticationError, ExecutionTimeout, InvalidResponseError, NotFoundError, PermissionDeniedError, RateLimitError, SubforkError, TransportError, ValidationError
4+
from .errors import (
5+
APIError,
6+
AuthenticationError,
7+
ExecutionTimeout,
8+
InvalidResponseError,
9+
NotFoundError,
10+
PermissionDeniedError,
11+
RateLimitError,
12+
SubforkError,
13+
TransportError,
14+
ValidationError,
15+
)
416

5-
__version__ = '0.1.0a1'
6-
__all__ = ['Subfork', 'SubforkError', 'APIError', 'AuthenticationError', 'PermissionDeniedError',
7-
'NotFoundError', 'ValidationError', 'RateLimitError', 'TransportError',
8-
'InvalidResponseError', 'ExecutionTimeout']
17+
__version__ = "0.1.0a1"
18+
__all__ = [
19+
"Subfork",
20+
"SubforkError",
21+
"APIError",
22+
"AuthenticationError",
23+
"PermissionDeniedError",
24+
"NotFoundError",
25+
"ValidationError",
26+
"RateLimitError",
27+
"TransportError",
28+
"InvalidResponseError",
29+
"ExecutionTimeout",
30+
]

0 commit comments

Comments
 (0)