usdata 0.4.0__tar.gz → 0.6.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.
Files changed (38) hide show
  1. {usdata-0.4.0 → usdata-0.6.0}/PKG-INFO +46 -11
  2. {usdata-0.4.0 → usdata-0.6.0}/README.md +43 -10
  3. {usdata-0.4.0 → usdata-0.6.0}/pyproject.toml +4 -1
  4. {usdata-0.4.0 → usdata-0.6.0}/pyproject.toml.orig +4 -1
  5. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/cli/app.py +13 -4
  6. usdata-0.6.0/src/usdata/data/places.csv +3292 -0
  7. usdata-0.6.0/src/usdata/data/places.sources.json +20 -0
  8. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/data/registry.yaml +27 -23
  9. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/fetch.py +22 -0
  10. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/manifest.py +1 -0
  11. usdata-0.6.0/src/usdata/protocols/erddap.py +115 -0
  12. usdata-0.6.0/src/usdata/protocols/http.py +96 -0
  13. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/protocols/s3.py +1 -1
  14. usdata-0.6.0/src/usdata/providers/noaa/coastwatch.py +148 -0
  15. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/noaa/ghcnd.py +12 -3
  16. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/noaa/nexrad.py +24 -4
  17. usdata-0.6.0/src/usdata/providers/usgs/__init__.py +1 -0
  18. usdata-0.6.0/src/usdata/providers/usgs/daily.py +145 -0
  19. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/pull.py +24 -8
  20. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/query.py +50 -16
  21. usdata-0.6.0/src/usdata/readers.py +103 -0
  22. usdata-0.4.0/src/usdata/data/places.yaml +0 -10
  23. usdata-0.4.0/src/usdata/protocols/http.py +0 -38
  24. usdata-0.4.0/src/usdata/providers/noaa/coastwatch.py +0 -20
  25. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/__init__.py +0 -0
  26. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/_files.py +0 -0
  27. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/cache.py +0 -0
  28. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/cli/__init__.py +0 -0
  29. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/data/nexrad_sites.csv +0 -0
  30. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/models.py +0 -0
  31. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/protocols/__init__.py +0 -0
  32. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/provenance.py +0 -0
  33. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/__init__.py +0 -0
  34. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/base.py +0 -0
  35. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/noaa/__init__.py +0 -0
  36. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/providers/noaa/sites.py +0 -0
  37. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/py.typed +0 -0
  38. {usdata-0.4.0 → usdata-0.6.0}/src/usdata/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usdata
3
- Version: 0.4.0
3
+ Version: 0.6.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,nasa,open-data,scientific-data,provenance
6
6
  Author: Jake Van Slyke
@@ -14,9 +14,11 @@ Requires-Dist: httpx>=0.28.1
14
14
  Requires-Dist: pydantic>=2.7
15
15
  Requires-Dist: pyyaml>=6.0
16
16
  Requires-Dist: typer>=0.12
17
+ Requires-Dist: pandas>=3.0 ; extra == 'pandas'
17
18
  Requires-Python: >=3.11
18
19
  Project-URL: Homepage, https://github.com/jakeryderv/usdata
19
20
  Project-URL: Repository, https://github.com/jakeryderv/usdata
21
+ Provides-Extra: pandas
20
22
  Description-Content-Type: text/markdown
21
23
 
22
24
  # usdata
@@ -24,24 +26,25 @@ Description-Content-Type: text/markdown
24
26
  Unified Python SDK and CLI for discovering, fetching, and tracking the
25
27
  provenance of U.S. public scientific data (NOAA, USGS, NASA, and more).
26
28
 
27
- > Status: pre-alpha. `noaa:ghcn-daily` and `noaa:nexrad-level2` fetch real
28
- > data with provenance; other registry entries are stubs.
29
+ > Status: pre-alpha. v0.6 supports GHCN-Daily, NEXRAD Level II, USGS daily
30
+ > values, and CoastWatch SST subsets with provenance, plus Census state/county
31
+ > lookup and optional pandas CSV readers. Other datasets are planned.
29
32
  > See [docs/roadmap.md](docs/roadmap.md).
30
33
 
31
34
  ## Providers
