Skip to content

Commit 730266c

Browse files
committed
Hugo's review
1 parent 412cc99 commit 730266c

File tree

3 files changed

+54
-38
lines changed

3 files changed

+54
-38
lines changed

pytest.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ addopts =
55
--strict-config
66
--strict-markers
77
--import-mode=importlib
8-
--cov check_peps --cov pep_sphinx_extensions
8+
--cov check_peps --cov pep_sphinx_extensions --cov release_management
99
--cov-report html --cov-report xml
1010
empty_parameter_set_mark = fail_at_collect
1111
filterwarnings =
1212
error
1313
minversion = 6.0
14-
testpaths = pep_sphinx_extensions
14+
testpaths = pep_sphinx_extensions release_management
1515
xfail_strict = True
1616
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True

release_management/serialize.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@
88

99
TYPE_CHECKING = False
1010
if TYPE_CHECKING:
11-
from release_management import VersionMetadata
11+
from release_management import ReleaseInfo, VersionMetadata
1212

1313
# Seven years captures the full lifecycle from prereleases to end-of-life
1414
TODAY = dt.date.today()
1515
SEVEN_YEARS_AGO = TODAY.replace(year=TODAY.year - 7)
1616

17+
# https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.11
18+
CALENDAR_ESCAPE_TEXT = str.maketrans({
19+
'\\': r'\\',
20+
';': r'\;',
21+
',': r'\,',
22+
'\n': r'\n',
23+
})
24+
1725

1826
def create_release_json() -> str:
1927
python_releases = dataclasses.asdict(load_python_releases())
@@ -57,26 +65,37 @@ def version_info(metadata: VersionMetadata, /) -> dict[str, str | int]:
5765

5866
def create_release_schedule_calendar() -> str:
5967
python_releases = load_python_releases()
60-
all_releases = [
61-
(version, release)
62-
for version, releases in python_releases.releases.items()
63-
for release in releases
64-
# Keep size reasonable by omitting releases older than 7 years
65-
if release.date >= SEVEN_YEARS_AGO
66-
]
67-
all_releases.sort(key=lambda r: r[1].date)
68+
releases = []
69+
for version, all_releases in python_releases.releases.items():
70+
pep_number = python_releases.metadata[version].pep
71+
for release in all_releases:
72+
# Keep size reasonable by omitting releases older than 7 years
73+
if release.date < SEVEN_YEARS_AGO:
74+
continue
75+
releases.append((pep_number, release))
76+
releases.sort(key=lambda r: r[1].date)
77+
lines = release_schedule_calendar_lines(releases)
78+
return '\r\n'.join(lines)
6879

80+
81+
def release_schedule_calendar_lines(
82+
releases: list[tuple[int, ReleaseInfo]], /
83+
) -> list[str]:
6984
lines = [
7085
'BEGIN:VCALENDAR',
7186
'VERSION:2.0',
7287
'PRODID:-//Python Software Foundation//Python release schedule//EN',
7388
'X-WR-CALDESC:Python releases schedule from https://peps.python.org',
7489
'X-WR-CALNAME:Python releases schedule',
7590
]
76-
for version, release in all_releases:
91+
for pep_number, release in releases:
7792
normalised_stage = release.stage.casefold().replace(' ', '')
78-
note = (f'DESCRIPTION:Note: {release.note}',) if release.note else ()
79-
pep_number = python_releases.metadata[version].pep
93+
normalised_stage = normalised_stage.translate(CALENDAR_ESCAPE_TEXT)
94+
if release.note:
95+
normalised_note = release.note.translate(CALENDAR_ESCAPE_TEXT)
96+
note = (f'DESCRIPTION:Note: {normalised_note}',)
97+
else:
98+
note = ()
8099
lines += (
81100
'BEGIN:VEVENT',
82101
f'SUMMARY:Python {release.stage}',
@@ -90,4 +109,4 @@ def create_release_schedule_calendar() -> str:
90109
'END:VCALENDAR',
91110
'',
92111
)
93-
return '\n'.join(lines)
112+
return lines
Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
import pytest
1+
import datetime as dt
22

3-
from release_management import serialize
3+
from release_management import ReleaseInfo, serialize
44

5-
6-
@pytest.mark.parametrize(
7-
('test_input', 'expected'),
8-
[
9-
('3.14.0 alpha 1', 'python-3.14.0alpha1@releases.python.org'),
10-
('3.14.0 beta 2', 'python-3.14.0beta2@releases.python.org'),
11-
('3.14.0 candidate 3', 'python-3.14.0candidate3@releases.python.org'),
12-
('3.14.1', 'python-3.14.1@releases.python.org'),
13-
],
5+
FAKE_RELEASE = ReleaseInfo(
6+
stage='X.Y.Z final',
7+
state='actual',
8+
date=dt.date(2000, 1, 1),
9+
note='These characters need escaping: \\ , ; \n',
1410
)
15-
def test_ical_uid(test_input, expected):
16-
assert serialize.ical_uid(test_input) == expected
1711

1812

19-
def test_create_release_calendar_has_calendar_metadata():
13+
def test_create_release_calendar_has_calendar_metadata() -> None:
2014
# Act
21-
cal_lines = serialize.create_release_schedule_calendar().split('\n')
15+
cal_lines = serialize.create_release_schedule_calendar().split('\r\n')
2216

2317
# Assert
2418

@@ -36,15 +30,18 @@ def test_create_release_calendar_has_calendar_metadata():
3630
]
3731

3832

39-
def test_create_release_calendar_first_event():
33+
def test_create_release_calendar_first_event() -> None:
4034
# Act
41-
cal_lines = serialize.create_release_schedule_calendar().split('\n')
35+
releases = [(9999, FAKE_RELEASE)]
36+
cal_lines = serialize.release_schedule_calendar_lines(releases)
4237

4338
# Assert
4439
assert cal_lines[5] == 'BEGIN:VEVENT'
45-
assert cal_lines[6].startswith('SUMMARY:Python ')
46-
assert cal_lines[7].startswith('DTSTART;VALUE=DATE:')
47-
assert cal_lines[8].startswith('UID:python-')
48-
assert cal_lines[8].endswith('@release.python.org')
49-
assert cal_lines[9].startswith('URL:https://peps.python.org/pep-')
50-
assert cal_lines[10].startswith('END:VEVENT')
40+
assert cal_lines[6] == 'SUMMARY:Python X.Y.Z final'
41+
assert cal_lines[7] == 'DTSTART;VALUE=DATE:20000101'
42+
assert cal_lines[8] == 'UID:python-x.y.zfinal@releases.python.org'
43+
assert cal_lines[9] == (
44+
'DESCRIPTION:Note: These characters need escaping: \\\\ \\, \\; \\n'
45+
)
46+
assert cal_lines[10] == 'URL:https://peps.python.org/pep-9999/'
47+
assert cal_lines[11] == 'END:VEVENT'

0 commit comments

Comments
 (0)