Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d9bd9e9
docs(spec): add spec for python-sdk
Divkix Jan 17, 2026
a2da1f4
feat(python-sdk): scaffold package structure
Divkix Jan 17, 2026
8889e57
chore: add Python ignores to .gitignore
Divkix Jan 17, 2026
379951b
feat(python-sdk): add type definitions
Divkix Jan 17, 2026
9ee5a1d
feat(python-sdk): add error types
Divkix Jan 17, 2026
11c199d
feat(python-sdk): add config validation
Divkix Jan 17, 2026
a82ec72
feat(python-sdk): add HTTP transport with retry
Divkix Jan 17, 2026
83cc841
feat(python-sdk): add batch queue with auto-flush
Divkix Jan 17, 2026
e2927bc
feat(python-sdk): add source location capture
Divkix Jan 17, 2026
3c928c0
feat(python-sdk): add Logwell client class
Divkix Jan 17, 2026
920ba8d
feat(python-sdk): expose public API
Divkix Jan 17, 2026
ca26d46
feat(python-sdk): complete POC
Divkix Jan 17, 2026
fcc0e0a
refactor(python-sdk): add thread safety to queue
Divkix Jan 17, 2026
25379af
refactor(python-sdk): improve error messages
Divkix Jan 17, 2026
3018588
refactor(python-sdk): add strict type hints
Divkix Jan 17, 2026
34fb8d3
docs(python-sdk): add README and LICENSE
Divkix Jan 17, 2026
9e8a29b
test(python-sdk): add test fixtures
Divkix Jan 17, 2026
ae134b3
test(python-sdk): add config unit tests
Divkix Jan 17, 2026
43877df
test(python-sdk): add error unit tests
Divkix Jan 17, 2026
1bc2f3b
test(python-sdk): add queue unit tests
Divkix Jan 17, 2026
fe0bae7
test(python-sdk): add source location tests
Divkix Jan 17, 2026
d9fc2d8
test(python-sdk): add client unit tests
Divkix Jan 17, 2026
d2c5a41
test(python-sdk): add integration tests
Divkix Jan 17, 2026
195b1f5
fix(python-sdk): address lint/type issues
Divkix Jan 17, 2026
0b23b2d
chore(python-sdk): complete spec - PR #11 created
Divkix Jan 17, 2026
d304bde
fix(python-sdk): remove unused imports in test files
Divkix Jan 17, 2026
b955527
ci(python-sdk): add CI workflow with PyPI publishing
Divkix Jan 17, 2026
d425a29
fix(python-sdk): resolve lint errors in test files
Divkix Jan 17, 2026
1ddaee9
chore(python-sdk): update author name to Divkix
Divkix Jan 17, 2026
60b8de2
all done
Divkix Jan 17, 2026
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
272 changes: 272 additions & 0 deletions .github/workflows/sdk-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
name: SDK Python

on:
push:
branches: [main]
paths:
- "sdks/python/**"
- ".github/workflows/sdk-python.yml"
pull_request:
branches: [main]
paths:
- "sdks/python/**"
- ".github/workflows/sdk-python.yml"
workflow_dispatch:

permissions:
contents: read
id-token: write

# Cancel in-progress runs on same branch/PR
concurrency:
group: sdk-py-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

defaults:
run:
working-directory: sdks/python

jobs:
# =============================================================================
# Lint & Type Check
# =============================================================================
lint:
name: Lint & Type Check
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"

- name: Run ruff linter
run: uv run ruff check src tests

- name: Run ruff formatter check
run: uv run ruff format --check src tests

- name: Run mypy type check
run: uv run mypy --strict src

# =============================================================================
# Unit Tests
# =============================================================================
test-unit:
name: Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"

- name: Run unit tests
run: uv run pytest tests/unit -v --tb=short

# =============================================================================
# Integration Tests
# =============================================================================
test-integration:
name: Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"

- name: Run integration tests
run: uv run pytest tests/integration -v --tb=short

# =============================================================================
# Coverage
# =============================================================================
coverage:
name: Coverage Report
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"

- name: Run tests with coverage
run: uv run pytest --cov=src --cov-report=term-missing --cov-report=xml --cov-fail-under=90

- name: Upload coverage to job summary
run: |
echo "## 📊 Coverage Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
uv run coverage report --format=markdown >> $GITHUB_STEP_SUMMARY

# =============================================================================
# Build & Verify
# =============================================================================
build:
name: Build & Verify
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install build tools
run: uv pip install --system build twine

- name: Build package
run: python -m build

- name: Verify package with twine
run: twine check dist/*

- name: Test install from wheel
run: |
uv venv test-install
uv pip install --python test-install dist/*.whl
test-install/bin/python -c "from logwell import Logwell; print('Import OK')"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: sdk-python-dist
path: sdks/python/dist/
retention-days: 7

# =============================================================================
# Publish to PyPI (only on main, only if version changed)
# =============================================================================
publish:
name: Publish to PyPI
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [lint, test-unit, test-integration, coverage, build]
if: github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
environment:
name: pypi
url: https://pypi.org/project/logwell/

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install build tools
run: uv pip install --system build

- name: Build package
run: python -m build

- name: Check if version exists on PyPI
id: version-check
run: |
PACKAGE_NAME=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['name'])")
LOCAL_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
echo "local_version=$LOCAL_VERSION" >> $GITHUB_OUTPUT

# Check if this version already exists on PyPI
if pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$LOCAL_VERSION"; then
echo "Version $LOCAL_VERSION already exists on PyPI"
echo "should_publish=false" >> $GITHUB_OUTPUT
else
echo "Version $LOCAL_VERSION is new, will publish"
echo "should_publish=true" >> $GITHUB_OUTPUT
fi

- name: Publish to PyPI (Trusted Publisher)
if: steps.version-check.outputs.should_publish == 'true'
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: sdks/python/dist/

- name: Add publish info to job summary
if: steps.version-check.outputs.should_publish == 'true'
run: |
echo "## 📦 SDK Published to PyPI" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Package:** \`${{ steps.version-check.outputs.package_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Version:** \`${{ steps.version-check.outputs.local_version }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Install with:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "pip install ${{ steps.version-check.outputs.package_name }}==${{ steps.version-check.outputs.local_version }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

- name: Skip publish info
if: steps.version-check.outputs.should_publish == 'false'
run: |
echo "## ℹ️ SDK Publish Skipped" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Version \`${{ steps.version-check.outputs.local_version }}\` already exists on PyPI." >> $GITHUB_STEP_SUMMARY
echo "Bump the version in \`sdks/python/pyproject.toml\` to trigger a new publish." >> $GITHUB_STEP_SUMMARY
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ playwright-report/
.playwright/
specs/.current-spec
**/.progress.md

# Python
__pycache__/
*.py[cod]
*$py.class
.venv/
*.egg-info/
dist/
build/
.mypy_cache/
.ruff_cache/
.pytest_cache/
Loading
Loading