1# Copyright 2023 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Docs widget that provides up-to-date info about the next Pigweed Live.""" 15 16 17import datetime 18import sys 19 20from docutils import nodes 21from docutils.parsers.rst import Directive 22from sphinx.application import Sphinx 23 24try: 25 import pytz # type: ignore 26 27 PYTZ_AVAILABLE = True 28except ImportError: 29 PYTZ_AVAILABLE = False 30 31 32class PigweedLiveDirective(Directive): 33 """Generates the up-to-date Pigweed Live info.""" 34 35 datetime_format = '%Y-%m-%d %H:%M:%S' 36 # TODO: b/303859828 - Update this data sometime between 2024-09-23 37 # and 2024-10-07. 38 meetings = [ 39 '2023-10-09 13:00:00', 40 '2023-10-23 13:00:00', 41 '2023-11-06 13:00:00', 42 # 2023-11-20 skipped since it's a holiday(ish) 43 '2023-12-04 13:00:00', 44 # 2023-12-18 skipped due to its holiday proximity 45 # 2024-01-01 and 2024-01-15 are skipped because they're holidays. 46 '2024-01-29 13:00:00', 47 '2024-02-12 13:00:00', 48 '2024-02-26 13:00:00', 49 '2024-03-11 13:00:00', 50 '2024-03-25 13:00:00', 51 '2024-04-08 13:00:00', 52 '2024-04-22 13:00:00', 53 '2024-05-06 13:00:00', 54 '2024-05-20 13:00:00', 55 '2024-06-03 13:00:00', 56 '2024-06-17 13:00:00', 57 '2024-07-01 13:00:00', 58 '2024-07-15 13:00:00', 59 '2024-07-29 13:00:00', 60 '2024-08-12 13:00:00', 61 '2024-08-26 13:00:00', 62 '2024-09-09 13:00:00', 63 '2024-09-23 13:00:00', 64 '2024-10-07 13:00:00', 65 ] 66 timezone = pytz.timezone('US/Pacific') 67 68 def run(self) -> list[nodes.Node]: 69 return [self._make_paragraph()] 70 71 def _make_paragraph(self) -> nodes.Node: 72 next_meeting = self._find_next_meeting() 73 paragraph = nodes.paragraph() 74 paragraph += nodes.Text('Our next Pigweed Live is ') 75 meeting_text = nodes.strong() 76 meeting_text += nodes.Text(next_meeting) 77 paragraph += meeting_text 78 paragraph += nodes.Text(". Please ") 79 refuri = ( 80 'https://discord.com/channels/691686718377558037/' 81 '951228399119126548' 82 ) 83 link = nodes.reference(refuri=refuri) 84 link += nodes.Text('join us') 85 paragraph += link 86 paragraph += nodes.Text( 87 ( 88 " to discuss what's new in Pigweed and anything else " 89 "Pigweed-related." 90 ) 91 ) 92 return paragraph 93 94 def _find_next_meeting(self) -> str: 95 current_datetime = self.timezone.localize(datetime.datetime.now()) 96 next_meeting = None 97 for meeting in self.meetings: 98 unlocalized_datetime = datetime.datetime.strptime( 99 meeting, self.datetime_format 100 ) 101 meeting_datetime = self.timezone.localize(unlocalized_datetime) 102 if current_datetime > meeting_datetime: 103 continue 104 next_meeting = meeting_datetime 105 break 106 if next_meeting is None: 107 sys.exit( 108 'ERROR: Pigweed Live meeting data needs to be updated. ' 109 'Update the `meetings` list in `PigweedLiveDirective`. ' 110 'See b/303859828.' 111 ) 112 else: 113 date = next_meeting.strftime('%a %b %d, %Y') 114 hour = next_meeting.strftime('%I%p').lstrip('0') 115 timezone = 'PDT' if next_meeting.dst() else 'PST' 116 return f'{date} {hour} ({timezone})' 117 118 119def setup(app: Sphinx) -> dict[str, bool]: 120 """Initialize the directive.""" 121 if PYTZ_AVAILABLE: 122 app.add_directive('pigweed-live', PigweedLiveDirective) 123 return { 124 'parallel_read_safe': True, 125 'parallel_write_safe': True, 126 } 127