Imported from archive.

* Release 1.1.

* weather: Switched to "#!/usr/bin/env python" instead for
portability.

* weather.1, weather.5, weather.py: Implemented the --omit-forecast
option to cancel --forecast.

* weather.py: Calling with undefined aliases now throws an error and
exits. Aliases, options and default overrides operate more
logically. Upped the version to 1.1.

* weatherrc: Added 214 standard aliases.
This commit is contained in:
Jeremy Stanley
2006-04-18 04:33:21 +00:00
parent 155d8574df
commit b755668b64
8 changed files with 1317 additions and 48 deletions

71
FAQ Normal file
View File

@@ -0,0 +1,71 @@
FREQUENTLY ASKED QUESTIONS ABOUT THE WEATHER UTILITY
Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
Licensed per terms in the LICENSE file distributed with this software.
1. Can I help?
Sure! Bug reports and feature suggestions are always welcome, but
fixes and patches are of course preferred. Contact
fungi@yuggoth.org if desired, but please read this FAQ and the
included manuals for weather(1) and weatherrc(5) before asking
questions that might be answered therein. One big way anyone can
help is to provide me with some additional mappings of METAR
station ID, city name and state abbreviation for inclusion in the
default /etc/weatherrc file.
2. How do I figure out my local METAR station ID?
The list of stations is found at
http://weather.noaa.gov/data/nsd_cccc.gz (it's thousands of lines
long, so I recommend keyword searching in your browser or using
grep(1) to find what you're looking for).
3. How do I figure out my local city name and state abbreviation?
The forecasts can be located starting from
http://weather.noaa.gov/pub/data/forecasts/city/ (choose the
state abbreviation to get to a list of cities in that state).
4. I live outside the USA--can this be made to work for me
anyway?
If you have any recommendations for similar forecast data in
other countries, I will be happy to try and find a way to
integrate it into the weather utility, but I suspect that some
serious modification would be necessary given that the data is
likely to be published in a non-English language, requiring some
additional input from speakers of that language for how to handle
filtering and formatting of the text.
5. I get a warning when using apt-get to install on Debian Etch
or later...
If you're getting a warning from apt-get update like:
W: GPG error: http://fungi.yuggoth.org ./ Release: The
following signatures couldn't be verified because the
public key is not available: NO_PUBKEY 29ABF7441FB84657
...it means my PGP key is not recognized by apt-get. Since this
isn't an official Debian package repository, the Release.gpg
file can't be signed by a key on the default keyring. To add my
personal key to the list of trusted package repository Release
signers, run (as root):
finger fungi@yuggoth.org | apt-key add -
...or if you want to be a little paranoid, retrieve it from a
public keyserver instead (all one line):
wget -O- "http://subkeys.pgp.net:11371/pks
/lookup?op=get&search=0x29ABF7441FB84657" | apt-key add -
Though if you're really, truly paranoid, you'll re-write the
program from scratch anyway, right?

35
INSTALL
View File

@@ -1,17 +1,36 @@
BASIC UNIX INSTALLATION INSTRUCTIONS FOR THE WEATHER UTILITY
Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
Licensed per terms in the LICENSE file distributed with this software.
PREREQUISITES
You need the Python interpreter installed somewhere in your path
(most modern UNIX derivatives come with one already). The weather
executable assumes your Python interpreter is /usr/bin/python so you
may need to edit the #! line if that is not the case. If you need
Python for some reason, it can be obtained from
http://www.python.org/ (but chances are your operating system at
least provides some sort of native package for it, which you should
probably install in whatever means is recommended by your OS
vendor/distributor).
(most modern UNIX derivatives come with one already). If you need to
get Python, it can be obtained from http://www.python.org/ (but
chances are your operating system at least provides some sort of
native package for it, which you should probably install in whatever
means is recommended by your OS vendor/distributor).
RUNNING IN PLACE
An easy way to try it out is to unpack the tarball and change to the
resulting directory:
tar xzf weather-*.tar.gz
cd weather
./weather --version
./weather --help
man ./weather.1
man ./weatherrc.5
./weather --forecast --no-conditions --city=charlotte --st=nc
./weather ord sea
...and so on. The weather utility, included Python module and
documentation are all fully functional when kept together in one
directory, if somewhat inconvenient.
INSTALLING THE UTILITY

63
README Normal file
View File

