Skip to content

Commit 43a062e

Browse files
committed
feat: initial Python SDK implementation
- Add sync and async Forminit clients - Add comprehensive type definitions - Add 21 tests with 85% coverage - Add Flask, FastAPI, and Django examples - Add GitHub Actions for CI/CD - Add dual authentication support for PyPI publishing
1 parent e9ddba0 commit 43a062e

32 files changed

Lines changed: 3741 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Lint
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.12"
20+
21+
- name: Install uv
22+
uses: astral-sh/setup-uv@v4
23+
with:
24+
enable-cache: true
25+
26+
- name: Install dependencies
27+
run: uv sync
28+
29+
- name: Run ruff check
30+
run: uv run ruff check .
31+
32+
- name: Run ruff format check
33+
run: uv run ruff format --check .
34+
35+
test:
36+
name: Test Python ${{ matrix.python-version }}
37+
runs-on: ubuntu-latest
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
42+
43+
steps:
44+
- uses: actions/checkout@v4
45+
46+
- name: Set up Python ${{ matrix.python-version }}
47+
uses: actions/setup-python@v5
48+
with:
49+
python-version: ${{ matrix.python-version }}
50+
51+
- name: Install uv
52+
uses: astral-sh/setup-uv@v4
53+
with:
54+
enable-cache: true
55+
56+
- name: Install dependencies
57+
run: uv sync
58+
59+
- name: Run tests
60+
run: uv run pytest -v --tb=short
61+
62+
coverage:
63+
name: Coverage
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Set up Python
69+
uses: actions/setup-python@v5
70+
with:
71+
python-version: "3.12"
72+
73+
- name: Install uv
74+
uses: astral-sh/setup-uv@v4
75+
with:
76+
enable-cache: true
77+
78+
- name: Install dependencies
79+
run: uv sync
80+
81+
- name: Run tests with coverage
82+
run: uv run pytest --cov=forminit --cov-report=xml --cov-report=term
83+
84+
- name: Upload coverage to Codecov
85+
uses: codecov/codecov-action@v4
86+
with:
87+
file: ./coverage.xml
88+
fail_ci_if_error: false

.github/workflows/publish.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
test-pypi:
9+
description: 'Publish to Test PyPI instead of PyPI'
10+
required: false
11+
type: boolean
12+
default: false
13+
14+
jobs:
15+
build:
16+
name: Build distribution
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.12"
25+
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v4
28+
29+
- name: Build package
30+
run: uv build
31+
32+
- name: Store the distribution packages
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: python-package-distributions
36+
path: dist/
37+
38+
publish-to-pypi:
39+
name: Publish to PyPI
40+
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.test-pypi)
41+
needs:
42+
- build
43+
runs-on: ubuntu-latest
44+
environment:
45+
name: pypi
46+
url: https://pypi.org/p/forminit
47+
permissions:
48+
id-token: write
49+
steps:
50+
- name: Download all the dists
51+
uses: actions/download-artifact@v4
52+
with:
53+
name: python-package-distributions
54+
path: dist/
55+
56+
- name: Publish to PyPI (Trusted Publishing with Token Fallback)
57+
uses: pypa/gh-action-pypi-publish@release/v1
58+
with:
59+
password: ${{ secrets.PYPI_API_TOKEN || '' }}
60+
skip-existing: true
61+
62+
publish-to-testpypi:
63+
name: Publish to TestPyPI
64+
if: github.event_name == 'workflow_dispatch' && inputs.test-pypi
65+
needs:
66+
- build
67+
runs-on: ubuntu-latest
68+
environment:
69+
name: testpypi
70+
url: https://test.pypi.org/p/forminit
71+
permissions:
72+
id-token: write
73+
steps:
74+
- name: Download all the dists
75+
uses: actions/download-artifact@v4
76+
with:
77+
name: python-package-distributions
78+
path: dist/
79+
80+
- name: Publish to TestPyPI (Trusted Publishing with Token Fallback)
81+
uses: pypa/gh-action-pypi-publish@release/v1
82+
with:
83+
repository-url: https://test.pypi.org/legacy/
84+
password: ${{ secrets.TEST_PYPI_API_TOKEN || '' }}
85+
skip-existing: true

.github/workflows/release.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
create-release:
13+
name: Create GitHub Release
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Extract version from tag
21+
id: version
22+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
23+
24+
- name: Generate changelog
25+
id: changelog
26+
run: |
27+
# Get the previous tag
28+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
29+
30+
if [ -z "$PREV_TAG" ]; then
31+
# First release, get all commits
32+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
33+
else
34+
# Get commits since previous tag
35+
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
36+
fi
37+
38+
# Save to file for multiline support
39+
echo "$CHANGELOG" > changelog.txt
40+
41+
- name: Create Release
42+
uses: softprops/action-gh-release@v2
43+
with:
44+
name: Release ${{ steps.version.outputs.VERSION }}
45+
body_path: changelog.txt
46+
draft: false
47+
prerelease: false
48+
env:
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.pyd
5+
*.so
6+
7+
# Virtual environments
8+
.venv/
9+
venv/
10+
ENV/
11+
12+
# Packaging
13+
build/
14+
dist/
15+
*.egg-info/
16+
17+
# Test/coverage
18+
.pytest_cache/
19+
.coverage
20+
.coverage.*
21+
htmlcov/
22+
coverage.xml
23+
24+
# IDE/editor
25+
.vscode/
26+
.idea/
27+
28+
# OS
29+
.DS_Store

.pre-commit-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.5.5
4+
hooks:
5+
- id: ruff
6+
args: ["--fix"]
7+
- id: ruff-format

0 commit comments

Comments
 (0)