From a1c859ab025ae90647ec164b08a71e11960d1a4a Mon Sep 17 00:00:00 2001 From: Jakko Yang Date: Thu, 12 Nov 2026 23:11:17 -0500 Subject: [PATCH] Add ical_value property to vMonth Part of #876. AI: Claude Opus 5.5 Prompt (summary): help pick a return type for vMonth.ical_value and draft tests. Output: Draft of the tests and docstring. I reviewed and edited them, wrote the news entry, and ran the full test suite locally. --- news/876.feature.2 | 1 + src/icalendar/prop/recur/month.py | 8 ++++++ src/icalendar/tests/prop/test_vMonth.py | 33 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 news/876.feature.2 create mode 100644 src/icalendar/tests/prop/test_vMonth.py diff --git a/news/876.feature.2 b/news/876.feature.2 new file mode 100644 index 000000000..1926fe8b3 --- /dev/null +++ b/news/876.feature.2 @@ -0,0 +1 @@ +Added :attr:`vMonth.ical_value `, which returns the month number as an :class:`int`. For :rfc:`7529` leap months such as ``5L``, the leap flag stays available as :attr:`~icalendar.prop.recur.month.vMonth.leap`. I used Claude Opus 5.5 to help choose the return type and draft some of the tests. @jakkoyang \ No newline at end of file diff --git a/src/icalendar/prop/recur/month.py b/src/icalendar/prop/recur/month.py index fd2bda57a..4bdede60b 100644 --- a/src/icalendar/prop/recur/month.py +++ b/src/icalendar/prop/recur/month.py @@ -76,6 +76,14 @@ def to_ical(self) -> bytes: """The ical representation.""" return str(self).encode("utf-8") + @property + def ical_value(self) -> int: + """Returns the month number as an int, for example, ``5``. + + The :rfc:`7529` leap flag is not included. Use :attr:`leap` for it. + """ + return int(self) + @classmethod def from_ical(cls, ical: str): return cls(ical) diff --git a/src/icalendar/tests/prop/test_vMonth.py b/src/icalendar/tests/prop/test_vMonth.py new file mode 100644 index 000000000..2e7d22ec4 --- /dev/null +++ b/src/icalendar/tests/prop/test_vMonth.py @@ -0,0 +1,33 @@ +"""Tests for vMonth.ical_value (issue #876).""" + +import pytest + +from icalendar.prop import vMonth, vRecur + + +@pytest.mark.parametrize("month", [1, 5, 12]) +def test_ical_value_is_the_month_number(month): + """ical_value returns the month number for a regular month.""" + assert vMonth(month).ical_value == month + + +def test_ical_value_is_a_plain_int(): + """ical_value is a plain int, not a vMonth (isinstance would accept both).""" + assert type(vMonth(5).ical_value) is int + + +def test_ical_value_of_leap_month_is_the_month_number(): + """A RFC 7529 leap month like 5L returns its month number.""" + assert vMonth("5L").ical_value == 5 + + +def test_leap_flag_is_unchanged(): + """The leap flag stays available on vMonth itself.""" + assert vMonth("5L").leap is True + assert vMonth(5).leap is False + + +def test_ical_value_inside_a_recurrence_rule(): + """BYMONTH values parsed from an RRULE expose ical_value.""" + month = vRecur.from_ical("FREQ=YEARLY;BYMONTH=5")["BYMONTH"][0] + assert month.ical_value == 5