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
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

[*.{yml,yaml,toml}]
indent_size = 2

[Makefile]
indent_style = tab
7 changes: 7 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[flake8]
max-line-length = 100
max-complexity = 35
exclude = .git,__pycache__,.venv*,venv,build,dist,*.egg-info
extend-ignore = E203,E501,W503
# Enforce documentation for modules, classes, functions, methods, and constructors.
docstring-convention = google
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Normalize text to LF in the repository and on checkout, on every platform.
# Git detects binary files and leaves their contents unchanged.
* text=auto eol=lf
18 changes: 18 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Lint and type check

on: [push, pull_request]

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python -m pip install --upgrade pip
- run: python -m pip install -e '.[dev]'
- run: make lint typecheck
59 changes: 59 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Pages

on:
push:
branches: [master]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: pages-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install MkPages
run: python -m pip install '.[docs]'
- name: Generate Jekyll source
run: >-
mkpages build docs --output .mkpages
--url "https://subforkdev.github.io"
--baseurl "/subfork-python"
- name: Build site
uses: actions/jekyll-build-pages@v1
with:
source: ./.mkpages
destination: ./_site
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./_site

deploy:
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Configure Pages
uses: actions/configure-pages@v5
- name: Deploy Pages
id: deployment
uses: actions/deploy-pages@v4
20 changes: 20 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Test and package
on: [push, pull_request]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.8', '3.10', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- run: python -m pip install --upgrade pip
- run: python -m pip install '.[dev]'
- run: python -m pytest
- run: python -m build
- run: python -m twine check dist/*
56 changes: 56 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Python bytecode and compiled extensions
__pycache__/
*.py[cod]
*$py.class
*.so

# Packaging and build output
build/
dist/
.eggs/
*.egg-info/
*.egg
MANIFEST

# Virtual environments and local credentials
.venv*/
venv*/
.env
.env.*
!.env.example
!.env.*.example

# Test, coverage, type-checker, and linter caches
.pytest_cache/
.mypy_cache/
.ruff_cache/
.tox/
.nox/
.coverage
.coverage.*
htmlcov/
coverage.xml
junit.xml
.hypothesis/

# Local scratch data and notebook checkpoints
/tmp/
/logs/
.ipynb_checkpoints/

# Editor, OS, and agent-local settings
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Thumbs.db
Desktop.ini
.codex/
.agents/

# Generated documentation site
.mkpages/
_site/
.jekyll-cache/
67 changes: 67 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Contributing

To contribute to this Python client, install its development dependencies using
Python 3.8+ and a modern pip:

```bash
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
```

## Code quality

Install `.[dev]` to get the pinned development tools. Black 24.8.0, isort 5.13.2,
and Flake8 7.1.1 use 100-column formatting, isort's Black profile, and a Python
3.8 target.

```bash
make format # Sort imports and apply Black to src/ and tests/
make lint # Check formatting, imports, Flake8 and Google-style docstrings
make typecheck # Check annotated library code with mypy
make test # Run the HTTP contract tests
make check # Run lint, type checking and tests
make build # Build distributions and check their metadata
```

Activate your environment first, or specify it explicitly, for example:
`make check PYTHON=.venv/bin/python`. The CI lint job uses the same commands.
EditorConfig defines whitespace and newline conventions for supporting editors.

Add annotations and docstrings to new functions, methods and classes, including
constructors and test helpers. Public docstrings should explain side effects,
permissions, return values and failure behavior where useful. JSON dictionaries
retain `Any` values because node parameters and server response fields are dynamic;
this release does not pretend to provide complete generated response models.
Mypy checks library signatures and bodies; Flake8 and formatting cover both the
library and tests. Runtime tests continue to cover Python 3.8 in CI.

## Versioning

```bash
make version # Show the current version
make check-version # Verify both version fields agree
make bump-patch # 2.0.0 -> 2.0.1
make bump-minor # 2.0.0 -> 2.1.0
make bump-major # 2.0.0 -> 3.0.0
make bump-version VERSION=2.1.0 # Set an explicit stable version
```

Bumps update `pyproject.toml` and `subfork.__version__` together. They do not
commit, tag, or publish. Review and commit the changes before releasing.

## Documentation site

Public documentation lives in `docs/`. Its `mkpages.yml` selects the dark theme.
To generate the Jekyll source with Python 3.12:

```bash
python -m pip install -e '.[docs]'
mkpages build docs --output .mkpages
mkpages preview docs/
```

The Pages workflow builds pull requests and deploys `master`. In repository
**Settings → Pages**, select **GitHub Actions** as the source. The initial site
URL is `https://subforkdev.github.io/subfork-python/`; the workflow supplies its
`--url` and `--baseurl` options. Update those if a custom domain is configured.
Preview serves the documentation at `http://127.0.0.1:4000/`.
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2026, Ryan Galloway
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 changes: 38 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
PYTHON ?= python

.PHONY: format lint typecheck test check build
format:
$(PYTHON) -m isort src tests scripts
$(PYTHON) -m black src tests scripts

lint:
$(PYTHON) -m black --check src tests scripts
$(PYTHON) -m isort --check-only src tests scripts
$(PYTHON) -m flake8 src tests scripts

typecheck:
$(PYTHON) -m mypy

test:
$(PYTHON) -m pytest

check: lint typecheck test check-version

build: check-version
$(PYTHON) -m build
$(PYTHON) -m twine check dist/*

.PHONY: version check-version bump-patch bump-minor bump-major bump-version
export VERSION

version:
@$(PYTHON) scripts/bump-version.py --show

check-version:
@$(PYTHON) scripts/bump-version.py --check

bump-patch bump-minor bump-major:
@$(PYTHON) scripts/bump-version.py --bump $(@:bump-%=%)

bump-version:
@$(PYTHON) scripts/bump-version.py --set
Loading
Loading