Merge lp:~samuel-buffet/entertainer/bug_379824 into lp:entertainer
- bug_379824
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Matt Layman | ||||
Approved revision: | 380 | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~samuel-buffet/entertainer/bug_379824 | ||||
Merge into: | lp:entertainer | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp:~samuel-buffet/entertainer/bug_379824 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matt Layman | Approve | ||
Review via email: mp+6750@code.launchpad.net |
Commit message
Weather conditions download from Google are more robust. (Fixes Bug 379824)
Description of the change
Samuel Buffet (samuel-buffet) wrote : | # |
Matt Layman (mblayman) wrote : | # |
Samuel,
`make check` was good. The new tests look good and the code is good. I have a couple of minor comments but I'm approving.
1) The init location parameter isn't connected to the self._location instance variable. This means that if refresh() is called before the set_location method is used, then it will try to get the location of ''.
2) The test method docstrings could use a full stop.
3) set_location and get_location don't do much. Could you get rid of the getter and setter and just use self.location?
4) The branch needs a commit message.
Samuel Buffet (samuel-buffet) wrote : | # |
Matt,
Branch updated an pushed.
incremental diff :
=== modified file 'entertainerlib
--- entertainerlib/
+++ entertainerlib/
@@ -20,11 +20,11 @@
- if (self.weather.
+ if (self.weather.
else:
- location_text = self.weather.
+ location_text = self.weather.
=== modified file 'entertainerlib
--- entertainerlib/
+++ entertainerlib/
@@ -74,7 +74,7 @@
england = EnglandTimeZone()
- self.weather.
+ self.weather.
forecasts = self.weather.
today = forecasts[0]
@@ -93,57 +93,52 @@
- def testWeatherSetL
- """Tests the location setting of the weather module"""
- self.weather.
- self.assertEqua
-
def testWeatherLoca
"""Tests whether code can handle Latin-1 encoding back from google"""
#Check for Montreal which gets info back from google in Latin-1
- self.weather.
+ self.weather.
results = self.weather.
#if there are results then it's working
def test_yuma_
- """Tests that there's no 'weather-na' in Yuma"""
+ """Tests that there's no 'weather-na' in Yuma."""
# Here we expect sun http://
# `Yuma is the sunniest place on earth` (90% of the time)
- self.weather.
+ self.weather.
forecasts = self.weather.
for day in forecasts:
def test_london_
- """Tests that there's no 'weather-na' in London"""
- self.weather.
+ """Tests that there's no 'weather-na' in London."""
+ self.weather.
forecasts = self.weather.
for day in forecasts:
def test_perth_
- ""...
- 380. By Samuel Buffet
-
Fixes after Matt's comments.
Preview Diff
1 | === modified file 'entertainerlib/tests/test_weather.py' |
2 | --- entertainerlib/tests/test_weather.py 2009-05-09 17:03:51 +0000 |
3 | +++ entertainerlib/tests/test_weather.py 2009-05-23 21:08:16 +0000 |
4 | @@ -106,3 +106,46 @@ |
5 | results = self.weather.get_forecasts() |
6 | #if there are results then it's working |
7 | self.assertTrue(len(results) > 0) |
8 | + |
9 | + def test_yuma_conditions(self): |
10 | + """Tests that there's no 'weather-na' in Yuma""" |
11 | + # Here we expect sun http://en.wikipedia.org/wiki/Yuma,_Arizona. |
12 | + # `Yuma is the sunniest place on earth` (90% of the time) |
13 | + self.weather.set_location("Yuma") |
14 | + self.weather.refresh() |
15 | + forecasts = self.weather.get_forecasts() |
16 | + for day in forecasts: |
17 | + self.assertFalse(day["Image"] == 'weather-na') |
18 | + |
19 | + def test_london_conditions(self): |
20 | + """Tests that there's no 'weather-na' in London""" |
21 | + self.weather.set_location("London") |
22 | + self.weather.refresh() |
23 | + forecasts = self.weather.get_forecasts() |
24 | + for day in forecasts: |
25 | + self.assertFalse(day["Image"] == 'weather-na') |
26 | + |
27 | + def test_perth_conditions(self): |
28 | + """Tests that there's no 'weather-na' in Perth""" |
29 | + self.weather.set_location("Perth") |
30 | + self.weather.refresh() |
31 | + forecasts = self.weather.get_forecasts() |
32 | + for day in forecasts: |
33 | + self.assertFalse(day["Image"] == 'weather-na') |
34 | + |
35 | + def test_nyc_conditions(self): |
36 | + """Tests that there's no 'weather-na' in New York""" |
37 | + self.weather.set_location("New York") |
38 | + self.weather.refresh() |
39 | + forecasts = self.weather.get_forecasts() |
40 | + for day in forecasts: |
41 | + self.assertFalse(day["Image"] == 'weather-na') |
42 | + |
43 | + def test_north_pole_conditions(self): |
44 | + """Tests that there's no 'weather-na' in North Pole""" |
45 | + self.weather.set_location("North Pole") |
46 | + self.weather.refresh() |
47 | + forecasts = self.weather.get_forecasts() |
48 | + for day in forecasts: |
49 | + self.assertFalse(day["Image"] == 'weather-na') |
50 | + |
51 | |
52 | === modified file 'entertainerlib/utils/weather.py' |
53 | --- entertainerlib/utils/weather.py 2009-04-28 22:45:31 +0000 |
54 | +++ entertainerlib/utils/weather.py 2009-05-23 21:08:16 +0000 |
55 | @@ -6,6 +6,7 @@ |
56 | """ |
57 | |
58 | import locale |
59 | +import os |
60 | import urllib2 |
61 | from xml.dom import minidom |
62 | |
63 | @@ -14,21 +15,16 @@ |
64 | #The lookup url for the google weather API |
65 | WEATHER_LOOKUP_URL = "http://www.google.co.uk/ig/api?weather=" |
66 | |
67 | -#use the icon instead of condition to make it work with any languages |
68 | -WEATHER_IMAGES = {'/images/weather/mostly_sunny.gif': 'weather-sun-mostly', |
69 | - '/images/weather/chance_of_rain.gif': 'weather-rain-chance', |
70 | - #'/images/weather/partly_sunny.gif': 'weather-sun-clouds', |
71 | - # no dedicated gif provided by google for that weather |
72 | - # condition. |
73 | - # it's a *mostly_sunny* gif wich is given instead :( |
74 | - '/images/weather/rain.gif': 'weather-rain', |
75 | - '/images/weather/storm.gif': 'weather-lightning', |
76 | - '/images/weather/fog.gif': 'weather-fog', |
77 | - '/images/weather/sunny.gif': 'weather-sun', |
78 | - '/images/weather/icy.gif': 'weather-ice', |
79 | - '/images/weather/cloudy.gif': 'weather-clouds', |
80 | - '/images/weather/snow.gif': 'weather-snow' |
81 | - } |
82 | +WEATHER_IMAGES = {'mostly_sunny.gif': 'weather-sun-mostly', |
83 | + 'chance_of_rain.gif': 'weather-rain-chance', |
84 | + 'partly_cloudy.gif': 'weather-sun-clouds', |
85 | + 'rain.gif': 'weather-rain', |
86 | + 'storm.gif': 'weather-lightning', |
87 | + 'fog.gif': 'weather-fog', |
88 | + 'sunny.gif': 'weather-sun', |
89 | + 'icy.gif': 'weather-ice', |
90 | + 'cloudy.gif': 'weather-clouds', |
91 | + 'snow.gif': 'weather-snow'} |
92 | |
93 | class Weather: |
94 | """ |
95 | @@ -36,20 +32,15 @@ |
96 | """ |
97 | |
98 | def __init__(self, location=""): |
99 | - """ |
100 | - Sets up the weather object |
101 | - @param location (String) location of weather to get forecast |
102 | - for. |
103 | - """ |
104 | - self.__location = '' |
105 | - self.__forecasts = [] |
106 | + self._location = '' |
107 | + self._forecasts = [] |
108 | self.theme = Configuration().theme |
109 | self.set_location(location) |
110 | - self.locale = self.__get_locale () |
111 | + self.locale = self._get_locale() |
112 | self.refresh() |
113 | |
114 | - def __get_locale (self): |
115 | - '''Get locale information from user\'s machine''' |
116 | + def _get_locale(self): |
117 | + """Get locale information from user's machine.""" |
118 | default = locale.getdefaultlocale ()[0] |
119 | if default: |
120 | lang = default.split("_")[0] |
121 | @@ -59,21 +50,17 @@ |
122 | return lang |
123 | |
124 | def find_forecast(self, search): |
125 | - """ |
126 | - Returns the search results page for the search |
127 | - @param search String |
128 | - @return array of forecasts |
129 | - """ |
130 | + """Returns the search results page for the search.""" |
131 | url = WEATHER_LOOKUP_URL + search + "&hl=" + self.locale |
132 | url = url.replace(" ", "%20") |
133 | |
134 | raw_data = urllib2.urlopen(url) |
135 | - # We get the charset from the content-type of the http answer |
136 | + # We get the charset from the content-type of the http answer. |
137 | conent_type = raw_data.info()["Content-Type"] |
138 | encoding = conent_type.split("=")[1] |
139 | |
140 | - # we read data according to the relevant charset and then we |
141 | - # prepare it to be parsed by minidom |
142 | + # We read data according to the relevant charset and then we |
143 | + # prepare it to be parsed by minidom. |
144 | data = unicode(raw_data.read(), encoding) |
145 | data = data.encode("utf8") |
146 | dom = minidom.parseString(data) |
147 | @@ -107,11 +94,11 @@ |
148 | if node.nodeName == 'condition': |
149 | condition = node.getAttribute('data') |
150 | if node.nodeName == 'icon': |
151 | - imagename = node.getAttribute('data') |
152 | - image = self.set_image (imagename) |
153 | + imagename = os.path.split(node.getAttribute('data'))[-1] |
154 | + image = self.set_image(imagename) |
155 | |
156 | - # condition is the last element of the forecast we are |
157 | - # interested in so write out the forecast if this is set. |
158 | + # Condition is the last element of the forecast we are |
159 | + # interested in so write out the forecast if this is set. |
160 | if (condition): |
161 | forecast = {"Day":day, |
162 | "Low":str(converted_low), |
163 | @@ -127,48 +114,30 @@ |
164 | imagename = '' |
165 | image = '' |
166 | |
167 | - return self.__forecasts |
168 | + return self._forecasts |
169 | |
170 | def set_location(self, location): |
171 | - """ |
172 | - Sets the current location |
173 | - @param type String should be a city, country name or |
174 | - post/zip code |
175 | - """ |
176 | - self.__location = location |
177 | + """Sets the current location.""" |
178 | + self._location = location |
179 | |
180 | def get_location(self): |
181 | - """ |
182 | - Gets the current location |
183 | - @return type String of city, country name or post/zip code |
184 | - """ |
185 | - return self.__location |
186 | + """Gets the current location.""" |
187 | + return self._location |
188 | |
189 | def clear_forecasts(self): |
190 | - """ |
191 | - Resets the forecast array |
192 | - """ |
193 | - self.__forecasts = [] |
194 | + """Resets the forecast array.""" |
195 | + self._forecasts = [] |
196 | |
197 | def add_forecast(self, forecast): |
198 | - """ |
199 | - Appends a forecast to the forecast array |
200 | - @param forecast dict |
201 | - """ |
202 | - self.__forecasts.append(forecast) |
203 | + """Appends a forecast to the forecast array.""" |
204 | + self._forecasts.append(forecast) |
205 | |
206 | def get_forecasts(self): |
207 | - """ |
208 | - Returns an array of forecasts |
209 | - @return array of forecasts |
210 | - """ |
211 | - return self.__forecasts |
212 | + """Returns an array of forecasts.""" |
213 | + return self._forecasts |
214 | |
215 | def set_image(self, condition): |
216 | - """ |
217 | - Returns an image for a given weather condition. |
218 | - @return type String of weather image |
219 | - """ |
220 | + """Returns an image for a given weather condition.""" |
221 | try: |
222 | image_name = WEATHER_IMAGES[condition] |
223 | except KeyError: |
224 | @@ -179,11 +148,8 @@ |
225 | return image |
226 | |
227 | def refresh(self): |
228 | - """ |
229 | - Clear current weather and forecasts and then loads new data |
230 | - from xml or rss feed |
231 | - """ |
232 | - if (self.__location): |
233 | + """Clear current weather and forecasts and then loads new data.""" |
234 | + if (self._location): |
235 | self.clear_forecasts() |
236 | - self.find_forecast(self.__location) |
237 | + self.find_forecast(self._location) |
238 |
Devs,
This is a fix I propose for the linked bug.
The bug was caused by a change made by google in the format of the returned result.
They've changed the way they give us the condition pictures.
Before we received things like that : '/images/ weather/ sunny.gif' .
And now we receive : '/ig/images/ weather/ sunny.gif' .
So I've fixed the code by spliting the result to only consider the short filename (without the relative path).
This will protect us to any change in the relative path.
I've added a tests also to get conditions from different cities on earth. This is to prevent from future change on short filenames this time.
Samuel-