Metadata-Version: 2.4
Name: fitcxgp
Version: 0.1.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Classifier: Typing :: Typed
License-File: LICENSE
Summary: Fast, all-in-one GPX/TCX/FIT toolkit
Author: fitcxgp contributors
License: MIT
Requires-Python: >=3.12
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# fitcxgp

**Fast, all-in-one GPX/TCX/FIT toolkit.**

Load, inspect, and convert GPX, TCX, and FIT files with one Python, Rust, or
CLI API. Every supported input can be written to every supported output.

## Why fitcxgp?

- **All in one** — GPX, TCX, and FIT read/write support.
- **Fast** — Rust-powered streaming parsers; GPX parsing is up to 31x faster
  than `gpxpy` on the real-data benchmark.
- **Useful model** — points, segments, telemetry, device info, moving stats,
  elevation gain, bounds, and track simplification.
- **Reliable** — FIT CRC validation, property tests, and 8,280 conversion
  chains verified on 920 real GPX files.
- **Easy to embed** — Python 3.12+ ABI3 wheel, Rust library, and CLI.

## Python

```console
uv add fitcxgp
```

Load once, write any format:

```python
import fitcxgp

activity_file = fitcxgp.load("run.gpx")  # GPX, TCX, or FIT

gpx = activity_file.to_gpx()
tcx = activity_file.to_tcx()
fit = activity_file.to_fit()
```

Inspect an activity:

```python
activity = activity_file.activities[0]

print(activity.point_count)
print(activity.distance_meters)
print(activity.duration_seconds)
print(activity.average_heart_rate_bpm)
print(activity.elevation_gain.uphill_meters)
```

Convert files directly:

```python
fitcxgp.convert("run.gpx", "run.fit")
fitcxgp.convert("run.fit", "run.tcx")
```

Add device information when creating FIT output:

```python
device = fitcxgp.DeviceInfo(
    manufacturer_id=1,
    product_id=3415,
    serial_number=1234567890,
)
fit = activity_file.with_device_info(device).to_fit()
```

## CLI

```console
cargo run --release -- convert run.gpx run.fit
cargo run --release -- info run.fit
cargo run --release -- detect run.tcx
```

## Rust

```rust
use fitcxgp_core::{convert, load};

let activity_file = load("run.fit").unwrap();
println!("{} points", activity_file.point_count());
convert("run.fit", "run.gpx").unwrap();
```

## Development

```console
uv sync --python 3.12
uv run pytest
cargo test --workspace
```

Conversions preserve the shared activity model, not format-specific data such
as FIT developer fields or GPX routes and waypoints.

See [testing](docs/testing.md), [benchmarks](docs/benchmark.md), and the
[real-data report](docs/real-data-benchmark.md) for details.

