Type-safe Python client for Snail Orbit project management system with read operations and issue management
Project description
Snail Orbit Python Client
Type-safe Python client for the Snail Orbit project management API.
Installation
uv add snail-orbit-client
# or
pip install snail-orbit-client
Usage
Sync Client
from snail_orbit_client import SnailOrbitClient
client = SnailOrbitClient(
base_url='https://your-snail-orbit.example.com',
token='your-api-token'
)
# Get current user
profile = client.auth.get_profile()
print(f'Logged in as: {profile.name}')
# List issues
for issue in client.issues.list(q='priority:high and status:open'):
print(f'{issue.id_readable}: {issue.subject}')
# Get specific issue
issue = client.issues.get('issue-id')
# Access custom fields
priority_field = issue.fields.get('priority')
if priority_field:
print(f'Priority: {priority_field.value}')
Async Client
import asyncio
from snail_orbit_client import SnailOrbitAsyncClient
async def main():
async with SnailOrbitAsyncClient(
base_url='https://your-snail-orbit.example.com',
token='your-api-token'
) as client:
profile = await client.auth.get_profile()
async for issue in client.issues.list(q='status:open'):
print(f'{issue.id_readable}: {issue.subject}')
asyncio.run(main())
API Resources
client.auth # Authentication and profile
client.users # User operations
client.projects # Project operations
client.issues # Issue CRUD operations
client.custom_fields # Custom field definitions
client.activity # Activity tracking
Issues
client.issues.list(q=None, search=None) # List/query issues
client.issues.get(issue_id) # Get by ID
client.issues.get_by_readable_id(readable_id) # Get by readable ID (e.g., 'PRJ-123')
client.issues.create(issue_data) # Create issue
client.issues.update(issue_id, issue_data) # Update issue
# Comments
client.issues.get_comments(issue_id)
client.issues.create_comment(issue_id, comment_data)
client.issues.update_comment(issue_id, comment_id, comment_data)
client.issues.delete_comment(issue_id, comment_id)
# Tags
client.issues.add_tag(issue_id, tag_id)
client.issues.remove_tag(issue_id, tag_id)
# Attachments
client.issues.list_attachments(issue_id) # List attachments
client.issues.add_attachment(issue_id, attachment_input) # Add attachment
client.issues.remove_attachment(issue_id, attachment_id) # Remove attachment
client.issues.download_attachment(issue_id, attachment_id) # Stream download
client.issues.upload_and_attach(issue_id, file) # Upload and attach in one call
File Uploads
# Upload a file (loads into memory)
result = client.upload_file(b'content', filename='doc.pdf')
result = client.upload_file('/path/to/file.pdf')
result = client.upload_file(open('file.pdf', 'rb'))
# Streaming upload (memory-efficient for large files)
def read_chunks():
with open('large_file.zip', 'rb') as f:
while chunk := f.read(8192):
yield chunk
result = client.stream_upload(read_chunks(), 'large_file.zip')
# Attach uploaded file to issue
from snail_orbit_client.models import IssueAttachmentInput
client.issues.add_attachment(issue_id, IssueAttachmentInput(id=result.id))
# Or use the convenience method
attachment = client.issues.upload_and_attach(issue_id, '/path/to/file.pdf')
Downloading Attachments
# Stream to file (memory-efficient)
with open('output.pdf', 'wb') as f:
for chunk in client.issues.download_attachment(issue_id, attachment_id):
f.write(chunk)
# Collect in memory (if you need bytes)
content = b''.join(client.issues.download_attachment(issue_id, attachment_id))
# Async streaming to file
async with aiofiles.open('output.pdf', 'wb') as f:
async for chunk in client.issues.download_attachment(issue_id, attachment_id):
await f.write(chunk)
Search and Filtering
# Issue query language
client.issues.list(q='priority:high and status:open')
client.issues.list(q='assignee:me and project:myproject')
# Text search
client.issues.list(search='database bug')
# Users and projects use filter parameter
client.users.list(search='john', filter='is_active___eq:true')
client.projects.list(filter='created_at___gte:2024-01-01')
Configuration
from snail_orbit_client import SnailOrbitClient, ClientConfig
config = ClientConfig(
timeout=30.0, # Request timeout in seconds
max_retries=3, # Maximum retry attempts
retry_delay=1.0, # Base delay between retries
)
client = SnailOrbitClient(
base_url='https://your-snail-orbit.example.com',
token='your-token',
config=config
)
JWT Authentication
# JWT signing with service credentials
client = SnailOrbitClient(
base_url='https://api.snail-orbit.com',
token=('key-id', 'secret', 'user-id')
)
Error Handling
from snail_orbit_client.exceptions import (
SnailOrbitError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
)
try:
issue = client.issues.get('invalid-id')
except NotFoundError:
print('Issue not found')
except AuthenticationError:
print('Authentication failed')
except ValidationError as e:
print(f'Validation errors: {e.validation_errors}')
except RateLimitError as e:
print(f'Rate limited, retry after {e.retry_after}s')
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
No source distribution files available for this release.See tutorial on generating distribution archives.
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 snail_orbit_client-0.13.2-py3-none-any.whl.
File metadata
- Download URL: snail_orbit_client-0.13.2-py3-none-any.whl
- Upload date:
- Size: 40.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1068257681eaa35c1339319895f02add666b16d7b980080303c68c9deced051
|
|
| MD5 |
979cc99f35701af778b80cb057971429
|
|
| BLAKE2b-256 |
4c95ce379d5746aaf60dfb25a8e9c21d2b86fda27e22ac3c7fa1c93c24e1ca17
|