Source code for i3pystatus.weather

from i3pystatus import SettingsBase, IntervalModule, formatp
from i3pystatus.core.util import user_open, internet, require


class Backend(SettingsBase):
    settings = ()


[docs]class Weather(IntervalModule): ''' This is a generic weather-checker which must use a configured weather backend. For list of all available backends see :ref:`weatherbackends`. Left clicking on the module will launch the forecast page for the location being checked. .. _weather-formatters: .. rubric:: Available formatters * `{city}` — Location of weather observation * `{condition}` — Current weather condition (Rain, Snow, Overcast, etc.) * `{icon}` — Icon representing the current weather condition * `{observation_time}` — Time of weather observation (supports strftime format flags) * `{current_temp}` — Current temperature, excluding unit * `{low_temp}` — Forecasted low temperature, excluding unit * `{high_temp}` — Forecasted high temperature, excluding unit (may be empty in the late afternoon) * `{temp_unit}` — Either ``°C`` or ``°F``, depending on whether metric or * `{feelslike}` — "Feels Like" temperature, excluding unit * `{dewpoint}` — Dewpoint temperature, excluding unit imperial units are being used * `{wind_speed}` — Wind speed, excluding unit * `{wind_unit}` — Either ``kph`` or ``mph``, depending on whether metric or imperial units are being used * `{wind_direction}` — Wind direction * `{wind_gust}` — Speed of wind gusts in mph/kph, excluding unit * `{pressure}` — Barometric pressure, excluding unit * `{pressure_unit}` — ``mb`` or ``in``, depending on whether metric or imperial units are being used * `{pressure_trend}` — ``+`` if rising, ``-`` if falling, or an empty string if the pressure is steady (neither rising nor falling) * `{visibility}` — Visibility distance, excluding unit * `{visibility_unit}` — Either ``km`` or ``mi``, depending on whether metric or imperial units are being used * `{humidity}` — Current humidity, excluding percentage symbol * `{uv_index}` — UV Index This module supports the :ref:`formatp <formatp>` extended string format syntax. This allows for values to be hidden when they evaluate as False. This comes in handy for the :py:mod:`weathercom <.weather.weathercom>` backend, which at a certain point in the afternoon will have a blank ``{high_temp}`` value. Using the following snippet in your format string will only display the high temperature information if it is not blank: :: {current_temp}{temp_unit}[ Hi: {high_temp}[{temp_unit}]] Lo: {low_temp}{temp_unit} Brackets are evaluated from the outside-in, so the fact that the only formatter in the outer block (``{high_temp}``) is empty would keep the inner block from being evaluated at all, and entire block would not be displayed. See the following links for usage examples for the available weather backends: - :ref:`Weather.com <weather-usage-weathercom>` - :ref:`Weather Underground <weather-usage-wunderground>` ''' settings = ( ('colorize', 'Vary the color depending on the current conditions.'), ('color_icons', 'Dictionary mapping weather conditions to tuples ' 'containing a UTF-8 code for the icon, and the color ' 'to be used.'), ('color', 'Display color (or fallback color if ``colorize`` is True). ' 'If not specified, falls back to default i3bar color.'), ('backend', 'Weather backend instance'), 'interval', 'format', ) required = ('backend',) colorize = False color_icons = { 'Fair': (u'\u263c', '#ffcc00'), 'Fog': (u'', '#949494'), 'Cloudy': (u'\u2601', '#f8f8ff'), 'Partly Cloudy': (u'\u2601', '#f8f8ff'), # \u26c5 is not in many fonts 'Rainy': (u'\u26c8', '#cbd2c0'), 'Thunderstorm': (u'\u26a1', '#cbd2c0'), 'Sunny': (u'\u2600', '#ffff00'), 'Snow': (u'\u2603', '#ffffff'), 'default': ('', None), } color = None backend = None interval = 1800 format = '{current_temp}{temp_unit}' on_leftclick = 'open_forecast_url' def open_forecast_url(self): if self.backend.forecast_url and self.backend.forecast_url != 'N/A': user_open(self.backend.forecast_url) def init(self): pass
[docs] def get_color_data(self, condition): ''' Disambiguate similarly-named weather conditions, and return the icon and color that match. ''' if condition not in self.color_icons: # Check for similarly-named conditions if no exact match found condition_lc = condition.lower() if 'cloudy' in condition_lc: if 'partly' in condition_lc: condition = 'Partly Cloudy' else: condition = 'Cloudy' elif 'thunder' in condition_lc or 't-storm' in condition_lc: condition = 'Thunderstorm' elif 'snow' in condition_lc: condition = 'Snow' elif 'rain' in condition_lc or 'showers' in condition_lc: condition = 'Rainy' elif 'sunny' in condition_lc: condition = 'Sunny' elif 'clear' in condition_lc or 'fair' in condition_lc: condition = 'Fair' elif 'fog' in condition_lc: condition = 'Fog' return self.color_icons['default'] \ if condition not in self.color_icons \ else self.color_icons[condition]
@require(internet) def run(self): data = self.backend.weather_data() data['icon'], condition_color = self.get_color_data(data['condition']) color = condition_color if self.colorize else self.color self.output = { 'full_text': formatp(self.format, **data).strip(), 'color': color, }