description: chiptime Python API entry points: parse, iter_messages, iter_frames, repair, validate — one call, then navigate plain data.¶
Python API — core¶
Five entry points, one mental model: make one call, then navigate the result (the object tree). There are no sessions to open, no configuration objects, no state to manage — every function is input → complete result.
Which entry point?¶
| You want | Call |
|---|---|
| The workout, fully interpreted | parse — the main call, 99% of uses |
| To stream a huge file in constant memory | iter_messages |
| Wire-level bytes forensics | iter_frames |
| To know why a platform refuses a file | doctor |
| A broken file made uploadable | repair |
| Metadata changed (sport, device, clock) | edit |
| An activity cropped, totals rebuilt | trim |
| To know what a file discloses | reveal |
| Personal data removed before sharing | scrub |
| "Will this platform accept it?" | validate |
parse reads everything into a ParseResult; the iterators yield as they go
and skip the semantic layer entirely. repair and validate are built on
parse — they see exactly what it sees.
Parse¶
chiptime.parse ¶
parse(
src: Source,
*,
mode: Mode = "lenient",
strip_pii: bool = False,
include_unknown: bool = True,
include_raw: bool = False,
) -> ParseResult
Parse a FIT source. lenient (default) recovers and annotates; strict raises the first FitError; forensic maximizes salvage and never drops.
Stream without the semantic layer¶
chiptime.iter_messages ¶
Profile-applied message stream without building the semantic model.
chiptime.iter_frames ¶
Lossless wire-level frame events (forensics layer).
Doctor¶
chiptime.doctor ¶
Why won't this file upload, and what should I run? (F29)
The most persistent unanswered question in the FIT world is not "is my file broken" — it is "I fixed it and the platform still refuses it, and nothing tells me why." chiptime already knows the answer: it validates against platform profiles and it has verbs that repair and edit. What was missing is the join — a single command that reads a stubborn file and prints what is wrong, who cares, and the exact command that fixes it.
That is the "errors are written for agents" contract (code + sentence + suggested flag) applied to a whole file, for humans.
Remedy
dataclass
¶
A concrete next step, not a hint.
Attributes:
| Name | Type | Description |
|---|---|---|
command |
str
|
The command to run, ready to paste. |
reason |
str
|
Why this fixes the findings it covers. |
codes |
tuple[str, ...]
|
The finding codes this remedy resolves. |
priority |
int
|
Lower runs first (structural repair before cosmetics). |
Diagnosis
dataclass
¶
What a platform will make of this file, and what to do about it.
Attributes:
| Name | Type | Description |
|---|---|---|
platform |
str
|
The profile the verdict is against. |
will_upload |
bool
|
True when nothing blocking was found. |
blocking |
list[Finding]
|
Findings that will cause rejection. |
advisory |
list[Finding]
|
Findings worth knowing that should not block. |
remedies |
list[Remedy]
|
Ordered, deduplicated next steps. |
unresolved |
list[Finding]
|
Blocking findings with no known automatic fix. |
summary |
str
|
One-line description of the parse itself. |
doctor ¶
doctor(
src: Source,
*,
platform: Platform = "garmin-connect",
mode: Mode = "lenient",
) -> Diagnosis
Diagnose why a platform will refuse a file, and prescribe the fix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Source
|
Path, bytes, or binary file object. |
required |
platform
|
Platform
|
Which platform's observed rules to judge against. |
'garmin-connect'
|
mode
|
Mode
|
Parse policy for reading the input. |
'lenient'
|
Returns:
| Type | Description |
|---|---|
Diagnosis
|
|
Diagnosis
|
remedies, and any blocking finding for which chiptime has no |
Diagnosis
|
automatic fix (named honestly rather than papered over). |
chiptime.doctor.Diagnosis
dataclass
¶
What a platform will make of this file, and what to do about it.
Attributes:
| Name | Type | Description |
|---|---|---|
platform |
str
|
The profile the verdict is against. |
will_upload |
bool
|
True when nothing blocking was found. |
blocking |
list[Finding]
|
Findings that will cause rejection. |
advisory |
list[Finding]
|
Findings worth knowing that should not block. |
remedies |
list[Remedy]
|
Ordered, deduplicated next steps. |
unresolved |
list[Finding]
|
Blocking findings with no known automatic fix. |
summary |
str
|
One-line description of the parse itself. |
chiptime.doctor.Remedy
dataclass
¶
A concrete next step, not a hint.
Attributes:
| Name | Type | Description |
|---|---|---|
command |
str
|
The command to run, ready to paste. |
reason |
str
|
Why this fixes the findings it covers. |
codes |
tuple[str, ...]
|
The finding codes this remedy resolves. |
priority |
int
|
Lower runs first (structural repair before cosmetics). |
Repair¶
chiptime.repair ¶
Repair: salvage → synthesize missing structure → valid canonical .fit.
Every synthesis lands in provenance (REPAIR_*). Genuinely absent data is refused, never fabricated (taxonomy #16, contract #8).
RepairResult
dataclass
¶
A repaired file plus the proof of what repair did.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The complete, valid |
provenance |
list[ProvenanceEntry]
|
Every salvaged, synthesized, and dropped element. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The salvage parse of the input, for inspection. |
Edit¶
chiptime.edit ¶
User-directed metadata edits with a validated round-trip (F26).
The distinction that governs this module (PRD §5): chiptime never infers
intent and never mutates a file on its own — but when the user names an
edit explicitly, it is performed, recorded in provenance[], and the
result is re-parsed in strict mode to prove the file is still sound.
Metadata only: this module never touches a measurement.
EditError ¶
Bases: FitError
A requested edit cannot be performed; no bytes are written.
EditResult
dataclass
¶
The edited file plus proof of what changed.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The edited |
provenance |
list[ProvenanceEntry]
|
One entry per edit performed, with before/after values. |
warnings |
list[Diagnostic]
|
Non-fatal observations (e.g. a sport/sub-sport pair worth a second look). chiptime flags; it does not silently fix. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The parse of the input, for inspection. |
edit ¶
edit(
src: Source,
*,
sport: str | int | None = None,
sub_sport: str | int | None = None,
manufacturer: str | int | None = None,
product: int | None = None,
time_shift_s: int | None = None,
total_distance_m: float | None = None,
mode: Mode = "lenient",
) -> EditResult
Change what a file says about itself, then prove it still parses.
Only the named edits are applied; every other message, field, developer
field, and unknown value round-trips untouched. Each edit is recorded in
provenance[], and the output is re-parsed in strict mode
(output_strict_ok).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Source
|
Path, bytes, or binary file object. |
required |
sport
|
str | int | None
|
New sport, by profile name ( |
None
|
sub_sport
|
str | int | None
|
New sub-sport; never inferred from |
None
|
manufacturer
|
str | int | None
|
New recording-device manufacturer, name or number. |
None
|
product
|
int | None
|
New product id (numeric — products are vendor-specific). |
None
|
time_shift_s
|
int | None
|
Signed seconds added to every profile-typed timestamp. |
None
|
total_distance_m
|
float | None
|
Set the activity's true distance (treadmill calibration). Records and speed are scaled by the same factor so the stream and the summaries still agree. |
None
|
mode
|
Mode
|
Parse policy for reading the input. |
'lenient'
|
Returns:
| Type | Description |
|---|---|
EditResult
|
|
EditResult
|
strict-mode self-check verdict. |
Raises:
| Type | Description |
|---|---|
EditError
|
no edit was requested, an enum name is unknown, or a time shift would leave the representable range. No bytes are written in any of these cases. |
chiptime.edit.EditResult
dataclass
¶
The edited file plus proof of what changed.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The edited |
provenance |
list[ProvenanceEntry]
|
One entry per edit performed, with before/after values. |
warnings |
list[Diagnostic]
|
Non-fatal observations (e.g. a sport/sub-sport pair worth a second look). chiptime flags; it does not silently fix. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The parse of the input, for inspection. |
Trim¶
chiptime.trim ¶
Crop an activity without letting the file lie about itself (F27).
Removing records is easy; the hard part is that every number computed from those records — session totals, activity totals, averages — is wrong the moment they disappear. A trimmed file with stale totals is worse than an untrimmed one, because the error is invisible and travels downstream forever.
So trimming here is two acts: filter the records, then rebuild everything that depended on them, using the same semantic layer that computes totals during a normal parse. There is no second implementation of totals arithmetic to drift.
TrimError ¶
Bases: FitError
A trim cannot be performed; no bytes are written.
TrimResult
dataclass
¶
The cropped file plus an account of what was removed and rebuilt.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The trimmed |
provenance |
list[ProvenanceEntry]
|
What was dropped and what was rebuilt, with counts. |
records_kept |
int
|
Records inside the keep-window. |
records_dropped |
int
|
Records removed by the trim. |
warnings |
list[Diagnostic]
|
Non-fatal observations carried from the rebuild. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The parse of the input, for inspection. |
trim ¶
trim(
src: Source,
*,
after: datetime | str | int | None = None,
before: datetime | str | int | None = None,
mode: Mode = "lenient",
) -> TrimResult
Crop an activity to a time window and rebuild every derived number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Source
|
Path, bytes, or binary file object. |
required |
after
|
datetime | str | int | None
|
Keep records at or after this bound. Absolute |
None
|
before
|
datetime | str | int | None
|
Keep records at or before this bound. |
None
|
mode
|
Mode
|
Parse policy for reading the input. |
'lenient'
|
Returns:
| Type | Description |
|---|---|
TrimResult
|
|
TrimResult
|
and the strict-mode self-check verdict. |
Raises:
| Type | Description |
|---|---|
TrimError
|
no bound given, a bound cannot be interpreted, the file has no records, or the window keeps nothing. No bytes are written. |
chiptime.trim.TrimResult
dataclass
¶
The cropped file plus an account of what was removed and rebuilt.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The trimmed |
provenance |
list[ProvenanceEntry]
|
What was dropped and what was rebuilt, with counts. |
records_kept |
int
|
Records inside the keep-window. |
records_dropped |
int
|
Records removed by the trim. |
warnings |
list[Diagnostic]
|
Non-fatal observations carried from the rebuild. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The parse of the input, for inspection. |
Privacy¶
chiptime.reveal ¶
Report what a file discloses about you. Reads only; writes nothing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Source
|
Path, bytes, or binary file object. |
required |
mode
|
Mode
|
Parse policy for reading the input. |
'lenient'
|
Returns:
| Type | Description |
|---|---|
PrivacyReport
|
|
PrivacyReport
|
itself is safe to share — which is the whole point of having one. |
chiptime.scrub ¶
scrub(
src: Source,
*,
identity: bool = True,
serials: bool = True,
body_metrics: bool = True,
gps_radius_m: float | None = None,
drop_all_gps: bool = False,
mode: Mode = "lenient",
) -> ScrubResult
Remove personal data and write a file that still parses and uploads.
Metadata categories are on by default because removing them costs no measurements. Location scrubbing is opt-in and explicit, because it does.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Source
|
Path, bytes, or binary file object. |
required |
identity
|
bool
|
Drop |
True
|
serials
|
bool
|
Null device serial numbers and ANT device ids. Note that
platforms are reported to use |
True
|
body_metrics
|
bool
|
Drop |
True
|
gps_radius_m
|
float | None
|
Conceal every GPS point within this many metres of the route's first or last fix — wherever it occurs in the ride, so a loop that passes home mid-route is covered too. |
None
|
drop_all_gps
|
bool
|
Remove every coordinate outright. |
False
|
mode
|
Mode
|
Parse policy for reading the input. |
'lenient'
|
Returns:
| Type | Description |
|---|---|
ScrubResult
|
|
ScrubResult
|
counts, and the strict-mode self-check verdict. |
Raises:
| Type | Description |
|---|---|
ScrubError
|
nothing was selected to remove. |
chiptime.privacy.PrivacyReport
dataclass
¶
What a file discloses, by category.
Coordinates are deliberately coarse (see COARSE_DECIMALS).
Attributes:
| Name | Type | Description |
|---|---|---|
findings |
list[PrivacyFinding]
|
One entry per disclosing message/field, with counts. |
positions_present |
int
|
Records carrying GPS coordinates. |
start_coarse |
tuple[float, float] | None
|
Approximate start coordinate, rounded, or None. |
end_coarse |
tuple[float, float] | None
|
Approximate end coordinate, rounded, or None. |
clean_categories |
list[str]
|
Categories this file does not disclose at all. |
chiptime.privacy.ScrubResult
dataclass
¶
The scrubbed file plus an account of what was removed.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
bytes
|
The scrubbed |
provenance |
list[ProvenanceEntry]
|
One entry per category removed, with counts. |
warnings |
list[Diagnostic]
|
Non-fatal observations (e.g. every position was concealed). |
removed |
dict[str, int]
|
Count of removals per category key. |
output_strict_ok |
bool
|
Self-check — the output re-parsed in strict mode. |
parse_result |
ParseResult | None
|
The parse of the input, for inspection. |