Skip to content
Draft
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
25 changes: 25 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from dataclasses import KW_ONLY, dataclass
from datetime import datetime
from typing import Generic, TypeVar

T = TypeVar("T", int, float)


@dataclass(kw_only=True, frozen=True, slots=True)
class Bounds(Generic[T]):
lo: T | None = None
hi: T | None = None


@dataclass(frozen=True, slots=True)
class ColumnMetadata(Generic[T]):
name: str
_: KW_ONLY
type: type[T]
bounds: Bounds[T] = Bounds()


JAN_1_1962_DT = datetime(1962, 1, 1)
JAN_1_1962_MJD = 37665.0
NOW_DT = datetime.now()
NOW_MJD = JAN_1_1962_MJD + (NOW_DT - JAN_1_1962_DT).days
109 changes: 109 additions & 0 deletions tests/test_Leap_Second_dat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import csv
import re
from dataclasses import KW_ONLY, dataclass
from datetime import datetime
from itertools import takewhile
from pathlib import Path
from typing import Generic, Mapping, NewType, TypeVar

import pytest

from . import JAN_1_1962_MJD, NOW_DT, NOW_MJD, Bounds, ColumnMetadata

DATA_DIR = Path(__file__).parents[1] / "astropy_iers_data" / "data"
DATA_FILE = DATA_DIR / "Leap_Second.dat"

T = TypeVar("T", int, float)

EXPECTED_COLUMN_META = [
ColumnMetadata("MJD", type=float, bounds=Bounds(lo=JAN_1_1962_MJD, hi=NOW_MJD)),
ColumnMetadata("day", type=int, bounds=Bounds(lo=1, hi=12)),
ColumnMetadata("month", type=int, bounds=Bounds(lo=1, hi=31)),
ColumnMetadata("year", type=int, bounds=Bounds(lo=1972, hi=NOW_DT.year)),
ColumnMetadata(
"tai-utc",
type=int,
bounds=Bounds(
lo=0,
# there is no theoritical upper bound here,
# however a value much larger than 100 is definitely suspicious
# as of 2026, when the maximum (then current) value was 37
hi=100,
),
),
]


@dataclass(kw_only=True, frozen=True, slots=True)
class CSV_Data:
header: list[str]
rows: list[list[str]]
names: list[str]
types: list[type]

def __post_init__(self):
ncols = len(self.names)
assert len(self.types) == ncols
assert all(len(r) == ncols for r in self.rows)

@property
def ncols(self) -> int:
return len(self.types)

@property
def nrows(self) -> int:
return len(self.rows)

def get_columns(
self, *, max_rows: int | None = None
) -> list[list[float] | list[int]]:
# last nrows of each column, cast to infered Python types
nrows = min(max_rows or self.nrows, self.nrows)
tail_rows = self.rows[self.nrows - nrows :]
assert len(tail_rows) == nrows
tail_cols = [[r[i] for r in tail_rows] for i in range(self.ncols)]
return [
[tp(c[i]) for i in range(nrows)]
for c, tp in zip(
tail_cols,
self.types,
strict=True,
)
]


@pytest.fixture(scope="module")
def csv_data():
with DATA_FILE.open() as fh:
header = [
L.removeprefix("#").strip()
for L in takewhile(lambda L: L.startswith("#"), fh)
]
rows = list(csv.reader(fh, delimiter=" ", skipinitialspace=True))

return CSV_Data(
header=header,
rows=rows,
names=["MJD", "day", "month", "year", "TAI-UTC"],
types=[float, int, int, int, int],
)


def test_header(csv_data):
assert "File expires on" in "\n".join(csv_data.header)


def test_data(csv_data, subtests):
cols = csv_data.get_columns()
for c, meta in zip(cols, EXPECTED_COLUMN_META, strict=True):
tp = meta.type
with subtests.test(f"{meta.name} (types)"):
assert all(type(e) == tp for e in c)

if (lo := meta.bounds.lo) is not None:
with subtests.test(f"{meta.name} (min)"):
assert min(c) >= lo

if (hi := meta.bounds.hi) is not None:
with subtests.test(f"{meta.name} (max)"):
assert max(c) <= hi
29 changes: 5 additions & 24 deletions tests/test_eopc04_1962-now.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,11 @@

import pytest

from . import JAN_1_1962_MJD, NOW_DT, NOW_MJD, Bounds, ColumnMetadata

DATA_DIR = Path(__file__).parents[1] / "astropy_iers_data" / "data"
DATA_FILE = DATA_DIR / "eopc04.1962-now"

T = TypeVar("T", int, float)


@dataclass(kw_only=True, frozen=True, slots=True)
class Bounds(Generic[T]):
lo: T | None = None
hi: T | None = None


@dataclass(frozen=True, slots=True)
class ColumnMetadata(Generic[T]):
name: str
_: KW_ONLY
type: type[T]
bounds: Bounds[T] = Bounds()


JAN_1_1962_DT = datetime(1962, 1, 1)
JAN_1_1962_MJD = 37665.0
NOW_DT = datetime.now()
NOW_MJD = JAN_1_1962_MJD + (NOW_DT - JAN_1_1962_DT).days


EXPECTED_COLUMN_META = [
ColumnMetadata("YR", type=int, bounds=Bounds(lo=1962, hi=NOW_DT.year)),
ColumnMetadata("MM", type=int, bounds=Bounds(lo=1, hi=12)),
Expand Down Expand Up @@ -116,7 +95,9 @@ def compatible_py_types(self) -> list[type]:
def names(self) -> list[str]:
return re.split(r"\s\s+", self.header[5].removeprefix("#").strip())

def get_columns(self, *, max_rows: int | None = None) -> list[list[float] | list[int]]:
def get_columns(
self, *, max_rows: int | None = None
) -> list[list[float] | list[int]]:
# last nrows of each column, cast to infered Python types
nrows = min(max_rows or self.nrows, self.nrows)
tail_rows = self.rows[self.nrows - nrows :]
Expand Down
Loading