Skip to main content

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: TimerSyncClient for synchronous operations
  • Async Client: TimerAsyncClient for 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 black and isort

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

  1. TimerClientMixin defines business logic (API methods)
  2. TimerSyncClient implements _request() using requests (sync)
  3. TimerAsyncClient implements _request() using aiohttp (async)
  4. 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

timer_client-0.1.2.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

timer_client-0.1.2-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

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

Hashes for timer_client-0.1.2.tar.gz
Algorithm Hash digest
SHA256 7aa48bb11e9a6d819581f2100d7ec2a58becec1f1ccce3c422e9b725389eabba
MD5 df249a20cf8e2d19f4d5b0f86fcb5f4f
BLAKE2b-256 46c5fe80895d711891e4691f03ffa33cc505f4684144b6367977cbaef33d4296

See more details on using hashes here.

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

Hashes for timer_client-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c247f982774010a73049d2c4edfbe74ed5f2c314736b04ac0fe9a948a97cd40c
MD5 c61f5db6082a3283089be21f694f631f
BLAKE2b-256 d56b8ed0c8cd925ec310fb9014641d01d5948745e610ed1e2aee3b34fb0bfd5e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page