32
35
 
33
36
  <!-- registry:start -->
34
- | Provider | Available | Stub | Planned | Next up (0.5) | Datasets |
37
+ | Provider | Available | Stub | Planned | Next up (unassigned) | Datasets |
35
38
  |---|---:|---:|---:|---|---|
36
- | [NOAA](docs/providers/noaa.md) | 2 | 1 | 26 | `gsom`, `gsoy`, `storm-events`, `mrms`, `goes-abi`, `hurdat2`, `ibtracs`, `climate-normals`, `coops-water-levels`, `coastwatch-sst` | `ghcn-daily`, `nexrad-level2`, _coastwatch-sst_, +26 planned |
39
+ | [NOAA](docs/providers/noaa.md) | 3 | 0 | 26 | — | `ghcn-daily`, `nexrad-level2`, `coastwatch-sst`, +26 planned |
40
+ | [USGS](docs/providers/usgs.md) | 1 | 0 | 2 | — | `water-daily`, +2 planned |
37
41
  | [Census Bureau](docs/providers/census.md) | 0 | 0 | 1 | — | +1 planned |
38
42
  | [EPA](docs/providers/epa.md) | 0 | 0 | 1 | — | +1 planned |
39
43
  | [FEMA](docs/providers/fema.md) | 0 | 0 | 1 | — | +1 planned |
40
44
  | [NASA](docs/providers/nasa.md) | 0 | 0 | 1 | — | +1 planned |
41
45
  | [USDA](docs/providers/usda.md) | 0 | 0 | 1 | — | +1 planned |
42
- | [USGS](docs/providers/usgs.md) | 0 | 0 | 3 | `water-daily` | +3 planned |
43
46
 
