usdata 0.14.0__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- usdata-0.16.0/PKG-INFO +122 -0
- usdata-0.16.0/README.md +88 -0
- {usdata-0.14.0 → usdata-0.16.0}/pyproject.toml +8 -1
- {usdata-0.14.0 → usdata-0.16.0}/pyproject.toml.orig +9 -1
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/__init__.py +5 -0
- usdata-0.14.0/src/usdata/fetch.py → usdata-0.16.0/src/usdata/_fetch.py +41 -10
- usdata-0.16.0/src/usdata/_grib.py +308 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/_hurdat2.py +1 -1
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/_netcdf.py +1 -1
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/_radar.py +1 -1
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/cache.py +3 -5
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/cli/app.py +2 -2
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/data/registry.yaml +284 -34
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/models.py +0 -2
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/protocols/listing.py +11 -6
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/base.py +89 -6
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/coastwatch.py +24 -11
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/coops.py +69 -47
- usdata-0.16.0/src/usdata/providers/noaa/gfs.py +112 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/ghcnd.py +26 -32
- usdata-0.16.0/src/usdata/providers/noaa/glm.py +80 -0
- usdata-0.16.0/src/usdata/providers/noaa/goes.py +157 -0
- usdata-0.16.0/src/usdata/providers/noaa/hrrr.py +224 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/hurdat2.py +23 -12
- usdata-0.16.0/src/usdata/providers/noaa/mrms.py +154 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/nexrad.py +55 -39
- usdata-0.16.0/src/usdata/providers/noaa/nexrad_level3.py +154 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/normals.py +21 -24
- usdata-0.16.0/src/usdata/providers/noaa/spc.py +99 -0
- usdata-0.16.0/src/usdata/providers/params.py +126 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/usgs/daily.py +51 -38
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/pull.py +33 -13
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/readers.py +37 -4
- usdata-0.14.0/PKG-INFO +0 -93
- usdata-0.14.0/README.md +0 -64
- usdata-0.14.0/src/usdata/providers/noaa/goes.py +0 -116
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/_files.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/_progress.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/cli/__init__.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/cli/progress.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/data/nexrad_sites.csv +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/data/places.csv +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/data/places.sources.json +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/manifest.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/protocols/__init__.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/protocols/erddap.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/protocols/http.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/protocols/s3.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/provenance.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/__init__.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/_http.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/__init__.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/gsom.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/gsoy.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/lcd.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/sites.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/noaa/storm_events.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/providers/usgs/__init__.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/py.typed +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/query.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/registry.py +0 -0
- {usdata-0.14.0 → usdata-0.16.0}/src/usdata/selection.py +0 -0
usdata-0.16.0/PKG-INFO
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: usdata
|
|
3
|
+
Version: 0.16.0
|
|
4
|
+
Summary: Unified Python SDK and CLI for discovering, fetching, and tracking provenance of U.S. public scientific data
|
|
5
|
+
Keywords: noaa,usgs,nasa,open-data,scientific-data,provenance
|
|
6
|
+
Author: Jake Van Slyke
|
|
7
|
+
Author-email: Jake Van Slyke <jakervanslyke@gmail.com>
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Requires-Dist: httpx>=0.28.1
|
|
14
|
+
Requires-Dist: pydantic>=2.7
|
|
15
|
+
Requires-Dist: pyyaml>=6.0
|
|
16
|
+
Requires-Dist: typer>=0.18
|
|
17
|
+
Requires-Dist: eccodes>=2.48 ; extra == 'grib'
|
|
18
|
+
Requires-Dist: eccodeslib>=2.48 ; sys_platform == 'linux' and extra == 'grib'
|
|
19
|
+
Requires-Dist: xarray>=2025.1 ; extra == 'grib'
|
|
20
|
+
Requires-Dist: numpy>=2 ; extra == 'grib'
|
|
21
|
+
Requires-Dist: xarray>=2025.1 ; extra == 'netcdf'
|
|
22
|
+
Requires-Dist: h5netcdf[h5py]>=1.8.1 ; extra == 'netcdf'
|
|
23
|
+
Requires-Dist: pandas>=2.2 ; extra == 'pandas'
|
|
24
|
+
Requires-Dist: xradar>=0.12.0 ; extra == 'radar'
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Project-URL: Homepage, https://usdata.dev/
|
|
27
|
+
Project-URL: Documentation, https://docs.usdata.dev/
|
|
28
|
+
Project-URL: Repository, https://github.com/jakeryderv/usdata
|
|
29
|
+
Provides-Extra: grib
|
|
30
|
+
Provides-Extra: netcdf
|
|
31
|
+
Provides-Extra: pandas
|
|
32
|
+
Provides-Extra: radar
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# usdata
|
|
36
|
+
|
|
37
|
+
Discover U.S. scientific datasets, fetch their files, and keep a reproducible
|
|
38
|
+
record of where every input came from. One Python SDK and CLI across supported
|
|
39
|
+
NOAA and USGS datasets, with provenance sidecars and lockable manifests.
|
|
40
|
+
|
|
41
|
+
**Pre-alpha.** Features marked **Unreleased** in the documentation require a
|
|
42
|
+
source installation; the [changelog](CHANGELOG.md) lists what each published
|
|
43
|
+
version contains.
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
| Site | For |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| [usdata.dev](https://usdata.dev/) | What the package is for: the dataset browser and worked examples with saved results |
|
|
50
|
+
| [docs.usdata.dev](https://docs.usdata.dev/) | Using the package: install, first dataset, guides, dataset notes, and reference |
|
|
51
|
+
| This repository | Changing the project: everything below, plus [contributing](CONTRIBUTING.md), [architecture](docs/architecture.md), [testing](docs/testing.md), [decisions](docs/adr/README.md), [roadmap](docs/roadmap.md), and [versioning](docs/versioning.md) |
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pip install "usdata[pandas]"
|
|
55
|
+
usdata search precipitation --location Oklahoma
|
|
56
|
+
usdata info noaa:ghcn-daily
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
Requires a source checkout, [uv](https://docs.astral.sh/uv/), and
|
|
62
|
+
[just](https://just.systems/):
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
git clone https://github.com/jakeryderv/usdata && cd usdata
|
|
66
|
+
just setup # install toolchain and dependencies
|
|
67
|
+
just check # format, lint, typecheck, offline tests, generated docs, release notices
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`just setup` uses the tested Python 3.14.7 pin in `.python-version`. Older Linux
|
|
71
|
+
uv Python 3.14 builds can crash during NumPy array operations; see
|
|
72
|
+
[the upstream fix](https://github.com/astral-sh/python-build-standalone/issues/991).
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
just hooks-install # optional: install fast staged-file checks
|
|
76
|
+
just test # all offline tests
|
|
77
|
+
just check-pandas # install the CSV extra and run the same checks
|
|
78
|
+
just check-radar # install the radar extra and run the same checks
|
|
79
|
+
just check-netcdf # install the NetCDF4 extra and run the same checks
|
|
80
|
+
just check-grib # install the GRIB2 extra and run the same checks (Linux, Windows <= 3.13)
|
|
81
|
+
just notebooks # launch the optional Jupyter examples environment
|
|
82
|
+
just run-notebooks # execute notebooks live in fresh kernels and temporary caches
|
|
83
|
+
just docs-serve # build and preview the documentation locally, with reload
|
|
84
|
+
just check-docs # validate generated content and build the site strictly
|
|
85
|
+
just build # build wheel and sdist
|
|
86
|
+
just smoke # exercise core and pandas wheel installations outside the checkout
|
|
87
|
+
just changes # preview upcoming release notes
|
|
88
|
+
just cleanup 123 # from main: remove PR #123's merged branch and clean worktree
|
|
89
|
+
just run search radar
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Commit hooks fix and format staged Python files using the locked Ruff version,
|
|
93
|
+
and check configuration, merge conflicts, and GitHub Actions workflows. Full
|
|
94
|
+
validation remains `just check`; `just check-hooks` runs the non-mutating config
|
|
95
|
+
and workflow checks alone. Hooks do not rewrite notebooks or raw data fixtures.
|
|
96
|
+
The first hook run downloads its isolated tools and requires network access.
|
|
97
|
+
|
|
98
|
+
Offline tests mechanically block network connections. Tests that hit live
|
|
99
|
+
services run with `just test-live`; see [testing levels and organization](docs/testing.md).
|
|
100
|
+
CI checks Python 3.11 and 3.14 on Linux with core-only, pandas, radar, NetCDF,
|
|
101
|
+
and GRIB2 dependency profiles. A further Python 3.11 profile replaces the locked
|
|
102
|
+
pandas with the oldest release the project declares, so the `>=` floor is
|
|
103
|
+
executed rather than assumed; the number comes from `pyproject.toml` through
|
|
104
|
+
`scripts/lowest_version.py`. Installed-wheel checks cover core, pandas, radar,
|
|
105
|
+
and NetCDF on Linux, macOS, and Windows. The full offline and live-service
|
|
106
|
+
suites run on Linux. `just setup` restores a core-only development environment;
|
|
107
|
+
the `check-*` commands install their respective extras.
|
|
108
|
+
|
|
109
|
+
Releases: `just release minor` prepares a release branch. Update release
|
|
110
|
+
notices, then `just release-pr` validates and opens a draft for review. Merging
|
|
111
|
+
the reviewed PR publishes to PyPI and creates the tag and GitHub release. See
|
|
112
|
+
[versioning](docs/versioning.md).
|
|
113
|
+
|
|
114
|
+
The main way the project grows is a new dataset: one registry entry and one
|
|
115
|
+
adapter, following [adding a dataset](docs/guides/adding-a-dataset.md). The two
|
|
116
|
+
websites deploy automatically from `main`; see
|
|
117
|
+
[website operations](docs/guides/website-operations.md) and
|
|
118
|
+
[maintaining documentation](docs/guides/documentation.md).
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
[Apache-2.0](LICENSE).
|
usdata-0.16.0/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# usdata
|
|
2
|
+
|
|
3
|
+
Discover U.S. scientific datasets, fetch their files, and keep a reproducible
|
|
4
|
+
record of where every input came from. One Python SDK and CLI across supported
|
|
5
|
+
NOAA and USGS datasets, with provenance sidecars and lockable manifests.
|
|
6
|
+
|
|
7
|
+
**Pre-alpha.** Features marked **Unreleased** in the documentation require a
|
|
8
|
+
source installation; the [changelog](CHANGELOG.md) lists what each published
|
|
9
|
+
version contains.
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
| Site | For |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| [usdata.dev](https://usdata.dev/) | What the package is for: the dataset browser and worked examples with saved results |
|
|
16
|
+
| [docs.usdata.dev](https://docs.usdata.dev/) | Using the package: install, first dataset, guides, dataset notes, and reference |
|
|
17
|
+
| This repository | Changing the project: everything below, plus [contributing](CONTRIBUTING.md), [architecture](docs/architecture.md), [testing](docs/testing.md), [decisions](docs/adr/README.md), [roadmap](docs/roadmap.md), and [versioning](docs/versioning.md) |
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install "usdata[pandas]"
|
|
21
|
+
usdata search precipitation --location Oklahoma
|
|
22
|
+
usdata info noaa:ghcn-daily
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Development
|
|
26
|
+
|
|
27
|
+
Requires a source checkout, [uv](https://docs.astral.sh/uv/), and
|
|
28
|
+
[just](https://just.systems/):
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
git clone https://github.com/jakeryderv/usdata && cd usdata
|
|
32
|
+
just setup # install toolchain and dependencies
|
|
33
|
+
just check # format, lint, typecheck, offline tests, generated docs, release notices
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`just setup` uses the tested Python 3.14.7 pin in `.python-version`. Older Linux
|
|
37
|
+
uv Python 3.14 builds can crash during NumPy array operations; see
|
|
38
|
+
[the upstream fix](https://github.com/astral-sh/python-build-standalone/issues/991).
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
just hooks-install # optional: install fast staged-file checks
|
|
42
|
+
just test # all offline tests
|
|
43
|
+
just check-pandas # install the CSV extra and run the same checks
|
|
44
|
+
just check-radar # install the radar extra and run the same checks
|
|
45
|
+
just check-netcdf # install the NetCDF4 extra and run the same checks
|
|
46
|
+
just check-grib # install the GRIB2 extra and run the same checks (Linux, Windows <= 3.13)
|
|
47
|
+
just notebooks # launch the optional Jupyter examples environment
|
|
48
|
+
just run-notebooks # execute notebooks live in fresh kernels and temporary caches
|
|
49
|
+
just docs-serve # build and preview the documentation locally, with reload
|
|
50
|
+
just check-docs # validate generated content and build the site strictly
|
|
51
|
+
just build # build wheel and sdist
|
|
52
|
+
just smoke # exercise core and pandas wheel installations outside the checkout
|
|
53
|
+
just changes # preview upcoming release notes
|
|
54
|
+
just cleanup 123 # from main: remove PR #123's merged branch and clean worktree
|
|
55
|
+
just run search radar
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Commit hooks fix and format staged Python files using the locked Ruff version,
|
|
59
|
+
and check configuration, merge conflicts, and GitHub Actions workflows. Full
|
|
60
|
+
validation remains `just check`; `just check-hooks` runs the non-mutating config
|
|
61
|
+
and workflow checks alone. Hooks do not rewrite notebooks or raw data fixtures.
|
|
62
|
+
The first hook run downloads its isolated tools and requires network access.
|
|
63
|
+
|
|
64
|
+
Offline tests mechanically block network connections. Tests that hit live
|
|
65
|
+
services run with `just test-live`; see [testing levels and organization](docs/testing.md).
|
|
66
|
+
CI checks Python 3.11 and 3.14 on Linux with core-only, pandas, radar, NetCDF,
|
|
67
|
+
and GRIB2 dependency profiles. A further Python 3.11 profile replaces the locked
|
|
68
|
+
pandas with the oldest release the project declares, so the `>=` floor is
|
|
69
|
+
executed rather than assumed; the number comes from `pyproject.toml` through
|
|
70
|
+
`scripts/lowest_version.py`. Installed-wheel checks cover core, pandas, radar,
|
|
71
|
+
and NetCDF on Linux, macOS, and Windows. The full offline and live-service
|
|
72
|
+
suites run on Linux. `just setup` restores a core-only development environment;
|
|
73
|
+
the `check-*` commands install their respective extras.
|
|
74
|
+
|
|
75
|
+
Releases: `just release minor` prepares a release branch. Update release
|
|
76
|
+
notices, then `just release-pr` validates and opens a draft for review. Merging
|
|
77
|
+
the reviewed PR publishes to PyPI and creates the tag and GitHub release. See
|
|
78
|
+
[versioning](docs/versioning.md).
|
|
79
|
+
|
|
80
|
+
The main way the project grows is a new dataset: one registry entry and one
|
|
81
|
+
adapter, following [adding a dataset](docs/guides/adding-a-dataset.md). The two
|
|
82
|
+
websites deploy automatically from `main`; see
|
|
83
|
+
[website operations](docs/guides/website-operations.md) and
|
|
84
|
+
[maintaining documentation](docs/guides/documentation.md).
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
[Apache-2.0](LICENSE).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "usdata"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.16.0"
|
|
4
4
|
description = "Unified Python SDK and CLI for discovering, fetching, and tracking provenance of U.S. public scientific data"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -37,6 +37,12 @@ netcdf = [
|
|
|
37
37
|
"xarray>=2025.1",
|
|
38
38
|
"h5netcdf[h5py]>=1.8.1",
|
|
39
39
|
]
|
|
40
|
+
grib = [
|
|
41
|
+
"eccodes>=2.48",
|
|
42
|
+
"eccodeslib>=2.48; sys_platform == 'linux'",
|
|
43
|
+
"xarray>=2025.1",
|
|
44
|
+
"numpy>=2",
|
|
45
|
+
]
|
|
40
46
|
|
|
41
47
|
[project.urls]
|
|
42
48
|
Homepage = "https://usdata.dev/"
|
|
@@ -129,6 +135,7 @@ markers = [
|
|
|
129
135
|
"pandas: optional CSV reader coverage",
|
|
130
136
|
"radar: optional radar reader coverage",
|
|
131
137
|
"netcdf: optional NetCDF reader coverage",
|
|
138
|
+
"grib: optional GRIB2 reader coverage",
|
|
132
139
|
]
|
|
133
140
|
addopts = "-ra --strict-markers"
|
|
134
141
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "usdata"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.16.0"
|
|
4
4
|
description = "Unified Python SDK and CLI for discovering, fetching, and tracking provenance of U.S. public scientific data"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -26,6 +26,13 @@ dependencies = [
|
|
|
26
26
|
pandas = ["pandas>=2.2"]
|
|
27
27
|
radar = ["xradar>=0.12.0"]
|
|
28
28
|
netcdf = ["xarray>=2025.1", "h5netcdf[h5py]>=1.8.1"]
|
|
29
|
+
grib = [
|
|
30
|
+
"eccodes>=2.48",
|
|
31
|
+
# The eccodes sdist metadata omits the library wheel that its own wheel declares.
|
|
32
|
+
"eccodeslib>=2.48; sys_platform == 'linux'",
|
|
33
|
+
"xarray>=2025.1",
|
|
34
|
+
"numpy>=2",
|
|
35
|
+
]
|
|
29
36
|
|
|
30
37
|
[project.urls]
|
|
31
38
|
Homepage = "https://usdata.dev/"
|
|
@@ -101,6 +108,7 @@ markers = [
|
|
|
101
108
|
"pandas: optional CSV reader coverage",
|
|
102
109
|
"radar: optional radar reader coverage",
|
|
103
110
|
"netcdf: optional NetCDF reader coverage",
|
|
111
|
+
"grib: optional GRIB2 reader coverage",
|
|
104
112
|
]
|
|
105
113
|
addopts = "-ra --strict-markers"
|
|
106
114
|
|
|
@@ -10,6 +10,7 @@ try:
|
|
|
10
10
|
except PackageNotFoundError: # running from a source tree without an install
|
|
11
11
|
__version__ = "0.0.0"
|
|
12
12
|
|
|
13
|
+
from usdata._fetch import ChecksumMismatch, FetchedAsset, fetch, fetch_asset
|
|
13
14
|
from usdata.models import Asset, BBox, Dataset, Provenance, Query, TemporalSelection, TimeRange
|
|
14
15
|
from usdata.pull import pull, verify
|
|
15
16
|
from usdata.query import build_query
|
|
@@ -19,8 +20,10 @@ from usdata.selection import select_by_time
|
|
|
19
20
|
__all__ = [
|
|
20
21
|
"Asset",
|
|
21
22
|
"BBox",
|
|
23
|
+
"ChecksumMismatch",
|
|
22
24
|
"Dataset",
|
|
23
25
|
"DatasetNotFound",
|
|
26
|
+
"FetchedAsset",
|
|
24
27
|
"Provenance",
|
|
25
28
|
"Query",
|
|
26
29
|
"Registry",
|
|
@@ -30,6 +33,8 @@ __all__ = [
|
|
|
30
33
|
"__version__",
|
|
31
34
|
"build_query",
|
|
32
35
|
"default_registry",
|
|
36
|
+
"fetch",
|
|
37
|
+
"fetch_asset",
|
|
33
38
|
"get",
|
|
34
39
|
"pull",
|
|
35
40
|
"search",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Mapping
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
@@ -35,15 +36,17 @@ class FetchedAsset(BaseModel):
|
|
|
35
36
|
usecols: list[str] | None = None,
|
|
36
37
|
nrows: int | None = None,
|
|
37
38
|
sweep: int | list[int] | None = None,
|
|
39
|
+
select: Mapping[str, Any] | None = None,
|
|
38
40
|
) -> Any:
|
|
39
|
-
"""Open local data with an optional ``pandas``, ``radar``, or ``
|
|
41
|
+
"""Open local data with an optional ``pandas``, ``radar``, ``netcdf``, or ``grib`` reader.
|
|
40
42
|
|
|
41
43
|
ERDDAP units are kept in ``frame.attrs["units"]`` and source provenance
|
|
42
44
|
in ``frame.attrs["usdata"]``. NEXRAD returns a xarray DataTree with provenance
|
|
43
|
-
in ``radar.attrs["usdata"]``. NetCDF4
|
|
44
|
-
matching provenance in its attributes. See ``usdata.readers.open_asset``
|
|
45
|
-
Use ``sweep=0`` or ``sweep=[0, 2]`` to load selected zero-based
|
|
46
|
-
|
|
45
|
+
in ``radar.attrs["usdata"]``. NetCDF4 and GRIB2 return a loaded xarray Dataset
|
|
46
|
+
with matching provenance in its attributes. See ``usdata.readers.open_asset``
|
|
47
|
+
for options. Use ``sweep=0`` or ``sweep=[0, 2]`` to load selected zero-based
|
|
48
|
+
radar sweeps, and ``select={"shortName": "cape", "typeOfLevel": "surface"}``
|
|
49
|
+
to choose GRIB2 messages. Cached files and provenance sidecars are never changed.
|
|
47
50
|
"""
|
|
48
51
|
from usdata.readers import open_asset
|
|
49
52
|
|
|
@@ -55,9 +58,24 @@ class FetchedAsset(BaseModel):
|
|
|
55
58
|
usecols=usecols,
|
|
56
59
|
nrows=nrows,
|
|
57
60
|
sweep=sweep,
|
|
61
|
+
select=select,
|
|
58
62
|
)
|
|
59
63
|
|
|
60
64
|
|
|
65
|
+
def _sidecar_not_older(path: Path) -> bool:
|
|
66
|
+
"""Whether ``path`` still carries the mtime it had when its sidecar was written.
|
|
67
|
+
|
|
68
|
+
The sidecar is always written after the data file lands, so a data file that
|
|
69
|
+
is newer than its sidecar was touched afterwards and the record no longer
|
|
70
|
+
implies its bytes. See ADR 0024.
|
|
71
|
+
"""
|
|
72
|
+
try:
|
|
73
|
+
sidecar = provenance.sidecar_path(path).stat()
|
|
74
|
+
return path.stat().st_mtime_ns <= sidecar.st_mtime_ns
|
|
75
|
+
except OSError:
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
|
|
61
79
|
def _fetch_asset(
|
|
62
80
|
dataset: Dataset,
|
|
63
81
|
asset: Asset,
|
|
@@ -82,7 +100,8 @@ def _fetch_asset(
|
|
|
82
100
|
and prov.source_url == asset.href
|
|
83
101
|
and prov.size == path.stat().st_size
|
|
84
102
|
and (asset.checksum is None or prov.checksum == asset.checksum)
|
|
85
|
-
|
|
103
|
+
# Trust an untouched cached file; hash whenever anything is unclear.
|
|
104
|
+
and (_sidecar_not_older(path) or sha256_file(path) == prov.checksum)
|
|
86
105
|
):
|
|
87
106
|
_progress.emit(_progress.AssetProgress(asset.id, "cached", prov.size))
|
|
88
107
|
return FetchedAsset(asset=asset, path=path, provenance=prov, from_cache=True)
|
|
@@ -100,16 +119,28 @@ def _fetch_asset(
|
|
|
100
119
|
def fetch_asset(
|
|
101
120
|
dataset: Dataset, asset: Asset, *, root: Path | None = None, force: bool = False
|
|
102
121
|
) -> FetchedAsset:
|
|
103
|
-
"""Fetch one asset, reusing the cache only when
|
|
122
|
+
"""Fetch one asset, reusing the cache only when its provenance still describes it."""
|
|
104
123
|
with load_adapter(dataset) as adapter:
|
|
105
124
|
return _fetch_asset(dataset, asset, adapter, root=root, force=force)
|
|
106
125
|
|
|
107
126
|
|
|
127
|
+
def _fetch_with(
|
|
128
|
+
adapter: Provider,
|
|
129
|
+
dataset: Dataset,
|
|
130
|
+
query: Query,
|
|
131
|
+
*,
|
|
132
|
+
root: Path | None = None,
|
|
133
|
+
force: bool = False,
|
|
134
|
+
) -> list[FetchedAsset]:
|
|
135
|
+
"""Run the loop on an adapter the caller opened, so one adapter can serve many queries."""
|
|
136
|
+
assets = adapter.list_assets(query)
|
|
137
|
+
_progress.batch([asset.size for asset in assets])
|
|
138
|
+
return [_fetch_asset(dataset, a, adapter, root=root, force=force) for a in assets]
|
|
139
|
+
|
|
140
|
+
|
|
108
141
|
def fetch(
|
|
109
142
|
dataset: Dataset, query: Query, *, root: Path | None = None, force: bool = False
|
|
110
143
|
) -> list[FetchedAsset]:
|
|
111
144
|
"""Resolve and fetch a query, sharing one adapter and closing its owned resources."""
|
|
112
145
|
with load_adapter(dataset) as adapter:
|
|
113
|
-
|
|
114
|
-
_progress.batch([asset.size for asset in assets])
|
|
115
|
-
return [_fetch_asset(dataset, a, adapter, root=root, force=force) for a in assets]
|
|
146
|
+
return _fetch_with(adapter, dataset, query, root=root, force=force)
|