committed 07:18PM - 03 Sep 26 UTC
* feat(model)!: resolve periods against the metadata on every request
`periods`… was a field of the three request classes that hand-rolled it, so
providers that never opted in dropped the argument -- silently through the CLI
and REST API, as a TypeError from Python. What each of the three then did with
it was its own copy of the same parse-and-intersect, whose empty result read as
"no periods requested" and fell back to every period there is, so asking for a
period a dataset is not published under returned more data than asking for one
it is.
Periods are a required field of every dataset in the metadata, so the concept is
universal and only the choice is sometimes trivial. `periods` moves to
`TimeseriesRequest` and is resolved against what the requested datasets publish;
deriving them from the requested interval stays a provider hook, `_get_periods`,
which DWD observation and phenology override.
BREAKING CHANGE: a period none of the requested datasets publishes raises
`NoPeriodsFoundError` instead of being dropped and replaced by all of them, the
default is the requested datasets' periods rather than the provider's, and
`periods` precedes the subclass fields of DWD MOSMIX/DMO positionally.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(model): check derived periods, and say when periods do not narrow
Three findings from review of the previous commit.
The periods derived from `start_date`/`end_date` were returned without the
check the requested ones pass, so a request could land on a period its datasets
do not publish: an interval reaching into today derives `now`, which `daily/kl`
has no release for, and the request then read no station index at all and
reported no stations -- while `periods="now"` raises for the same datasets.
Where the interval reaches past the newest release a dataset has, that release
is what can answer for it.
Four providers -- SMHI, MeteoSwiss, met.no Frost and Meteo-France observation --
declare datasets with more than one period but fetch all of them by design.
Accepting a narrowed request from them in silence answers it with everything, so
they say so instead. `_selects_by_period` is a diagnostic, not a gate: a
provider that leaves it False still validates periods, and getting it wrong
costs a spurious warning rather than a dropped argument.
The MCP instructions and the REST `values` docstring both advised `periods` as
"usually recent" for every provider, which is now a 400 for the ones publishing
under a single period.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(model): leave an interval that reaches no release empty
CI caught two things about the derived-period check.
An interval that overlaps no release at all -- a window in the future -- derives
an empty set, which the fallback then widened to the dataset's newest release,
so a request 720 days ahead would have downloaded `recent` to find nothing.
There is nothing to read and nothing to fall back to, so it stays empty.
The five tests of the interval-to-release mapping asked `daily/climate_summary`
for periods including `now`, which it has no release for -- the assertion only
says something when the dataset publishes the release the interval reaches, so
they use `10_minutes/temperature_air` now. What `climate_summary` does with such
an interval is its own test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(dwd): settle a derived station on its newest description
The derived station index iterated the period set with `reversed(list(...))`
before deduplicating with `keep="first"`, so which of a station's descriptions
won came down to the set's iteration order. Sorted, as the observation index
already does, the newest period wins.
The empty period set that says an interval reaches no release now stops the
phenology values from reading anything, where it used to widen back to every
published period and download a whole network's records to filter them all
away. Station discovery keeps widening on purpose -- a station does not stop
existing because the requested window lies outside every release -- which is
now said where it happens.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>