1 # Copyright (c) 2006 Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
2 # Licensed per terms in the LICENSE file distributed with this software.
7 """An object to contain selection data."""
9 """Store the config, options and arguments."""
10 self.config = get_config()
11 self.options, self.arguments = get_options()
13 self.arguments = [(x.lower()) for x in self.arguments]
14 else: self.arguments = [ None ]
15 def get(self, option, argument=None):
16 """Retrieve data from the config or options."""
17 if not argument: argument = "default"
18 if self.config.has_option(argument, option):
19 return self.config.get(argument, option)
20 else: return self.options.__dict__[option]
21 def get_boolean(self, option, argument=None):
22 """Get data and coerce to a boolean if necessary."""
23 data = self.get(option, argument)
25 if eval(data): return True
32 """Wrap a string in quotes if it contains spaces."""
33 if words.find(" ") != -1: words = "\"" + words + "\""
37 """Return a sorted copy of a list."""
43 """Return a string containing the results of a URL GET."""
45 return urllib.urlopen(url).read()
47 def get_metar(id, verbose=False):
48 """Return a summarized METAR for the specified station."""
50 "http://weather.noaa.gov/pub/data/observations/metar/decoded/" \
51 + id.upper() + ".TXT")
52 if verbose: return metar
54 lines = metar.split("\n")
57 "Precipitation last hour",
64 output.append("Current conditions at " \
65 + lines[0].split(", ")[1] + " (" \
67 output.append("Last updated " + lines[1])
69 for heading in headings:
70 if line.startswith(heading + ":"):
71 output.append(" " + line)
72 return "\n".join(output)
74 def get_forecast(city, st, verbose=False):
75 """Return the forecast for a specified city/st combination."""
76 forecast = get_url("http://weather.noaa.gov/pub/data/forecasts/city/" \
77 + st.lower() + "/" + city.lower().replace(" ", "_") \
79 if verbose: return forecast
81 lines = forecast.split("\n")
83 output.append(lines[2])
84 output.append(lines[3])
86 if line.startswith("."):
87 output.append(line.replace(".", " ", 1))
88 return "\n".join(output)
91 """Parse the options passed on the command line."""
93 usage = "usage: %prog [ options ] [ alias [ alias [...] ] ]"
94 verstring = "%prog " + version
95 option_parser = optparse.OptionParser(usage=usage, version=verstring)
96 option_parser.add_option("-c", "--city",
98 default="Raleigh Durham",
99 help="the city name (ex: \"Raleigh Durham\")")
100 option_parser.add_option("-f", "--forecast",
104 help="include forecast (needs -c and -s)")
105 option_parser.add_option("-i", "--id",
108 help="the METAR station ID (ex: KRDU)")
109 option_parser.add_option("-l", "--list",
113 help="print a list of configured aliases")
114 option_parser.add_option("-n", "--no-conditions",
116 action="store_false",
118 help="disable output of current conditions (implies --forecast)")
119 option_parser.add_option("-s", "--st",
122 help="the state abbreviation (ex: NC)")
123 option_parser.add_option("-v", "--verbose",
127 help="show full decoded feeds")
128 options, arguments = option_parser.parse_args()
129 return options, arguments
132 """Parse the aliases and configuration."""
134 config = ConfigParser.ConfigParser()
138 os.path.expanduser("~/.weatherrc"),
142 for rcfile in rcfiles:
143 if os.access(rcfile, os.R_OK): config.read(rcfile)
144 for section in config.sections():
145 if section != section.lower():
146 if config.has_section(section.lower()):
147 config.remove_section(section.lower())
148 config.add_section(section.lower())
149 for option,value in config.items(section):
150 config.set(section.lower(), option, value)
153 def list_aliases(config):
154 """Return a formatted list of aliases defined in the config."""
156 for section in config.sections():
157 if section.lower() not in sections and section != "default":
158 sections.append(section.lower())
159 output = "configured aliases..."
160 for section in sorted(sections):
164 + quote(config.get(section, "id")) \
166 + quote(config.get(section, "city")) \
168 + quote(config.get(section, "st"))