usdata 0.29.0__tar.gz → 0.30.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.29.0 → usdata-0.30.0}/PKG-INFO +1 -1
- {usdata-0.29.0 → usdata-0.30.0}/pyproject.toml +1 -1
- {usdata-0.29.0 → usdata-0.30.0}/pyproject.toml.orig +1 -1
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_fetch.py +13 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_grib.py +12 -7
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cache.py +14 -5
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/data/places.csv +3300 -3292
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/data/places.sources.json +17 -1
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/manifest.py +79 -8
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/models.py +20 -4
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/provenance.py +1 -3
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/base.py +22 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/epa/aqs.py +4 -1
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/fema/declarations.py +6 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/coastwatch.py +5 -5
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/nws_vtec.py +4 -1
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/pull.py +40 -11
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/query.py +36 -5
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/readers.py +6 -6
- {usdata-0.29.0 → usdata-0.30.0}/README.md +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/__main__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_aqs.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_files.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_hurdat2.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_netcdf.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_progress.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/_radar.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cache_ops.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cite.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/app.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/cache.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/cite.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/doctor.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/inspect.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/cli/progress.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/data/nexrad_sites.csv +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/data/registry.yaml +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/doctor.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/inspect.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/mirror.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/protocols/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/protocols/erddap.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/protocols/http.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/protocols/listing.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/protocols/s3.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/credentials.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/epa/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/fema/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/http.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/coops.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/gfs.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/ghcnd.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/glm.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/goes.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/grib_index.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/gsom.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/gsoy.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/hrrr.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/hurdat2.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/ibtracs.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/lcd.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/mrms.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/nbm.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/nexrad.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/nexrad_level3.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/normals.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/rap.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/sites.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/spc.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/noaa/storm_events.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/params.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/usgs/__init__.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/usgs/daily.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/providers/usgs/earthquakes.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/py.typed +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/registry.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/selection.py +0 -0
- {usdata-0.29.0 → usdata-0.30.0}/src/usdata/testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: usdata
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.30.0
|
|
4
4
|
Summary: Unified Python SDK and CLI for discovering, fetching, and tracking provenance of U.S. public scientific data
|
|
5
5
|
Keywords: noaa,usgs,open-data,scientific-data,provenance,reproducible-research,weather,climate,meteorology
|
|
6
6
|
Author: Jake Van Slyke
|
|
@@ -234,6 +234,19 @@ def _fetch_with(
|
|
|
234
234
|
``staging`` is passed to each fetch; see ``_fetch_asset``.
|
|
235
235
|
"""
|
|
236
236
|
assets = ordered(adapter.list_assets(query))
|
|
237
|
+
return _fetch_listed(adapter, dataset, assets, root=root, force=force, staging=staging)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _fetch_listed(
|
|
241
|
+
adapter: Provider,
|
|
242
|
+
dataset: Dataset,
|
|
243
|
+
assets: list[Asset],
|
|
244
|
+
*,
|
|
245
|
+
root: Path | None = None,
|
|
246
|
+
force: bool = False,
|
|
247
|
+
staging: Path | None = None,
|
|
248
|
+
) -> list[FetchedAsset]:
|
|
249
|
+
"""Fetch assets already listed and put in order, as the loop does once it has listed them."""
|
|
237
250
|
_progress.batch([asset.size for asset in assets])
|
|
238
251
|
return [
|
|
239
252
|
_fetch_asset(dataset, a, adapter, root=root, force=force, staging=staging) for a in assets
|
|
@@ -304,15 +304,19 @@ def base_name(short_name: str | None, parameter: Sequence[Any], source: str) ->
|
|
|
304
304
|
return _product_name(source) or f"parameter_{discipline}_{category}_{number}"
|
|
305
305
|
|
|
306
306
|
|
|
307
|
-
def _time(date: Any, time: Any) -> str | None:
|
|
307
|
+
def _time(date: Any, time: Any, second: Any = None) -> str | None:
|
|
308
|
+
"""An ecCodes date and ``HHMM`` time as ISO 8601 UTC, with the message's seconds.
|
|
309
|
+
|
|
310
|
+
ecCodes spells times to the minute and keeps the reference time's seconds
|
|
311
|
+
in a key of their own, which MRMS sets: a file stamped ``20:00:41`` would
|
|
312
|
+
otherwise read as ``20:00:00``. A validity time is the reference time plus
|
|
313
|
+
a whole-minute step, so it carries the same seconds.
|
|
314
|
+
"""
|
|
308
315
|
if date is None or time is None:
|
|
309
316
|
return None
|
|
310
317
|
try:
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
.replace(tzinfo=UTC)
|
|
314
|
-
.isoformat()
|
|
315
|
-
)
|
|
318
|
+
stamp = datetime.strptime(f"{int(date):08d}{int(time):04d}", "%Y%m%d%H%M")
|
|
319
|
+
return stamp.replace(second=int(second or 0), tzinfo=UTC).isoformat()
|
|
316
320
|
except ValueError:
|
|
317
321
|
return None
|
|
318
322
|
|
|
@@ -494,11 +498,12 @@ def open_grib2(
|
|
|
494
498
|
# The file's own spelling stays beside the rewritten one, as cfgrib keeps it.
|
|
495
499
|
attrs["GRIB_units"] = units
|
|
496
500
|
attrs["units"] = plain
|
|
501
|
+
second = _get(eccodes, h, "second", int)
|
|
497
502
|
for label, date_key, time_key in (
|
|
498
503
|
("reference_time", "dataDate", "dataTime"),
|
|
499
504
|
("valid_time", "validityDate", "validityTime"),
|
|
500
505
|
):
|
|
501
|
-
stamp = _time(attrs.get(date_key), attrs.get(time_key))
|
|
506
|
+
stamp = _time(attrs.get(date_key), attrs.get(time_key), second)
|
|
502
507
|
if stamp:
|
|
503
508
|
attrs[label] = stamp
|
|
504
509
|
message: dict[str, Any] = {
|
|
@@ -10,6 +10,8 @@ from pathlib import Path
|
|
|
10
10
|
from usdata.models import Asset
|
|
11
11
|
|
|
12
12
|
ENV_VAR = "USDATA_CACHE_DIR"
|
|
13
|
+
SIDECAR_SUFFIX = ".provenance.json"
|
|
14
|
+
"""What a provenance sidecar's name adds to its data file's; ``provenance`` names it from here."""
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def cache_dir() -> Path:
|
|
@@ -38,7 +40,9 @@ def cached_path(dataset_id: str, asset_id: str, root: Path | None = None) -> Pat
|
|
|
38
40
|
The path the cache uses for that asset, whether or not it exists.
|
|
39
41
|
|
|
40
42
|
Raises:
|
|
41
|
-
ValueError: Either id is unsafe,
|
|
43
|
+
ValueError: Either id is unsafe, names a sidecar or temporary file, or the
|
|
44
|
+
path would escape the cache root. Symlinks inside the root are
|
|
45
|
+
followed like any directory, so part of the cache can live elsewhere.
|
|
42
46
|
"""
|
|
43
47
|
provider, sep, name = dataset_id.partition(":")
|
|
44
48
|
if not sep or any(
|
|
@@ -48,11 +52,16 @@ def cached_path(dataset_id: str, asset_id: str, root: Path | None = None) -> Pat
|
|
|
48
52
|
safe_id = asset_id.replace("/", "_")
|
|
49
53
|
if not safe_id or safe_id in {".", ".."} or "\\" in safe_id or "\x00" in safe_id:
|
|
50
54
|
raise ValueError(f"unsafe asset id: {asset_id!r}")
|
|
55
|
+
# A file of this name would be taken for another asset's sidecar, or for a temporary file.
|
|
56
|
+
if safe_id.endswith(SIDECAR_SUFFIX) or (safe_id.startswith(".") and safe_id.endswith(".part")):
|
|
57
|
+
raise ValueError(f"asset id {asset_id!r} names a file the cache keeps for itself")
|
|
51
58
|
base = (root or cache_dir()).expanduser().resolve()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
home = base / provider / name
|
|
60
|
+
path = home / safe_id
|
|
61
|
+
# Checked on the path as written, so a directory the user symlinked elsewhere is still
|
|
62
|
+
# inside the cache; only an id that re-anchors the path, such as C:x on Windows, is not.
|
|
63
|
+
if path.parent != home:
|
|
64
|
+
raise ValueError(f"cache path escapes root: {path}")
|
|
56
65
|
return path
|
|
57
66
|
|
|
58
67
|
|