Command-line utilities

weewx-nws manual · weewx-nws on GitHub · Report an issue


nws.py is not only the extension: run it directly and it becomes a diagnostic tool. Its job is answering the question no log line can — what is NWS actually serving for my location right now? — which is where a problem with this extension is usually settled.

Running it

nws.py imports WeeWX, so it must run with the python that runs WeeWX. Which command that is depends on your install:

# pip install (activate WeeWX's virtual environment first):
source ~/weewx-venv/bin/activate
python ~/weewx-data/bin/user/nws.py --help

# Debian or Red Hat package install:
PYTHONPATH=/usr/share/weewx python3 /etc/weewx/bin/user/nws.py --help

The examples below shorten that to bin/user/nws.py; use whichever of the forms above matches your install.

One exception: --test-service stands up a WeeWX engine, which imports user.nws, so it also needs the directory containing user on PYTHONPATH — ~/weewx-data/bin for a pip install, and for a package install both: PYTHONPATH=/usr/share/weewx:/etc/weewx/bin.

The utilities

--check-grid

Check that NWS maps your latitude and longitude to a gridpoint that really contains them, and print the weewx.conf lines that pin the correct one if it does not. See Gridpoints.

python bin/user/nws.py --check-grid --latitude 38.8977 --longitude -77.0365

--test-requester

Fetch one type of forecast for a location, parse it, and pretty print every record. The quickest way to see exactly what NWS is serving — and the first thing to run when a field looks wrong on a page. --type takes ONE_HOUR, TWELVE_HOUR or ALERTS.

python bin/user/nws.py --test-requester --type TWELVE_HOUR --latitude 38.8977 --longitude -77.0365

--test-parse-all-alerts

Fetch every alert currently active in the United States — several hundred — and run each through the sanity check and the parser, reporting how many parsed. This is the widest net there is for alert-parsing problems, and it is what to run after any change to the alert code. --print-records prints each alert as well as counting it.

python bin/user/nws.py --test-parse-all-alerts

--test-service

Stand up the full NWS service as WeeWX would, against a temporary sqlite database: request forecasts, save them, read them back. --binding uses a data binding other than nws_binding.

PYTHONPATH=/home/weewx/bin python bin/user/nws.py --test-service --latitude 38.8977 --longitude -77.0365

--test-multiple-gridpoints

Fetch twelve-hour and one-hour forecasts for several dozen US cities — a broad sample of NWS forecast offices, and the best way to catch a parsing assumption that only holds in one part of the country. It makes about 150 requests; do not run it in a loop.

python bin/user/nws.py --test-multiple-gridpoints

--test-point-in-polygon

An offline self-test of the gridpoint containment check. The only utility that does not contact NWS.

python bin/user/nws.py --test-point-in-polygon

--view-forecasts

Inspect an nws.sdb — read-only, and safe to run against the live database. Requires --type and --view-criterion:

Criterion Prints
SUMMARY One line per forecast: inserted, generated, and the first and last period it covers
LATEST Every record of the most recently generated forecast of that type
ALL Every record of that type in the database
python bin/user/nws.py --view-forecasts --type ONE_HOUR \
    --nws-database /home/weewx/archive/nws.sdb --view-criterion SUMMARY

--insert-forecast

Load a forecast saved to a file (json, as NWS returned it) into an nws.sdb — for reproducing a problem from a captured forecast. Requires --type, --filename, --nws-database, --latitude and --longitude; --archive_interval defaults to 300 seconds.

python bin/user/nws.py --insert-forecast --type ONE_HOUR --filename /tmp/ONE_HOUR \
    --nws-database /tmp/nws.sdb --latitude 38.8977 --longitude -77.0365

--help

Lists every option.

Testing a checkout

The repository carries a hermetic pytest suite — it never contacts NWS — plus one harness that does, and three more that are offline but need something the suite does not. Run them from the repository root, with the same python as above:

python -m pytest tests              # the hermetic suite
python tests/verify_cli.py          # every utility above, against live NWS, PASS/FAIL each
python tests/validate_skin_html.py  # renders the skin; validates every page and its css
python tests/verify_theme.py        # drives the pages in a browser at both color settings
python tests/verify_ink.py          # scores every piece of text against the pixels under it

verify_cli.py is the only one that contacts NWS; it takes --skip-multigrid to leave out the 50-city sweep and its ~150 requests. validate_skin_html.py needs java and vnu.jar. verify_theme.py and verify_ink.py need Playwright: the first is the only check that can catch a dark theme that validates, tests clean and never actually applies, and the second measures text against what is really painted under it — in both themes, at desktop and phone widths, and in every tab, chart readout and alert state — to WCAG 4.5 and APCA Lc 60.

The layers have different jobs, and both are needed: the suite catches regressions in this extension, while the live utility catches changes in what NWS serves — which the hermetic tests, validating our assumptions against saved responses, cannot see.


weewx-nws is Copyright © 2020–2026 John A Kline and is licensed under the GNU Public License v3.