From 40f12c0d63de705f7464be5dd7147884e0f1f7d4 Mon Sep 17 00:00:00 2001 From: Thierry Carrez Date: Wed, 25 Feb 2015 12:16:50 +0100 Subject: [PATCH] Fix conflict detection Fix conflict detection by providing finer rules. Meetings on alternating weeks no longer conflict. Meetings on overlapping times now conflict. Add proper tests to check all combinations. Change-Id: I069cdd40fecb5fd7a2ab828a495bdf627ca1a811 --- yaml2ical/meeting.py | 18 ++++++++------- yaml2ical/tests/sample_data.py | 37 +++++++++++++++++++++++++----- yaml2ical/tests/test_meeting.py | 40 +++++++++++++++++++++++++-------- 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/yaml2ical/meeting.py b/yaml2ical/meeting.py index e75fbb7..732df04 100644 --- a/yaml2ical/meeting.py +++ b/yaml2ical/meeting.py @@ -28,15 +28,17 @@ class Schedule(object): self.time = datetime.datetime.strptime(sched_yaml['time'], '%H%M') self.day = sched_yaml['day'] self.irc = sched_yaml['irc'] + self.freq = sched_yaml['frequency'] self.recurrence = supported_recurrences[sched_yaml['frequency']] - def __eq__(self, other): - #TODO(ttx): This is a bit overzealous (it will report as conflict - # biweekly-odd/biweekly-even on same date/hour/irc) so this should be - # revamped especially if we want to add more complex recurrence rules - return ((self.day == other.day) and - (self.time == other.time) and - (self.irc == other.irc)) + def conflicts(self, other): + """Checks for conflicting schedules.""" + alternating = set(['biweekly-odd', 'biweekly-even']) + return ( + ((self.day == other.day) and + (abs(self.time - other.time) < datetime.timedelta(hours=1)) and + (self.irc == other.irc)) and + (set([self.freq, other.freq]) != alternating)) class Meeting(object): @@ -106,7 +108,7 @@ def check_for_meeting_conflicts(meetings): other_schedules = meetings[j].schedules for schedule in schedules: for other_schedule in other_schedules: - if schedule == other_schedule: + if schedule.conflicts(other_schedule): msg_dict = {'one': schedule.filefrom, 'two': other_schedule.filefrom} raise MeetingConflictError( diff --git a/yaml2ical/tests/sample_data.py b/yaml2ical/tests/sample_data.py index ea302f1..891a456 100644 --- a/yaml2ical/tests/sample_data.py +++ b/yaml2ical/tests/sample_data.py @@ -14,7 +14,7 @@ """Sample meeting data to use for testing.""" -FIRST_MEETING_YAML = """ +WEEKLY_MEETING = """ project: OpenStack Subteam Meeting schedule: - time: '1200' @@ -28,10 +28,10 @@ agenda: | * Top bugs this week """ -SECOND_MEETING_YAML = """ +CONFLICTING_WEEKLY_MEETING = """ project: OpenStack Subteam Meeting 2 schedule: - - time: '1200' + - time: '1230' day: Wednesday irc: openstack-meeting frequency: weekly @@ -42,7 +42,7 @@ agenda: | * New features """ -THIRD_MEETING_YAML = """ +WEEKLY_OTHER_CHANNEL_MEETING = """ project: OpenStack Subteam Meeting 3 schedule: - time: '1200' @@ -56,13 +56,40 @@ agenda: | * New features """ -BIWEEKLY_MEETING_YAML = """ +ALTERNATING_MEETING = """ project: OpenStack Subteam Meeting schedule: - time: '1200' day: Wednesday irc: openstack-meeting frequency: biweekly-even + - time: '2200' + day: Wednesday + irc: openstack-meeting + frequency: biweekly-odd +chair: Jane Developer +description: > + Weekly meeting for Subteam project. +agenda: | + * Top bugs this week +""" + +BIWEEKLY_EVEN_MEETING = """ +project: OpenStack Subteam 12 Meeting +schedule: + - time: '2200' + day: Wednesday + irc: openstack-meeting + frequency: biweekly-even +chair: Jane Developer +description: > + Weekly meeting for Subteam project. +agenda: | + * Top bugs this week +""" + +BIWEEKLY_ODD_MEETING = """ +project: OpenStack Subteam 12 Meeting schedule: - time: '2200' day: Wednesday diff --git a/yaml2ical/tests/test_meeting.py b/yaml2ical/tests/test_meeting.py index 736e642..998bcbc 100644 --- a/yaml2ical/tests/test_meeting.py +++ b/yaml2ical/tests/test_meeting.py @@ -19,24 +19,46 @@ from yaml2ical.tests import sample_data class MeetingTestCase(unittest.TestCase): def test_load_yaml_file(self): - m = meeting.load_meetings(sample_data.FIRST_MEETING_YAML)[0] + m = meeting.load_meetings(sample_data.WEEKLY_MEETING)[0] self.assertEqual('OpenStack Subteam Meeting', m.project) self.assertEqual('Joe Developer', m.chair) self.assertEqual('Weekly meeting for Subteam project.\n', m.description) - def test_exception_raised_when_conflict_detected(self): - """Exception is raised when a meeting conflict is detected.""" - meeting_one = meeting.load_meetings(sample_data.FIRST_MEETING_YAML) - meeting_two = meeting.load_meetings(sample_data.SECOND_MEETING_YAML) + def should_be_conflicting(self, yaml1, yaml2): + """Exception is raised when meetings should conflict.""" + meeting_one = meeting.load_meetings(yaml1) + meeting_two = meeting.load_meetings(yaml2) meeting_list = [meeting_one.pop(), meeting_two.pop()] self.assertRaises(meeting.MeetingConflictError, meeting.check_for_meeting_conflicts, meeting_list) - def test_no_exception_raised_with_diff_irc_rooms(self): - """No exception raised when using different IRC rooms.""" - meeting_one = meeting.load_meetings(sample_data.FIRST_MEETING_YAML) - meeting_two = meeting.load_meetings(sample_data.THIRD_MEETING_YAML) + def should_not_conflict(self, yaml1, yaml2): + """No exception raised when meetings shouldn't conflict.""" + meeting_one = meeting.load_meetings(yaml1) + meeting_two = meeting.load_meetings(yaml2) meeting_list = [meeting_one.pop(), meeting_two.pop()] meeting.check_for_meeting_conflicts(meeting_list) + + def test_weekly_conflict(self): + self.should_be_conflicting( + sample_data.WEEKLY_MEETING, + sample_data.CONFLICTING_WEEKLY_MEETING) + self.should_not_conflict( + sample_data.WEEKLY_MEETING, + sample_data.WEEKLY_OTHER_CHANNEL_MEETING) + + def test_biweekly_conflict(self): + self.should_be_conflicting( + sample_data.WEEKLY_MEETING, + sample_data.ALTERNATING_MEETING) + self.should_not_conflict( + sample_data.ALTERNATING_MEETING, + sample_data.BIWEEKLY_EVEN_MEETING) + self.should_be_conflicting( + sample_data.ALTERNATING_MEETING, + sample_data.BIWEEKLY_ODD_MEETING) + self.should_not_conflict( + sample_data.BIWEEKLY_ODD_MEETING, + sample_data.BIWEEKLY_EVEN_MEETING)