hook/email: remove/solve some type:ignore

This commit is contained in:
Peter Bieringer
2026-04-10 07:48:10 +02:00
parent 717985763c
commit 785b19812e

View File

@@ -296,7 +296,7 @@ class VComponent:
return [None] return [None]
if not isinstance(sub_vobjects, (list, tuple)): if not isinstance(sub_vobjects, (list, tuple)):
sub_vobjects = [sub_vobjects] sub_vobjects = [sub_vobjects]
return ([_class(vobject_item=so) for so in sub_vobjects if # type: ignore return ([_class(vobject_item=so) for so in sub_vobjects if # type: ignore # TODO: Missing positional argument "component_type" in call to "VComponent"
isinstance(so, vobject.base.Component)] isinstance(so, vobject.base.Component)]
or [None]) or [None])
@@ -444,12 +444,12 @@ class Timezone(VComponent):
@property @property
def standard(self) -> Optional[StandardTimezone]: def standard(self) -> Optional[StandardTimezone]:
"""Return the STANDARD subcomponent if it exists.""" """Return the STANDARD subcomponent if it exists."""
return self._get_sub_vobjects("standard", StandardTimezone)[0] # type: ignore return self._get_sub_vobjects("standard", StandardTimezone)[0] # type: ignore # TODO: got "VComponent | None", expected "StandardTimezone | None"
@property @property
def daylight(self) -> Optional[DaylightTimezone]: def daylight(self) -> Optional[DaylightTimezone]:
"""Return the DAYLIGHT subcomponent if it exists.""" """Return the DAYLIGHT subcomponent if it exists."""
return self._get_sub_vobjects("daylight", DaylightTimezone)[0] # type: ignore return self._get_sub_vobjects("daylight", DaylightTimezone)[0] # type: ignore # TODO: got "VComponent | None", expected "DaylightTimezone | None"
class Event(VComponent): class Event(VComponent):
@@ -513,7 +513,7 @@ class Event(VComponent):
@property @property
def alarms(self) -> List[Alarm]: def alarms(self) -> List[Alarm]:
"""Return a list of VALARM items in the event.""" """Return a list of VALARM items in the event."""
return self._get_sub_vobjects("valarm", Alarm) # type: ignore # Can be multiple return self._get_sub_vobjects("valarm", Alarm) # type: ignore # Can be multiple # TODO: got "list[VComponent | None]", expected "list[Alarm]"
@property @property
def attendees(self) -> List[Attendee]: def attendees(self) -> List[Attendee]:
@@ -541,14 +541,14 @@ class Calendar(VComponent):
@property @property
def event(self) -> Optional[Event]: def event(self) -> Optional[Event]:
"""Return the VEVENT item in the calendar.""" """Return the VEVENT item in the calendar."""
return self._get_sub_vobjects("vevent", Event)[0] # type: ignore return self._get_sub_vobjects("vevent", Event)[0] # type: ignore # TODO: got "VComponent | None", expected "Event | None"
# TODO: Add VTODO and VJOURNAL support if needed # TODO: Add VTODO and VJOURNAL support if needed
@property @property
def timezone(self) -> Optional[Timezone]: def timezone(self) -> Optional[Timezone]:
"""Return the VTIMEZONE item in the calendar.""" """Return the VTIMEZONE item in the calendar."""
return self._get_sub_vobjects("vtimezone", Timezone)[0] # type: ignore return self._get_sub_vobjects("vtimezone", Timezone)[0] # type: ignore # TODO: got "VComponent | None", expected "Timezone | None"
class EmailEvent: class EmailEvent:
@@ -637,19 +637,20 @@ class MessageTemplate:
:param attendee: The specific attendee to include in the message, if not a mass email. :param attendee: The specific attendee to include in the message, if not a mass email.
:return: The formatted message body. :return: The formatted message body.
""" """
attendee_name: Union[str, None]
if mass_email: if mass_email:
# If this is a mass email, we do not use individual attendee names # If this is a mass email, we do not use individual attendee names
attendee_name = "everyone" attendee_name = "everyone"
else: else:
assert attendee is not None, "Attendee must be provided for non-mass emails" assert attendee is not None, "Attendee must be provided for non-mass emails"
attendee_name = attendee.name if attendee else "Unknown Name" # type: ignore attendee_name = attendee.name if attendee else "Unknown Name"
context = { context = {
"attendee_name": attendee_name, "attendee_name": attendee_name,
"from_email": from_email, "from_email": from_email,
"organizer_name": event.event.organizer or "Unknown Organizer", "organizer_name": event.event.organizer or "Unknown Organizer",
"event_title": event.event.summary or "No Title", "event_title": event.event.summary or "No Title",
"event_start_time": event.event.datetime_start.time_string(), # type: ignore "event_start_time": event.event.datetime_start.time_string() if event.event.datetime_start else "No Start Time",
"event_end_time": event.event.datetime_end.time_string() if event.event.datetime_end else "No End Time", "event_end_time": event.event.datetime_end.time_string() if event.event.datetime_end else "No End Time",
"event_location": event.event.location or "No Location Specified", "event_location": event.event.location or "No Location Specified",
} }
@@ -666,19 +667,20 @@ class MessageTemplate:
:param attendee: The specific attendee to include in the message, if not a mass email. :param attendee: The specific attendee to include in the message, if not a mass email.
:return: The formatted message subject. :return: The formatted message subject.
""" """
attendee_name: Union[str, None]
if mass_email: if mass_email:
# If this is a mass email, we do not use individual attendee names # If this is a mass email, we do not use individual attendee names
attendee_name = "everyone" attendee_name = "everyone"
else: else:
assert attendee is not None, "Attendee must be provided for non-mass emails" assert attendee is not None, "Attendee must be provided for non-mass emails"
attendee_name = attendee.name if attendee else "Unknown Name" # type: ignore attendee_name = attendee.name if attendee else "Unknown Name"
context = { context = {
"attendee_name": attendee_name, "attendee_name": attendee_name,
"from_email": from_email, "from_email": from_email,
"organizer_name": event.event.organizer or "Unknown Organizer", "organizer_name": event.event.organizer or "Unknown Organizer",
"event_title": event.event.summary or "No Title", "event_title": event.event.summary or "No Title",
"event_start_time": event.event.datetime_start.time_string(), # type: ignore "event_start_time": event.event.datetime_start.time_string() if event.event.datetime_start else "No Start Time",
"event_end_time": event.event.datetime_end.time_string() if event.event.datetime_end else "No End Time", "event_end_time": event.event.datetime_end.time_string() if event.event.datetime_end else "No End Time",
"event_location": event.event.location or "No Location Specified", "event_location": event.event.location or "No Location Specified",
} }
@@ -890,10 +892,10 @@ def _read_event(vobject_data: str) -> EmailEvent:
""" """
v_cal: vobject.base.Component = vobject.readOne(vobject_data) v_cal: vobject.base.Component = vobject.readOne(vobject_data)
cal: Calendar = Calendar(vobject_item=v_cal) cal: Calendar = Calendar(vobject_item=v_cal)
event: Event = cal.event # type: ignore event: Union[Event, None] = cal.event
return EmailEvent( return EmailEvent(
event=event, event=event, # type: ignore # TODO: Argument "event" to "EmailEvent" has incompatible type "Event | None"; expected "Event"
ics_content=vobject_data, ics_content=vobject_data,
ics_file_name="event.ics" ics_file_name="event.ics"
) )
@@ -955,6 +957,10 @@ class Hook(BaseHook):
:type notification_item: HookNotificationItem :type notification_item: HookNotificationItem
:return: None :return: None
""" """
email_success: bool
email_event: EmailEvent
new_event: Union[Event, None]
if self.email_config.dryrun: if self.email_config.dryrun:
logger.warning("Hook 'email': DRY-RUN received notification_item: %r", vars(notification_item)) logger.warning("Hook 'email': DRY-RUN received notification_item: %r", vars(notification_item))
else: else:
@@ -972,7 +978,7 @@ class Hook(BaseHook):
elif notification_type == HookNotificationItemTypes.UPSERT: elif notification_type == HookNotificationItemTypes.UPSERT:
# Handle upsert notifications # Handle upsert notifications
new_item_str: str = notification_item.new_content # type: ignore # A serialized vobject.base.Component new_item_str: str = notification_item.new_content # A serialized vobject.base.Component
previous_item_str: Optional[str] = notification_item.old_content previous_item_str: Optional[str] = notification_item.old_content
if not ics_contents_contains_event(contents=new_item_str): if not ics_contents_contains_event(contents=new_item_str):
@@ -980,15 +986,15 @@ class Hook(BaseHook):
logger.debug("No event found in the ICS file, skipping notification.") logger.debug("No event found in the ICS file, skipping notification.")
return return
email_event: EmailEvent = _read_event(vobject_data=new_item_str) # type: ignore email_event = _read_event(vobject_data=new_item_str)
if not email_event: if not email_event:
logger.error("Failed to read event from new content: %s", new_item_str) logger.error("Failed to read event from new content: %s", new_item_str)
return return
email_event_event = email_event.event # type: ignore email_event_event = email_event.event
if not email_event_event: if not email_event_event:
logger.error("Event could not be parsed from the new content: %s", new_item_str) logger.error("Event could not be parsed from the new content: %s", new_item_str)
return return
email_event_end_time = email_event_event.datetime_end # type: ignore email_event_end_time = email_event_event.datetime_end
# Skip notification if the event end time is more than 1 minute in the past. # Skip notification if the event end time is more than 1 minute in the past.
if email_event_end_time and email_event_end_time.time: if email_event_end_time and email_event_end_time.time:
event_end = email_event_end_time.time event_end = email_event_end_time.time
@@ -1038,7 +1044,7 @@ class Hook(BaseHook):
# Notify added attendees as "event created" # Notify added attendees as "event created"
if added_attendees: if added_attendees:
email_success: bool = self.email_config.send_added_email( # type: ignore email_success = self.email_config.send_added_email(
attendees=added_attendees, attendees=added_attendees,
event=email_event event=email_event
) )
@@ -1048,7 +1054,7 @@ class Hook(BaseHook):
# Notify removed attendees as "event deleted" # Notify removed attendees as "event deleted"
if removed_attendees: if removed_attendees:
email_success: bool = self.email_config.send_deleted_email( # type: ignore email_success = self.email_config.send_deleted_email(
attendees=removed_attendees, attendees=removed_attendees,
event=email_event event=email_event
) )
@@ -1059,7 +1065,7 @@ class Hook(BaseHook):
# Notify unaltered attendees as "event updated" if details other than attendees have changed # Notify unaltered attendees as "event updated" if details other than attendees have changed
if unaltered_attendees and event_details_other_than_attendees_changed(original_event=previous_event, if unaltered_attendees and event_details_other_than_attendees_changed(original_event=previous_event,
new_event=new_event): new_event=new_event):
email_success: bool = self.email_config.send_updated_email( # type: ignore email_success = self.email_config.send_updated_email(
attendees=unaltered_attendees, attendees=unaltered_attendees,
event=email_event event=email_event
) )
@@ -1075,16 +1081,16 @@ class Hook(BaseHook):
elif notification_type == HookNotificationItemTypes.DELETE: elif notification_type == HookNotificationItemTypes.DELETE:
# Handle delete notifications # Handle delete notifications
deleted_item_str: str = notification_item.old_content # type: ignore # A serialized vobject.base.Component deleted_item_str: str = notification_item.old_content # A serialized vobject.base.Component
if not ics_contents_contains_event(contents=deleted_item_str): if not ics_contents_contains_event(contents=deleted_item_str):
# If the ICS file does not contain an event, we do not send any notifications. # If the ICS file does not contain an event, we do not send any notifications.
logger.debug("No event found in the ICS file, skipping notification.") logger.debug("No event found in the ICS file, skipping notification.")
return return
email_event: EmailEvent = _read_event(vobject_data=deleted_item_str) # type: ignore email_event = _read_event(vobject_data=deleted_item_str)
email_success: bool = self.email_config.send_deleted_email( # type: ignore email_success = self.email_config.send_deleted_email(
attendees=email_event.event.attendees, attendees=email_event.event.attendees,
event=email_event event=email_event
) )