* Initial release 1.0.
--- /dev/null
+BASIC UNIX INSTALLATION INSTRUCTIONS FOR THE WEATHER UTILITY
+
+
+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).
+
+
+INSTALLING THE UTILITY
+
+The file named weather should be made executable and put somewhere
+in your path (/usr/local/bin/ or ~/bin/ for example). Similarly,
+weather.py needs to be somewhere in Python's include path. You can
+see your Python interpreter's default include path by running:
+
+ python -c "import sys ; print sys.path"
+
+
+CONFIGURATION
+
+The weatherrc file should go in /etc/ or you can save it in your
+home directory as a dotfile (~/.weatherrc) to support user-specific
+alias configuration and overrides of the global /etc/weatherrc file.
+
+
+MANUALS
+
+Optionally, the weather.1 and weatherrc.5 files can be placed in
+sane locations for TROFF/NROFF manual files on your system (for
+example, /usr/local/share/man/ or ~/man/).
+
--- /dev/null
+Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
--- /dev/null
+#!/usr/bin/python
+
+# Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
+# Licensed per terms in the LICENSE file distributed with this software.
+
+import weather
+
+# initialize options and configs
+selections = weather.Selections()
+get = selections.get
+get_boolean = selections.get_boolean
+
+# this mode just lists the aliases defined in the config
+if get_boolean("list"): print weather.list_aliases(selections.config)
+
+# normal operation
+else:
+ for argument in selections.arguments:
+ if get_boolean("conditions", argument):
+ print weather.get_metar(
+ get("id", argument),
+ get_boolean("verbose", argument)
+ )
+ if not get_boolean("conditions", argument) \
+ or get_boolean("forecast", argument):
+ print weather.get_forecast(
+ get("city", argument),
+ get("st", argument),
+ get_boolean("verbose", argument)
+ )
+
--- /dev/null
+.TH WEATHER 1 "March 26, 2006"
+.SH NAME
+weather \- command\-line tool to obtain weather conditions and forecasts
+.SH SYNOPSIS
+.B weather [ options ] [ alias [ alias [...] ] ]
+.SH DESCRIPTION
+This utility is intended to provide quick access to current weather
+conditions and forecasts. Presently, it is capable of providing data for
+localities throughout the United States of America by retrieving and
+processing METAR data from the National Oceanic and Atmospheric
+Administration and forecasts from the National Weather Service. Behavior
+can be determined by command\-line options and specification of zero or
+more aliases. Aliases are defined in weatherrc files, as a convenient
+means of grouping option combinations together using a short name.
+Specifying multiple aliases on the command line causes the utility to
+output data for each, as if it had been invoked multiple times. If no
+alias is specified, then an alias of "default" is used (assuming it has
+been defined) or the built\-in default values are chosen (if it has not).
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.B \-\-version
+show program's version number and exit
+.TP
+.B \-h, \-\-help
+show a help message and exit
+.TP
+.B \-cCITY, \-\-city=CITY
+the city name (ex: "Raleigh Durham")
+.TP
+.B \-f, \-\-forecast
+include a local forecast
+.TP
+.B \-iID, \-\-id=ID
+the METAR station ID (ex: KRDU)
+.TP
+.B \-l, \-\-list
+print a list of configured aliases
+.TP
+.B \-n, \-\-no\-conditions
+disable output of current conditions (implies \-\-forecast)
+.TP
+.B \-sST, \-\-st=ST
+the state abbreviation (ex: NC)
+.TP
+.B \-v, \-\-verbose
+show full decoded feeds
+.SH FILES
+.B weather
+may additionally obtain configuration data from a system\-wide
+configuration file, a per\-user configuration file, and a local
+directory configuration file. The file format and configuration options
+are described in
+.BR weatherrc (5) .
+They are aggregated in the following order:
+.TP
+.B /etc/weatherrc
+the system\-wide configuration
+.TP
+.B ~/.weatherrc
+the per\-user configuration (can be used to override the above)
+.TP
+.B ./.weatherrc
+the local directory configuration (can be used to override the above)
+.SH EXAMPLES
+.TP
+.B weather
+View output for the defined default alias, or the built-in default values
+if there is no default alias defined in the configuration files.
+.TP
+.B weather -i kavl
+Display current conditions at the KAVL METAR station.
+.TP
+.B weather -n -c asheville -s nc
+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,
+without filtering or fancy formatting.
+.TP
+.B weather home work
+Show current conditions for both the home and work aliases in that order.
+.SH SEE ALSO
+.BR weatherrc (5)
+.SH AUTHOR
+Utility and manual written by Jeremy Stanley <fungi@yuggoth.org>.
--- /dev/null
+# 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"
+
+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()
+ 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):
+ return self.config.get(argument, option)
+ else: return self.options.__dict__[option]
+ def get_boolean(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
+
+def quote(words):
+ """Wrap a string in quotes if it contains spaces."""
+ if words.find(" ") != -1: words = "\"" + words + "\""
+ return words
+
+def sorted(data):
+ """Return a sorted copy of a list."""
+ new_copy = data[:]
+ new_copy.sort()
+ return new_copy
+
+def get_url(url):
+ """Return a string containing the results of a URL GET."""
+ import urllib
+ return urllib.urlopen(url).read()
+
+def get_metar(id, verbose=False):
+ """Return a summarized METAR for the specified station."""
+ metar = get_url(
+ "http://weather.noaa.gov/pub/data/observations/metar/decoded/" \
+ + id.upper() + ".TXT")
+ if verbose: return metar
+ else:
+ lines = metar.split("\n")
+ headings = [
+ "Relative Humidity",
+ "Precipitation last hour",
+ "Sky conditions",
+ "Temperature",
+ "Weather",
+ "Wind"
+ ]
+ output = []
+ output.append("Current conditions at " \
+ + lines[0].split(", ")[1] + " (" \
+ + id.upper() +")")
+ output.append("Last updated " + lines[1])
+ for line in lines:
+ for heading in headings:
+ if line.startswith(heading + ":"):
+ output.append(" " + line)
+ return "\n".join(output)
+
+def get_forecast(city, st, verbose=False):
+ """Return the forecast for a specified city/st combination."""
+ forecast = get_url("http://weather.noaa.gov/pub/data/forecasts/city/" \
+ + st.lower() + "/" + city.lower().replace(" ", "_") \
+ + ".txt")
+ if verbose: return forecast
+ else:
+ lines = forecast.split("\n")
+ output = []
+ output.append(lines[2])
+ output.append(lines[3])
+ for line in lines:
+ if line.startswith("."):
+ output.append(line.replace(".", " ", 1))
+ return "\n".join(output)
+
+def get_options():
+ """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)
+ option_parser.add_option("-c", "--city",
+ dest="city",
+ default="Raleigh Durham",
+ help="the city name (ex: \"Raleigh Durham\")")
+ option_parser.add_option("-f", "--forecast",
+ dest="forecast",
+ action="store_true",
+ default=False,
+ help="include forecast (needs -c and -s)")
+ option_parser.add_option("-i", "--id",
+ dest="id",
+ default="KRDU",
+ 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")
+ option_parser.add_option("-n", "--no-conditions",
+ dest="conditions",
+ action="store_false",
+ default=True,
+ help="disable output of current conditions (implies --forecast)")
+ option_parser.add_option("-s", "--st",
+ dest="st",
+ default="NC",
+ help="the state abbreviation (ex: NC)")
+ option_parser.add_option("-v", "--verbose",
+ dest="verbose",
+ action="store_true",
+ default=False,
+ help="show full decoded feeds")
+ options, arguments = option_parser.parse_args()
+ return options, arguments
+
+def get_config():
+ """Parse the aliases and configuration."""
+ import ConfigParser
+ config = ConfigParser.ConfigParser()
+ import os.path
+ rcfiles = [
+ ".weatherrc",
+ os.path.expanduser("~/.weatherrc"),
+ "/etc/weatherrc"
+ ]
+ import os
+ for rcfile in rcfiles:
+ if os.access(rcfile, os.R_OK): config.read(rcfile)
+ for section in config.sections():
+ if section != section.lower():
+ if config.has_section(section.lower()):
+ config.remove_section(section.lower())
+ config.add_section(section.lower())
+ for option,value in config.items(section):
+ config.set(section.lower(), option, value)
+ return config
+
+def list_aliases(config):
+ """Return a formatted list of aliases defined in the config."""
+ sections = []
+ for section in config.sections():
+ if section.lower() not in sections and section != "default":
+ sections.append(section.lower())
+ output = "configured aliases..."
+ for section in sorted(sections):
+ output += "\n " \
+ + section \
+ + ": --id=" \
+ + quote(config.get(section, "id")) \
+ + " --city=" \
+ + quote(config.get(section, "city")) \
+ + " --st=" \
+ + quote(config.get(section, "st"))
+ return output
+
--- /dev/null
+[AVL]
+City = Asheville
+ID = KAVL
+St = NC
+
+[GSO]
+City = Greensboro
+ID = KGSO
+St = NC
+
+[RDU]
+City = Raleigh Durham
+ID = KRDU
+St = NC
+
--- /dev/null
+.TH WEATHERRC 5 "March 26, 2006"
+.SH NAME
+weatherrc \- configuration file format for the
+.BR weather (1)
+utility
+.SH DESCRIPTION
+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
+lines. Parameters and their values as separated by = or : characters.
+Multi-word values do not need quoting.
+.SH PARAMETERS
+These parameters are supported...
+.TP
+.B city
+the city name (ex: Raleigh Durham)
+.TP
+.B forecast
+include a local forecast (possible values are False and True or 0 and 1)
+.TP
+.B id
+the METAR station ID (ex: KRDU)
+.TP
+.B conditions
+output current conditions (possible values are False and True or 0 and 1)
+.TP
+.B st
+the state abbreviation (ex: NC)
+.TP
+.B verbose
+show full decoded feeds (possible values are False and True or 0 and 1)
+.SH EXAMPLES
+Following is an example
+.B ~/.weatherrc
+defining the default settings to be used when running the utility with no
+aliases specified, and a couple definitions for aliases named home and
+work...
+.P
+.RS
+[default]
+.br
+City = Asheville
+.br
+Forecast = True
+.br
+ID = KAVL
+.br
+St = NC
+.P
+[home]
+.br
+City = Raleigh Durham
+.br
+ID = KRDU
+.br
+St = NC
+.P
+[work]
+.br
+City = Greensboro
+.br
+ID = KGSO
+.br
+St = NC
+.RE
+.SH SEE ALSO
+.BR weather (1)
+.SH AUTHOR
+Specification and manual written by Jeremy Stanley <fungi@yuggoth.org>.