@@ -0,0 +1,63 @@
GENERAL INFORMATION ABOUT THE WEATHER UTILITY
Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
Licensed per terms in the LICENSE file distributed with this software.
WHAT?
This command-line utility is intended to provide quick access to
current weather conditions and forecasts. Presently, it is
capable of returning data for localities throughout the USA by
retrieving and formatting decoded METARs (Meteorological
Aerodrome Reports) from NOAA (the National Oceanic and
Atmospheric Administration) and forecasts from the NWS (National
Weather Service). The tool is written to function in the same
spirit as other command-line informational utilities like cal(1),
calendar(1) and dict(1). It can retrieve arbitrary weather data
via specific command-line switches (station ID, city, state), or
aliases can be configured system wide and on a per-user basis. It
can be freely used and redistributed under the terms of the BSD
License.
WHY?
My girlfriend has a long commute to/from work and school, and
often wants to check the weather both for home and her office.
Unfortunately, starting a Web browser, pulling up a weather site,
entering multiple ZIP codes and waiting for them to load is
time-consuming for the marginally-impatient. Since she tends to
stay logged into a shell server most of the time, I figured I'd
install a quick command-line tool to retrieve weather info for
her commute, but to my surprise, a quick search turned up little
that met my basic requirements:
* retrieve current data on-demand
* provide both current conditions and short-term forecasts
* simple, human-readable output
* easy to configure and use
* flexible command-line switches and options
WHERE?
A tarball for the most recent version of the weather utility can
be had here:
http://fungi.yuggoth.org/weather/src/
Alternatively, Debian users can grab a pre-built DEB package
here:
http://fungi.yuggoth.org/weather/debian/
...or add these lines for binary and, optionally, source packages
to /etc/apt/sources.list:
deb http://fungi.yuggoth.org/weather/debian ./
deb-src http://fungi.yuggoth.org/weather/debian ./
...then 'apt-get update && apt-get install weather-util' as root
to get the current package installed and working.

19
weather
View File

@@ -1,31 +1,34 @@
#!/usr/bin/python
#!/usr/bin/env python
# weather version 1.1, http://fungi.yuggoth.org/weather/
# Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
# Licensed per terms in the LICENSE file distributed with this software.
"""Wrapper utility using the weather.py module."""
import weather
# initialize options and configs
selections = weather.Selections()
get = selections.get
get_boolean = selections.get_boolean
get_bool = selections.get_bool
# this mode just lists the aliases defined in the config
if get_boolean("list"): print weather.list_aliases(selections.config)
if get_bool("list"): print weather.list_aliases(selections.config)
# normal operation
else:
for argument in selections.arguments:
if get_boolean("conditions", argument):
if get_bool("conditions", argument):
print weather.get_metar(
get("id", argument),
get_boolean("verbose", argument)
get_bool("verbose", argument)
)
if not get_boolean("conditions", argument) \
or get_boolean("forecast", argument):
if not get_bool("conditions", argument) \
or get_bool("forecast", argument):
print weather.get_forecast(
get("city", argument),
get("st", argument),
get_boolean("verbose", argument)
get_bool("verbose", argument)
)

View File

@@ -1,4 +1,6 @@
.TH WEATHER 1 "March 26, 2006"
.TH WEATHER 1 "March 26, 2006" "" \" -*- nroff -*-
\" Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
\" Licensed per terms in the LICENSE file distributed with this software.
.SH NAME
weather \- command\-line tool to obtain weather conditions and forecasts
.SH SYNOPSIS
@@ -38,7 +40,10 @@ the METAR station ID (ex: KRDU)
print a list of configured aliases
.TP
.B \-n, \-\-no\-conditions
disable output of current conditions (implies \-\-forecast)
disable output of current conditions (forces \-f)
.TP
.B \-o, \-\-omit\-forecast
omit the local forecast (cancels \-f)
.TP
.B \-sST, \-\-st=ST
the state abbreviation (ex: NC)
@@ -60,7 +65,7 @@ the system\-wide configuration
.B ~/.weatherrc
the per\-user configuration (can be used to override the above)
.TP
.B ./.weatherrc
.B ./weatherrc
the local directory configuration (can be used to override the above)
.SH EXAMPLES
.TP
@@ -76,7 +81,7 @@ See a forecast for the Asheville, NC area.
.TP
.B weather -fv gso
Get the full decoded METAR for the station associated with the gso alias,
and the forecast data for the City/State associated with the gso alias,
and the forecast data for the city/state associated with the gso alias,
without filtering or fancy formatting.
.TP
.B weather home work

View File

