Thank you for your interest in contributing to the Gatewayz Python SDK! This guide will help you understand the SDK architecture and how to set up your development environment.
- SDK Architecture
- Getting Started
- Development Setup
- Making Changes
- Testing
- Code Style
- Submitting Changes
This SDK is auto-generated by docsalot from an OpenAPI specification. Understanding this is crucial:
- Source of Truth: The OpenAPI spec (
openapi.json) defines the API structure - Generated Code: Most Python files are generated and should NOT be manually edited
- Regeneration: Changes to the API require regenerating the SDK from the updated OpenAPI spec
sdks/python/
├── __init__.py # Main package exports (generated)
├── client.py # Main client classes (generated)
├── raw_client.py # Raw HTTP client (generated)
├── core/ # Core utilities (generated)
│ ├── http_client.py # HTTP client implementation
│ ├── client_wrapper.py # Client wrapper utilities
│ ├── request_options.py # Request configuration
│ ├── api_error.py # Error handling
│ └── ...
├── types/ # Type definitions (generated)
│ ├── message.py
│ ├── chat_session.py
│ └── ...
├── errors/ # Custom error classes (generated)
│ └── unprocessable_entity_error.py
├── [modules]/ # API endpoint modules (generated)
│ ├── chat/
│ ├── authentication/
│ ├── providers/
│ ├── models/
│ └── ...
├── openapi.json # OpenAPI specification (source)
├── pyproject.toml # Package configuration (manual)
├── setup.py # Setup script (manual)
├── requirements.txt # Dependencies (manual)
├── README.md # Documentation (manual)
├── examples.py # Usage examples (manual)
└── test_install.py # Installation test (manual)
Main Clients:
GatewayzApi- Synchronous clientAsyncGatewayzApi- Asynchronous client
Properties:
client = GatewayzApi(token="...", base_url="...")
# Sub-clients accessed as properties
client.chat # Chat operations
client.authentication # Auth operations
client.models # Model catalog
client.providers # Provider catalog
client.admin # Admin operations
# ... etchttp_client.py- HTTP communication layer (httpx wrapper)client_wrapper.py- Manages base URL, headers, authenticationrequest_options.py- Per-request configuration (timeout, retries, headers)api_error.py- Base exception class for API errorspydantic_utilities.py- Pydantic v2 compatibility utilities
Pydantic models for request/response serialization:
from gatewayz.types import Message, ChatSession, UserProfileResponse
# All types are Pydantic models with validation
message = Message(role="user", content="Hello")Each module has its own client class:
# Example: chat/client.py
class ChatClient:
def chat_completions(self, model: str, messages: List[Message], ...):
# Implementation
passLower-level clients that return raw HTTP responses:
# For advanced use cases needing direct HTTP response access
raw_response = client.with_raw_response.chat.chat_completions(...)
print(raw_response.status_code)
print(raw_response.headers)Important: The package uses a special directory mapping:
# pyproject.toml
[tool.setuptools]
package-dir = {"gatewayz" = "."}This tells Python:
- The current directory (
.) should be installed as thegatewayzpackage - When you
import gatewayz, Python loads from this directory - All subdirectories become subpackages:
gatewayz.core,gatewayz.types, etc.
- Python 3.7 or higher
- pip (Python package installer)
- git
- Virtual environment tool (venv, virtualenv, or conda)
# Clone the repository
git clone https://github.com/yourusername/gatewayz-sdk.git
cd gatewayz-sdk/sdks/python
# Or if this is a monorepo
cd /path/to/repo/sdks/python# Using venv (recommended)
python -m venv venv
# Activate on Linux/Mac
source venv/bin/activate
# Activate on Windows
venv\Scripts\activate
# Using conda
conda create -n gatewayz-dev python=3.10
conda activate gatewayz-dev# Install the SDK in editable/development mode
pip install -e .
# Install with development dependencies
pip install -e ".[dev]"This installs:
- Core dependencies: httpx, pydantic
- Dev dependencies: pytest, black, isort, mypy, ruff
# Run the installation test
python test_install.py
# Or test import directly
python -c "from gatewayz import GatewayzApi; print('✓ SDK installed')"# Create a .env file for local testing
cat > .env << EOF
GATEWAYZ_API_TOKEN=your-api-token-here
GATEWAYZ_BASE_URL=https://api.gatewayz.ai
EOF
# Add .env to .gitignore (if not already there)
echo ".env" >> .gitignoreREADME.md- DocumentationCONTRIBUTING.md- This filepyproject.toml- Package configurationsetup.py- Setup scriptrequirements.txt- Dependenciesexamples.py- Usage examplestest_install.py- Installation tests- Any custom test files you create
.gitignore,.env, etc.
client.pyraw_client.py__init__.pycore/*types/*errors/*[module]/client.py[module]/raw_client.py- Any file with "This file was auto-generated by docsalot" header
The proper process:
- Modify the OpenAPI specification (
openapi.json) - Regenerate the SDK using docsalot:
# Install docsalot CLI npm install -g docsalot-api # Regenerate SDK docsalot generate --group python
- Test the regenerated SDK
- Commit both the spec and regenerated code
# Edit examples.py
vim examples.py
# Add a new example function
def new_example():
"""Description of the example."""
client = GatewayzApi(
token="YOUR_API_TOKEN",
base_url="https://api.gatewayz.ai"
)
# Your example code here
result = client.models.get_models(limit=5)
print(result)# Create a tests directory
mkdir -p tests
# Create a test file
cat > tests/test_authentication.py << 'EOF'
import pytest
from gatewayz import GatewayzApi
from gatewayz.core import ApiError
def test_client_initialization():
"""Test that client can be initialized."""
client = GatewayzApi(
token="test-token",
base_url="https://api.gatewayz.ai"
)
assert client is not None
assert client._client_wrapper is not None
def test_health_check():
"""Test health check endpoint."""
client = GatewayzApi(
token="test",
base_url="https://api.gatewayz.ai"
)
# This would need a mock or real API for actual testing
# response = client.health_check_health_get()
# assert response is not None
EOF
# Run tests
pytest tests/python test_install.py# Run all tests
pytest
# Run with coverage
pytest --cov=gatewayz tests/
# Run specific test file
pytest tests/test_authentication.py
# Run with verbose output
pytest -v# Create a test script
cat > manual_test.py << 'EOF'
from gatewayz import GatewayzApi
client = GatewayzApi(
token="your-api-token",
base_url="https://api.gatewayz.ai"
)
# Test endpoints
try:
health = client.health_check_health_get()
print(f"✓ Health check: {health}")
models = client.models.get_models(limit=3)
print(f"✓ Found {len(models)} models")
except Exception as e:
print(f"✗ Error: {e}")
EOF
python manual_test.pyIf you're running a local instance of the Gatewayz API:
from gatewayz import GatewayzApi
# Point to local API
client = GatewayzApi(
token="test-token",
base_url="http://localhost:8000"
)
response = client.health_check_health_get()
print(response)This project uses standard Python formatting tools:
# Format code with black
black .
# Sort imports with isort
isort .
# Run both
black . && isort .# Run ruff (fast Python linter)
ruff check .
# Fix auto-fixable issues
ruff check --fix .
# Run mypy for type checking
mypy .Before committing, run:
# Format and lint
black . && isort . && ruff check --fix .
# Run tests
python test_install.py
# Verify imports work
python -c "from gatewayz import GatewayzApi; print('✓')"- Type hints: Use type hints for all function signatures
- Docstrings: Document all public functions with docstrings
- Line length: 120 characters (configured in pyproject.toml)
- Naming:
- Classes:
PascalCase - Functions/methods:
snake_case - Constants:
UPPER_CASE - Private: prefix with
_
- Classes:
Example:
from typing import List, Optional
from gatewayz.types import Message
def send_chat_message(
client: GatewayzApi,
message: str,
model: str = "gpt-3.5-turbo",
max_tokens: Optional[int] = None
) -> dict:
"""
Send a chat message and return the response.
Args:
client: Initialized GatewayzApi client
message: The message to send
model: Model to use (default: gpt-3.5-turbo)
max_tokens: Maximum tokens in response
Returns:
dict: API response
Example:
>>> client = GatewayzApi(token="...", base_url="...")
>>> response = send_chat_message(client, "Hello!")
"""
response = client.chat.chat_completions(
model=model,
messages=[Message(role="user", content=message)],
max_tokens=max_tokens
)
return response-
Create a branch
git checkout -b feature/add-new-examples
-
Make your changes
- Edit documentation, examples, or configuration
- DO NOT modify generated code directly
-
Test your changes
python test_install.py # Run any other relevant tests -
Format and lint
black . && isort . ruff check --fix .
-
Commit your changes
git add . git commit -m "Add examples for subscription management"
-
Push to your fork
git push origin feature/add-new-examples
-
Create a Pull Request
- Go to GitHub and create a PR
- Describe your changes
- Link any related issues
Use conventional commit format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat:New featurefix:Bug fixdocs:Documentation changesstyle:Formatting, missing semi-colons, etc.refactor:Code refactoringtest:Adding testschore:Maintenance
Examples:
git commit -m "docs: add async usage examples to README"
git commit -m "feat: add helper functions for common operations"
git commit -m "fix: correct get_user_balance usage in examples"
git commit -m "chore: update dependencies to latest versions"Before submitting a PR:
- Changes are tested and working
- Code is formatted with black and isort
- No linting errors from ruff
- Documentation is updated (if applicable)
- Examples are updated (if applicable)
- Commit messages follow guidelines
- No generated files are manually modified
- PR description explains the changes
- Input:
openapi.jsonspecification - Processing: docsalot reads the spec and generates:
- Client classes for each endpoint group
- Pydantic models for all request/response types
- Type-safe methods with proper signatures
- Async variants of all methods
- Output: Complete Python SDK
User Code
↓
GatewayzApi Client
↓
Module Client (e.g., ChatClient)
↓
RawClient (HTTP layer)
↓
ClientWrapper (adds auth, headers)
↓
HttpClient (httpx wrapper)
↓
HTTP Request → API
# Token is passed during initialization
client = GatewayzApi(token="sk-xxx", base_url="...")
# ClientWrapper wraps the token
wrapper = SyncClientWrapper(token="sk-xxx", ...)
# HttpClient adds it to every request
headers = {"Authorization": f"Bearer {token}"}API returns error
↓
HttpClient receives response
↓
ApiError raised (if status >= 400)
↓
Specific error type (e.g., UnprocessableEntityError)
↓
User's except block
All types are Pydantic v2 models:
# types/message.py (generated)
class Message(pydantic.BaseModel):
role: str
content: str
# Automatic validation
# Serialization to JSON
# IDE autocomplete support# Reinstall in editable mode
pip uninstall gatewayz -y
pip install -e .If you see "types" module conflicts:
- This is due to the
types/directory conflicting with Python's built-intypesmodule - The SDK handles this, but running Python from the SDK directory can cause issues
- Solution: Always run tests from outside the SDK directory or use absolute imports
If SDK regeneration fails:
# Check docsalot version
docsalot --version
# Update docsalot
npm update -g docsalot-api
# Validate OpenAPI spec
docsalot check- Issues: Open an issue on GitHub
- Questions: Start a discussion in GitHub Discussions
- Security: Email security@gatewayz.ai for security issues
- docsalot Docs: https://docs.docsalot.dev
By contributing, you agree that your contributions will be licensed under the same license as the project.
Thank you for contributing to Gatewayz Python SDK! 🚀