# Tabroom Python Client

A type-safe Python client library for the [Tabroom.com](https://www.tabroom.com) API. Built with Pydantic for data validation and Requests for reliable HTTP requests.

## Features

- **Type-safe**: All API responses are validated with Pydantic models
- **Organized**: Resources grouped by domain (user, tournaments, tabulation, etc.)
- **Easy to use**: Fluent API with method chaining for nested resources
- **Well-documented**: Comprehensive docstrings and examples
- **Error handling**: Custom exceptions for different error types
- **Context manager support**: Automatic connection cleanup

## Installation

```bash
pip install tabroom
```

## Quick Start

```python
from tabroom import TabroomClient

# Initialize the client
client = TabroomClient(
    username="your_email@example.com",
    password="your_password"
)

# Get your profile
profile = client.user.get_profile()
print(f"Logged in as: {profile.first} {profile.last}")

# Search for tournaments
tournaments = client.public.search_tournaments("future", "TOC")
print(f"Found {len(tournaments)} tournaments")

# Don't forget to close the connection
client.close()

# Or use as context manager (auto-closes)
with TabroomClient(username="user", password="pass") as client:
    profile = client.user.get_profile()
```

## API Resources

The client organizes API endpoints into logical resource groups:

### User (`client.user`)
- `get_profile()` - Get your user profile
- `get_profile_by_id(person_id)` - Get another user's profile

### Public (`client.public`)
- `search_tournaments(time, search_string, circuit_id=None)` - Search tournaments
- `get_upcoming_tournaments(circuit=None)` - List upcoming tournaments
- `get_ads()` - Get front page advertisements
- `get_tournament_by_id(tourn_id)` - Get tournament by ID
- `get_tournament_by_webname(webname)` - Get tournament by webname

### Tab (`client.tab`)
Tournament tabulation operations with nested resources:

```python
# Tournament-level operations
client.tab.tournament(tourn_id).get_dashboard()
client.tab.tournament(tourn_id).get_attendance()
client.tab.tournament(tourn_id).mark_attendance(data)
client.tab.tournament(tourn_id).get_category_checkin(category_id)

# Round-level operations
client.tab.tournament(tourn_id).round(round_id).get_dashboard()
client.tab.tournament(tourn_id).round(round_id).get_attendance()
client.tab.tournament(tourn_id).round(round_id).mark_attendance(data)

# Timeslot-level operations
client.tab.tournament(tourn_id).timeslot(timeslot_id).get_dashboard()
client.tab.tournament(tourn_id).timeslot(timeslot_id).get_attendance()
```

### Access (`client.access`)
Permission management with hierarchical access control:

```python
# Tournament-level access
client.access.tournament(tourn_id).grant(person_id, permissions)
client.access.tournament(tourn_id).revoke(person_id)

# Event-level access
client.access.tournament(tourn_id).event(event_id).grant(person_id, permissions)
client.access.tournament(tourn_id).event(event_id).revoke(person_id)

# Category-level access
client.access.tournament(tourn_id).category(category_id).grant(person_id, permissions)
client.access.tournament(tourn_id).category(category_id).revoke(person_id)
```

### Caselist (`client.caselist`)
- `get_students(person_id)` - Get students for a person
- `get_rounds(person_id)` - Get rounds for a person
- `get_chapters(person_id)` - Get chapters for a person
- `create_link(data)` - Create a caselist link

### NSDA (`client.nsda`)
- `get_history(nsda_id)` - Get NSDA membership history

### Share (`client.share`)
- `send_share_file(data)` - Send document to docchain

### Payment (`client.payment`)
- `process_paypal(data)` - Process PayPal payment
- `process_authorize(data)` - Process Authorize.net payment

### System (`client.system`)
- `get_status()` - Check API status
- `post_status(data)` - Check API status via POST

### Extra (`client.extra`)
Additional operations not in the official API spec:

```python
from tabroom import DebateEvent

# Get TOC bid information for a specific event
bids = client.extra.get_bids(DebateEvent.POLICY, year="2025")
for bid in bids:
    print(f"{bid['school']} - {bid['entry']}: {bid['bids']} bids")
```

#### Available Debate Events
The `DebateEvent` enum provides type-safe event selection:
- `DebateEvent.LINCOLN_DOUGLAS`
- `DebateEvent.POLICY`
- `DebateEvent.PUBLIC_FORUM`
- `DebateEvent.WORLDS_SCHOOLS`
- `DebateEvent.DRAMATIC_INTERP`
- `DebateEvent.DUO_INTERP`
- `DebateEvent.EXTEMP`
- `DebateEvent.HUMOROUS_INTERP`
- `DebateEvent.INFORMATIVE_SPEAKING`
- `DebateEvent.ORAL_INTERP_OF_LITERATURE`
- `DebateEvent.ORIGINAL_ORATORY`
- `DebateEvent.PROGRAM_ORAL_INTERP`
- `DebateEvent.CONGRESSIONAL_DEBATE`

## Error Handling

The client provides specific exception types for different errors:

```python
from tabroom import (
    TabroomError,           # Base exception
    TabroomAuthError,       # 401/403 errors
    TabroomNotFoundError,   # 404 errors
    TabroomValidationError, # 422 errors
    TabroomServerError,     # 5xx errors
    TabroomAPIError,        # Other API errors
)

try:
    profile = client.user.get_profile()
except TabroomAuthError:
    print("Authentication failed - check credentials")
except TabroomNotFoundError:
    print("Resource not found")
except TabroomError as e:
    print(f"API error: {e.message}")
```

## Data Models

All API responses are parsed into Pydantic models for type safety:

- `Person` - User profile data
- `Session` - Login session information
- `Invite` - Tournament invitation/details
- `Event` - Tournament event
- `Round` - Tournament round
- `Search` - Search result
- `Student` - Student information
- `Chapter` - Chapter/school chapter
- `Ad` - Advertisement
- And more...

## Examples

See the [`examples/`](examples/) directory for comprehensive usage examples:

- [`basic_usage.py`](examples/basic_usage.py) - Getting started
- [`tournament_management.py`](examples/tournament_management.py) - Tabulation operations
- [`access_control.py`](examples/access_control.py) - Permission management
- [`caselist_nsda.py`](examples/caselist_nsda.py) - Caselist and NSDA integration
- [`error_handling.py`](examples/error_handling.py) - Error handling patterns

## Development

```bash
# Install with dev dependencies
uv pip install -e ".[dev]"

# Run type checking
mypy tabroom

# Run tests
pytest
```

## Project Structure

```
tabroom-python/
├── src/tabroom/
│   ├── __init__.py          # Main TabroomClient
│   ├── client.py            # Base HTTP client
│   ├── auth.py              # Authentication
│   ├── exceptions.py        # Custom exceptions
│   ├── types.py             # Type definitions (DebateEvent enum)
│   ├── models/              # Pydantic models
│   │   ├── common.py
│   │   ├── auth.py
│   │   ├── user.py
│   │   ├── tournament.py
│   │   ├── school.py
│   │   ├── caselist.py
│   │   └── share.py
│   └── resources/           # API resource groups
│       ├── user.py
│       ├── public.py
│       ├── tab.py
│       ├── access.py
│       ├── caselist.py
│       ├── nsda.py
│       ├── share.py
│       ├── payment.py
│       ├── system.py
│       └── extra.py
├── examples/                # Usage examples
└── tests/                   # Test suite
```

## API Documentation

This client is based on the Tabroom API v1. For detailed API documentation, visit the [Tabroom API docs](https://api.tabroom.com/v1/docs).

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
