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:
71
FAQ
Normal file
71
FAQ
Normal 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
35
INSTALL
@@ -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
63
README
Normal 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
19
weather
@@ -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)
|
||||
)
|
||||
|
||||
|
||||
13
weather.1
13
weather.1
@@ -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
|
||||
|
||||
84
weather.py
84
weather.py
@@ -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..."
|
||||
|
||||
10
weatherrc.5
10
weatherrc.5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user