From d8365db8f52add39348079da99e1c2845da05ee3 Mon Sep 17 00:00:00 2001 From: Innokentii Konstantinov Date: Thu, 8 Sep 2022 16:11:03 +0500 Subject: [PATCH] is_icals_equal fixes (#510) * is_icals_equal fixes * treat None SEQUENCE as equal --- .../tasks/notify_ical_schedule_shift.py | 2 +- engine/apps/schedules/ical_utils.py | 36 ++++++++++--------- .../schedules/tasks/refresh_ical_files.py | 6 ++-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/engine/apps/alerts/tasks/notify_ical_schedule_shift.py b/engine/apps/alerts/tasks/notify_ical_schedule_shift.py index be0cece0..1a261880 100644 --- a/engine/apps/alerts/tasks/notify_ical_schedule_shift.py +++ b/engine/apps/alerts/tasks/notify_ical_schedule_shift.py @@ -255,7 +255,7 @@ def notify_ical_schedule_shift(schedule_pk): for prev_ical_file, current_ical_file in prev_and_current_ical_files: if prev_ical_file is not None and ( - current_ical_file is None or not is_icals_equal(current_ical_file, prev_ical_file, schedule) + current_ical_file is None or not is_icals_equal(current_ical_file, prev_ical_file) ): # If icals are not equal then compare current_events from them is_prev_ical_diff = True diff --git a/engine/apps/schedules/ical_utils.py b/engine/apps/schedules/ical_utils.py index f53a1ab7..12fb5bd1 100644 --- a/engine/apps/schedules/ical_utils.py +++ b/engine/apps/schedules/ical_utils.py @@ -423,28 +423,32 @@ def is_icals_equal_line_by_line(first, second): return True -def is_icals_equal(first, second, schedule): - from apps.schedules.models import OnCallScheduleICal # noqa - - if isinstance(schedule, OnCallScheduleICal): - first_cal = Calendar.from_ical(first) +def is_icals_equal(first, second): + first_cal = Calendar.from_ical(first) + if first_cal.get("PRODID", None) in ("-//My calendar product//amixr//", "-//web schedule//oncall//"): + # Compare schedules generated by oncall line by line, since they not support SEQUENCE field yet. + # But we are sure that same calendars will have same lines, since we are generating it. + return is_icals_equal_line_by_line(first, second) + else: + # Compare external calendars by events, since sometimes they contain different lines even for equal calendars. second_cal = Calendar.from_ical(second) first_subcomponents = first_cal.subcomponents second_subcomponents = second_cal.subcomponents if len(first_subcomponents) != len(second_subcomponents): return False - for idx, first_cmp in enumerate(first_cal.subcomponents): - second_cmp = second_subcomponents[idx] - if first_cmp.name == second_cmp.name == "VEVENT": - first_uid, first_seq = first_cmp.get("UID", None), first_cmp.get("SEQUENCE", None) - second_uid, second_seq = second_cmp.get("UID", None), second_cmp.get("SEQUENCE", None) - if first_uid != second_uid: - return False - elif first_seq != second_seq: - return False + first_cal_events = {} + second_cal_events = {} + for cmp in first_cal.subcomponents: + first_cal_events[cmp.get("UID", None)] = cmp.get("SEQUENCE", None) + for cmp in second_cal.subcomponents: + second_cal_events[cmp.get("UID", None)] = cmp.get("SEQUENCE", None) + for first_uid, first_seq in first_cal_events.items(): + if first_uid not in second_cal_events: + return False + second_seq = second_cal_events.get(first_uid, None) + if first_seq != second_seq: + return False return True - else: - return is_icals_equal_line_by_line(first, second) def ical_date_to_datetime(date, tz, start): diff --git a/engine/apps/schedules/tasks/refresh_ical_files.py b/engine/apps/schedules/tasks/refresh_ical_files.py index cad0baee..918564fb 100644 --- a/engine/apps/schedules/tasks/refresh_ical_files.py +++ b/engine/apps/schedules/tasks/refresh_ical_files.py @@ -47,7 +47,8 @@ def refresh_ical_file(schedule_pk): task_logger.info(f"run_task_primary {schedule_pk} {run_task_primary} prev_ical_file_primary is None") else: run_task_primary = not is_icals_equal( - schedule.cached_ical_file_primary, schedule.prev_ical_file_primary, schedule + schedule.cached_ical_file_primary, + schedule.prev_ical_file_primary, ) task_logger.info(f"run_task_primary {schedule_pk} {run_task_primary} icals not equal") run_task_overrides = False @@ -57,7 +58,8 @@ def refresh_ical_file(schedule_pk): task_logger.info(f"run_task_overrides {schedule_pk} {run_task_primary} prev_ical_file_overrides is None") else: run_task_overrides = not is_icals_equal( - schedule.cached_ical_file_overrides, schedule.prev_ical_file_overrides, schedule + schedule.cached_ical_file_overrides, + schedule.prev_ical_file_overrides, ) task_logger.info(f"run_task_overrides {schedule_pk} {run_task_primary} icals not equal") run_task = run_task_primary or run_task_overrides