From 630657cafd6600d6ac40452a7c917ea75ac18ff5 Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Wed, 9 Apr 2025 12:15:05 -0700 Subject: [PATCH] Add ability to have per-meeting chairs Wanting to schedule multiple meeting slots is often driven by a desire to include more timezones; there's no reason to assume that a single person will be available to chair all meetings. Change-Id: If7f565d481dd0ae4bd4ee084cfddb203d170b2e8 --- README.rst | 3 ++- meetings/example.jinja | 4 +++- meetings/example3.yaml | 3 ++- yaml2ical/ical.py | 2 +- yaml2ical/meeting.py | 11 ++++++++++- yaml2ical/tests/sample_data.py | 19 +++++++++++++++++++ yaml2ical/tests/test_meeting.py | 19 +++++++++++++++++++ 7 files changed, 56 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 315c284..bf8e152 100644 --- a/README.rst +++ b/README.rst @@ -128,7 +128,8 @@ Each meeting consists of: * ``skip_date``: Skip the meeting for specified date. Format as ``start_date`` * ``reason``: A comment for why the meeting was skipped -* ``chair``: name of the meeting's chair [MANDATORY] + * ``chair``: name of the schedule's chair (defaults to meeting's chair) +* ``chair``: name of the meeting's chair [MANDATORY, unless all schedules have a chair] * ``description``: a paragraph description about the meeting [MANDATORY] * ``agenda_url``: a link to the agenda page for the meeting * ``project_url``: a link to the project home page for the meeting diff --git a/meetings/example.jinja b/meetings/example.jinja index 6c4542d..4b002fc 100644 --- a/meetings/example.jinja +++ b/meetings/example.jinja @@ -7,11 +7,13 @@ {% for schedule in meeting.schedules %}
  • {{ schedule.recurrence }} on {{ schedule.day }} at {{ schedule.utc }} UTC -in #{{ schedule.irc }}
  • +in #{{ schedule.irc }}{% if schedule.chair != meeting.chair %}, chair: {{ schedule.chair }}{% endif %} {% endfor %} +{% if meeting.chair %} Chair (to contact for more information): {{ meeting.chair }}

    +{% endif %} {{ meeting.description|urlize }} diff --git a/meetings/example3.yaml b/meetings/example3.yaml index add4483..c78ba8b 100644 --- a/meetings/example3.yaml +++ b/meetings/example3.yaml @@ -8,12 +8,13 @@ schedule: day: Thursday irc: openstack-meeting frequency: quadweekly + chair: Jane Doe - time: '600' duration: 45 start_date: 20150801 day: Thursday irc: openstack-meeting frequency: quadweekly-alternate -chair: John Doe + chair: John Doe description: > quadweekly diff --git a/yaml2ical/ical.py b/yaml2ical/ical.py index cd8d1da..8386899 100644 --- a/yaml2ical/ical.py +++ b/yaml2ical/ical.py @@ -60,7 +60,7 @@ class Yaml2IcalCalendar(icalendar.Calendar): # add ical description project_descript = "Project: %s" % (meeting.project) - chair_descript = "Chair: %s" % (meeting.chair) + chair_descript = "Chair: %s" % (sch.chair) descript_descript = "Description: %s" % (meeting.description) ical_descript = "\n".join((project_descript, chair_descript, diff --git a/yaml2ical/meeting.py b/yaml2ical/meeting.py index bae80f9..5d6e145 100644 --- a/yaml2ical/meeting.py +++ b/yaml2ical/meeting.py @@ -54,6 +54,7 @@ class Schedule(object): self.project = meeting.project self.filefrom = meeting.filefrom + self.chair = sched_yaml.get('chair', meeting.chair) # mandatory: time, day, irc, freq, recurrence try: self.utc = sched_yaml['time'] @@ -189,7 +190,6 @@ class Meeting(object): yaml_obj = yaml.safe_load(data) try: - self.chair = yaml_obj['chair'] self.description = yaml_obj['description'] self.project = yaml_obj['project'] except KeyError as e: @@ -197,6 +197,15 @@ class Meeting(object): "attribute '{0}'".format(e.args[0])) raise + try: + self.chair = yaml_obj['chair'] + except KeyError as e: + if any('chair' not in s for s in yaml_obj['schedule']): + print("Invalid YAML meeting definition - missing " + "attribute '{0}'".format(e.args[0])) + raise + self.chair = None + # Find any extra values the user has provided that they might # want to have access to in their templates. self.extras = {} diff --git a/yaml2ical/tests/sample_data.py b/yaml2ical/tests/sample_data.py index 1885031..e18a671 100644 --- a/yaml2ical/tests/sample_data.py +++ b/yaml2ical/tests/sample_data.py @@ -86,6 +86,25 @@ agenda: | * Top bugs this week """ +ALTERNATING_CHAIRS_MEETING = """ +project: OpenStack Subteam Meeting +schedule: + - time: '1200' + day: Wednesday + irc: openstack-meeting + frequency: biweekly-even + chair: Jane Developer + - time: '2200' + day: Wednesday + irc: openstack-meeting + frequency: biweekly-odd + chair: John Developer +description: > + Weekly meeting for Subteam project. +agenda: | + * Top bugs this week +""" + BIWEEKLY_EVEN_MEETING = """ project: OpenStack Subteam 12 Meeting schedule: diff --git a/yaml2ical/tests/test_meeting.py b/yaml2ical/tests/test_meeting.py index 9a2445c..eeb9799 100644 --- a/yaml2ical/tests/test_meeting.py +++ b/yaml2ical/tests/test_meeting.py @@ -31,6 +31,16 @@ class MeetingTestCase(unittest.TestCase): self.assertEqual('Joe Developer', m.chair) self.assertEqual('Weekly meeting for Subteam project.\n', m.description) + self.assertEqual('Joe Developer', m.schedules[0].chair) + + def test_chair_overrides(self): + m = meeting.load_meetings(sample_data.ALTERNATING_CHAIRS_MEETING)[0] + self.assertEqual('OpenStack Subteam Meeting', m.project) + self.assertIsNone(m.chair) + self.assertEqual('Weekly meeting for Subteam project.\n', + m.description) + self.assertEqual('Jane Developer', m.schedules[0].chair) + self.assertEqual('John Developer', m.schedules[1].chair) def should_be_conflicting(self, yaml1, yaml2): """Exception is raised when meetings should conflict.""" @@ -208,6 +218,15 @@ class MeetingTestCase(unittest.TestCase): cal.add_meeting(m) self.assertEqual(cal, ical.Yaml2IcalCalendar()) + def test_alternating_chairs_meeting(self): + meeting_yaml = sample_data.ALTERNATING_CHAIRS_MEETING + m = meeting.load_meetings(meeting_yaml)[0] + cal = ical.Yaml2IcalCalendar() + cal.add_meeting(m) + self.assertEqual(2, len(cal.events), cal) + self.assertIn('Chair: Jane Developer', cal.events[0]['description']) + self.assertIn('Chair: John Developer', cal.events[1]['description']) + def test_skip_meeting_missing_skip_date(self): self.assertRaises(KeyError, meeting.load_meetings,