diff --git a/weather.gismeteo/addon.xml b/weather.gismeteo/addon.xml index 754992c0d..8dc10c696 100644 --- a/weather.gismeteo/addon.xml +++ b/weather.gismeteo/addon.xml @@ -1,5 +1,5 @@ - + @@ -13,25 +13,28 @@ Gismeteo prévisions météorologiques. Prévisions météorologiques en temps réel à travers le monde. Gismeteo Weather Forecast. Realtidsväder och detaljerade prognoser över hela världen Gismeteo veðurspá. Rauntíma veðurlýsing og nákvæmar veðurspár um víða veröld + Gismeteo Wettervorhersage. Echtzeitwetter und detailierte Vorhersagen auf der ganzen Welt The weather is provided solely for personal non-commercial use Погода предоставлена исключительно для личного некоммерческого использования El clima se proporciona únicamente para su uso personal y no comercial La météo est fournie pour un usage personnel non-commercial. Vädret tillhandahålls enbart för personligt, icke-kommersiellt bruk Veðurupplýsingarnar eru einungis til einkanota og ekki í hagnaðarskyni + Das Wetter wird nur für persönlichen, nicht-kommerziellen Gebrauch zur Verfügung gestellt The weather forecast has been prepared by MapMakers Group Ltd Прогноз погоды подготовлен НПЦ "Мэп Мейкер" El pronóstico del tiempo ha sido preparado por MapMakers Group Ltd Les prévisions météorologiques sont mises à disposition par MapMakers Group Ltd Väderprognosen har utarbetats av MapMakers Group Ltd. Veðurspáin var útbúin af MapMakers Group Ltd + Die Wettervorhersage wurde von MapMakers Group Ltd vorbereitet all GPL-3.0-only https://forum.kodi.tv/showthread.php?tid=323624 https://www.gismeteo.com/ vl.maksime@gmail.com https://github.com/vlmaksime/weather.gismeteo - v0.6.3 (2021-09-27)[CR]- Fixed identified bugs[CR][CR]v0.6.2 (2021-05-31)[CR]- Updated compatibility with Kodi 19[CR]- Added Icelandic translation (sveinki) [CR][CR]v0.6.1 (2021-04-03)[CR]- SimplePlugin 3 module moved into external addon[CR]- Small changes in the add-on structure [CR]- Added French translation (DavidHenryThoreau)[CR]- Added Swedish translation (Sopor) + v0.6.4 (2023-10-30)[CR]- Adapted to changes in the service API[CR]- Added German translation (kyoforkshomebrews)[CR][CR]v0.6.3 (2021-09-27)[CR]- Fixed identified bugs[CR][CR]v0.6.2 (2021-05-31)[CR]- Updated compatibility with Kodi 19[CR]- Added Icelandic translation (sveinki)[CR][CR]v0.6.1 (2021-04-03)[CR]- SimplePlugin 3 module moved into external addon[CR]- Small changes in the add-on structure [CR]- Added French translation (DavidHenryThoreau)[CR]- Added Swedish translation (Sopor) icon.png diff --git a/weather.gismeteo/changelog.txt b/weather.gismeteo/changelog.txt index 775ba1b67..a5dbf1f39 100644 --- a/weather.gismeteo/changelog.txt +++ b/weather.gismeteo/changelog.txt @@ -1,3 +1,7 @@ +v0.6.4 (2023-11-30) +- Adapted to changes in the service API +- Added German translation (kyoforkshomebrews) + v0.6.3 (2021-09-27) - Fixed identified bugs diff --git a/weather.gismeteo/default.py b/weather.gismeteo/default.py index 121633487..3b3dd5908 100644 --- a/weather.gismeteo/default.py +++ b/weather.gismeteo/default.py @@ -3,14 +3,14 @@ from __future__ import unicode_literals -from builtins import range import os import time +from builtins import range import xbmc +from simpleplugin import translate_path from resources.libs import Gismeteo, GismeteoError, Location, Weather, WebClientError -from simpleplugin import translate_path weather = Weather() _ = weather.initialize_gettext() @@ -68,8 +68,8 @@ def set_item_info(props, item, item_type, icon='%s.png', day_temp=None): if 'FanartCode' in keys: props['FanartCode'] = weather_code - if 'ProviderIcon' in keys\ - and weather.use_provider_icon: + if 'ProviderIcon' in keys \ + and weather.use_provider_icon: props['ProviderIcon'] = 'resource://resource.images.weatherprovidericons.gismeteo/{0}.png'.format(item['icon']) # Wind @@ -126,13 +126,17 @@ def set_item_info(props, item, item_type, icon='%s.png', day_temp=None): props['FeelsLike'] = weather.TEMP(item['temperature']['comfort']) + weather.TEMPUNIT if day_temp is not None: - if 'TempMorn' in keys: + if 'TempMorn' in keys \ + and day_temp.get('morn') is not None: props['TempMorn'] = weather.TEMP(day_temp['morn']) + weather.TEMPUNIT - if 'TempDay' in keys: + if 'TempDay' in keys \ + and day_temp.get('day') is not None: props['TempDay'] = weather.TEMP(day_temp['day']) + weather.TEMPUNIT - if 'TempEve' in keys: + if 'TempEve' in keys \ + and day_temp.get('eve') is not None: props['TempEve'] = weather.TEMP(day_temp['eve']) + weather.TEMPUNIT - if 'TempNight' in keys: + if 'TempNight' in keys \ + and day_temp.get('night') is not None: props['TempNight'] = weather.TEMP(day_temp['night']) + weather.TEMPUNIT # Humidity @@ -154,17 +158,18 @@ def set_item_info(props, item, item_type, icon='%s.png', day_temp=None): if 'Pressure' in keys: pressure = item['pressure']['avg'] if item_type == 'day' else item['pressure'] - props['Pressure'] = '{0} {1}'.format(weather.PRESSURE(pressure), _(weather.PRESUNIT)) if pressure is not None else _('n/a') + props['Pressure'] = '{0} {1}'.format(weather.PRESSURE(pressure), + _(weather.PRESUNIT)) if pressure is not None else _('n/a') # Precipitation if 'Precipitation' in keys: precip = item['precipitation']['amount'] - props['Precipitation'] = '{0} {1}'.format(weather.PRECIPITATION(precip), _(weather.PRECIPUNIT)) if precip is not None else _('n/a') + props['Precipitation'] = '{0} {1}'.format(weather.PRECIPITATION(precip), + _(weather.PRECIPUNIT)) if precip is not None else _('n/a') def clear(): - # Current weather.set_properties(weather.prop_current(), 'Current') @@ -279,7 +284,7 @@ def set_location_props(forecast_info): # Hourly if count_hourly < MAX_HOURLY \ - and hour['date']['unix'] >= CURRENT_TIME['unix']: + and hour['date']['unix'] >= CURRENT_TIME['unix']: hourly_props = weather.prop_hourly() set_item_info(hourly_props, hour, 'hour', WEATHER_ICON) weather.set_properties(hourly_props, 'Hourly', count_hourly + 1) @@ -288,10 +293,10 @@ def set_location_props(forecast_info): # 36Hour if count_36hour < MAX_36HOUR \ - and hour['tod'] in [2, 3]: + and hour['tod'] in [2, 3]: if hour['tod'] == 2 \ - and hour['date']['unix'] >= CURRENT_TIME['unix'] \ - or hour['tod'] == 3: + and hour['date']['unix'] >= CURRENT_TIME['unix'] \ + or hour['tod'] == 3: _36hour_props = weather.prop_36hour() set_item_info(_36hour_props, hour, 'hour', WEATHER_ICON) @@ -320,7 +325,7 @@ def set_location_props(forecast_info): # Weekend if weather.is_weekend(day) \ - and count_weekends <= MAX_WEEKENDS: + and count_weekends <= MAX_WEEKENDS: weekend_props = weather.prop_daily() set_item_info(weekend_props, day, 'day', WEATHER_ICON, day_temp) weather.set_properties(weekend_props, 'Weekend', count_weekends + 1) @@ -356,7 +361,6 @@ def set_location_props(forecast_info): @weather.action('root') def forecast(params): - location = get_location(params.id) if location.id: try: @@ -406,7 +410,6 @@ def location(params): @weather.mem_cached(30) def _location_forecast(lang, _id): - gismeteo = Gismeteo(lang) params = {'city_id': _id, @@ -415,20 +418,18 @@ def _location_forecast(lang, _id): return _call_method(gismeteo.forecast, params) - @weather.mem_cached(10) def _ip_locations(lang): - gismeteo = Gismeteo(lang) return _call_method(gismeteo.cities_ip) -def get_location(loc_id): +def get_location(loc_id): use_current_location = weather.get_setting('CurrentLocation') if loc_id == '1' \ - and use_current_location: + and use_current_location: try: lang = weather.gismeteo_lang() ip_locations = _ip_locations(lang) @@ -446,7 +447,7 @@ def get_location(loc_id): location_id = weather.get_setting('Location{0}ID'.format(int_loc_id)) if not location_id \ - and int_loc_id != 1: + and int_loc_id != 1: int_loc_id = 1 location_id = weather.get_setting('Location{0}ID'.format(int_loc_id)) @@ -479,7 +480,6 @@ def _call_method(func, params=None): if __name__ == '__main__': - description = weather.prop_description() description['Forecast.IsFetched'] = 'true' diff --git a/weather.gismeteo/resources/language/resource.language.de_de/strings.po b/weather.gismeteo/resources/language/resource.language.de_de/strings.po new file mode 100644 index 000000000..ae921a9e8 --- /dev/null +++ b/weather.gismeteo/resources/language/resource.language.de_de/strings.po @@ -0,0 +1,275 @@ +# Kodi Media Center language file +# Addon Name: Gismeteo +# Addon id: weather.gismeteo +# Addon Provider: vl.maksime + +msgid "" +msgstr "" + +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" + +# Categories + +msgctxt "#32101" +msgid "Location setup" +msgstr "Ortseinstellungen" + +msgctxt "#32102" +msgid "Advanced" +msgstr "Erweitert" + +msgctxt "#32103" +msgid "Expert" +msgstr "Experten" + +# Location setup + +msgctxt "#32110" +msgid "Current Location" +msgstr "Derzeitiger Ort" + +msgctxt "#32111" +msgid "Location 1" +msgstr "Ort 1" + +msgctxt "#32112" +msgid "Location 2" +msgstr "Ort 2" + +msgctxt "#32113" +msgid "Location 3" +msgstr "Ort 3" + +msgctxt "#32114" +msgid "Location 4" +msgstr "Ort 4" + +msgctxt "#32115" +msgid "Location 5" +msgstr "Ort 5" + +msgctxt "#32116" +msgid "Location 1 ID" +msgstr "Ort 1 ID" + +msgctxt "#32117" +msgid "Location 2 ID" +msgstr "Ort 2 ID" + +msgctxt "#32118" +msgid "Location 3 ID" +msgstr "Ort 3 ID" + +msgctxt "#32119" +msgid "Location 4 ID" +msgstr "Ort 4 ID" + +msgctxt "#32120" +msgid "Location 5 ID" +msgstr "Ort 5 ID" + +# Advanced + +msgctxt "#32122" +msgid "Weekend" +msgstr "Wochenende" + +msgctxt "#32123" +msgid "Saturday/Sunday" +msgstr "Samstag/Sonntag" + +msgctxt "#32124" +msgid "Friday/Saturday" +msgstr "Freitag/Samstag" + +msgctxt "#32125" +msgid "Thursday/Friday" +msgstr "Donnerstag/Freitag" + +msgctxt "#32130" +msgid "Time zone" +msgstr "Zeitzone" + +msgctxt "#32131" +msgid "from system settings" +msgstr "von Systemeinstellungen" + +msgctxt "#32132" +msgid "from location" +msgstr "von Ort" + +msgctxt "#32133" +msgid "Measure units" +msgstr "Einheiten" + +msgctxt "#32134" +msgid "Pressure" +msgstr "Druck" + +msgctxt "#32135" +msgid "Precipitation" +msgstr "Niederschlag" + +msgctxt "#32136" +msgid "Clear cache" +msgstr "Cache leeren" + +msgctxt "#32200" +msgid "User interface language" +msgstr "Benutzeroberflächen-Sprache" + +msgctxt "#32201" +msgid "Russian" +msgstr "Russisch" + +msgctxt "#32202" +msgid "Ukrainian" +msgstr "Ukrainisch" + +msgctxt "#32203" +msgid "Lithuanian" +msgstr "Litauisch" + +msgctxt "#32204" +msgid "Latvian" +msgstr "Lettisch" + +msgctxt "#32205" +msgid "English" +msgstr "Englisch" + +msgctxt "#32206" +msgid "Romanian" +msgstr "Rumänisch" + +msgctxt "#32207" +msgid "German" +msgstr "Deutsch" + +msgctxt "#32208" +msgid "Polish" +msgstr "Polnisch" + +msgctxt "#32220" +msgid "Gismeteo icons" +msgstr "Gismeteo-Icons" + +msgctxt "#32221" +msgid "Use Gismeteo icons" +msgstr "Gismeteo-Icons verwenden" + +msgctxt "#32222" +msgid "Install icon package" +msgstr "Icon-Paket installieren" + +msgctxt "#32223" +msgid "Requires Kodi 16+ and skin support" +msgstr "Erfordert Kodi 16+ und Unterstützung des Skins" + +msgctxt "#32299" +msgid "Language" +msgstr "Sprache" + +msgctxt "#32301" +msgid "a/p" +msgstr "" + +# Speed + +msgctxt "#32401" +msgid "m/s" +msgstr "" + +msgctxt "#32402" +msgid "km/h" +msgstr "" + +msgctxt "#32403" +msgid "m/min" +msgstr "" + +msgctxt "#32404" +msgid "ft/h" +msgstr "" + +msgctxt "#32405" +msgid "ft/min" +msgstr "" + +msgctxt "#32406" +msgid "ft/s" +msgstr "" + +msgctxt "#32407" +msgid "knots" +msgstr "" + +msgctxt "#32408" +msgid "Beaufort" +msgstr "" + +msgctxt "#32409" +msgid "inch/s" +msgstr "" + +msgctxt "#32410" +msgid "yard/s" +msgstr "" + +msgctxt "#32411" +msgid "Furlong/Fortnight" +msgstr "" + +msgctxt "#32412" +msgid "mph" +msgstr "" + +msgctxt "#32413" +msgid "kts" +msgstr "" + +# Wind direction + +msgctxt "#32420" +msgid "calm" +msgstr "Ruhig" + +# Precipitation + +msgctxt "#32430" +msgid "mm" +msgstr "" + +msgctxt "#32431" +msgid "inch" +msgstr "" + +msgctxt "#32432" +msgid "n/a" +msgstr "" + +# Pressure + +msgctxt "#32440" +msgid "mmHg" +msgstr "" + +msgctxt "#32441" +msgid "hPa" +msgstr "" + +msgctxt "#32442" +msgid "mbar" +msgstr "" + +msgctxt "#32443" +msgid "inHg" +msgstr "" + +# Messages + +msgctxt "#32501" +msgid "Connection error" +msgstr "Verbindungsfehler" diff --git a/weather.gismeteo/resources/libs/__init__.py b/weather.gismeteo/resources/libs/__init__.py index 4676ba99a..4d4588945 100644 --- a/weather.gismeteo/resources/libs/__init__.py +++ b/weather.gismeteo/resources/libs/__init__.py @@ -2,7 +2,9 @@ # License: GPL v.3 https://www.gnu.org/copyleft/gpl.html from __future__ import unicode_literals + import time + import xbmc from .gismeteo import GismeteoError, GismeteoClient @@ -16,10 +18,9 @@ class Gismeteo(GismeteoClient): def __init__(self, *args, **kwargs): - super(Gismeteo, self).__init__(*args, **kwargs) - addon = simpleweather.Addon() + addon = Addon() headers = self._client.headers if addon.kodi_major_version() >= '17': @@ -76,6 +77,8 @@ def gismeteo_lang(self): lang = 'de' elif lang_id == 8: lang = 'pl' + else: + lang = 'en' return lang @@ -120,7 +123,7 @@ def convert_date(self, date): return localtime + ' ' + localdate def is_weekend(self, day): - return (self.get_weekday(day['date'], 'x') in self.WEEKENDS) + return self.get_weekday(day['date'], 'x') in self.WEEKENDS def get_weekday(self, date, form): date_time = self._get_timestamp(date) @@ -146,6 +149,9 @@ def get_month(self, date, form): label = xbmc.getLocalizedString(self.MONTH_NAME_SHORT[month]) + ' ' + day elif form == 'ml': label = xbmc.getLocalizedString(self.MONTH_NAME_LONG[month]) + ' ' + day + else: + label = '' + return label def _weekends(self): @@ -164,80 +170,80 @@ def _weekends(self): def _lang(): return { # kodi lang name # gismeteo code - 'afrikaans' : '', - 'albanian' : '', - 'amharic' : '', - 'arabic' : '', - 'armenian' : '', - 'azerbaijani' : '', - 'basque' : '', - 'belarusian' : 'ru', - 'bosnian' : '', - 'bulgarian' : '', - 'burmese' : '', - 'catalan' : '', - 'chinese (simple)' : '', - 'chinese (traditional)' : '', - 'croatian' : '', - 'czech' : '', - 'danish' : '', - 'dutch' : '', - 'english' : 'en', - 'english (us)' : 'en', - 'english (australia)' : 'en', - 'english (new zealand)' : 'en', - 'esperanto' : '', - 'estonian' : '', - 'faroese' : '', - 'finnish' : '', - 'french' : '', - 'galician' : '', - 'german' : 'de', - 'greek' : '', - 'georgian' : '', - 'hebrew' : '', - 'hindi (devanagiri)' : '', - 'hungarian' : '', - 'icelandic' : '', - 'indonesian' : '', - 'italian' : '', - 'japanese' : '', - 'korean' : '', - 'latvian' : 'lt', - 'lithuanian' : 'li', - 'macedonian' : '', - 'malay' : '', - 'malayalam' : '', - 'maltese' : '', - 'maori' : '', - 'mongolian (mongolia)' : '', - 'norwegian' : '', - 'ossetic' : '', - 'persian' : '', - 'persian (iran)' : '', - 'polish' : 'pl', - 'portuguese' : '', - 'portuguese (brazil)' : '', - 'romanian' : 'ro', - 'russian' : 'ru', - 'serbian' : '', - 'serbian (cyrillic)' : '', - 'sinhala' : '', - 'slovak' : '', - 'slovenian' : '', - 'spanish' : '', - 'spanish (argentina)' : '', - 'spanish (mexico)' : '', - 'swedish' : '', - 'tajik' : '', - 'tamil (india)' : '', - 'telugu' : '', - 'thai' : '', - 'turkish' : '', - 'ukrainian' : 'ua', - 'uzbek' : '', - 'vietnamese' : '', - 'welsh' : '', + 'afrikaans': '', + 'albanian': '', + 'amharic': '', + 'arabic': '', + 'armenian': '', + 'azerbaijani': '', + 'basque': '', + 'belarusian': 'ru', + 'bosnian': '', + 'bulgarian': '', + 'burmese': '', + 'catalan': '', + 'chinese (simple)': '', + 'chinese (traditional)': '', + 'croatian': '', + 'czech': '', + 'danish': '', + 'dutch': '', + 'english': 'en', + 'english (us)': 'en', + 'english (australia)': 'en', + 'english (new zealand)': 'en', + 'esperanto': '', + 'estonian': '', + 'faroese': '', + 'finnish': '', + 'french': '', + 'galician': '', + 'german': 'de', + 'greek': '', + 'georgian': '', + 'hebrew': '', + 'hindi (devanagiri)': '', + 'hungarian': '', + 'icelandic': '', + 'indonesian': '', + 'italian': '', + 'japanese': '', + 'korean': '', + 'latvian': 'lt', + 'lithuanian': 'li', + 'macedonian': '', + 'malay': '', + 'malayalam': '', + 'maltese': '', + 'maori': '', + 'mongolian (mongolia)': '', + 'norwegian': '', + 'ossetic': '', + 'persian': '', + 'persian (iran)': '', + 'polish': 'pl', + 'portuguese': '', + 'portuguese (brazil)': '', + 'romanian': 'ro', + 'russian': 'ru', + 'serbian': '', + 'serbian (cyrillic)': '', + 'sinhala': '', + 'slovak': '', + 'slovenian': '', + 'spanish': '', + 'spanish (argentina)': '', + 'spanish (mexico)': '', + 'swedish': '', + 'tajik': '', + 'tamil (india)': '', + 'telugu': '', + 'thai': '', + 'turkish': '', + 'ukrainian': 'ua', + 'uzbek': '', + 'vietnamese': '', + 'welsh': '', } @staticmethod diff --git a/weather.gismeteo/resources/libs/gismeteo.py b/weather.gismeteo/resources/libs/gismeteo.py index 33fda999a..fa745dba9 100644 --- a/weather.gismeteo/resources/libs/gismeteo.py +++ b/weather.gismeteo/resources/libs/gismeteo.py @@ -3,12 +3,14 @@ from __future__ import unicode_literals -import time import calendar +import time + import requests -import xml.etree.cElementTree as etree try: + import xml.etree.cElementTree as etree + etree.fromstring('') except TypeError: import xml.etree.ElementTree as etree @@ -17,12 +19,10 @@ class GismeteoError(Exception): - pass class GismeteoClient(object): - _base_url = 'https://services.gismeteo.net/inform-service/inf_chrome' def __init__(self, lang='en'): @@ -57,8 +57,7 @@ def _get_locations_list(root): result = [] for item in root: - - location = {'name' : item.attrib['n'], + location = {'name': item.attrib['n'], 'id': item.attrib['id'], 'country': item.attrib['country_name'], 'district': item.attrib.get('district_name', ''), @@ -95,14 +94,15 @@ def _get_forecast_info(self, root): xml_location = root[0] - return {'name' : xml_location.attrib['name'], + return {'name': xml_location.attrib['name'], 'id': xml_location.attrib['id'], 'kind': xml_location.attrib['kind'], 'country': xml_location.attrib['country_name'], 'district': xml_location.attrib.get('district_name', ''), 'lat': xml_location.attrib['lat'], 'lng': xml_location.attrib['lng'], - 'cur_time': self._get_date(xml_location.attrib['cur_time'], self._get_int(xml_location.attrib['tzone'])), + 'cur_time': self._get_date(xml_location.attrib['cur_time'], + self._get_int(xml_location.attrib['tzone'])), 'current': self._get_fact_forecast(xml_location), 'days': self._get_days_forecast(xml_location), } @@ -129,11 +129,11 @@ def _get_item_forecast(self, xml_item, tzone): result['cloudiness'] = xml_values.attrib['cl'] result['storm'] = (xml_values.attrib['ts'] == '1') result['precipitation'] = {'type': xml_values.attrib['pt'], - 'amount': xml_values.attrib.get('prflt'), + 'amount': self._get_float(xml_values.attrib.get('prflt')), 'intensity': xml_values.attrib['pr'], } if xml_values.attrib.get('ph') is not None \ - and xml_values.attrib['ph']: + and xml_values.attrib['ph']: result['phenomenon'] = self._get_int(xml_values.attrib['ph']) if xml_item.attrib.get('tod') is not None: result['tod'] = self._get_int(xml_item.attrib['tod']) @@ -171,12 +171,12 @@ def _get_days_forecast(self, xml_location): }, 'pressure': {'min': self._get_int(xml_day.attrib['pmin']), 'max': self._get_int(xml_day.attrib['pmax']), - 'avg': self._get_int(xml_day.attrib['p']), + 'avg': self._get_int(xml_day.attrib.get('p')), }, 'cloudiness': xml_day.attrib['cl'], 'storm': (xml_day.attrib['ts'] == '1'), 'precipitation': {'type': xml_day.attrib['pt'], - 'amount': xml_day.attrib['prflt'], + 'amount': self._get_float(xml_day.attrib.get('prflt')), 'intensity': xml_day.attrib['pr'], }, 'icon': xml_day.attrib['icon'], @@ -205,6 +205,9 @@ def _get_hourly_forecast(self, xml_day, tzone): @staticmethod def _get_int(value): + if value is None: + return 0 + try: return int(value) except ValueError: @@ -212,6 +215,9 @@ def _get_int(value): @staticmethod def _get_float(value): + if value is None: + return 0.0 + try: return float(value) except ValueError: diff --git a/weather.gismeteo/resources/libs/simpleweather/webclient.py b/weather.gismeteo/resources/libs/simpleweather/webclient.py index c29c5e8cc..92b5bd694 100644 --- a/weather.gismeteo/resources/libs/simpleweather/webclient.py +++ b/weather.gismeteo/resources/libs/simpleweather/webclient.py @@ -67,6 +67,11 @@ def delete(self, url, **kwargs): func = super(WebClient, self).delete return self._run(func, url, **kwargs) + def head(self, url, **kwargs): + + func = super(WebClient, self).head + return self._run(func, url, **kwargs) + def _run(self, func, url, **kwargs): try: