Skip to content
Draft
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
37 changes: 37 additions & 0 deletions .github/release-drafter-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name-template: 'river-client-py/v$RESOLVED_VERSION'
tag-template: 'river-client-py/v$RESOLVED_VERSION'
filter-by-commitish: true
include-paths:
- 'python-client/'
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- 'python'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
label: 'chore'
- title: '🤖 Dependencies'
label: 'dependencies'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch
template: |
## Changes

$CHANGES
29 changes: 29 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,32 @@ jobs:
name: Test Report (${{ matrix.os }})
path: ./test-results.xml
reporter: java-junit

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install Python dependencies
working-directory: python-client
run: pip install -e ".[dev]" ty

- name: Python lint
working-directory: python-client
run: |
ruff check .
ruff format --check .

- name: Python type check
working-directory: python-client
run: ty check river/

- name: Python tests
working-directory: python-client
run: python -m pytest tests/ -v

- name: Python type check generated clients
working-directory: python-client
run: |
ty check tests/generated/
ty check tests/test_codegen.py
47 changes: 47 additions & 0 deletions .github/workflows/publish-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build and Publish Python Package

on:
release:
types: [published]

jobs:
build-and-publish:
# Only run for Python releases
if: startsWith(github.event.release.tag_name, 'river-client-py/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Check if version already published
working-directory: python-client
id: check
run: |
version=$(python -c "
import tomllib
with open('pyproject.toml', 'rb') as f:
print(tomllib.load(f)['project']['version'])
")
echo "version=$version" >> "$GITHUB_OUTPUT"
if uv pip install --dry-run "river-client==$version" 2>/dev/null; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Build and publish
if: steps.check.outputs.skip == 'false'
working-directory: python-client
run: |
uv build
UV_PUBLISH_TOKEN="${{ secrets.PYPI_TOKEN }}" \
uv publish
27 changes: 27 additions & 0 deletions .github/workflows/release-drafter-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release Drafter (Python)

on:
workflow_dispatch: {}
push:
branches:
- main
pull_request:
types: [opened, reopened, synchronize]
pull_request_target:
types: [opened, reopened, synchronize]

permissions:
contents: read

jobs:
update_release_draft:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter-python.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
.cache
node_modules
python-client/.venv
python-client/.pytest_cache
python-client/tests/*.mjs
python-client/tests/test_schema.json
python-client/tests/generated
.codex-review-tmp
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"format:fix": "npx prettier . --write",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"fix": "npm run format:fix && npm run lint:fix",
"fix": "npm run format:fix && npm run lint:fix && npm run fix:python",
"fix:python": "cd python-client && ruff check --fix . && ruff format .",
"build": "rm -rf dist && tsup && du -sh dist",
"prepack": "npm run build",
"release": "npm publish --access public",
Expand Down
10 changes: 10 additions & 0 deletions python-client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.venv/
__pycache__/
*.pyc
*.egg-info/
.pytest_cache/
dist/
build/
.coverage
# esbuild build artifacts (built from .ts at test time)
tests/*.mjs
45 changes: 45 additions & 0 deletions python-client/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "river-client"
version = "0.1.0"
description = "Python client for River protocol v2.0"
requires-python = ">=3.10"
license = {text = "MIT"}
dependencies = [
"websockets>=12.0",
"msgpack>=1.0",
"typing_extensions>=4.0",
"jinja2>=3.0",
"opentelemetry-api>=1.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"ruff>=0.4",
]

[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
testpaths = ["tests"]

[tool.ruff]
target-version = "py310"
exclude = ["tests/generated"]

[tool.ruff.lint]
select = ["E", "F", "I", "W"]

[tool.ty.environment]
extra-paths = ["tests"]

[tool.setuptools.packages.find]
include = ["river*"]

[tool.setuptools.package-data]
"river.codegen" = ["templates/*.j2"]
35 changes: 35 additions & 0 deletions python-client/river/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""River protocol v2.0 Python client implementation.

This client was generated with the assistance of AI (Claude).
"""

from river.client import (
ErrResult,
OkResult,
RiverClient,
StreamResult,
SubscriptionResult,
UploadResult,
)
from river.codec import BinaryCodec
from river.session import SessionOptions
from river.streams import Readable, Writable
from river.transport import WebSocketClientTransport
from river.types import Err, Ok, TransportMessage

__all__ = [
"RiverClient",
"OkResult",
"ErrResult",
"StreamResult",
"UploadResult",
"SubscriptionResult",
"WebSocketClientTransport",
"BinaryCodec",
"SessionOptions",
"TransportMessage",
"Ok",
"Err",
"Readable",
"Writable",
]
Loading
Loading