Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
python: "3.14"

python:
install:
Expand Down
22 changes: 14 additions & 8 deletions docs/community/monthly-meeting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@ Documentation Community Monthly Meetings

Monthly meetings are held on the first Tuesday of the month
on the `Discord server <https://discord.gg/sMWqvzXvde>`_ and last one hour.
Check the agenda or Discourse announcement to verify the start time.
Upcoming meeting dates and times:

+-----------------+--------------+--------------+
| Period | Even months | Odd months |
+=================+==============+==============+
| April-October | 19:00 UTC | 16:00 UTC |
+-----------------+--------------+--------------+
| November-March | 20:00 UTC | 17:00 UTC |
+-----------------+--------------+--------------+
.. meeting-dates::

`Download iCalendar file </docs-community-meetings.ics>`_

The agenda and later the meeting minutes are written in the `HackMD <https://hackmd.io/@encukou/pydocswg1>`_.
To edit notes, click the “pencil” or “split view” button on the `HackMD Document <https://hackmd.io/@encukou/pydocswg1>`_.
Expand All @@ -27,6 +23,16 @@ By participating in meetings, you are agreeing to abide by and uphold the
`PSF Code of Conduct <https://policies.python.org/python.org/code-of-conduct/>`_.
Please take a second to read through it!

Meetings follow the pattern:

+-----------------+--------------+--------------+
| Period | Even months | Odd months |
+=================+==============+==============+
| April-October | 19:00 UTC | 16:00 UTC |
+-----------------+--------------+--------------+
| November-March | 20:00 UTC | 17:00 UTC |
+-----------------+--------------+--------------+


Minutes template
----------------
Expand Down
10 changes: 10 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

# A list of strings that are module names of Sphinx extensions
import os
import sys

sys.path.append(os.path.abspath("tools/"))

extensions = [
"sphinx_copybutton",
"sphinx.ext.intersphinx",
"myst_parser",
"meeting_dates",
]

myst_enable_extensions = ["linkify"]
Expand Down Expand Up @@ -68,6 +74,10 @@
r"https://plausible.io/docs.python.org",
r"https://plausible.io/packaging.python.org",
r"https://us.pycon.org/2024/registration/category/4",
# Have redirects:
r"https://arewemeetingyet.com/.*",
Comment thread
StanFromIreland marked this conversation as resolved.
# Generated at build time:
r"/docs-community-meetings.ics",
]

# A list of document names to exclude from linkcheck
Expand Down
109 changes: 109 additions & 0 deletions docs/tools/meeting_dates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""Sphinx extension to generate a list of upcoming meeting dates."""

import datetime as dt
import os

from docutils import nodes
from sphinx.util.docutils import SphinxDirective


def utc_hour(date):
if 4 <= date.month <= 10:
# Daylight saving time in Europe and the US
return 19 if date.month % 2 == 0 else 16
else:
# Winter time in Europe and the US
return 20 if date.month % 2 == 0 else 17


def first_tuesday(year, month):
first = dt.date(year, month, 1)
days_ahead = (1 - first.weekday()) % 7
return first + dt.timedelta(days=days_ahead)


def upcoming_meetings(today, count):
meetings = []
year, month = today.year, today.month
while len(meetings) < count:
meeting_date = first_tuesday(year, month)
if meeting_date >= today:
meetings.append((meeting_date, utc_hour(meeting_date)))
month += 1
if month > 12:
month = 1
year += 1
return meetings


def past_meetings(today, count):
meetings = []
year, month = today.year, today.month
while len(meetings) < count:
meeting_date = first_tuesday(year, month)
if meeting_date < today:
meetings.append((meeting_date, utc_hour(meeting_date)))
month -= 1
if month < 1:
month = 12
year -= 1
meetings.reverse()
return meetings


class MeetingDatesDirective(SphinxDirective):
has_content = False

def run(self):
bullets = nodes.bullet_list()
for date, hour in upcoming_meetings(dt.date.today(), 6):
item = nodes.list_item()
text = f"{date.strftime('%B %d, %Y')} - {hour:02d}:00 UTC"
url = f"https://arewemeetingyet.com/UTC/{date.isoformat()}/{hour}:00/Docs Community Meeting"

paragraph = nodes.paragraph()
ref = nodes.reference("", text, refuri=url)
paragraph += ref
item += paragraph
bullets += item

return [bullets]


def generate_ics(app, exception):
if exception:
return

lines = [
"BEGIN:VCALENDAR",
"VERSION:2.0",
"PRODID:-//Python Docs Community//Meeting dates//EN",
"X-WR-CALDESC:Python docs community meeting dates from https://docs-community.readthedocs.io/",
"X-WR-CALNAME:Python docs community meeting dates",
Comment thread
StanFromIreland marked this conversation as resolved.
Outdated
]
Comment thread
StanFromIreland marked this conversation as resolved.
today = dt.date.today()
meetings = past_meetings(today, 12) + upcoming_meetings(today, 12)
for date, hour in meetings:
start = dt.datetime(date.year, date.month, date.day, hour, 0, 0)
end = start + dt.timedelta(hours=1)
lines += [
"BEGIN:VEVENT",
f"UID:{start.strftime('%Y%m%dT%H%M%SZ')}@python-docs-community",
f"DTSTAMP:{dt.datetime.now(dt.timezone.utc).strftime('%Y%m%dT%H%M%SZ')}",
f"DTSTART:{start.strftime('%Y%m%dT%H%M%SZ')}",
f"DTEND:{end.strftime('%Y%m%dT%H%M%SZ')}",
"SUMMARY:Docs Community Meeting",
f"URL:https://arewemeetingyet.com/UTC/{date.isoformat()}/{hour}:00/Docs Community Meeting",
Comment thread
StanFromIreland marked this conversation as resolved.
Outdated
"END:VEVENT",
]
lines += ["END:VCALENDAR"]
ics = "\r\n".join(lines) + "\r\n"

with open(os.path.join(app.outdir, "docs-community-meetings.ics"), "w") as f:
f.write(ics)


def setup(app):
app.add_directive("meeting-dates", MeetingDatesDirective)
app.connect("build-finished", generate_ics)
return {"version": "1.0", "parallel_read_safe": True}
Loading