@@ -1,32 +1,43 @@
# weather.py version 1.1, http://fungi.yuggoth.org/weather/
# Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
# Licensed per terms in the LICENSE file distributed with this software.
version = "1.0"
"""Contains various object definitions needed by the weather utility."""
version = "1.1"
class Selections:
"""An object to contain selection data."""
def __init__(self):
"""Store the config, options and arguments."""
self.config = get_config()
self.options, self.arguments = get_options()
self.options, self.arguments = get_options(self.config)
if self.arguments:
self.arguments = [(x.lower()) for x in self.arguments]
else: self.arguments = [ None ]
def get(self, option, argument=None):
"""Retrieve data from the config or options."""
if not argument: argument = "default"
if self.config.has_option(argument, option):
if not argument: return self.options.__dict__[option]
elif not self.config.has_section(argument):
import sys
sys.stderr.write("ERROR: no alias defined for " \
+ argument + "\n")
sys.exit(1)
elif self.config.has_option(argument, option):
return self.config.get(argument, option)
else: return self.options.__dict__[option]
def get_boolean(self, option, argument=None):
def get_bool(self, option, argument=None):
"""Get data and coerce to a boolean if necessary."""
data = self.get(option, argument)
if type(data) is str:
if eval(data): return True
else: return False
else:
if data: return True
else: return False
return bool(self.get(option, argument))
def bool(data):
"""Coerce data to a boolean value."""
if type(data) is str:
if eval(data): return True
else: return False
else:
if data: return True
else: return False
def quote(words):
"""Wrap a string in quotes if it contains spaces."""
@@ -68,6 +79,8 @@ def get_metar(id, verbose=False):
for line in lines:
for heading in headings:
if line.startswith(heading + ":"):
if line.endswith(":0"):
line = line[:-2]
output.append(" " + line)
return "\n".join(output)
@@ -87,43 +100,66 @@ def get_forecast(city, st, verbose=False):
output.append(line.replace(".", " ", 1))
return "\n".join(output)
def get_options():
def get_options(config):
"""Parse the options passed on the command line."""
import optparse
usage = "usage: %prog [ options ] [ alias [ alias [...] ] ]"
verstring = "%prog " + version
option_parser = optparse.OptionParser(usage=usage, version=verstring)
if config.has_option("default", "city"):
default_city = config.get("default", "city")
else: default_city = "Raleigh Durham"
option_parser.add_option("-c", "--city",
dest="city",
default="Raleigh Durham",
default=default_city,
help="the city name (ex: \"Raleigh Durham\")")
if config.has_option("default", "forecast"):
default_forecast = bool(config.get("default", "forecast"))
else: default_forecast = False
option_parser.add_option("-f", "--forecast",
dest="forecast",
action="store_true",
default=False,
help="include forecast (needs -c and -s)")
default=default_forecast,
help="include a local forecast")
if config.has_option("default", "id"):
default_id = config.get("default", "id")
else: default_id = "KRDU"
option_parser.add_option("-i", "--id",
dest="id",
default="KRDU",
default=default_id,
help="the METAR station ID (ex: KRDU)")
option_parser.add_option("-l", "--list",
dest="list",
action="store_true",
default=False,
help="print a list of configured aliases")
if config.has_option("default", "conditions"):
default_conditions = bool(config.get("default", "conditions"))
else: default_conditions = True
option_parser.add_option("-n", "--no-conditions",
dest="conditions",
action="store_false",
default=True,
help="disable output of current conditions (implies --forecast)")
default=default_conditions,
help="disable output of current conditions (forces -f)")
option_parser.add_option("-o", "--omit-forecast",
dest="forecast",
action="store_false",
default=default_forecast,
help="omit the local forecast (cancels -f)")
if config.has_option("default", "st"):
default_st = config.get("default", "st")
else: default_st = "NC"
option_parser.add_option("-s", "--st",
dest="st",
default="NC",
default=default_st,
help="the state abbreviation (ex: NC)")
if config.has_option("default", "verbose"):
default_verbose = bool(config.get("default", "verbose"))
else: default_verbose = False
option_parser.add_option("-v", "--verbose",
dest="verbose",
action="store_true",
default=False,
default=default_verbose,
help="show full decoded feeds")
options, arguments = option_parser.parse_args()
return options, arguments
@@ -134,9 +170,9 @@ def get_config():
config = ConfigParser.ConfigParser()
import os.path
rcfiles = [
".weatherrc",
"/etc/weatherrc",
os.path.expanduser("~/.weatherrc"),
"/etc/weatherrc"
"weatherrc"
]
import os
for rcfile in rcfiles:
@@ -153,7 +189,7 @@ def get_config():
def list_aliases(config):
"""Return a formatted list of aliases defined in the config."""
sections = []
for section in config.sections():
for section in sorted(config.sections()):
if section.lower() not in sections and section != "default":
sections.append(section.lower())
output = "configured aliases..."

1070
weatherrc

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
.TH WEATHERRC 5 "March 26, 2006"
.TH WEATHERRC 5 "March 26, 2006" "" \" -*- nroff -*-
\" Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
\" Licensed per terms in the LICENSE file distributed with this software.
.SH NAME
weatherrc \- configuration file format for the
.BR weather (1)
@@ -7,9 +9,9 @@ utility
The weatherrc file format is intended to specify a set of macros
by which to group a METAR station ID for current conditions data with a
city/state combination for a forecast, but many of the other
command\-line options/flags for the weather utility can be specified as
well. The file is organized as an INI-format config, with the alias name
in [] brackets and the associated parameter/value pairs on following
command\-line options and flags for the weather utility can be specified
as well. The file is organized as an INI-format config, with the alias
name in [] brackets and the associated parameter/value pairs on following
lines. Parameters and their values as separated by = or : characters.
Multi-word values do not need quoting.
.SH PARAMETERS