44
- Available datasets are in `code`, stubs in _italics_; planned ones are counted. Each provider page has access notes and full dataset details; [docs/roadmap.md](docs/roadmap.md) lists datasets by target version.
47
+ Available datasets are in `code`, stubs in _italics_; planned ones are counted. Available means implemented in this source checkout; consult the [releases](https://github.com/jakeryderv/usdata/releases) for published support. Each provider page has access notes and full dataset details; [docs/roadmap.md](docs/roadmap.md) lists datasets by target version.
45
48
  <!-- registry:end -->
46
49
 
47
50
  ## Install
@@ -74,6 +77,7 @@ for item in fetch(ds, query):
74
77
 
75
78
  ```sh
76
79
  usdata search "tornado radar" --state OK
80
+ usdata search precipitation --location "Cleveland County, OK"
77
81
  usdata info noaa:ghcn-daily
78
82
  usdata fetch noaa:ghcn-daily --lat 35.39 --lon -97.60 --radius-km 15 \
79
83
  --start 2024-05-06 --end 2024-05-07 --vars PRCP,TMAX
@@ -81,6 +85,10 @@ usdata fetch noaa:ghcn-daily -p stations=USW00013967 --start 2024-01-01 --end 20
81
85
  usdata fetch noaa:nexrad-level2 --lat 35.47 --lon -97.52 \
82
86
  --start 2024-05-06T20:00 --end 2024-05-06T23:00 # nearest radar (KTLX)
83
87
  usdata fetch noaa:nexrad-level2 -p site=KTLX --start 2024-05-06T20:00 --end 2024-05-06T20:30 --dry-run
88
+ usdata fetch usgs:water-daily -p sites=07164500 --vars 00060 \
89
+ --start 2024-05-06 --end 2024-05-07
90
+ usdata fetch noaa:coastwatch-sst --bbox=-80.08,30.02,-80.02,30.08 \
91
+ --start 2024-05-06T12:00Z --end 2024-05-06T12:00Z # four grid cells
84
92
  usdata pull dataset.yaml # resolve, fetch, write dataset.lock.json
85
93
  usdata verify dataset.yaml # exit 1 if any cached input drifted
86
94
  ```
@@ -89,6 +97,11 @@ Fetched files land in `~/.cache/usdata/<provider>/<dataset>/` (override with
89
97
  `USDATA_CACHE_DIR` or `--cache-dir`), each with a `.provenance.json` sidecar
90
98
  recording source URL, retrieval time, checksum, size, and license.
91
99
 
100
+ Locations accept state names/postal codes, county/state names, and quoted FIPS
101
+ codes. These select bounding rectangles; see [place lookup](docs/reference/places.md)
102
+ for coverage, ambiguity, and antimeridian limits. CoastWatch CSV includes a
103
+ second header row containing units; see its [access notes](docs/providers/noaa.md#coastwatch-sst).
104
+
92
105
  Manifest and source fields are validated strictly; unknown fields are errors.
93
106
  Provider-specific options belong under `params`.
94
107
 
@@ -96,8 +109,15 @@ A manifest declares every input a project needs. `pull` resolves each source,
96
109
  fetches it, and writes `dataset.lock.json` pinning every asset with its checksum
97
110
  and provenance. A second `pull` restores exactly what the lockfile pins without
98
111
  re-querying upstream, so the inputs stay reproducible even if the source
99
- changes. `verify` re-hashes the cached files against the lockfile. Editing the
100
- manifest after locking requires `pull --force` to re-resolve.
112
+ changes. `verify` checks the manifest checksum and re-hashes cached files
113
+ against the lockfile. Editing the manifest after locking requires `pull --force`
114
+ to re-resolve. A required source matching no assets fails the pull; set
115
+ `allow_empty: true` on a source only when an empty result is intentional.
116
+
117
+ Checksums detect upstream changes; they cannot recover historical bytes that
118
+ are no longer available. Preserve the cache for long-lived reproducibility.
119
+ See the [manifest reference](docs/reference/manifests.md) and the small
120
+ [NOAA/USGS example](examples/weather-and-streamflow/README.md).
101
121
 
102
122
  ```yaml
103
123
  name: tornado-environment
@@ -112,6 +132,14 @@ sources:
112
132
  end: 2024-05-31
113
133
  ```
114
134
 
135
+ ## Opening CSV data
136
+
137
+ `FetchedAsset.open()` is available since v0.6 with the optional pandas
138
+ extra (`pip install "usdata[pandas]"`). It reads cached CSV into a DataFrame,
139
+ preserves identifier strings, and keeps CoastWatch units as metadata.
140
+ See the [reader reference](docs/reference/readers.md)
141
+ and [fetch → open → analyze example](examples/sst-analysis/README.md).
142
+
115
143
  ## Development
116
144
 
117
145
  Requires [uv](https://docs.astral.sh/uv/) and [just](https://just.systems/).
@@ -120,11 +148,18 @@ Requires [uv](https://docs.astral.sh/uv/) and [just](https://just.systems/).
120
148
  git clone https://github.com/jakeryderv/usdata && cd usdata
121
149
  just setup # install toolchain and dependencies
122
150
  just test # unit tests
123
- just check # format, lint, typecheck, tests (what CI runs)
151
+ just check # format, lint, typecheck, offline tests, generated docs, release notices
152
+ just check-pandas # install the CSV extra and run the same checks
153
+ just build # build wheel and sdist
154
+ just smoke # exercise core and pandas wheel installations outside the checkout
124
155
  just run search radar
125
156
  ```
126
157
 
127
- Integration tests that hit live services run with `just test-integration`.
158
+ Unit tests mechanically block network connections. Integration tests that hit
159
+ live services run with `just test-integration`. CI checks Python 3.11 and 3.14 on
160
+ Linux, both with and without pandas, and smoke-tests both installed-wheel
161
+ profiles on Linux, macOS, and Windows. The full unit and live-service suites currently run on Linux. `just setup` restores
162
+ a core-only development environment; `just check-pandas` installs the extra.
128
163
 
129
164
  Releases: `just release minor` opens a version-bump PR; merging it publishes
130
165
  to PyPI and creates the tag and GitHub release. See
@@ -3,24 +3,25 @@
3
3
  Unified Python SDK and CLI for discovering, fetching, and tracking the
4
4
  provenance of U.S. public scientific data (NOAA, USGS, NASA, and more).
5
5
 
6
- > Status: pre-alpha. `noaa:ghcn-daily` and `noaa:nexrad-level2` fetch real
7
- > data with provenance; other registry entries are stubs.
6
+ > Status: pre-alpha. v0.6 supports GHCN-Daily, NEXRAD Level II, USGS daily
7
+ > values, and CoastWatch SST subsets with provenance, plus Census state/county
8
+ > lookup and optional pandas CSV readers. Other datasets are planned.
8
9
  > See [docs/roadmap.md](docs/roadmap.md).
9
10
 
10
11
  ## Providers
11
12
 
12
13
  <!-- registry:start -->
13
- | Provider | Available | Stub | Planned | Next up (0.5) | Datasets |
14
+ | Provider | Available | Stub | Planned | Next up (unassigned) | Datasets |
14
15
  |---|---:|---:|---:|---|---|
15
- | [NOAA](docs/providers/noaa.md) | 2 | 1 | 26 | `gsom`, `gsoy`, `storm-events`, `mrms`, `goes-abi`, `hurdat2`, `ibtracs`, `climate-normals`, `coops-water-levels`, `coastwatch-sst` | `ghcn-daily`, `nexrad-level2`, _coastwatch-sst_, +26 planned |
16
+ | [NOAA](docs/providers/noaa.md) | 3 | 0 | 26 | — | `ghcn-daily`, `nexrad-level2`, `coastwatch-sst`, +26 planned |
17
+ | [USGS](docs/providers/usgs.md) | 1 | 0 | 2 | — | `water-daily`, +2 planned |
16
18
  | [Census Bureau](docs/providers/census.md) | 0 | 0 | 1 | — | +1 planned |
17
19
  | [EPA](docs/providers/epa.md) | 0 | 0 | 1 | — | +1 planned |
18
20
  | [FEMA](docs/providers/fema.md) | 0 | 0 | 1 | — | +1 planned |
19
21
  | [NASA](docs/providers/nasa.md) | 0 | 0 | 1 | — | +1 planned |
20
22
  | [USDA](docs/providers/usda.md) | 0 | 0 | 1 | — | +1 planned |
21
- | [USGS](docs/providers/usgs.md) | 0 | 0 | 3 | `water-daily` | +3 planned |
22
23
 
23
- Available datasets are in `code`, stubs in _italics_; planned ones are counted. Each provider page has access notes and full dataset details; [docs/roadmap.md](docs/roadmap.md) lists datasets by target version.
24
+ Available datasets are in `code`, stubs in _italics_; planned ones are counted. Available means implemented in this source checkout; consult the [releases](https://github.com/jakeryderv/usdata/releases) for published support. Each provider page has access notes and full dataset details; [docs/roadmap.md](docs/roadmap.md) lists datasets by target version.
24
25
  <!-- registry:end -->
25
26
 
26
27
  ## Install
@@ -53,6 +54,7 @@ for item in fetch(ds, query):
53
54
 
54
55
  ```sh
55
56
  usdata search "tornado radar" --state OK
57
+ usdata search precipitation --location "Cleveland County, OK"
56
58
  usdata info noaa:ghcn-daily
57
59
  usdata fetch noaa:ghcn-daily --lat 35.39 --lon -97.60 --radius-km 15 \
58
60
  --start 2024-05-06 --end 2024-05-07 --vars PRCP,TMAX
@@ -60,6 +62,10 @@ usdata fetch noaa:ghcn-daily -p stations=USW00013967 --start 2024-01-01 --end 20
60
62
  usdata fetch noaa:nexrad-level2 --lat 35.47 --lon -97.52 \
61
63
  --start 2024-05-06T20:00 --end 2024-05-06T23:00 # nearest radar (KTLX)
62
64
  usdata fetch noaa:nexrad-level2 -p site=KTLX --start 2024-05-06T20:00 --end 2024-05-06T20:30 --dry-run
65
+ usdata fetch usgs:water-daily -p sites=07164500 --vars 00060 \
66
+ --start 2024-05-06 --end 2024-05-07
67
+ usdata fetch noaa:coastwatch-sst --bbox=-80.08,30.02,-80.02,30.08 \
68
+ --start 2024-05-06T12:00Z --end 2024-05-06T12:00Z # four grid cells
63
69
  usdata pull dataset.yaml # resolve, fetch, write dataset.lock.json
64
70
  usdata verify dataset.yaml # exit 1 if any cached input drifted
65
71
  ```
@@ -68,6 +74,11 @@ Fetched files land in `~/.cache/usdata/<provider>/<dataset>/` (override with
68
74
  `USDATA_CACHE_DIR` or `--cache-dir`), each with a `.provenance.json` sidecar
69
75
  recording source URL, retrieval time, checksum, size, and license.
70
76
 
77
+ Locations accept state names/postal codes, county/state names, and quoted FIPS
78
+ codes. These select bounding rectangles; see [place lookup](docs/reference/places.md)
79
+ for coverage, ambiguity, and antimeridian limits. CoastWatch CSV includes a
80
+ second header row containing units; see its [access notes](docs/providers/noaa.md#coastwatch-sst).
81
+
71
82
  Manifest and source fields are validated strictly; unknown fields are errors.
72
83
  Provider-specific options belong under `params`.
73
84
 
@@ -75,8 +86,15 @@ A manifest declares every input a project needs. `pull` resolves each source,
75
86
  fetches it, and writes `dataset.lock.json` pinning every asset with its checksum
76
87
  and provenance. A second `pull` restores exactly what the lockfile pins without
77
88
  re-querying upstream, so the inputs stay reproducible even if the source
78
- changes. `verify` re-hashes the cached files against the lockfile. Editing the
79
- manifest after locking requires `pull --force` to re-resolve.
89
+ changes. `verify` checks the manifest checksum and re-hashes cached files
90
+ against the lockfile. Editing the manifest after locking requires `pull --force`
91
+ to re-resolve. A required source matching no assets fails the pull; set
92
+ `allow_empty: true` on a source only when an empty result is intentional.
93
+
94
+ Checksums detect upstream changes; they cannot recover historical bytes that
95
+ are no longer available. Preserve the cache for long-lived reproducibility.
96
+ See the [manifest reference](docs/reference/manifests.md) and the small
97
+ [NOAA/USGS example](examples/weather-and-streamflow/README.md).
80
98
 
81
99
  ```yaml
82
100
  name: tornado-environment
@@ -91,6 +109,14 @@ sources:
91
109
  end: 2024-05-31
92
110
  ```
93
111
 
112
+ ## Opening CSV data
113
+
114
+ `FetchedAsset.open()` is available since v0.6 with the optional pandas
115
+ extra (`pip install "usdata[pandas]"`). It reads cached CSV into a DataFrame,
116
+ preserves identifier strings, and keeps CoastWatch units as metadata.
117
+ See the [reader reference](docs/reference/readers.md)
118
+ and [fetch → open → analyze example](examples/sst-analysis/README.md).
119
+
94
120
  ## Development
95
121
 
96
122
  Requires [uv](https://docs.astral.sh/uv/) and [just](https://just.systems/).
@@ -99,11 +125,18 @@ Requires [uv](https://docs.astral.sh/uv/) and [just](https://just.systems/).
99
125
  git clone https://github.com/jakeryderv/usdata && cd usdata
100
126
  just setup # install toolchain and dependencies
101
127
  just test # unit tests
102
- just check # format, lint, typecheck, tests (what CI runs)
128
+ just check # format, lint, typecheck, offline tests, generated docs, release notices
129
+ just check-pandas # install the CSV extra and run the same checks
130
+ just build # build wheel and sdist
131
+ just smoke # exercise core and pandas wheel installations outside the checkout
103
132
  just run search radar
104
133
  ```
105
134
 
106
- Integration tests that hit live services run with `just test-integration`.
135
+ Unit tests mechanically block network connections. Integration tests that hit
136
+ live services run with `just test-integration`. CI checks Python 3.11 and 3.14 on
137
+ Linux, both with and without pandas, and smoke-tests both installed-wheel
138
+ profiles on Linux, macOS, and Windows. The full unit and live-service suites currently run on Linux. `just setup` restores
139
+ a core-only development environment; `just check-pandas` installs the extra.
107
140
 
108
141
  Releases: `just release minor` opens a version-bump PR; merging it publishes
109
142
  to PyPI and creates the tag and GitHub release. See
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "usdata"
3
- version = "0.4.0"
3
+ version = "0.6.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"
@@ -30,6 +30,9 @@ dependencies = [
30
30
  name = "Jake Van Slyke"
31
31
  email = "jakervanslyke@gmail.com"
32
32
 
33
+ [project.optional-dependencies]
34
+ pandas = ["pandas>=3.0"]
35
+
33
36
  [project.urls]
34
37
  Homepage = "https://github.com/jakeryderv/usdata"
35
38
  Repository = "https://github.com/jakeryderv/usdata"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "usdata"
3
- version = "0.4.0"
3
+ version = "0.6.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"
@@ -22,6 +22,9 @@ dependencies = [
22
22
  "typer>=0.12",
23
23
  ]
24
24
 
25
+ [project.optional-dependencies]
26
+ pandas = ["pandas>=3.0"]
27
+
25
28
  [project.urls]
26
29
  Homepage = "https://github.com/jakeryderv/usdata"
27
30
  Repository = "https://github.com/jakeryderv/usdata"
@@ -14,7 +14,7 @@ from usdata.fetch import fetch as fetch_query
14
14
  from usdata.manifest import lockfile_path
15
15
  from usdata.providers import load_adapter
16
16
  from usdata.providers.base import NotImplementedProvider
17
- from usdata.pull import ManifestChanged, UnknownDatasets
17
+ from usdata.pull import EmptySource, ManifestChanged, UnknownDatasets
18
18
  from usdata.pull import pull as pull_manifest
19
19
  from usdata.pull import verify as verify_manifest
20
20
  from usdata.query import UnknownPlace
@@ -50,7 +50,10 @@ def search(
50
50
  provider: Annotated[
51
51
  str | None, typer.Option(help="Restrict to one provider, e.g. noaa.")
52
52
  ] = None,
53
- state: Annotated[str | None, typer.Option(help="State name or postal code.")] = None,
53
+ state: Annotated[
54
+ str | None,
55
+ typer.Option("--location", "--state", help="State, 'County, ST', or quoted FIPS code."),
56
+ ] = None,
54
57
  start: Annotated[str | None, typer.Option(help="ISO date or datetime.")] = None,
55
58
  end: Annotated[str | None, typer.Option(help="ISO date or datetime.")] = None,
56
59
  planned: Annotated[
@@ -104,7 +107,10 @@ def info(
104
107
  @app.command()
105
108
  def fetch(
106
109
  dataset_id: Annotated[str, typer.Argument(help="Dataset id, e.g. noaa:ghcn-daily")],
107
- state: Annotated[str | None, typer.Option(help="State name or postal code.")] = None,
110
+ state: Annotated[
111
+ str | None,
112
+ typer.Option("--location", "--state", help="State, 'County, ST', or quoted FIPS code."),
113
+ ] = None,
108
114
  bbox: Annotated[str | None, typer.Option(help="west,south,east,north in degrees.")] = None,
109
115
  lat: Annotated[float | None, typer.Option()] = None,
110
116
  lon: Annotated[float | None, typer.Option()] = None,
@@ -190,6 +196,9 @@ def pull(
190
196
  """Fetch every source in a manifest and write (or restore from) its lockfile."""
191
197
  try:
192
198
  result = pull_manifest(manifest, root=cache_dir, force=force)
199
+ except EmptySource as e:
200
+ typer.secho(str(e), err=True, fg="yellow")
201
+ raise typer.Exit(code=1) from None
193
202
  except (DatasetNotFound, UnknownDatasets, ManifestChanged, UnknownPlace, ValueError) as e:
194
203
  typer.secho(str(e), err=True, fg="red")
195
204
  raise typer.Exit(code=2) from None
@@ -218,7 +227,7 @@ def verify(
218
227
  raise typer.Exit(code=2)
219
228
  try:
220
229
  drift = verify_manifest(manifest, root=cache_dir)
221
- except (ValueError, OSError) as e:
230
+ except (ManifestChanged, ValueError, OSError) as e:
222
231
  typer.secho(str(e), err=True, fg="red")
223
232
  raise typer.Exit(code=2) from None
224
233
  for d in drift: