From 84e7d0f0c7f9a44d81be2d705ed4d401a6505356 Mon Sep 17 00:00:00 2001 From: Prince Roshan Date: Sat, 29 Apr 2023 12:46:46 +0530 Subject: [PATCH] gh-103636: issue warning for deprecated calendar constants (#103833) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hugo van Kemenade Co-authored-by: Éric Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Doc/library/calendar.rst | 52 +++++++++++++++++++ Doc/whatsnew/3.12.rst | 9 ++++ Lib/calendar.py | 13 +++++ Lib/test/test_calendar.py | 9 ++++ ...-04-26-18-12-13.gh-issue-103636.-KvCgO.rst | 1 + 5 files changed, 84 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst index 66f59f0e2ce..07d04a1c7b5 100644 --- a/Doc/library/calendar.rst +++ b/Doc/library/calendar.rst @@ -28,6 +28,58 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is 2 BC, and so on. +.. class:: Day + + Enumeration defining the days of the week as integer constants, from 0 to 6. + + .. attribute:: MONDAY + + .. attribute:: TUESDAY + + .. attribute:: WEDNESDAY + + .. attribute:: THURSDAY + + .. attribute:: FRIDAY + + .. attribute:: SATURDAY + + .. attribute:: SUNDAY + + .. versionadded:: 3.12 + + +.. class:: Month + + Enumeration defining months of the year as integer constants, from 1 to 12. + + .. attribute:: JANUARY + + .. attribute:: FEBRUARY + + .. attribute:: MARCH + + .. attribute:: APRIL + + .. attribute:: MAY + + .. attribute:: JUNE + + .. attribute:: JULY + + .. attribute:: AUGUST + + .. attribute:: SEPTEMBER + + .. attribute:: OCTOBER + + .. attribute:: NOVEMBER + + .. attribute:: DECEMBER + + .. versionadded:: 3.12 + + .. class:: Calendar(firstweekday=0) Creates a :class:`Calendar` object. *firstweekday* is an integer specifying the diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index a75e88c2615..908cf3bb365 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -300,6 +300,12 @@ asyncio yielding tasks. (Contributed by Kumar Aditya in :gh:`78530`.) +calendar +-------- + +* Add enums :data:`~calendar.Month` and :data:`~calendar.Day`. + (Contributed by Prince Roshan in :gh:`103636`.) + csv --- @@ -692,6 +698,9 @@ Deprecated Python 3.14, when ``'data'`` filter will become the default. See :ref:`tarfile-extraction-filter` for details. +* ``calendar.January`` and ``calendar.February`` constants are deprecated and + replaced by :data:`calendar.Month.JANUARY` and :data:`calendar.Month.FEBRUARY`. + (Contributed by Prince Roshan in :gh:`103636`.) Pending Removal in Python 3.13 ------------------------------ diff --git a/Lib/calendar.py b/Lib/calendar.py index c219f0c218d..bbd4fea3b88 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -10,6 +10,7 @@ import datetime from enum import IntEnum, global_enum import locale as _locale from itertools import repeat +import warnings __all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday", "firstweekday", "isleap", "leapdays", "weekday", "monthrange", @@ -41,6 +42,18 @@ class IllegalWeekdayError(ValueError): return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday +def __getattr__(name): + if name in ('January', 'February'): + warnings.warn(f"The '{name}' attribute is deprecated, use '{name.upper()}' instead", + DeprecationWarning, stacklevel=2) + if name == 'January': + return 1 + else: + return 2 + + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") + + # Constants for months @global_enum class Month(IntEnum): diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index ccfbeede0be..03388e8c55d 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -8,6 +8,7 @@ import locale import sys import datetime import os +import warnings # From https://en.wikipedia.org/wiki/Leap_year_starting_on_Saturday result_0_02_text = """\ @@ -490,6 +491,14 @@ class OutputTestCase(unittest.TestCase): self.assertEqual(out.getvalue().strip(), "1 2 3") class CalendarTestCase(unittest.TestCase): + + def test_deprecation_warning(self): + with warnings.catch_warnings(record=True) as w: + calendar.January + self.assertEqual(len(w), 1) + self.assertEqual(w[0].category, DeprecationWarning) + self.assertIn("The 'January' attribute is deprecated, use 'JANUARY' instead", str(w[0].message)) + def test_isleap(self): # Make sure that the return is right for a few years, and # ensure that the return values are 1 or 0, not just true or diff --git a/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst b/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst new file mode 100644 index 00000000000..a05a6f5cbcd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst @@ -0,0 +1 @@ +Module-level attributes ``January`` and ``February`` are deprecated from :mod:`calendar`.