Python CLI SDK for Timer Cloud API
Project description
Timer Client
Python CLI SDK for Timer Cloud API. This package provides both synchronous and asynchronous clients for interacting with the Timer API.
Features
- Sync Client:
TimerSyncClientfor synchronous operations - Async Client:
TimerAsyncClientfor asynchronous operations - Environment Configuration: Configure via environment variables
- Type Hints: Full type annotation support
- Exception Handling: Custom exceptions for different error types
- Code Formatting: Enforced by
blackandisort
Installation
From PyPI (when published)
pip install timer_client
From Source
git clone https://github.com/TimechoLab/Timer-Client.git
cd Timer-Client
pip install -e .
With Optional Dependencies
# For sync client only
pip install timer_client[sync]
# For async client only
pip install timer_client[async]
# For all features
pip install timer_client[all]
# For development
pip install timer_client[dev]
Quick Start
Configuration
The client can be configured in multiple ways:
1. Environment Variables (Recommended)
export TIMER_CLIENT_API_KEY="your-api-key"
export TIMER_CLIENT_BASE_URL="https://api.timer.cloud" # Optional
export TIMER_CLIENT_TIMEOUT="30" # Optional, in seconds
from timer_client import TimerSyncClient
# API key will be read from TIMER_CLIENT_API_KEY environment variable
client = TimerSyncClient()
2. Explicit Parameters
from timer_client import TimerSyncClient
client = TimerSyncClient(
api_key="your-api-key",
base_url="https://api.timer.cloud/v1",
timeout=30.0,
)
3. Configuration Object
from timer_client import TimerSyncClient, ClientConfig
config = ClientConfig(
api_key="your-api-key",
base_url="https://api.timer.cloud/v1",
timeout=30.0,
)
client = TimerSyncClient(config=config)
Synchronous Usage
from timer_client import TimerSyncClient
# Using context manager (recommended)
with TimerSyncClient(api_key="your-api-key") as client:
response = client.hello_timer(name="World")
print(response)
# Or manually manage the client
client = TimerSyncClient(api_key="your-api-key")
try:
response = client.hello_timer(name="World")
print(response)
finally:
client.close()
Asynchronous Usage
import asyncio
from timer_client import TimerAsyncClient
async def main():
# Using async context manager (recommended)
async with TimerAsyncClient(api_key="your-api-key") as client:
response = await client.hello_timer(name="World")
print(response)
# Run the async function
asyncio.run(main())
API Reference
Clients
TimerSyncClient
Synchronous client for Timer API.
client = TimerSyncClient(
api_key=None, # API key or read from TIMER_CLIENT_API_KEY env var
base_url=None, # Base URL or read from TIMER_CLIENT_BASE_URL env var
timeout=None, # Timeout or read from TIMER_CLIENT_TIMEOUT env var
config=None, # Pre-built ClientConfig object
)
# Methods
response = client.hello_timer(name=None) # Hello API endpoint
client.close() # Close the client session
TimerAsyncClient
Asynchronous client for Timer API.
client = TimerAsyncClient(
api_key=None, # API key or read from TIMER_CLIENT_API_KEY env var
base_url=None, # Base URL or read from TIMER_CLIENT_BASE_URL env var
timeout=None, # Timeout or read from TIMER_CLIENT_TIMEOUT env var
config=None, # Pre-built ClientConfig object
)
# Methods
response = await client.hello_timer(name=None) # Hello API endpoint
await client.close() # Close the client session
Exceptions
| Exception | Description |
|---|---|
TimerClientError |
Base exception for all client errors |
AuthenticationError |
Raised when API key is missing or invalid |
APIError |
Raised when API returns an error response |
ConnectionError |
Raised when connection to API fails |
TimeoutError |
Raised when request times out |
ValidationError |
Raised when request validation fails |
Environment Variables
| Variable | Description | Default |
|---|---|---|
TIMER_CLIENT_API_KEY |
API key for authentication | Required |
TIMER_CLIENT_BASE_URL |
Base URL for the API | https://api.timer.cloud |
TIMER_CLIENT_TIMEOUT |
Request timeout in seconds | 30.0 |
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/TimechoLab/Timer-Client.git
cd Timer-Client
# Install in development mode with all dependencies
pip install -e ".[dev]"
Code Formatting
This project uses black and isort for code formatting.
# Format all code
./scripts/format.sh
# Check formatting without making changes
./scripts/lint.sh
Configuration:
- Line length: 100 characters
- Target Python versions: 3.9, 3.10, 3.11, 3.12
- Import style: Black-compatible (profile = "black")
Configuration is defined in pyproject.toml under [tool.black] and [tool.isort].
Pre-commit Hooks (Recommended)
Setup pre-commit hooks to automatically format code before each commit:
# Install pre-commit hooks
./scripts/setup_hooks.sh
# Or manually:
pip install pre-commit
pre-commit install
This will automatically run black and isort on your staged files before each commit.
To run hooks manually on all files:
pre-commit run --all-files
To skip hooks for a specific commit:
git commit --no-verify
Running Tests
# Run all tests
./scripts/run_tests.sh
# Or with pytest directly
pytest tests/ -v
Building Package
# Build wheel and source distribution
./scripts/build.sh
Publishing to PyPI
# 1. Build the package
./scripts/build.sh
# 2. Check the package
./scripts/check.sh
# 3. Publish to TestPyPI (for testing)
./scripts/publish_test.sh
# 4. Publish to PyPI (production)
./scripts/publish.sh
Extending the Client
This project uses a Mixin pattern to share API method definitions between sync and async clients.
Architecture
TimerClientMixin (timer_client/base.py)
↓ defines API methods (hello_timer, etc.)
↓ calls self._request(method, path, **kwargs)
TimerSyncClient ──→ implements _request() synchronously
TimerAsyncClient ──→ implements _request() asynchronously
Adding New API Endpoints
Important: Only add API methods to TimerClientMixin in timer_client/base.py:
# timer_client/base.py
class TimerClientMixin:
# ... existing methods ...
def get_timer(self, timer_id: str) -> Dict[str, Any]:
"""Get a timer by ID."""
return self._request("GET", f"/timers/{timer_id}")
def create_timer(self, name: str, duration: int) -> Dict[str, Any]:
"""Create a new timer."""
data = {"name": name, "duration": duration}
return self._request("POST", "/timers", json=data)
That's it! The method is automatically available in both TimerSyncClient and TimerAsyncClient:
# Sync usage
with TimerSyncClient(api_key="key") as client:
timer = client.get_timer("123") # Works!
# Async usage
async with TimerAsyncClient(api_key="key") as client:
timer = await client.get_timer("123") # Also works!
How It Works
TimerClientMixindefines business logic (API methods)TimerSyncClientimplements_request()usingrequests(sync)TimerAsyncClientimplements_request()usingaiohttp(async)- Both clients inherit from
TimerClientMixin, getting all API methods
Adding Tests
Add tests in tests/test_client_it.py:
@patch("timer_client.client.requests.Session.request")
def test_get_timer_success(self, mock_request):
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"id": "123", "name": "My Timer"}
mock_response.reason = "OK"
mock_request.return_value = mock_response
client = TimerSyncClient(api_key=self.api_key)
response = client.get_timer("123")
self.assertEqual(response["id"], "123")
See timer_client/base.py for a detailed template with more examples.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and feature requests, please use the GitHub Issues page.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file timer_client-0.1.2.tar.gz.
File metadata
- Download URL: timer_client-0.1.2.tar.gz
- Upload date:
- Size: 22.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7aa48bb11e9a6d819581f2100d7ec2a58becec1f1ccce3c422e9b725389eabba
|
|
| MD5 |
df249a20cf8e2d19f4d5b0f86fcb5f4f
|
|
| BLAKE2b-256 |
46c5fe80895d711891e4691f03ffa33cc505f4684144b6367977cbaef33d4296
|
File details
Details for the file timer_client-0.1.2-py3-none-any.whl.
File metadata
- Download URL: timer_client-0.1.2-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c247f982774010a73049d2c4edfbe74ed5f2c314736b04ac0fe9a948a97cd40c
|
|
| MD5 |
c61f5db6082a3283089be21f694f631f
|
|
| BLAKE2b-256 |
d56b8ed0c8cd925ec310fb9014641d01d5948745e610ed1e2aee3b34fb0bfd5e
|