From 5b125b3cc9c138438da10638c035302945362974 Mon Sep 17 00:00:00 2001 From: Bezleputh Date: Wed, 13 Jul 2016 17:33:35 +0200 Subject: [PATCH] [yahoo] fix module / bump to browser2 --- modules/yahoo/browser.py | 44 ++++++++++++++++++++++ modules/yahoo/module.py | 62 ++++++++----------------------- modules/yahoo/pages.py | 80 ++++++++++++++++++++++++++++++++++++++++ modules/yahoo/test.py | 8 +++- 4 files changed, 147 insertions(+), 47 deletions(-) create mode 100644 modules/yahoo/browser.py create mode 100644 modules/yahoo/pages.py diff --git a/modules/yahoo/browser.py b/modules/yahoo/browser.py new file mode 100644 index 0000000000..f0fd69aab2 --- /dev/null +++ b/modules/yahoo/browser.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Cedric Defortis +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + +from weboob.browser import PagesBrowser, URL +from .pages import YahooPage + +__all__ = ['YahooBrowser'] + + +class YahooBrowser(PagesBrowser): + BASEURL = 'https://query.yahooapis.com' + yahoo = URL('/v1/public/yql\?q=(?P.*)&format=json', YahooPage) + + def __init__(self, unit, *args, **kwargs): + self.unit = unit + PagesBrowser.__init__(self, *args, **kwargs) + + def iter_city_search(self, pattern): + query = 'select name, country, woeid, admin1 from geo.places where text="%s"' % pattern.encode('utf-8') + return self.yahoo.go(query=query).iter_cities() + + def iter_forecast(self, city): + query = 'select * from weather.forecast where woeid = %s and u="%s"' % (city, self.unit) + return self.yahoo.go(query=query).iter_forecast() + + def get_current(self, city): + query = 'select * from weather.forecast where woeid = %s and u="%s"' % (city, self.unit) + return self.yahoo.go(query=query).get_current() diff --git a/modules/yahoo/module.py b/modules/yahoo/module.py index 0051f7c410..e095581e05 100644 --- a/modules/yahoo/module.py +++ b/modules/yahoo/module.py @@ -17,14 +17,12 @@ # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . -import urllib2 -from xml.dom import minidom -from dateutil.parser import parse as parse_dt +from weboob.capabilities.weather import CapWeather +from weboob.tools.backend import Module, BackendConfig +from weboob.tools.ordereddict import OrderedDict +from weboob.tools.value import Value - -from weboob.capabilities.weather import CapWeather, CityNotFound, Current, Forecast, City -from weboob.tools.backend import Module -from weboob.deprecated.browser import StandardBrowser +from .browser import YahooBrowser __all__ = ['YahooModule'] @@ -35,51 +33,23 @@ class YahooModule(Module, CapWeather): MAINTAINER = u'Romain Bignon' EMAIL = 'romain@weboob.org' VERSION = '1.2' - DESCRIPTION = 'Yahoo!' + DESCRIPTION = 'Yahoo! Weather.' LICENSE = 'AGPLv3+' - BROWSER = StandardBrowser - WEATHER_URL = 'http://weather.yahooapis.com/forecastrss?w=%s&u=%s' - - def create_default_browser(self): - return self.create_browser(parser='json') + BROWSER = YahooBrowser - def iter_city_search(self, pattern): - args = {'q': 'select line1, line2, line3, line4, city, uzip, statecode, countrycode, latitude, longitude, ' - 'country, woeid, quality, house, street, state from locdrop.placefinder ' - 'where text="%s" and locale="fr-FR" and gflags="f"' % pattern.encode('utf-8'), - 'format': 'json', - } - doc = self.browser.location(self.browser.buildurl('http://locdrop.query.yahoo.com/v1/public/yql', **args)) + units_choice = OrderedDict([('c', 'International System of Units'), + ('f', 'U.S. System of Units')]) - cities = doc['query']['results']['Result'] - if not isinstance(cities, (tuple, list)): - cities = [cities] + CONFIG = BackendConfig(Value('units', label=u'System of Units', choices=units_choice)) - for result in cities: - c = City(result['woeid'], u'%s, %s, %s' % (result['city'], result['state'], result['country'])) - yield c - - def _get_weather_dom(self, city_id): - handler = urllib2.urlopen(self.WEATHER_URL % (city_id, 'c')) - dom = minidom.parse(handler) - handler.close() - if not dom.getElementsByTagName('yweather:condition'): - raise CityNotFound('City not found: %s' % city_id) + def create_default_browser(self): + return self.create_browser(unit=self.config['units'].get()) - return dom + def iter_city_search(self, pattern): + return self.browser.iter_city_search(pattern) def get_current(self, city_id): - dom = self._get_weather_dom(city_id) - current = dom.getElementsByTagName('yweather:condition')[0] - return Current(parse_dt(current.getAttribute('date')).date(), - float(current.getAttribute('temp')), unicode(current.getAttribute('text')), u'C') + return self.browser.get_current(city_id) def iter_forecast(self, city_id): - dom = self._get_weather_dom(city_id) - for forecast in dom.getElementsByTagName('yweather:forecast'): - yield Forecast(parse_dt(forecast.getAttribute('date')).date(), - float(forecast.getAttribute('low')), - float(forecast.getAttribute('high')), - unicode(forecast.getAttribute('text')), - u'C', - ) + return self.browser.iter_forecast(city_id) diff --git a/modules/yahoo/pages.py b/modules/yahoo/pages.py new file mode 100644 index 0000000000..10292b2e02 --- /dev/null +++ b/modules/yahoo/pages.py @@ -0,0 +1,80 @@ + +# -*- coding: utf-8 -*- + +# Copyright(C) 2010-2011 Cedric Defortis +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + +from weboob.browser.pages import JsonPage +from weboob.browser.elements import ItemElement, DictElement, method +from weboob.capabilities.weather import Forecast, Current, City, Temperature +from weboob.browser.filters.json import Dict +from weboob.browser.filters.standard import CleanText, CleanDecimal, Format, Date, Env + + +class YahooPage(JsonPage): + @method + class iter_cities(DictElement): + item_xpath = 'query/results/place' + + class item(ItemElement): + klass = City + + obj_id = Dict('woeid') + obj_name = Format(u'%s, %s, %s', Dict('name'), Dict('admin1/content'), Dict('country/content')) + + @method + class get_current(ItemElement): + klass = Current + + def parse(self, el): + self.env['pct'] = u'%' + + obj_id = Date(Dict('query/results/channel/item/condition/date')) + obj_date = Date(Dict('query/results/channel/item/condition/date')) + obj_text = Format('%s - wind: %s%s - humidity:%s%s', + Dict('query/results/channel/item/condition/text'), + Dict('query/results/channel/wind/speed'), + Dict('query/results/channel/units/speed'), + Dict('query/results/channel/atmosphere/humidity'), + Env('pct')) + + def obj_temp(self): + temp = CleanDecimal(Dict('query/results/channel/item/condition/temp'))(self) + unit = CleanText(Dict('query/results/channel/units/temperature'))(self) + return Temperature(float(temp), unit) + + @method + class iter_forecast(DictElement): + item_xpath = 'query/results/channel/item/forecast' + + def parse(self, el): + self.env['unit'] = Dict('query/results/channel/units/temperature')(el) + + class item(ItemElement): + klass = Forecast + + obj_id = Dict('date') + obj_date = Date(Dict('date')) + obj_text = Dict('text') + + def obj_low(self): + temp = CleanDecimal(Dict('low'))(self) + return Temperature(float(temp), Env('unit')(self)) + + def obj_high(self): + temp = CleanDecimal(Dict('high'))(self) + return Temperature(float(temp), Env('unit')(self)) diff --git a/modules/yahoo/test.py b/modules/yahoo/test.py index bb082c1031..28e4699b56 100644 --- a/modules/yahoo/test.py +++ b/modules/yahoo/test.py @@ -30,7 +30,13 @@ def test_meteo(self): city = l[0] current = self.backend.get_current(city.id) - self.assertTrue(current.temp.value > -20 and current.temp.value < 50) + + self.assertTrue(current.temp.unit in ['C', 'F']) + + if current.temp.unit == 'F': + self.assertTrue(current.temp.value > -4 and current.temp.value < 122) + else: + self.assertTrue(current.temp.value > -20 and current.temp.value < 50) forecasts = list(self.backend.iter_forecast(city.id)) self.assertTrue(len(forecasts) > 0) -- GitLab