Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.13"

- name: Set up uv
uses: astral-sh/setup-uv@v3
Expand Down
14 changes: 12 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,34 @@ repos:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- id: debug-statements

- repo: https://github.com/psf/black
rev: 24.1.1
rev: 25.9.0
hooks:
- id: black
language_version: python3
exclude: ^src/_vendor/kinexon_client/

- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
args: ["--profile", "black", "--line-length", "88"]
include: src/
exclude: ^src/_vendor/kinexon_client/

- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
args: ["--max-line-length=88", "--extend-ignore=E203,W503,D200,D103"]
exclude: ^src/_vendor/kinexon_client/

- repo: https://github.com/kynan/nbstripout
rev: 0.7.1
hooks:
- id: nbstripout
name: Strip output from Jupyter notebooks
282 changes: 61 additions & 221 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,261 +1,101 @@
# Kinexon Handball API

A Python wrapper for accessing and processing Kinexon Handball data. This library provides a clean, type-safe interface to interact with the Kinexon API for handball analytics and position data.
A Python wrapper for Kinexon Handball (DataCore) that performs session + main authentication, injects an API key, and wraps a generated OpenAPI client. It provides simple helpers for common handball endpoints (metrics/events, sessions, players, position exports).

## Features

- 🔐 **Secure Authentication**: Dual-layer authentication system with session and main login
- 📊 **Data Export**: Export position data, metrics, and events in various formats
- 🏃 **Team Management**: Access team IDs and session information
- 🛡️ **Error Handling**: Comprehensive error handling with custom exceptions
- ⚡ **Performance**: Built-in retry logic and connection pooling
- 🧪 **Testing**: Full test suite with integration and unit tests
- 📦 **Type Safety**: Full type hints and Pydantic validation
## Requirements
- Python 3.12+
- Package manager uv
- Valid Kinexon credentials (session and main usernames/passwords, API key, endpoints)

## Installation

### Prerequisites

- Python 3.12 or higher
- `uv` as package manager
- Valid Kinexon API credentials


### Install

```bash
git clone https://github.com/mad4ms/KinexonHandballAPI.git
cd KinexonHandballAPI
uv pip install -e .
```

## Quick Start

### Basic Usage

```python
from kinexon_handball_api.client import KinexonClient
from kinexon_handball_api.config import Settings

# Initialize settings from environment variables
settings = Settings()

# Create client instance
client = KinexonClient(settings)

# Get available teams
# Fetches a hardcoded DEFAULT_TEAM_IDS specified in fetchers.py
teams = client.get_team_ids()
print(f"Available teams: {len(teams)}")

# Get session IDs for a team
sessions = client.get_session_ids(
team_id=13, # Füchse Berlin
start="2025-01-01",
end="2025-01-31"
)

# Get position data
position_data = client.get_position_data_by_session_id("session_123")
```

### Environment Configuration

Create a `.env` file with your Kinexon credentials:
## Configuration
Provide credentials via environment variables. A `.env` file is supported (python-dotenv).

Example `.env`:
```env
# Session Authentication
# API key header
API_KEY_KINEXON=your_api_key

# Session auth (step 1)
USERNAME_KINEXON_SESSION=your_session_username
PASSWORD_KINEXON_SESSION=your_session_password
ENDPOINT_KINEXON_SESSION=https://api.kinexon.com/session
ENDPOINT_KINEXON_SESSION=https://hbl-cloud.kinexon.com/api/session

# Main Authentication
# Main auth (step 2)
USERNAME_KINEXON_MAIN=your_main_username
PASSWORD_KINEXON_MAIN=your_main_password
ENDPOINT_KINEXON_MAIN=https://api.kinexon.com/login

# API Configuration
ENDPOINT_KINEXON_API=https://api.kinexon.com/api
API_KEY_KINEXON=your_api_key
```

## Team Configuration

Team IDs are stored in `config/teams.yaml` and organized by season. To update team IDs for a new season:

1. Go to Kinexon Cloud web app
2. Click "Team" selection dropdown
3. Click user → profile
4. Switch to "Teams" tab
5. Copy IDs next to team names
6. Update `config/teams.yaml` with new season data

The current season is automatically used, or you can specify a season:
```python
# Get current season teams
teams = client.get_team_ids()

# Get specific season teams
teams_2024 = client.get_team_ids("2024-25")
```
```

## Development

### Setup Development Environment

```bash
# Clone repository
git clone https://github.com/mad4ms/KinexonHandballAPI.git
cd KinexonHandballAPI

# Install development dependencies
uv pip install -e ".[dev]"

# Install pre-commit hooks (optional but recommended)
uv pip install pre-commit
pre-commit install
```

### Running Tests

```bash
# Unit tests
pytest tests/test_client.py
ENDPOINT_KINEXON_MAIN=https://hbl-cloud.kinexon.com/api

# Integration tests (requires live API access)
pytest tests/test_integration_*.py -m integration

# All tests
pytest
# Base URL for API client
# Used as base_url when constructing the client
ENDPOINT_KINEXON_API=https://hbl-cloud.kinexon.com/api
```

## Examples

### Workflow

## Quick Start
```python
from dotenv import load_dotenv
import os
from datetime import datetime, timedelta
from kinexon_handball_api.client import KinexonClient
from kinexon_handball_api.config import Settings
from kinexon_handball_api.handball import HandballAPI
from kinexon_handball_api.fetchers import fetch_team_ids

# Load environment variables
from dotenv import load_dotenv
load_dotenv()

# Initialize client
settings = Settings()
client = KinexonClient(settings)

# Get all teams (current season)
teams = client.get_team_ids()
print(f"Found {len(teams)} teams")

# Get teams for specific season
teams_2024 = client.get_team_ids("2024-25")
print(f"Found {len(teams_2024)} teams in 2024-25 season")

# Get sessions for a specific team
team_id = 13 # Füchse Berlin

# Fetch any games of the last 30 days
end_date = datetime.now()
start_date = end_date - timedelta(days=30)

# Fetch session ids of the last 30 days
sessions = client.get_session_ids(
team_id=team_id,
start=start_date.strftime("%Y-%m-%d"),
end=end_date.strftime("%Y-%m-%d")
api = HandballAPI(
base_url=os.getenv("ENDPOINT_KINEXON_API", "https://hbl-cloud.kinexon.com/api"),
api_key=os.getenv("API_KEY_KINEXON", ""),
username_basic=os.getenv("USERNAME_KINEXON_SESSION", ""),
password_basic=os.getenv("PASSWORD_KINEXON_SESSION", ""),
username_main=os.getenv("USERNAME_KINEXON_MAIN", ""),
password_main=os.getenv("PASSWORD_KINEXON_MAIN", ""),
endpoint_session=os.getenv("ENDPOINT_KINEXON_SESSION", "https://hbl-cloud.kinexon.com/api/session"),
endpoint_main=os.getenv("ENDPOINT_KINEXON_MAIN", "https://hbl-cloud.kinexon.com/api"),
)

print(f"Found {len(sessions)} sessions for team {team_id}")

# Get position data for each session
for session in sessions:
session_id = session["session_id"]
description = session["description"]

print(f"Getting position data for session: {description} ({session_id})")

# Mind that the download can take ages, as a file is usually around 150 MB.
# @Kinexon: 160MB in 7min = terrible
# Probably using RDBMS for time-series data?
# Time-series DB (or even PG timescaledb) + compression + proper indexes + streaming
# Kinda using a screwdriver to hammer nails
try:
position_data = client.get_position_data_by_session_id(
session_id=session_id,
)

# Save to file
filename = f"positions_{session_id}.csv"
with open(filename, "wb") as f:
f.write(position_data)

print(f"Saved {filename}")

except Exception as e:
print(f"Failed to get position data for session {session_id}: {e}")
```

avail = api.get_available_metrics_and_events()
print("Available metrics/events:", avail)

## Contributing
teams = fetch_team_ids()
print(f"Teams: {len(teams)}")

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
players = api.get_team_players(team_id=teams[0]["id"])
print("Players:", players)
```

### Development Guidelines
## Project Structure (high level)
- `src/kinexon_handball_api/`
- `api.py` — Core client (two-step auth + API key header)
- `handball.py` — Handball helpers (metrics/events, sessions, players, positions)
- `fetchers.py` — Local team ID registry loaded from `config/teams.yaml`
- `src/_vendor/kinexon_client/` — Generated OpenAPI client (vendored)
- `openapi/` — OpenAPI spec and generator config
- `scripts/` — Client regeneration scripts
- `tests/` — Unit tests

- Follow PEP 8 style guidelines (enforced by flake8)
- Use Black for code formatting (88 character line length)
- Sort imports with isort (Black-compatible profile)
- Add type hints to all functions (enforced by mypy)
- Write tests for new functionality
- Update documentation for API changes
- Use conventional commit messages
## Regenerate the OpenAPI Client (optional)
The client is generated with `openapi-python-client` and vendored into `src/_vendor/kinexon_client`.

### Pre-commit Hooks
```bash
# ensure dev tools
uv pip install -e ".[dev]"
# run the generator (bash)
./scripts/codegen.sh
```

The project includes pre-commit hooks that automatically run code quality checks:
The script downloads the spec, generates the client, moves it under `src/_vendor/kinexon_client`, and cleans up.

## Testing
```bash
# Install pre-commit hooks
uv pip install pre-commit
pre-commit install

# Run manually (optional)
pre-commit run --all-files
pytest -q
```

This ensures all code meets quality standards before commits.

## License
MIT — see `LICENSE`.

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Support

For support and questions:

- Create an issue on GitHub
- Review the test examples for usage patterns

## Changelog

### v0.1.0
- Initial release
- Basic API client functionality
- Authentication system
- Position data retrieval with progress tracking
- Team and session management
- Comprehensive test suite
- Improved error handling for large CSV downloads

## Acknowledgments

- Kinexon for providing the handball analytics API
## Disclaimer
This project is an unofficial wrapper and is not affiliated with Kinexon. API access requires a valid contract and credentials from Kinexon.
5 changes: 5 additions & 0 deletions openapi/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project_name_override: kinexon-client # distribution (PyPI/project)
package_name_override: kinexon_client # importable package
class_name: KinexonClient
use_path_prefixes_for_title_model_names: true
package_version_override: 0.1.0
Loading
Loading