Skip to content

Commit cfb9e50

Browse files
uzunenescursoragent
andcommitted
visgate-sdk v0.2.2 — production-ready Python client for Visgate API
Co-authored-by: Cursor <cursoragent@cursor.com>
0 parents  commit cfb9e50

36 files changed

+3299
-0
lines changed

.cursorrules

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
You are working on visgate-python, the open-source Python SDK for the Visgate API.
2+
3+
Stack: Python 3.9+, httpx, pytest, ruff. Build: setuptools via pyproject.toml.
4+
5+
Architecture:
6+
- src/visgate_sdk/client.py — Client (sync) and AsyncClient (async), httpx-based with retry logic
7+
- src/visgate_sdk/resources/ — one module per API resource (generate, images, videos, models, usage, providers)
8+
- src/visgate_sdk/exceptions.py — typed exception hierarchy (VisgateError base)
9+
- src/visgate_sdk/_utils.py — internal helpers (datetime parsing)
10+
- tests/test_client.py — unit tests (pytest + pytest-asyncio)
11+
- examples/ — numbered scripts tested against the live API
12+
13+
Key design decisions:
14+
- api_key auto-discovers from VISGATE_API_KEY env var (like openai/stripe SDKs)
15+
- Version is single-sourced from pyproject.toml via importlib.metadata with fallback
16+
- _handle_response is a shared module-level function (not duplicated per client)
17+
- generate() is a proper method on Client, not a callable resource
18+
- max_retries with exponential backoff for transient errors (429, 5xx)
19+
- All BYOK keys (fal, replicate, runway) are constructor parameters
20+
- All result types have __repr__ for readable debugging
21+
- py.typed marker for PEP 561 compliance
22+
23+
Rules:
24+
- All modules use `from __future__ import annotations` for Python 3.9 compat
25+
- All user-facing text must be English only
26+
- Every public export must be in __init__.py __all__
27+
- Run `ruff check src/ tests/` and `pytest tests/ -v` before any commit
28+
- No unnecessary dependencies; httpx is the only runtime dep

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ci-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
strategy:
17+
matrix:
18+
python-version: ["3.9", "3.11", "3.12"]
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: Set up Python ${{ matrix.python-version }}
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
28+
- name: Install dependencies
29+
run: pip install -e ".[dev]"
30+
31+
- name: Lint
32+
run: ruff check src/ tests/
33+
34+
- name: Test
35+
run: pytest tests/ -v
36+
37+
- name: Smoke (offline)
38+
run: python examples/00_smoke_sdk.py

.github/workflows/publish-pypi.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Publish visgate-sdk to PyPI on GitHub Release.
2+
#
3+
# Authentication (in order of preference):
4+
# 1. PyPI trusted publisher (recommended, no secrets needed)
5+
# Setup: https://docs.pypi.org/trusted-publishers/adding-a-publisher/
6+
# 2. PYPI_API_TOKEN secret (fallback)
7+
name: Publish to PyPI
8+
9+
on:
10+
release:
11+
types: [published]
12+
13+
jobs:
14+
publish:
15+
runs-on: ubuntu-latest
16+
environment: pypi
17+
permissions:
18+
id-token: write
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: "3.12"
27+
28+
- name: Install build
29+
run: pip install build
30+
31+
- name: Build package
32+
run: python -m build
33+
34+
- name: Publish to PyPI
35+
uses: pypa/gh-action-pypi-publish@release/v1
36+
with:
37+
password: ${{ secrets.PYPI_API_TOKEN }}

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.egg-info/
5+
.eggs/
6+
dist/
7+
build/
8+
.venv/
9+
venv/
10+
11+
# Test / tools
12+
.pytest_cache/
13+
.coverage
14+
htmlcov/
15+
.ruff_cache/
16+
17+
# OS
18+
.DS_Store
19+
20+
# Env
21+
.env
22+
.env.*

CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Changelog
2+
3+
## [0.2.2] - 2026-02-11
4+
5+
### Added
6+
7+
- Automatic API key discovery from `VISGATE_API_KEY` environment variable.
8+
- `max_retries` parameter with exponential backoff for transient errors (429, 5xx).
9+
- `replicate_key` and `runway_key` constructor parameters for BYOK mode.
10+
- `client.health()` method for API health checks.
11+
- `client.usage.logs()` and `client.usage.dashboard()` methods.
12+
- `ValidationError` for 422 responses with `.field` attribute.
13+
- `TimeoutError` and `ConnectionError` for network failures.
14+
- `py.typed` marker (PEP 561) for downstream type checking.
15+
- `CONTRIBUTING.md` for contributor guidelines.
16+
- CI workflow testing Python 3.9, 3.11, and 3.12.
17+
- 54 unit tests covering client, errors, data classes, and async.
18+
19+
### Changed
20+
21+
- `api_key` is now optional -- reads from environment if not provided.
22+
- `generate()` is a proper method on the client, not a callable resource.
23+
- Response handling is shared between sync and async clients (fixes async `ProviderError` bug).
24+
- All datetime fields use consistent parsing via `_utils.parse_datetime`.
25+
- All result types have `__repr__` for readable debugging output.
26+
- User-Agent changed to `visgate-sdk-python/{version}`.
27+
- `__version__` falls back gracefully when package is not installed.
28+
- Usage resource uses proper `params=` instead of manual query string.
29+
- PyPI publish uses trusted publisher (no token required).
30+
31+
### Removed
32+
33+
- `VisGate` alias (use `Client` directly).
34+
- Redundant `sdk-test-project/` and `istanbul_prompt_to_image.py` examples.
35+
- Stale `RELEASE.md`, `RELEASE_CHECKLIST.md`, `docs/SDK-WORKFLOW.md`.
36+
37+
## [0.2.1] - 2026-02-10
38+
39+
### Changed
40+
41+
- Initial standalone release on PyPI.
42+
43+
## [0.2.0] - 2026-02-07
44+
45+
### Added
46+
47+
- BYOK proxy layer, unified `/v1/generate` endpoint, megapixel pricing.

CONTRIBUTING.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Contributing to visgate-sdk
2+
3+
Thanks for your interest in contributing.
4+
5+
## Setup
6+
7+
```bash
8+
git clone https://github.com/visgate-ai/visgate-python.git
9+
cd visgate-python
10+
python3 -m venv .venv
11+
source .venv/bin/activate
12+
pip install -e ".[dev]"
13+
```
14+
15+
## Development
16+
17+
```bash
18+
# Lint
19+
ruff check src/ tests/
20+
21+
# Unit tests
22+
pytest tests/ -v
23+
24+
# Smoke test (no network)
25+
python examples/00_smoke_sdk.py
26+
27+
# Live API smoke test (no auth needed)
28+
python examples/01_live_api_smoke.py
29+
```
30+
31+
## Pull Requests
32+
33+
1. Fork the repo and create a feature branch.
34+
2. Make your changes. Add tests for new functionality.
35+
3. Ensure `ruff check src/ tests/` and `pytest tests/ -v` pass.
36+
4. Open a PR with a clear description of what changed and why.
37+
38+
## Code Style
39+
40+
- Python 3.9+ compatible.
41+
- Use `from __future__ import annotations` in all modules.
42+
- Run `ruff check` before committing.
43+
- Keep the public API surface minimal.
44+
- Every public export must be in `__init__.py` `__all__`.
45+
46+
## Releasing
47+
48+
Version is single-sourced from `pyproject.toml`. To release:
49+
50+
1. Bump version in `pyproject.toml`.
51+
2. Update `CHANGELOG.md`.
52+
3. Commit and push to `main`.
53+
4. Create a GitHub Release with the tag (e.g. `v0.3.0`).
54+
5. The PyPI publish workflow runs automatically.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Visgate AI
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)