Skip to content

Commit

Permalink
Merge pull request #278 from aceinnolab/feature/#275
Browse files Browse the repository at this point in the history
 python 3.11 & code quality improvements
  • Loading branch information
aceisace authored Nov 7, 2023
2 parents 0ea7b30 + 8af21e4 commit de72c4c
Show file tree
Hide file tree
Showing 24 changed files with 244 additions and 156 deletions.
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
Expand Up @@ -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

Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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


Expand Down
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
Expand Up @@ -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}')
Expand Down Expand Up @@ -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}')

Expand All @@ -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}')

Expand Down
59 changes: 25 additions & 34 deletions inkycal/modules/inkycal_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}")

Expand Down Expand Up @@ -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)
Expand All @@ -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):
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
)
Expand Down
6 changes: 4 additions & 2 deletions inkycal/modules/inkycal_feeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions inkycal/modules/inkycal_jokes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}")

Expand Down
5 changes: 3 additions & 2 deletions inkycal/modules/inkycal_stocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}")

Expand Down
14 changes: 7 additions & 7 deletions inkycal/modules/inkycal_textfile_to_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)


Expand Down Expand Up @@ -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')

Expand Down Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions inkycal/modules/inkycal_todoist.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit de72c4c

Please sign in to comment.