Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python 3.11 & code quality improvements #278

Merged
merged 3 commits into from
Nov 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions inkycal/custom/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .functions import *
from .inkycal_exceptions import *
from .openweathermap_wrapper import OpenWeatherMap
43 changes: 32 additions & 11 deletions inkycal/custom/functions.py
Original file line number Diff line number Diff line change
@@ -6,8 +6,10 @@
Copyright by aceinnolab
"""
import logging
import traceback

from PIL import Image, ImageDraw, ImageFont, ImageColor
from urllib.request import urlopen
import requests
import os
import time

@@ -98,11 +100,13 @@ def auto_fontsize(font, max_height):
Returns:
A PIL font object with modified height.
"""

fontsize = font.getsize('hg')[1]
while font.getsize('hg')[1] <= (max_height * 0.80):
text_bbox = font.getbbox("hg")
text_height = text_bbox[3] - text_bbox[1]
fontsize = text_height
while text_height <= (max_height * 0.80):
fontsize += 1
font = ImageFont.truetype(font.path, fontsize)
text_height = text_bbox[3] - text_bbox[1]
return font


@@ -154,21 +158,34 @@ def write(image, xy, box_size, text, font=None, **kwargs):
if autofit or (fill_width != 1.0) or (fill_height != 0.8):
size = 8
font = ImageFont.truetype(font.path, size)
text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
text_bbox = font.getbbox(text)
text_width = text_bbox[2] - text_bbox[0]
text_bbox_height = font.getbbox("hg")
text_height = text_bbox_height[3] - text_bbox_height[1]

while (text_width < int(box_width * fill_width) and
text_height < int(box_height * fill_height)):
size += 1
font = ImageFont.truetype(font.path, size)
text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
text_bbox = font.getbbox(text)
text_width = text_bbox[2] - text_bbox[0]
text_bbox_height = font.getbbox("hg")
text_height = text_bbox_height[3] - text_bbox_height[1]

text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
text_bbox = font.getbbox(text)
text_width = text_bbox[2] - text_bbox[0]
text_bbox_height = font.getbbox("hg")
text_height = text_bbox_height[3] - text_bbox_height[1]

# Truncate text if text is too long so it can fit inside the box
if (text_width, text_height) > (box_width, box_height):
logs.debug(('truncating {}'.format(text)))
while (text_width, text_height) > (box_width, box_height):
text = text[0:-1]
text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
text_bbox = font.getbbox(text)
text_width = text_bbox[2] - text_bbox[0]
text_bbox_height = font.getbbox("hg")
text_height = text_bbox_height[3] - text_bbox_height[1]
logs.debug(text)

# Align text to desired position
@@ -215,14 +232,17 @@ def text_wrap(text, font=None, max_width=None):
A list containing chunked strings of the full text.
"""
lines = []
if font.getsize(text)[0] < max_width:

text_width = font.getlength(text)

if text_width < max_width:
lines.append(text)
else:
words = text.split(' ')
i = 0
while i < len(words):
line = ''
while i < len(words) and font.getsize(line + words[i])[0] <= max_width:
while i < len(words) and font.getlength(line + words[i]) <= max_width:
line = line + words[i] + " "
i += 1
if not line:
@@ -249,9 +269,10 @@ def internet_available():
"""

try:
urlopen('https://google.com', timeout=5)
requests.get('https://google.com', timeout=5)
return True
except:
print(f"Network could not be reached: {traceback.print_exc()}")
return False


43 changes: 43 additions & 0 deletions inkycal/custom/openweathermap_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import logging
from enum import Enum

import requests
import json

logger = logging.getLogger(__name__)

class WEATHER_OPTIONS(Enum):
CURRENT_WEATHER = "weather"

class FORECAST_INTERVAL(Enum):
THREE_HOURS = "3h"
FIVE_DAYS = "5d"



class OpenWeatherMap:
def __init__(self, api_key:str, city_id:int, units:str) -> None:
self.api_key = api_key
self.city_id = city_id
assert (units in ["metric", "imperial"] )
self.units = units
self._api_version = "2.5"
self._base_url = f"https://api.openweathermap.org/data/{self._api_version}"


