Metadata-Version: 2.5
Name: satchecker-client
Version: 0.2.0
Summary: Client for the IAU CPS SatChecker satellite orbital-record service.
Project-URL: Documentation, https://satchecker-client.readthedocs.io/
Project-URL: Repository, https://github.com/epfl-radio-astro/satchecker-client
Project-URL: Issues, https://github.com/epfl-radio-astro/satchecker-client/issues
Project-URL: SatChecker service, https://satchecker.cps.iau.org/
Author-email: Chris Finlay <christopher.finlay@epfl.ch>
Maintainer-email: Chris Finlay <christopher.finlay@epfl.ch>
License: MIT License
        
        Copyright (c) 2026 Chris Finlay
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: OMM,SatChecker,TLE,orbit,radio-astronomy,satellite
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Astronomy
Requires-Python: >=3.10
Requires-Dist: numpy
Requires-Dist: pandas
Provides-Extra: docs
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: sphinx; extra == 'docs'
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
Provides-Extra: test
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Description-Content-Type: text/markdown

# satchecker-client

A small Python client for the [IAU CPS SatChecker][satchecker] service, which
publishes nearest-epoch satellite orbital records — TLEs up to the 2026-07-12
archive handover, OMM element sets after it. No account or credentials are
needed.

> **Unofficial.** This is a third-party client written for the
> [TABASCAL][tabascal] and [tab-sim][tabsim] radio-astronomy packages. It is not
> published, endorsed, or maintained by the IAU CPS SatHub team, who develop the
> [SatChecker service itself][upstream]. The distribution name deliberately
> avoids `satchecker` so that name stays available to them.

## What it does

- **Transport** — both nearest-record endpoints and the catalogue name search,
  with normalised column sets and a typed error hierarchy that separates a
  per-satellite miss from a service outage or a rate limit.
- **Catalogue** — which satellites a name search leaves in play at a given
  epoch, past epochs included.
- **Parsing** — TLE line parsing including Alpha-5 catalogue numbers and
  checksums, plus the element range and finiteness checks both record kinds
  share. SatChecker's historical TLE archive has damaged lines: a stray backslash is
  repaired wherever the checksum confirms it, and lines with no checksum are
  accepted, with a warning, only where a caller allows it.
- **Kind dispatch** — one place that knows how TLE and OMM records differ, so
  callers spanning the archive handover do not thread a format flag through
  their own code.
- **Caching** — a validated, atomically-written per-NORAD JSON store, which also
  keeps catalogue search results so name-selected runs can work offline.
- **Batching** — bounded-concurrency fetches that stop on the first sign the
  service itself is the problem rather than working through the rest of a list.
- **Resolving** (optional) — one call that picks the record each satellite gets:
  source precedence per satellite, nearest-epoch selection, cache reuse held
  apart from the hard age ceiling, fallback to the other archive, and a result
  that tells an absent satellite from a failed request. Every rule is a required
  argument; it has no policy of its own.
- **Replay** (optional) — writing the records a run used and reading them back
  exactly, as the same doubles and the same lines, from two named files and
  nothing else.

## What it does not do

It takes no view on *which* record your observation should use. Source
precedence, how stale a record may be before it is refused, and whether missing
coverage is fatal are application policy and stay with the caller — including
when the resolver above executes them, which is why it requires every one of
them to be stated and defaults none.

## Install

```bash
pip install satchecker-client
```

Full documentation, including the usage guide and API reference, is at
[satchecker-client.readthedocs.io](https://satchecker-client.readthedocs.io/).

## Use

```python
import satchecker_client as sc

# Identify your application to the service operators. Optional, but the service
# is a courtesy to the community and shared traffic is easier to reason about
# when it is attributable.
sc.set_client_identifier("my-app/1.0")

epoch_jd = 2460800.5
norad_ids = [25544, 48274]

# nearest_endpoints_for picks TLE, OMM, or both, based on where the epoch falls
# relative to the archive handover.
for label, fetch in sc.nearest_endpoints_for(epoch_jd):
    result = sc.fetch_nearest_batch(norad_ids, epoch_jd, fetch_nearest=fetch, endpoint=label)
    if result.outage is not None:
        raise result.outage          # the service, not this satellite
    for norad_id, err in result.errors.items():
        print(f"{norad_id}: {err}")  # this satellite, keep going
    print(result.records)
```

Records are `pandas` rows; ask `record_kind`, `record_epoch_jd` and
`record_elements` about one rather than testing for columns yourself.

Caching a fetch for reuse across nearby epochs:

```python
cache = sc.TextOrbitCache("~/.cache/my-app/orbits")
sc.store_or_warn(
    lambda: cache.store(norad_id, result.records),
    cache.path(norad_id),
    "nearest records",
)
known = cache.get(norad_id)
```

## Development

```bash
pip install -e ".[test]"
pytest
```

The tests block outbound network access via an autouse fixture, so the suite
runs offline and never touches the live service.

## Licence

MIT — see [LICENSE](LICENSE). Extracted from [TABASCAL][tabascal], which is
GPL-3.0; this client is relicensed by its copyright holder so that a thin API
client is not the thing that constrains what it can be built into.

[satchecker]: https://satchecker.cps.iau.org/
[upstream]: https://github.com/iausathub/satchecker
[tabascal]: https://github.com/epfl-radio-astro/tabascal
[tabsim]: https://github.com/epfl-radio-astro/tab-sim
