diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst
index b292d828841f2f..fd397547a04437 100644
--- a/Doc/library/calendar.rst
+++ b/Doc/library/calendar.rst
@@ -501,6 +501,14 @@ The :mod:`calendar` module exports the following data attributes:
>>> list(calendar.month_name)
['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
+ .. caution::
+
+ In locales with alternative month names forms, the :data:`!month_name` sequence
+ may not be suitable when a month name stands by itself and not as part of a date.
+ For instance, in Greek and in many Slavic and Baltic languages, :data:`!month_name`
+ will produce the month in genitive case. Use :data:`standalone_month_name` for a form
+ suitable for standalone use.
+
.. data:: month_abbr
@@ -512,6 +520,31 @@ The :mod:`calendar` module exports the following data attributes:
>>> list(calendar.month_abbr)
['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ .. caution::
+
+ In locales with alternative month names forms, the :data:`!month_abbr` sequence
+ may not be suitable when a month name stands by itself and not as part of a date.
+ Use :data:`standalone_month_abbr` for a form suitable for standalone use.
+
+
+.. data:: standalone_month_name
+
+ A sequence that represents the months of the year in the current locale
+ in the standalone form if the locale provides one. Else it is equivalent
+ to :data:`month_name`.
+
+ .. versionadded:: next
+
+
+.. data:: standalone_month_abbr
+
+ A sequence that represents the abbreviated months of the year in the current
+ locale in the standalone form if the locale provides one. Else it is
+ equivalent to :data:`month_abbr`.
+
+ .. versionadded:: next
+
+
.. data:: JANUARY
FEBRUARY
MARCH
diff --git a/Lib/calendar.py b/Lib/calendar.py
index 3be1b50500eb07..45bb265a65602c 100644
--- a/Lib/calendar.py
+++ b/Lib/calendar.py
@@ -14,8 +14,9 @@
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
"monthcalendar", "prmonth", "month", "prcal", "calendar",
- "timegm", "month_name", "month_abbr", "day_name", "day_abbr",
- "Calendar", "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
+ "timegm", "month_name", "month_abbr", "standalone_month_name",
+ "standalone_month_abbr", "day_name", "day_abbr", "Calendar",
+ "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
"LocaleHTMLCalendar", "weekheader",
"Day", "Month", "JANUARY", "FEBRUARY", "MARCH",
"APRIL", "MAY", "JUNE", "JULY",
@@ -139,6 +140,16 @@ def __len__(self):
month_name = _localized_month('%B')
month_abbr = _localized_month('%b')
+# On platforms that support the %OB and %Ob specifiers, they are used
+# to get the standalone form of the month name. This is required for
+# some languages such as Greek, Slavic, and Baltic languages.
+try:
+ standalone_month_name = _localized_month('%OB')
+ standalone_month_abbr = _localized_month('%Ob')
+except ValueError:
+ standalone_month_name = month_name
+ standalone_month_abbr = month_abbr
+
def isleap(year):
"""Return True for leap years, False for non-leap years."""
@@ -377,7 +388,7 @@ def formatmonthname(self, theyear, themonth, width, withyear=True):
"""
_validate_month(themonth)
- s = month_name[themonth]
+ s = standalone_month_name[themonth]
if withyear:
s = "%s %r" % (s, theyear)
return s.center(width)
@@ -510,9 +521,9 @@ def formatmonthname(self, theyear, themonth, withyear=True):
"""
_validate_month(themonth)
if withyear:
- s = '%s %s' % (month_name[themonth], theyear)
+ s = '%s %s' % (standalone_month_name[themonth], theyear)
else:
- s = '%s' % month_name[themonth]
+ s = standalone_month_name[themonth]
return '
| %s |
' % (
self.cssclass_month_head, s)
diff --git a/Lib/concurrent/futures/__init__.py b/Lib/concurrent/futures/__init__.py
index e717222cf98b32..d6ac4b3e0b675f 100644
--- a/Lib/concurrent/futures/__init__.py
+++ b/Lib/concurrent/futures/__init__.py
@@ -44,7 +44,7 @@
def __dir__():
- return __all__ + ('__author__', '__doc__')
+ return __all__ + ['__author__', '__doc__']
def __getattr__(name):
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index f35b1194308262..8ded9f99248372 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -72,6 +72,8 @@ def check_all(self, modname):
all_set = set(all_list)
self.assertCountEqual(all_set, all_list, "in module {}".format(modname))
self.assertEqual(keys, all_set, "in module {}".format(modname))
+ # Verify __dir__ is non-empty and doesn't produce an error
+ self.assertTrue(dir(sys.modules[modname]))
def walk_modules(self, basedir, modpath):
for fn in sorted(os.listdir(basedir)):
diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py
index bc39c86b8cf62d..589a21baf7bd61 100644
--- a/Lib/test/test_calendar.py
+++ b/Lib/test/test_calendar.py
@@ -8,6 +8,7 @@
import io
import locale
import os
+import platform
import sys
import time
@@ -546,7 +547,8 @@ def test_days(self):
self.assertEqual(value[::-1], list(reversed(value)))
def test_months(self):
- for attr in "month_name", "month_abbr":
+ for attr in ("month_name", "month_abbr", "standalone_month_name",
+ "standalone_month_abbr"):
value = getattr(calendar, attr)
self.assertEqual(len(value), 13)
self.assertEqual(len(value[:]), 13)
@@ -556,6 +558,38 @@ def test_months(self):
# verify it "acts like a sequence" in two forms of iteration
self.assertEqual(value[::-1], list(reversed(value)))
+ @support.run_with_locale('LC_ALL', 'pl_PL')
+ @unittest.skipUnless(sys.platform == 'darwin' or platform.libc_ver()[0] == 'glibc',
+ "Guaranteed to work with glibc and macOS")
+ def test_standalone_month_name_and_abbr_pl_locale(self):
+ expected_standalone_month_names = [
+ "", "styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec",
+ "lipiec", "sierpień", "wrzesień", "październik", "listopad",
+ "grudzień"
+ ]
+ expected_standalone_month_abbr = [
+ "", "sty", "lut", "mar", "kwi", "maj", "cze",
+ "lip", "sie", "wrz", "paź", "lis", "gru"
+ ]
+ self.assertEqual(
+ list(calendar.standalone_month_name),
+ expected_standalone_month_names
+ )
+ self.assertEqual(
+ list(calendar.standalone_month_abbr),
+ expected_standalone_month_abbr
+ )
+
+ def test_standalone_month_name_and_abbr_C_locale(self):
+ # Ensure that the standalone month names and abbreviations are
+ # equal to the regular month names and abbreviations for
+ # the "C" locale.
+ with calendar.different_locale("C"):
+ self.assertListEqual(list(calendar.month_name),
+ list(calendar.standalone_month_name))
+ self.assertListEqual(list(calendar.month_abbr),
+ list(calendar.standalone_month_abbr))
+
def test_locale_text_calendar(self):
try:
cal = calendar.LocaleTextCalendar(locale='')
diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py
index a932ac80117d27..4122f786a9afb0 100644
--- a/Lib/test/test_monitoring.py
+++ b/Lib/test/test_monitoring.py
@@ -3,6 +3,7 @@
import collections
import dis
import functools
+import inspect
import math
import operator
import sys
@@ -1709,6 +1710,27 @@ def func(v=1):
('branch right', 'func', 6, 8),
('branch right', 'func', 2, 10)])
+ def test_callback_set_frame_lineno(self):
+ def func(s: str) -> int:
+ if s.startswith("t"):
+ return 1
+ else:
+ return 0
+
+ def callback(code, from_, to):
+ # try set frame.f_lineno
+ frame = inspect.currentframe()
+ while frame and frame.f_code is not code:
+ frame = frame.f_back
+
+ self.assertIsNotNone(frame)
+ frame.f_lineno = frame.f_lineno + 1 # run next instruction
+
+ sys.monitoring.set_local_events(TEST_TOOL, func.__code__, E.BRANCH_LEFT)
+ sys.monitoring.register_callback(TEST_TOOL, E.BRANCH_LEFT, callback)
+
+ self.assertEqual(func("true"), 1)
+
class TestBranchConsistency(MonitoringTestBase, unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2025-03-17-21-21-06.gh-issue-131146.A5Obgv.rst b/Misc/NEWS.d/next/Library/2025-03-17-21-21-06.gh-issue-131146.A5Obgv.rst
new file mode 100644
index 00000000000000..6d8bc0959aed52
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-03-17-21-21-06.gh-issue-131146.A5Obgv.rst
@@ -0,0 +1,6 @@
+Fix :class:`calendar.TextCalendar`, :class:`calendar.HTMLCalendar`,
+and the :mod:`calendar` CLI to display month names in the nominative
+case by adding :data:`calendar.standalone_month_name` and
+:data:`calendar.standalone_month_abbr`, which provide month names and
+abbreviations in the grammatical form used when a month name stands by
+itself, if the locale supports it.
diff --git a/Misc/NEWS.d/next/Library/2025-07-31-10-31-56.gh-issue-137282.GOCwIC.rst b/Misc/NEWS.d/next/Library/2025-07-31-10-31-56.gh-issue-137282.GOCwIC.rst
new file mode 100644
index 00000000000000..78f169ea029b17
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-07-31-10-31-56.gh-issue-137282.GOCwIC.rst
@@ -0,0 +1 @@
+Fix tab completion and :func:`dir` on :mod:`concurrent.futures`.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 97de1e06efe1b2..72c0ab0666e927 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1685,6 +1685,8 @@ frame_lineno_set_impl(PyFrameObject *self, PyObject *value)
case PY_MONITORING_EVENT_PY_RESUME:
case PY_MONITORING_EVENT_JUMP:
case PY_MONITORING_EVENT_BRANCH:
+ case PY_MONITORING_EVENT_BRANCH_LEFT:
+ case PY_MONITORING_EVENT_BRANCH_RIGHT:
case PY_MONITORING_EVENT_LINE:
case PY_MONITORING_EVENT_PY_YIELD:
/* Setting f_lineno is allowed for the above events */