def get_current_weather(self) -> dict:
current_weather_url = f"{self._base_url}/weather?id={self.city_id}&appid={self.api_key}&units={self.units}"
response = requests.get(current_weather_url)
if not response.ok:
raise AssertionError(f"Failure getting the current weather: code {response.status_code}. Reason: {response.text}")
data = json.loads(response.text)
return data

def get_weather_forecast(self) -> dict:
forecast_url = f"{self._base_url}/forecast?id={self.city_id}&appid={self.api_key}&units={self.units}"
response = requests.get(forecast_url)
if not response.ok:
raise AssertionError(f"Failure getting the current weather: code {response.status_code}. Reason: {response.text}")
data = json.loads(response.text)["list"]
return data

13 changes: 8 additions & 5 deletions inkycal/modules/inkycal_agenda.py
Original file line number Diff line number Diff line change
@@ -98,7 +98,9 @@ def generate_image(self):

# Calculate the max number of lines that can fit on the image
line_spacing = 1
line_height = int(self.font.getsize('hg')[1]) + line_spacing

text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
line_width = im_width
max_lines = im_height // line_height
logger.debug(f'max lines: {max_lines}')
@@ -133,8 +135,8 @@ def generate_image(self):
# parser.show_events()

# Set the width for date, time and event titles
date_width = int(max([self.font.getsize(
dates['begin'].format(self.date_format, locale=self.language))[0]
date_width = int(max([self.font.getlength(
dates['begin'].format(self.date_format, locale=self.language))
for dates in agenda_events]) * 1.2)
logger.debug(f'date_width: {date_width}')

@@ -147,8 +149,9 @@ def generate_image(self):
logger.info('Managed to parse events from urls')

# Find out how much space the event times take
time_width = int(max([self.font.getsize(
events['begin'].format(self.time_format, locale=self.language))[0]

time_width = int(max([self.font.getlength(
events['begin'].format(self.time_format, locale=self.language))
for events in upcoming_events]) * 1.2)
logger.debug(f'time_width: {time_width}')

59 changes: 25 additions & 34 deletions inkycal/modules/inkycal_calendar.py
Original file line number Diff line number Diff line change
@@ -110,7 +110,8 @@ def generate_image(self):

# Allocate space for month-names, weekdays etc.
month_name_height = int(im_height * 0.10)
weekdays_height = int(self.font.getsize('hg')[1] * 1.25)
text_bbox_height = self.font.getbbox("hg")
weekdays_height = int((text_bbox_height[3] - text_bbox_height[1])* 1.25)
logger.debug(f"month_name_height: {month_name_height}")
logger.debug(f"weekdays_height: {weekdays_height}")

@@ -182,15 +183,15 @@ def generate_image(self):
]
logger.debug(f'weekday names: {weekday_names}')

for idx, weekday in enumerate(weekday_pos):
for index, weekday in enumerate(weekday_pos):
write(
im_black,
weekday,
(icon_width, weekdays_height),
weekday_names[idx],
weekday_names[index],
font=self.font,
autofit=True,
fill_height=1.0,
fill_height=0.9,
)

# Create a calendar template and flatten (remove nestings)
@@ -207,6 +208,10 @@ def generate_image(self):
# remove zeros from calendar since they are not required
calendar_flat = [num for num in calendar_flat if num != 0]

# ensure all numbers have the same size
fontsize_numbers = int(min(icon_width, icon_height) * 0.5)
number_font = ImageFont.truetype(self.font.path, fontsize_numbers)

# Add the numbers on the correct positions
for number in calendar_flat:
if number != int(now.day):
@@ -215,9 +220,7 @@ def generate_image(self):
grid[number],
(icon_width, icon_height),
str(number),
font=self.num_font,
fill_height=0.5,
fill_width=0.5,
font=number_font,
)

# Draw a red/black circle with the current day of month in white
@@ -262,10 +265,10 @@ def generate_image(self):
from inkycal.modules.ical_parser import iCalendar

# find out how many lines can fit at max in the event section
line_spacing = 0
max_event_lines = events_height // (
self.font.getsize('hg')[1] + line_spacing
)
line_spacing = 2
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
max_event_lines = events_height // (line_height + line_spacing)

# generate list of coordinates for each line
events_offset = im_height - events_height
@@ -329,31 +332,18 @@ def generate_image(self):
# Find out how much space (width) the date format requires
lang = self.language

date_width = int(
max(
(
self.font.getsize(
events['begin'].format(self.date_format, locale=lang)
)[0]
for events in upcoming_events
)
)
* 1.1
date_width = int(max((
self.font.getlength(events['begin'].format(self.date_format, locale=lang))
for events in upcoming_events))* 1.1
)

time_width = int(
max(
(
self.font.getsize(
events['begin'].format(self.time_format, locale=lang)
)[0]
for events in upcoming_events
)
)
* 1.1
time_width = int(max((
self.font.getlength(events['begin'].format(self.time_format, locale=lang))
for events in upcoming_events))* 1.1
)

line_height = self.font.getsize('hg')[1] + line_spacing
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing

event_width_s = im_width - date_width - time_width
event_width_l = im_width - date_width
@@ -411,12 +401,13 @@ def generate_image(self):
cursor += 1
else:
symbol = '- '
while self.font.getsize(symbol)[0] < im_width * 0.9:

while self.font.getlength(symbol) < im_width * 0.9:
symbol += ' -'
write(
im_black,
event_lines[0],
(im_width, self.font.getsize(symbol)[1]),
(im_width, line_height),
symbol,
font=self.font,
)
6 changes: 4 additions & 2 deletions inkycal/modules/inkycal_feeds.py
Original file line number Diff line number Diff line change
@@ -91,9 +91,11 @@ def generate_image(self):

# Set some parameters for formatting feeds
line_spacing = 1
line_height = self.font.getsize('hg')[1] + line_spacing

line_width = im_width
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
max_lines = (im_height // (line_height + line_spacing))

# Calculate padding from top so the lines look centralised
spacing_top = int(im_height % line_height / 2)
7 changes: 4 additions & 3 deletions inkycal/modules/inkycal_jokes.py
Original file line number Diff line number Diff line change
@@ -54,10 +54,11 @@ def generate_image(self):
raise NetworkNotReachableError

# Set some parameters for formatting feeds
line_spacing = 1
line_height = self.font.getsize('hg')[1] + line_spacing
line_spacing = 5
text_bbox = self.font.getbbox("hg")
line_height = text_bbox[3] - text_bbox[1] + line_spacing
line_width = im_width
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
max_lines = (im_height // (line_height + line_spacing))

logger.debug(f"max_lines: {max_lines}")

5 changes: 3 additions & 2 deletions inkycal/modules/inkycal_stocks.py
Original file line number Diff line number Diff line change
@@ -96,9 +96,10 @@ def generate_image(self):

# Set some parameters for formatting feeds
line_spacing = 1
line_height = self.font.getsize('hg')[1] + line_spacing
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
line_width = im_width
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
max_lines = (im_height // line_height)

logger.debug(f"max_lines: {max_lines}")

14 changes: 7 additions & 7 deletions inkycal/modules/inkycal_textfile_to_display.py
Original file line number Diff line number Diff line change
@@ -7,11 +7,11 @@
Copyright by aceinnolab
"""
from inkycal.modules.template import inkycal_module
from inkycal.custom import *

from urllib.request import urlopen

from inkycal.custom import *
from inkycal.modules.template import inkycal_module

logger = logging.getLogger(__name__)


@@ -44,7 +44,6 @@ def __init__(self, config):

self.make_request = True if self.filepath.startswith("https://") else False


# give an OK message
print(f'{__name__} loaded')

@@ -73,10 +72,11 @@ def generate_image(self):
raise NetworkNotReachableError

# Set some parameters for formatting feeds
line_spacing = 1
line_height = self.font.getsize('hg')[1] + line_spacing
line_spacing = 4
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
line_width = im_width
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
max_lines = im_height // line_height

# Calculate padding from top so the lines look centralised
spacing_top = int(im_height % line_height / 2)
5 changes: 3 additions & 2 deletions inkycal/modules/inkycal_todoist.py
Original file line number Diff line number Diff line change
@@ -86,9 +86,10 @@ def generate_image(self):

# Set some parameters for formatting todos
line_spacing = 1
line_height = self.font.getsize('hg')[1] + line_spacing
text_bbox_height = self.font.getbbox("hg")
line_height = text_bbox_height[3] - text_bbox_height[1] + line_spacing
line_width = im_width
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
max_lines = im_height // line_height

# Calculate padding from top so the lines look centralised
spacing_top = int(im_height % line_height / 2)
155 changes: 94 additions & 61 deletions inkycal/modules/inkycal_weather.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
import decimal
import arrow

from pyowm.owm import OWM
from inkycal.custom import OpenWeatherMap

logger = logging.getLogger(__name__)

@@ -95,7 +95,7 @@ def __init__(self, config):
self.use_beaufort = config['use_beaufort']

# additional configuration
self.owm = OWM(self.api_key).weather_manager()
self.owm = OpenWeatherMap(api_key=self.api_key, city_id=self.location, units=config['units'])
self.timezone = get_system_tz()
self.locale = config['language']
self.weatherfont = ImageFont.truetype(
@@ -104,6 +104,42 @@ def __init__(self, config):
# give an OK message
print(f"{__name__} loaded")


@staticmethod
def mps_to_beaufort(meters_per_second:float) -> int:
"""Map meters per second to the beaufort scale.
Args:
meters_per_second:
float representing meters per seconds
Returns:
an integer of the beaufort scale mapping the input
"""
thresholds = [0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.7, 24.5, 28.4]
return next((i for i, threshold in enumerate(thresholds) if meters_per_second < threshold), 11)

@staticmethod
def mps_to_mph(meters_per_second:float) -> float:
"""Map meters per second to miles per hour, rounded to one decimal place.
Args:
meters_per_second:
float representing meters per seconds.
Returns:
float representing the input value in miles per hour.
"""
# 1 m/s is approximately equal to 2.23694 mph
miles_per_hour = meters_per_second * 2.23694
return round(miles_per_hour, 1)

@staticmethod
def celsius_to_fahrenheit(celsius:int or float):
"""Converts the given temperate from degrees Celsius to Fahrenheit."""
fahrenheit = (celsius * 9 / 5) + 32
return fahrenheit

def generate_image(self):
"""Generate image for this module"""

@@ -124,7 +160,11 @@ def generate_image(self):
raise NetworkNotReachableError

def get_moon_phase():
"""Calculate the current (approximate) moon phase"""
"""Calculate the current (approximate) moon phase
Returns:
The corresponding moonphase-icon.
"""

dec = decimal.Decimal
diff = now - arrow.get(2001, 1, 1)
@@ -154,7 +194,7 @@ def is_negative(temp):
return answer

# Lookup-table for weather icons and weather codes
weathericons = {
weather_icons = {
'01d': '\uf00d',
'02d': '\uf002',
'03d': '\uf013',
@@ -227,26 +267,26 @@ def draw_icon(image, xy, box_size, icon, rotation=None):
# Increase fontsize to fit specified height and width of text box
size = 8
font = ImageFont.truetype(font.path, size)
text_width, text_height = font.getsize(text)
text_width, text_height = font.getbbox(text)[2:]

while (text_width < int(box_width * 0.9) and
text_height < int(box_height * 0.9)):
size += 1
font = ImageFont.truetype(font.path, size)
text_width, text_height = font.getsize(text)
text_width, text_height = font.getbbox(text)[2:]

text_width, text_height = font.getsize(text)
text_width, text_height = font.getbbox(text)[2:]

# Align text to desired position
x = int((box_width / 2) - (text_width / 2))
y = int((box_height / 2) - (text_height / 2) - (icon_size_correction[icon] * size) / 2)
y = int((box_height / 2) - (text_height / 2))

# Draw the text in the text-box
draw = ImageDraw.Draw(image)
space = Image.new('RGBA', (box_width, box_height))
ImageDraw.Draw(space).text((x, y), text, fill='black', font=font)

if rotation != None:
if rotation:
space.rotate(rotation, expand=True)

# Update only region with text (add text with transparent background)
@@ -350,14 +390,9 @@ def draw_icon(image, xy, box_size, icon, rotation=None):
temp_fc4 = (col7, row3)

# Create current-weather and weather-forecast objects
if self.location.isdigit():
logging.debug('looking up location by ID')
weather = self.owm.weather_at_id(int(self.location)).weather
forecast = self.owm.forecast_at_id(int(self.location), '3h')
else:
logging.debug('looking up location by string')
weather = self.owm.weather_at_place(self.location).weather
forecast = self.owm.forecast_at_place(self.location, '3h')
logging.debug('looking up location by ID')
weather = self.owm.get_current_weather()
forecast = self.owm.get_weather_forecast()

# Set decimals
dec_temp = None if self.round_temperature == True else 1
@@ -369,12 +404,14 @@ def draw_icon(image, xy, box_size, icon, rotation=None):
elif self.units == 'imperial':
temp_unit = 'fahrenheit'

logging.debug(f'temperature unit: {temp_unit}')
logging.debug(f'temperature unit: {self.units}')
logging.debug(f'decimals temperature: {dec_temp} | decimals wind: {dec_wind}')

# Get current time
now = arrow.utcnow()

fc_data = {}

if self.forecast_interval == 'hourly':

logger.debug("getting hourly forecasts")
@@ -386,21 +423,22 @@ def draw_icon(image, xy, box_size, icon, rotation=None):
else:
hour_gap = 3

# Create timings for hourly forcasts
# Create timings for hourly forecasts
forecast_timings = [now.shift(hours=+ hour_gap + _).floor('hour')
for _ in range(0, 12, 3)]

# Create forecast objects for given timings
forecasts = [forecast.get_weather_at(forecast_time.datetime) for
forecast_time in forecast_timings]
forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in forecast_timings]

# Add forecast-data to fc_data dictionary
fc_data = {}
for forecast in forecasts:
temp = '{}°'.format(round(
forecast.temperature(unit=temp_unit)['temp'], ndigits=dec_temp))
if self.units == "metric":
temp = f"{round(weather['main']['temp'], ndigits=dec_temp)}°C"
else:
temp = f"{round(self.celsius_to_fahrenheit(weather['weather']['main']['temp']), ndigits=dec_temp)}°F"

icon = forecast.weather_icon_name
icon = forecast["weather"][0]["icon"]
fc_data['fc' + str(forecasts.index(forecast) + 1)] = {
'temp': temp,
'icon': icon,
@@ -412,38 +450,35 @@ def draw_icon(image, xy, box_size, icon, rotation=None):

logger.debug("getting daily forecasts")

def calculate_forecast(days_from_today):
def calculate_forecast(days_from_today) -> dict:
"""Get temperature range and most frequent icon code for forecast
days_from_today should be int from 1-4: e.g. 2 -> 2 days from today
"""

# Create a list containing time-objects for every 3rd hour of the day
time_range = list(arrow.Arrow.range('hour',
now.shift(days=days_from_today).floor('day'),
now.shift(days=days_from_today).ceil('day')
))[::3]
time_range = list(
arrow.Arrow.range('hour',
now.shift(days=days_from_today).floor('day'),now.shift(days=days_from_today).ceil('day')
))[::3]

# Get forecasts for each time-object
forecasts = [forecast.get_weather_at(_.datetime) for _ in time_range]
forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in time_range]

# Get all temperatures for this day
daily_temp = [round(_.temperature(unit=temp_unit)['temp'],
ndigits=dec_temp) for _ in forecasts]
daily_temp = [round(_["main"]["temp"]) for _ in forecasts]
# Calculate min. and max. temp for this day
temp_range = f'{max(daily_temp)}°/{min(daily_temp)}°'
temp_range = f'{min(daily_temp)}°/{max(daily_temp)}°'

# Get all weather icon codes for this day
daily_icons = [_.weather_icon_name for _ in forecasts]
daily_icons = [_["weather"][0]["icon"] for _ in forecasts]
# Find most common element from all weather icon codes
status = max(set(daily_icons), key=daily_icons.count)

weekday = now.shift(days=days_from_today).format('ddd', locale=
self.locale)
weekday = now.shift(days=days_from_today).format('ddd', locale=self.locale)
return {'temp': temp_range, 'icon': status, 'stamp': weekday}

forecasts = [calculate_forecast(days) for days in range(1, 5)]

fc_data = {}
for forecast in forecasts:
fc_data['fc' + str(forecasts.index(forecast) + 1)] = {
'temp': forecast['temp'],
@@ -455,47 +490,45 @@ def calculate_forecast(days_from_today):
logger.debug((key, val))

# Get some current weather details
temperature = '{}°'.format(round(
weather.temperature(unit=temp_unit)['temp'], ndigits=dec_temp))
if dec_temp != 0:
temperature = f"{round(weather['main']['temp'])}°"
else:
temperature = f"{round(weather['main']['temp'],ndigits=dec_temp)}°"

weather_icon = weather.weather_icon_name
humidity = str(weather.humidity)
sunrise_raw = arrow.get(weather.sunrise_time()).to(self.timezone)
sunset_raw = arrow.get(weather.sunset_time()).to(self.timezone)
weather_icon = weather["weather"][0]["icon"]
humidity = str(weather["main"]["humidity"])
sunrise_raw = arrow.get(weather["sys"]["sunrise"]).to(self.timezone)
sunset_raw = arrow.get(weather["sys"]["sunset"]).to(self.timezone)

logger.debug(f'weather_icon: {weather_icon}')

if self.hour_format == 12:
logger.debug('using 12 hour format for sunrise/sunset')
sunrise = sunrise_raw.format('h:mm a')
sunset = sunset_raw.format('h:mm a')

elif self.hour_format == 24:
else:
# 24 hours format
logger.debug('using 24 hour format for sunrise/sunset')
sunrise = sunrise_raw.format('H:mm')
sunset = sunset_raw.format('H:mm')

# Format the windspeed to user preference
# Format the wind-speed to user preference
if self.use_beaufort:
logger.debug("using beaufort for wind")
wind = str(weather.wind(unit='beaufort')['speed'])

wind = str(self.mps_to_beaufort(weather["wind"]["speed"]))
else:

if self.units == 'metric':
logging.debug('getting windspeed in metric unit')
wind = str(weather.wind(unit='meters_sec')['speed']) + 'm/s'

elif self.units == 'imperial':
logging.debug('getting windspeed in imperial unit')
wind = str(weather.wind(unit='miles_hour')['speed']) + 'miles/h'
logging.debug('getting wind speed in meters per second')
wind = f"{weather['wind']['speed']} m/s"
else:
logging.debug('getting wind speed in imperial unit')
wind = f"{self.mps_to_mph(weather['wind']['speed'])} miles/h"

dec = decimal.Decimal
moonphase = get_moon_phase()
moon_phase = get_moon_phase()

# Fill weather details in col 1 (current weather icon)
draw_icon(im_colour, weather_icon_pos, (col_width, im_height),
weathericons[weather_icon])
weather_icons[weather_icon])

# Fill weather details in col 2 (temp, humidity, wind)
draw_icon(im_colour, temperature_icon_pos, (icon_small, row_height),
@@ -521,7 +554,7 @@ def calculate_forecast(days_from_today):
wind, font=self.font)

# Fill weather details in col 3 (moonphase, sunrise, sunset)
draw_icon(im_colour, moonphase_pos, (col_width, row_height), moonphase)
draw_icon(im_colour, moonphase_pos, (col_width, row_height), moon_phase)

draw_icon(im_colour, sunrise_icon_pos, (icon_small, icon_small), '\uf051')
write(im_black, sunrise_time_pos, (col_width - icon_small, row_height),
@@ -535,7 +568,7 @@ def calculate_forecast(days_from_today):
for pos in range(1, len(fc_data) + 1):
stamp = fc_data[f'fc{pos}']['stamp']

icon = weathericons[fc_data[f'fc{pos}']['icon']]
icon = weather_icons[fc_data[f'fc{pos}']['icon']]
temp = fc_data[f'fc{pos}']['temp']

write(im_black, eval(f'stamp_fc{pos}'), (col_width, row_height),
@@ -548,7 +581,7 @@ def calculate_forecast(days_from_today):
border_h = row3 + row_height
border_w = col_width - 3 # leave 3 pixels gap

# Add borders around each sub-section
# Add borders around each subsection
draw_border(im_black, (col1, row1), (col_width * 3 - 3, border_h),
shrinkage=(0, 0))

2 changes: 1 addition & 1 deletion inkycal/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from config import Config
from .config import Config
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -57,8 +57,6 @@ def test_generate_image(self):
print('OK')
if Config.USE_PREVIEW:
preview(merge(im_black, im_colour))
im = merge(im_black, im_colour)
im.show()


if __name__ == '__main__':
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 0 additions & 2 deletions inkycal/tests/test_inkycal_textfile_to_display.py
Original file line number Diff line number Diff line change
@@ -112,8 +112,6 @@ def test_generate_image(self):
print('OK')
if Config.USE_PREVIEW:
preview(merge(im_black, im_colour))
im = merge(im_black, im_colour)
im.show()

if delete_file_after_parse:
print("cleaning up temp file")
Original file line number Diff line number Diff line change
@@ -46,7 +46,6 @@ def test_generate_image(self):
print('OK')
if Config.USE_PREVIEW:
preview(merge(im_black, im_colour))
merge(im_black, im_colour).show()
else:
print('No api key given, omitting test')

Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
merge = Inkyimage.merge

owm_api_key = Config.OPENWEATHERMAP_API_KEY
location = 'Stuttgart, DE'
location = '2825297'

tests = [
{
@@ -184,7 +184,8 @@ def test_generate_image(self):
im_black, im_colour = module.generate_image()
print('OK')
if Config.USE_PREVIEW:
preview(merge(im_black, im_colour))
merged = merge(im_black, im_colour)
preview(merged)



37 changes: 16 additions & 21 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
arrow==1.2.3
arrow==1.3.0
certifi==2023.7.22
cycler==0.11.0
cycler==0.12.1
feedparser==6.0.10
fonttools==4.40.0
geojson==2.3.0
icalendar==5.0.7
kiwisolver==1.4.4
lxml==4.9.2
matplotlib==3.7.1
multitasking==0.0.11
numpy==1.25.0
packaging==23.1
pandas==2.0.2
Pillow==9.5.0
pyowm==3.3.0
pyparsing==3.1.0
fonttools==4.44.0
icalendar==5.0.11
kiwisolver==1.4.5
lxml==4.9.3
matplotlib==3.8.1
numpy==1.26.1
packaging==23.2
Pillow==10.1.0
pyparsing==3.1.1
PySocks==1.7.1
python-dateutil==2.8.2
pytz==2023.3
recurring-ical-events==2.0.2
pytz==2023.3.post1
recurring-ical-events==2.1.0
requests==2.31.0
sgmllib3k==1.0.0
six==1.16.0
todoist-api-python==2.0.2
typing_extensions==4.6.3
todoist-api-python==2.1.3
typing_extensions==4.8.0
urllib3==2.0.7
yfinance==0.2.21
python-dotenv==1.0.0
setuptools==68.0.0
setuptools==68.2.2