Merge lp:~samuel-buffet/entertainer/bug_379824 into lp:entertainer

Proposed by Samuel Buffet
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
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)

To post a comment you must log in.
Revision history for this message
Samuel Buffet (samuel-buffet) wrote :

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-

Revision history for this message
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.

review: Approve
Revision history for this message
Samuel Buffet (samuel-buffet) wrote :
Download full text (6.0 KiB)

Matt,

Branch updated an pushed.

incremental diff :

=== modified file 'entertainerlib/frontend/gui/screens/weather.py'
--- entertainerlib/frontend/gui/screens/weather.py 2009-05-09 17:03:51 +0000
+++ entertainerlib/frontend/gui/screens/weather.py 2009-05-25 16:43:06 +0000
@@ -20,11 +20,11 @@
         screen_title = Label(0.13, "screentitle", 0, 0.87, _("Weather"))
         self.add(screen_title)

- if (self.weather.get_location() == ''):
+ if (self.weather.location == ''):
             self.add(Label(0.04167, "text", 0.30, 0.20,
                 _("No weather location defined!"), font_weight="bold"))
         else:
- location_text = self.weather.get_location()
+ location_text = self.weather.location

             location = Label(0.04167, "text", 0.40, 0.13, location_text,
                 font_weight="bold")

=== modified file 'entertainerlib/tests/test_weather.py'
--- entertainerlib/tests/test_weather.py 2009-05-23 21:08:16 +0000
+++ entertainerlib/tests/test_weather.py 2009-05-25 16:46:12 +0000
@@ -74,7 +74,7 @@
                     return ZERO
         england = EnglandTimeZone()

- self.weather.set_location('Bath,England')
+ self.weather.location = 'Bath,England'
         self.weather.refresh()
         forecasts = self.weather.get_forecasts()
         today = forecasts[0]
@@ -93,57 +93,52 @@
         self.assertEqual(today["High"], 20)
         self.assertEqual(today["Condition"],"Sunny")

- def testWeatherSetLocation(self):
- """Tests the location setting of the weather module"""
- self.weather.set_location('Bradford,England')
- self.assertEqual(self.weather.get_location(), 'Bradford,England')
-
     def testWeatherLocationLatinEncoding(self):
         """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.set_location("Montreal")
+ self.weather.location = "Montreal"
         self.weather.refresh()
         results = self.weather.get_forecasts()
         #if there are results then it's working
         self.assertTrue(len(results) > 0)

     def test_yuma_conditions(self):
- """Tests that there's no 'weather-na' in Yuma"""
+ """Tests that there's no 'weather-na' in Yuma."""
         # Here we expect sun http://en.wikipedia.org/wiki/Yuma,_Arizona.
         # `Yuma is the sunniest place on earth` (90% of the time)
- self.weather.set_location("Yuma")
+ self.weather.location = "Yuma"
         self.weather.refresh()
         forecasts = self.weather.get_forecasts()
         for day in forecasts:
             self.assertFalse(day["Image"] == 'weather-na')

     def test_london_conditions(self):
- """Tests that there's no 'weather-na' in London"""
- self.weather.set_location("London")
+ """Tests that there's no 'weather-na' in London."""
+ self.weather.location = "London"
         self.weather.refresh()
         forecasts = self.weather.get_forecasts()
         for day in forecasts:
             self.assertFalse(day["Image"] == 'weather-na')

     def test_perth_conditions(self):
- ""...

Read more...

380. By Samuel Buffet

Fixes after Matt's comments.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches