InkyCal module updated with Black and Pylint changes
This commit is contained in:
		| @@ -4,11 +4,13 @@ | |||||||
| Inkycal Calendar Module | Inkycal Calendar Module | ||||||
| Copyright by aceisace | Copyright by aceisace | ||||||
| """ | """ | ||||||
| from inkycal.modules.template import inkycal_module |  | ||||||
| from inkycal.custom import * | # pylint: disable=logging-fstring-interpolation | ||||||
|  |  | ||||||
| import calendar as cal | import calendar as cal | ||||||
| import arrow | import arrow | ||||||
|  | from inkycal.modules.template import inkycal_module | ||||||
|  | from inkycal.custom import * | ||||||
|  |  | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -21,39 +23,32 @@ class Calendar(inkycal_module): | |||||||
|     name = "Calendar - Show monthly calendar with events from iCalendars" |     name = "Calendar - Show monthly calendar with events from iCalendars" | ||||||
|  |  | ||||||
|     optional = { |     optional = { | ||||||
|  |  | ||||||
|         "week_starts_on": { |         "week_starts_on": { | ||||||
|             "label": "When does your week start? (default=Monday)", |             "label": "When does your week start? (default=Monday)", | ||||||
|             "options": ["Monday", "Sunday"], |             "options": ["Monday", "Sunday"], | ||||||
|             "default": "Monday" |             "default": "Monday", | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         "show_events": { |         "show_events": { | ||||||
|             "label": "Show parsed events? (default = True)", |             "label": "Show parsed events? (default = True)", | ||||||
|             "options": [True, False], |             "options": [True, False], | ||||||
|             "default": True |             "default": True, | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         "ical_urls": { |         "ical_urls": { | ||||||
|             "label": "iCalendar URL/s, separate multiple ones with a comma", |             "label": "iCalendar URL/s, separate multiple ones with a comma", | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         "ical_files": { |         "ical_files": { | ||||||
|             "label": "iCalendar filepaths, separated with a comma", |             "label": "iCalendar filepaths, separated with a comma", | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         "date_format": { |         "date_format": { | ||||||
|             "label": "Use an arrow-supported token for custom date formatting " + |             "label": "Use an arrow-supported token for custom date formatting " | ||||||
|                      "see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. D MMM", |             + "see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. D MMM", | ||||||
|             "default": "D MMM", |             "default": "D MMM", | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         "time_format": { |         "time_format": { | ||||||
|             "label": "Use an arrow-supported token for custom time formatting " + |             "label": "Use an arrow-supported token for custom time formatting " | ||||||
|                      "see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. HH:mm", |             + "see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. HH:mm", | ||||||
|             "default": "HH:mm" |             "default": "HH:mm", | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     def __init__(self, config): |     def __init__(self, config): | ||||||
| @@ -62,6 +57,11 @@ class Calendar(inkycal_module): | |||||||
|         super().__init__(config) |         super().__init__(config) | ||||||
|         config = config['config'] |         config = config['config'] | ||||||
|  |  | ||||||
|  |         self.ical = None | ||||||
|  |         self.month_events = None | ||||||
|  |         self._upcoming_events = None | ||||||
|  |         self._days_with_events = None | ||||||
|  |  | ||||||
|         # optional parameters |         # optional parameters | ||||||
|         self.weekstart = config['week_starts_on'] |         self.weekstart = config['week_starts_on'] | ||||||
|         self.show_events = config['show_events'] |         self.show_events = config['show_events'] | ||||||
| @@ -82,11 +82,17 @@ class Calendar(inkycal_module): | |||||||
|         # additional configuration |         # additional configuration | ||||||
|         self.timezone = get_system_tz() |         self.timezone = get_system_tz() | ||||||
|         self.num_font = ImageFont.truetype( |         self.num_font = ImageFont.truetype( | ||||||
|             fonts['NotoSans-SemiCondensed'], size=self.fontsize) |             fonts['NotoSans-SemiCondensed'], size=self.fontsize | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         # give an OK message |         # give an OK message | ||||||
|         print(f'{__name__} loaded') |         print(f'{__name__} loaded') | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def flatten(values): | ||||||
|  |         """Flatten the values.""" | ||||||
|  |         return [x for y in values for x in y] | ||||||
|  |  | ||||||
|     def generate_image(self): |     def generate_image(self): | ||||||
|         """Generate image for this module""" |         """Generate image for this module""" | ||||||
|  |  | ||||||
| @@ -94,6 +100,7 @@ class Calendar(inkycal_module): | |||||||
|         im_width = int(self.width - (2 * self.padding_left)) |         im_width = int(self.width - (2 * self.padding_left)) | ||||||
|         im_height = int(self.height - (2 * self.padding_top)) |         im_height = int(self.height - (2 * self.padding_top)) | ||||||
|         im_size = im_width, im_height |         im_size = im_width, im_height | ||||||
|  |         events_height = 0 | ||||||
|  |  | ||||||
|         logger.info(f'Image size: {im_size}') |         logger.info(f'Image size: {im_size}') | ||||||
|  |  | ||||||
| @@ -110,7 +117,9 @@ class Calendar(inkycal_module): | |||||||
|         if self.show_events: |         if self.show_events: | ||||||
|             logger.debug("Allocating space for events") |             logger.debug("Allocating space for events") | ||||||
|             calendar_height = int(im_height * 0.6) |             calendar_height = int(im_height * 0.6) | ||||||
|             events_height = im_height - month_name_height - weekdays_height - calendar_height |             events_height = ( | ||||||
|  |                 im_height - month_name_height - weekdays_height - calendar_height | ||||||
|  |             ) | ||||||
|             logger.debug(f'calendar-section size: {im_width} x {calendar_height} px') |             logger.debug(f'calendar-section size: {im_width} x {calendar_height} px') | ||||||
|             logger.debug(f'events-section size: {im_width} x {events_height} px') |             logger.debug(f'events-section size: {im_width} x {events_height} px') | ||||||
|         else: |         else: | ||||||
| @@ -132,49 +141,60 @@ class Calendar(inkycal_module): | |||||||
|         logger.debug(f"y_spacing_calendar :{y_spacing_calendar}") |         logger.debug(f"y_spacing_calendar :{y_spacing_calendar}") | ||||||
|  |  | ||||||
|         # Calculate positions for days of month |         # Calculate positions for days of month | ||||||
|         grid_start_y = (month_name_height + weekdays_height + y_spacing_calendar) |         grid_start_y = month_name_height + weekdays_height + y_spacing_calendar | ||||||
|         grid_start_x = x_spacing_calendar |         grid_start_x = x_spacing_calendar | ||||||
|  |  | ||||||
|         grid_coordinates = [(grid_start_x + icon_width * x, grid_start_y + icon_height * y) |         grid_coordinates = [ | ||||||
|                             for y in range(calendar_rows) for x in range(calendar_cols)] |             (grid_start_x + icon_width * x, grid_start_y + icon_height * y) | ||||||
|  |             for y in range(calendar_rows) | ||||||
|  |             for x in range(calendar_cols) | ||||||
|  |         ] | ||||||
|  |  | ||||||
|         weekday_pos = [(grid_start_x + icon_width * _, month_name_height) for _ in |         weekday_pos = [ | ||||||
|                        range(calendar_cols)] |             (grid_start_x + icon_width * _, month_name_height) | ||||||
|  |             for _ in range(calendar_cols) | ||||||
|  |         ] | ||||||
|  |  | ||||||
|         now = arrow.now(tz=self.timezone) |         now = arrow.now(tz=self.timezone) | ||||||
|  |  | ||||||
|         # Set weekstart of calendar to specified weekstart |         # Set weekstart of calendar to specified weekstart | ||||||
|         if self.weekstart == "Monday": |         if self.weekstart == "Monday": | ||||||
|             cal.setfirstweekday(cal.MONDAY) |             cal.setfirstweekday(cal.MONDAY) | ||||||
|             weekstart = now.shift(days=- now.weekday()) |             weekstart = now.shift(days=-now.weekday()) | ||||||
|         else: |         else: | ||||||
|             cal.setfirstweekday(cal.SUNDAY) |             cal.setfirstweekday(cal.SUNDAY) | ||||||
|             weekstart = now.shift(days=- now.isoweekday()) |             weekstart = now.shift(days=-now.isoweekday()) | ||||||
|  |  | ||||||
|         # Write the name of current month |         # Write the name of current month | ||||||
|         write(im_black, (0, 0), (im_width, month_name_height), |         write( | ||||||
|               str(now.format('MMMM', locale=self.language)), font=self.font, |             im_black, | ||||||
|               autofit=True) |             (0, 0), | ||||||
|  |             (im_width, month_name_height), | ||||||
|  |             str(now.format('MMMM', locale=self.language)), | ||||||
|  |             font=self.font, | ||||||
|  |             autofit=True, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         # Set up weeknames in local language and add to main section |         # Set up weeknames in local language and add to main section | ||||||
|         weekday_names = [weekstart.shift(days=+_).format('ddd', locale=self.language) |         weekday_names = [ | ||||||
|                          for _ in range(7)] |             weekstart.shift(days=+_).format('ddd', locale=self.language) | ||||||
|  |             for _ in range(7) | ||||||
|  |         ] | ||||||
|         logger.debug(f'weekday names: {weekday_names}') |         logger.debug(f'weekday names: {weekday_names}') | ||||||
|  |  | ||||||
|         for _ in range(len(weekday_pos)): |         for idx, weekday in enumerate(weekday_pos): | ||||||
|             write( |             write( | ||||||
|                 im_black, |                 im_black, | ||||||
|                 weekday_pos[_], |                 weekday, | ||||||
|                 (icon_width, weekdays_height), |                 (icon_width, weekdays_height), | ||||||
|                 weekday_names[_], |                 weekday_names[idx], | ||||||
|                 font=self.font, |                 font=self.font, | ||||||
|                 autofit=True, |                 autofit=True, | ||||||
|                 fill_height=1.0 |                 fill_height=1.0, | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         # Create a calendar template and flatten (remove nestings) |         # Create a calendar template and flatten (remove nestings) | ||||||
|         flatten = lambda z: [x for y in z for x in y] |         calendar_flat = self.flatten(cal.monthcalendar(now.year, now.month)) | ||||||
|         calendar_flat = flatten(cal.monthcalendar(now.year, now.month)) |  | ||||||
|         # logger.debug(f" calendar_flat: {calendar_flat}") |         # logger.debug(f" calendar_flat: {calendar_flat}") | ||||||
|  |  | ||||||
|         # Map days of month to co-ordinates of grid -> 3: (row2_x,col3_y) |         # Map days of month to co-ordinates of grid -> 3: (row2_x,col3_y) | ||||||
| @@ -190,8 +210,15 @@ class Calendar(inkycal_module): | |||||||
|         # Add the numbers on the correct positions |         # Add the numbers on the correct positions | ||||||
|         for number in calendar_flat: |         for number in calendar_flat: | ||||||
|             if number != int(now.day): |             if number != int(now.day): | ||||||
|                 write(im_black, grid[number], (icon_width, icon_height), |                 write( | ||||||
|                       str(number), font=self.num_font, fill_height=0.5, fill_width=0.5) |                     im_black, | ||||||
|  |                     grid[number], | ||||||
|  |                     (icon_width, icon_height), | ||||||
|  |                     str(number), | ||||||
|  |                     font=self.num_font, | ||||||
|  |                     fill_height=0.5, | ||||||
|  |                     fill_width=0.5, | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|         # Draw a red/black circle with the current day of month in white |         # Draw a red/black circle with the current day of month in white | ||||||
|         icon = Image.new('RGBA', (icon_width, icon_height)) |         icon = Image.new('RGBA', (icon_width, icon_height)) | ||||||
| @@ -199,10 +226,24 @@ class Calendar(inkycal_module): | |||||||
|         x_circle, y_circle = int(icon_width / 2), int(icon_height / 2) |         x_circle, y_circle = int(icon_width / 2), int(icon_height / 2) | ||||||
|         radius = int(icon_width * 0.2) |         radius = int(icon_width * 0.2) | ||||||
|         ImageDraw.Draw(icon).ellipse( |         ImageDraw.Draw(icon).ellipse( | ||||||
|             (x_circle - radius, y_circle - radius, x_circle + radius, y_circle + radius), |             ( | ||||||
|             fill='black', outline=None) |                 x_circle - radius, | ||||||
|         write(icon, (0, 0), (icon_width, icon_height), str(now.day), |                 y_circle - radius, | ||||||
|               font=self.num_font, fill_height=0.5, colour='white') |                 x_circle + radius, | ||||||
|  |                 y_circle + radius, | ||||||
|  |             ), | ||||||
|  |             fill='black', | ||||||
|  |             outline=None, | ||||||
|  |         ) | ||||||
|  |         write( | ||||||
|  |             icon, | ||||||
|  |             (0, 0), | ||||||
|  |             (icon_width, icon_height), | ||||||
|  |             str(now.day), | ||||||
|  |             font=self.num_font, | ||||||
|  |             fill_height=0.5, | ||||||
|  |             colour='white', | ||||||
|  |         ) | ||||||
|         im_colour.paste(icon, current_day_pos, icon) |         im_colour.paste(icon, current_day_pos, icon) | ||||||
|  |  | ||||||
|         # If events should be loaded and shown... |         # If events should be loaded and shown... | ||||||
| @@ -217,17 +258,21 @@ class Calendar(inkycal_module): | |||||||
|                 events_height += icon_height * 2 |                 events_height += icon_height * 2 | ||||||
|  |  | ||||||
|             # import the ical-parser |             # import the ical-parser | ||||||
|  |             # pylint: disable=import-outside-toplevel | ||||||
|             from inkycal.modules.ical_parser import iCalendar |             from inkycal.modules.ical_parser import iCalendar | ||||||
|  |  | ||||||
|             # find out how many lines can fit at max in the event section |             # find out how many lines can fit at max in the event section | ||||||
|             line_spacing = 0 |             line_spacing = 0 | ||||||
|             max_event_lines = events_height // (self.font.getsize('hg')[1] + |             max_event_lines = events_height // ( | ||||||
|                                                 line_spacing) |                 self.font.getsize('hg')[1] + line_spacing | ||||||
|  |             ) | ||||||
|  |  | ||||||
|             # generate list of coordinates for each line |             # generate list of coordinates for each line | ||||||
|             events_offset = im_height - events_height |             events_offset = im_height - events_height | ||||||
|             event_lines = [(0, events_offset + int(events_height / max_event_lines * _)) |             event_lines = [ | ||||||
|                            for _ in range(max_event_lines)] |                 (0, events_offset + int(events_height / max_event_lines * _)) | ||||||
|  |                 for _ in range(max_event_lines) | ||||||
|  |             ] | ||||||
|  |  | ||||||
|             # logger.debug(f"event_lines {event_lines}") |             # logger.debug(f"event_lines {event_lines}") | ||||||
|  |  | ||||||
| @@ -250,8 +295,9 @@ class Calendar(inkycal_module): | |||||||
|             self.month_events = month_events |             self.month_events = month_events | ||||||
|  |  | ||||||
|             # find out on which days of this month events are taking place |             # find out on which days of this month events are taking place | ||||||
|             days_with_events = [int(events['begin'].format('D')) for events in |             days_with_events = [ | ||||||
|                                 month_events] |                 int(events['begin'].format('D')) for events in month_events | ||||||
|  |             ] | ||||||
|  |  | ||||||
|             # remove duplicates (more than one event in a single day) |             # remove duplicates (more than one event in a single day) | ||||||
|             list(set(days_with_events)).sort() |             list(set(days_with_events)).sort() | ||||||
| @@ -266,13 +312,12 @@ class Calendar(inkycal_module): | |||||||
|                         (icon_width, icon_height), |                         (icon_width, icon_height), | ||||||
|                         radius=6, |                         radius=6, | ||||||
|                         thickness=1, |                         thickness=1, | ||||||
|                         shrinkage=(0.4, 0.2) |                         shrinkage=(0.4, 0.2), | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|             # Filter upcoming events until 4 weeks in the future |             # Filter upcoming events until 4 weeks in the future | ||||||
|             parser.clear_events() |             parser.clear_events() | ||||||
|             upcoming_events = parser.get_events(now, now.shift(weeks=4), |             upcoming_events = parser.get_events(now, now.shift(weeks=4), self.timezone) | ||||||
|                                                 self.timezone) |  | ||||||
|             self._upcoming_events = upcoming_events |             self._upcoming_events = upcoming_events | ||||||
|  |  | ||||||
|             # delete events which won't be able to fit (more events than lines) |             # delete events which won't be able to fit (more events than lines) | ||||||
| @@ -284,56 +329,97 @@ class Calendar(inkycal_module): | |||||||
|                 # Find out how much space (width) the date format requires |                 # Find out how much space (width) the date format requires | ||||||
|                 lang = self.language |                 lang = self.language | ||||||
|  |  | ||||||
|                 date_width = int(max([self.font.getsize( |                 date_width = int( | ||||||
|                     events['begin'].format(self.date_format, locale=lang))[0] |                     max( | ||||||
|                                       for events in upcoming_events]) * 1.1) |                         ( | ||||||
|  |                             self.font.getsize( | ||||||
|  |                                 events['begin'].format(self.date_format, locale=lang) | ||||||
|  |                             )[0] | ||||||
|  |                             for events in upcoming_events | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                     * 1.1 | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|                 time_width = int(max([self.font.getsize( |                 time_width = int( | ||||||
|                     events['begin'].format(self.time_format, locale=lang))[0] |                     max( | ||||||
|                                       for events in upcoming_events]) * 1.1) |                         ( | ||||||
|  |                             self.font.getsize( | ||||||
|  |                                 events['begin'].format(self.time_format, locale=lang) | ||||||
|  |                             )[0] | ||||||
|  |                             for events in upcoming_events | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                     * 1.1 | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|                 line_height = self.font.getsize('hg')[1] + line_spacing |                 line_height = self.font.getsize('hg')[1] + line_spacing | ||||||
|  |  | ||||||
|                 event_width_s = im_width - date_width - time_width |                 event_width_s = im_width - date_width - time_width | ||||||
|                 event_width_l = im_width - date_width |                 event_width_l = im_width - date_width | ||||||
|  |  | ||||||
|                 # Display upcoming events below calendar |                 # Display upcoming events below calendar TODO: not used? | ||||||
|                 tomorrow = now.shift(days=1).floor('day') |                 # tomorrow = now.shift(days=1).floor('day') | ||||||
|                 in_two_days = now.shift(days=2).floor('day') |                 # in_two_days = now.shift(days=2).floor('day') | ||||||
|  |  | ||||||
|                 cursor = 0 |                 cursor = 0 | ||||||
|                 for event in upcoming_events: |                 for event in upcoming_events: | ||||||
|                     if cursor < len(event_lines): |                     if cursor < len(event_lines): | ||||||
|                         name = event['title'] |                         the_name = event['title'] | ||||||
|                         date = event['begin'].format(self.date_format, locale=lang) |                         the_date = event['begin'].format(self.date_format, locale=lang) | ||||||
|                         time = event['begin'].format(self.time_format, locale=lang) |                         the_time = event['begin'].format(self.time_format, locale=lang) | ||||||
|                         # logger.debug(f"name:{name}   date:{date} time:{time}") |                         # logger.debug(f"name:{the_name}   date:{the_date} time:{the_time}") | ||||||
|  |  | ||||||
|                         if now < event['end']: |                         if now < event['end']: | ||||||
|                             write(im_colour, event_lines[cursor], (date_width, line_height), |                             write( | ||||||
|                                   date, font=self.font, alignment='left') |                                 im_colour, | ||||||
|  |                                 event_lines[cursor], | ||||||
|  |                                 (date_width, line_height), | ||||||
|  |                                 the_date, | ||||||
|  |                                 font=self.font, | ||||||
|  |                                 alignment='left', | ||||||
|  |                             ) | ||||||
|  |  | ||||||
|                             # Check if event is all day |                             # Check if event is all day | ||||||
|                             if parser.all_day(event): |                             if parser.all_day(event): | ||||||
|                                 write(im_black, (date_width, event_lines[cursor][1]), |                                 write( | ||||||
|                                       (event_width_l, line_height), name, font=self.font, |                                     im_black, | ||||||
|                                       alignment='left') |                                     (date_width, event_lines[cursor][1]), | ||||||
|  |                                     (event_width_l, line_height), | ||||||
|  |                                     the_name, | ||||||
|  |                                     font=self.font, | ||||||
|  |                                     alignment='left', | ||||||
|  |                                 ) | ||||||
|                             else: |                             else: | ||||||
|                                 write(im_black, (date_width, event_lines[cursor][1]), |                                 write( | ||||||
|                                       (time_width, line_height), time, font=self.font, |                                     im_black, | ||||||
|                                       alignment='left') |                                     (date_width, event_lines[cursor][1]), | ||||||
|  |                                     (time_width, line_height), | ||||||
|  |                                     the_time, | ||||||
|  |                                     font=self.font, | ||||||
|  |                                     alignment='left', | ||||||
|  |                                 ) | ||||||
|  |  | ||||||
|                                 write(im_black, (date_width + time_width, event_lines[cursor][1]), |                                 write( | ||||||
|                                       (event_width_s, line_height), name, font=self.font, |                                     im_black, | ||||||
|                                       alignment='left') |                                     (date_width + time_width, event_lines[cursor][1]), | ||||||
|  |                                     (event_width_s, line_height), | ||||||
|  |                                     the_name, | ||||||
|  |                                     font=self.font, | ||||||
|  |                                     alignment='left', | ||||||
|  |                                 ) | ||||||
|                             cursor += 1 |                             cursor += 1 | ||||||
|             else: |             else: | ||||||
|                 symbol = '- ' |                 symbol = '- ' | ||||||
|                 while self.font.getsize(symbol)[0] < im_width * 0.9: |                 while self.font.getsize(symbol)[0] < im_width * 0.9: | ||||||
|                     symbol += ' -' |                     symbol += ' -' | ||||||
|                 write(im_black, event_lines[0], |                 write( | ||||||
|                       (im_width, self.font.getsize(symbol)[1]), symbol, |                     im_black, | ||||||
|                       font=self.font) |                     event_lines[0], | ||||||
|  |                     (im_width, self.font.getsize(symbol)[1]), | ||||||
|  |                     symbol, | ||||||
|  |                     font=self.font, | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|         # return the images ready for the display |         # return the images ready for the display | ||||||
|         return im_black, im_colour |         return im_black, im_colour | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user