A fully type-hinted Python client for the Token Bowl Chat Server API with sync and async support
Project description
Token Bowl Chat
A fully type-hinted Python client for the Token Bowl Chat Server API. Built with modern Python best practices and comprehensive error handling.
Features
- Full Type Safety: Complete type hints for all APIs using Pydantic models
- Sync & Async Support: Both synchronous and asynchronous client implementations
- Comprehensive Error Handling: Specific exceptions for different error types
- Auto-generated from OpenAPI: Models derived directly from the OpenAPI specification
- Well Tested: High test coverage with pytest
- Modern Python: Supports Python 3.10+
- Developer Friendly: Context manager support, detailed docstrings
Installation
For users
Using uv (recommended, fastest):
uv pip install token-bowl-chat
Using pip:
pip install token-bowl-chat
For development
Using uv (recommended):
# Clone the repository
git clone https://github.com/RobSpectre/token-bowl-chat.git
cd token-bowl-chat
# Create virtual environment and install with dev dependencies
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip install -e ".[dev]"
Using traditional tools:
# Clone the repository
git clone https://github.com/RobSpectre/token-bowl-chat.git
cd token-bowl-chat
# Create a virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in editable mode with development dependencies
pip install -e ".[dev]"
Quick Start
Synchronous Client
from token_bowl_chat import TokenBowlClient
# Create a client instance
client = TokenBowlClient(base_url="http://localhost:8000")
# Register a new user
response = client.register(username="alice")
print(f"Registered with API key: {response.api_key}")
# Set the API key for authenticated requests
client.api_key = response.api_key
# Send a message to the room
message = client.send_message("Hello, everyone!")
print(f"Sent message: {message.id}")
# Get recent messages
messages = client.get_messages(limit=10)
for msg in messages.messages:
print(f"{msg.from_username}: {msg.content}")
# Send a direct message
dm = client.send_message("Hi Bob!", to_username="bob")
# Get all users
users = client.get_users()
print(f"Users: {users}")
# Get online users
online = client.get_online_users()
print(f"Online: {online}")
Asynchronous Client
import asyncio
from token_bowl_chat import AsyncTokenBowlClient
async def main():
# Use as async context manager
async with AsyncTokenBowlClient(base_url="http://localhost:8000") as client:
# Register
response = await client.register(username="alice")
client.api_key = response.api_key
# Send message
message = await client.send_message("Hello, async world!")
# Get messages
messages = await client.get_messages(limit=10)
for msg in messages.messages:
print(f"{msg.from_username}: {msg.content}")
asyncio.run(main())
Context Manager Support
# Synchronous
with TokenBowlClient(base_url="http://localhost:8000") as client:
client.api_key = "your-api-key"
client.send_message("Hello!")
# Asynchronous
async with AsyncTokenBowlClient(base_url="http://localhost:8000") as client:
client.api_key = "your-api-key"
await client.send_message("Hello!")
API Reference
Client Methods
register(username: str, webhook_url: Optional[str] = None) -> UserRegistrationResponse
Register a new user and receive an API key.
Parameters:
username: Username to register (1-50 characters)webhook_url: Optional webhook URL for notifications
Returns: UserRegistrationResponse with username, api_key, and webhook_url
Raises:
ConflictError: Username already existsValidationError: Invalid input
send_message(content: str, to_username: Optional[str] = None) -> MessageResponse
Send a message to the room or as a direct message.
Parameters:
content: Message content (1-10000 characters)to_username: Optional recipient for direct messages
Returns: MessageResponse with message details
Requires: Authentication
get_messages(limit: int = 50, offset: int = 0, since: Optional[str] = None) -> PaginatedMessagesResponse
Get recent room messages with pagination.
Parameters:
limit: Maximum messages to return (default: 50)offset: Number of messages to skip (default: 0)since: ISO timestamp to get messages after
Returns: PaginatedMessagesResponse with messages and pagination metadata
Requires: Authentication
get_direct_messages(limit: int = 50, offset: int = 0, since: Optional[str] = None) -> PaginatedMessagesResponse
Get direct messages for the current user.
Parameters: Same as get_messages()
Returns: PaginatedMessagesResponse with direct messages
Requires: Authentication
get_users() -> list[str]
Get list of all registered usernames.
Returns: List of usernames
Requires: Authentication
get_online_users() -> list[str]
Get list of currently online users.
Returns: List of online usernames
Requires: Authentication
health_check() -> dict[str, str]
Check server health status.
Returns: Health status dictionary
Models
All models are fully type-hinted Pydantic models:
UserRegistration: User registration requestUserRegistrationResponse: Registration response with API keySendMessageRequest: Message sending requestMessageResponse: Message detailsMessageType: Enum (ROOM, DIRECT, SYSTEM)PaginatedMessagesResponse: Paginated message listPaginationMetadata: Pagination information
Exceptions
All exceptions inherit from TokenBowlError:
AuthenticationError: Invalid or missing API key (401)NotFoundError: Resource not found (404)ConflictError: Conflict, e.g., duplicate username (409)ValidationError: Request validation failed (422)RateLimitError: Rate limit exceeded (429)ServerError: Server error (5xx)NetworkError: Network connectivity issueTimeoutError: Request timeout
Error Handling
from token_bowl_chat import (
TokenBowlClient,
AuthenticationError,
ConflictError,
ValidationError,
)
client = TokenBowlClient(base_url="http://localhost:8000")
try:
response = client.register(username="alice")
except ConflictError:
print("Username already taken!")
except ValidationError as e:
print(f"Invalid input: {e.message}")
try:
client.send_message("Hello!")
except AuthenticationError:
print("Please set API key first!")
Development
Running tests
pytest
Running tests with coverage
pytest --cov=token_bowl_chat --cov-report=html
Linting and formatting
# Check code quality
ruff check .
# Format code
ruff format .
# Type checking
mypy src
Auto-fix issues
# Fix auto-fixable linting issues
ruff check --fix .
Project Structure
token-bowl-chat/
├── src/
│ └── token_bowl_chat/
│ ├── __init__.py
│ └── py.typed
├── tests/
│ └── __init__.py
├── docs/
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Project details
Release history Release notifications | RSS feed
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 token_bowl_chat-0.1.1.tar.gz.
File metadata
- Download URL: token_bowl_chat-0.1.1.tar.gz
- Upload date:
- Size: 57.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d049007d6fd1431998613d6047a7a4fab55f7404214238f7b13e4fa9f78be88
|
|
| MD5 |
97d0f4d6476db83b0e17ec3d777b0ff8
|
|
| BLAKE2b-256 |
44643a199af343afc1b2046b78740ba682f1e49156bd17ae363157a61ff30a73
|
Provenance
The following attestation bundles were made for token_bowl_chat-0.1.1.tar.gz:
Publisher:
publish.yml on RobSpectre/token-bowl-chat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
token_bowl_chat-0.1.1.tar.gz -
Subject digest:
9d049007d6fd1431998613d6047a7a4fab55f7404214238f7b13e4fa9f78be88 - Sigstore transparency entry: 619791609
- Sigstore integration time:
-
Permalink:
RobSpectre/token-bowl-chat@c861bdeffac7a8c775ead71bfa9ce11c3a0c2287 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/RobSpectre
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c861bdeffac7a8c775ead71bfa9ce11c3a0c2287 -
Trigger Event:
release
-
Statement type:
File details
Details for the file token_bowl_chat-0.1.1-py3-none-any.whl.
File metadata
- Download URL: token_bowl_chat-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88d925323999bce4f821d78b04bce3cc00a74ef55eeae15fa34039484739c5c4
|
|
| MD5 |
6a005e984b2e02c5df49532c6793661b
|
|
| BLAKE2b-256 |
0785052ae6d267e839dacfeb5f2ead312585b7794505f4652ae6f1f1e621fb6e
|
Provenance
The following attestation bundles were made for token_bowl_chat-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on RobSpectre/token-bowl-chat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
token_bowl_chat-0.1.1-py3-none-any.whl -
Subject digest:
88d925323999bce4f821d78b04bce3cc00a74ef55eeae15fa34039484739c5c4 - Sigstore transparency entry: 619791654
- Sigstore integration time:
-
Permalink:
RobSpectre/token-bowl-chat@c861bdeffac7a8c775ead71bfa9ce11c3a0c2287 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/RobSpectre
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c861bdeffac7a8c775ead71bfa9ce11c3a0c2287 -
Trigger Event:
release
-
Statement type: