diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 2fe1494a3d770f..f4880c3ce86806 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -357,6 +357,10 @@ Deprecated It was not documented and only supported in the C implementation. (Contributed by Serhiy Storchaka in :gh:`89902`.) +* Emit deprecation warning for non-integer numbers in :mod:`gettext` functions + and methods that consider plural forms even if the translation was not found. + (Contributed by Serhiy Storchaka in :gh:`88434`.) + Pending Removal in Python 3.14 ------------------------------ diff --git a/Lib/gettext.py b/Lib/gettext.py index e84765bfdf0649..62cff81b7b3d49 100644 --- a/Lib/gettext.py +++ b/Lib/gettext.py @@ -171,6 +171,13 @@ def _as_int(n): except TypeError: raise TypeError('Plural value must be an integer, got %s' % (n.__class__.__name__,)) from None + return _as_int2(n) + +def _as_int2(n): + try: + return operator.index(n) + except TypeError: + pass import warnings frame = sys._getframe(1) @@ -288,6 +295,7 @@ def gettext(self, message): def ngettext(self, msgid1, msgid2, n): if self._fallback: return self._fallback.ngettext(msgid1, msgid2, n) + n = _as_int2(n) if n == 1: return msgid1 else: @@ -301,6 +309,7 @@ def pgettext(self, context, message): def npgettext(self, context, msgid1, msgid2, n): if self._fallback: return self._fallback.npgettext(context, msgid1, msgid2, n) + n = _as_int2(n) if n == 1: return msgid1 else: @@ -587,6 +596,7 @@ def dngettext(domain, msgid1, msgid2, n): try: t = translation(domain, _localedirs.get(domain, None)) except OSError: + n = _as_int2(n) if n == 1: return msgid1 else: @@ -606,6 +616,7 @@ def dnpgettext(domain, context, msgid1, msgid2, n): try: t = translation(domain, _localedirs.get(domain, None)) except OSError: + n = _as_int2(n) if n == 1: return msgid1 else: diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py index dd33b9b88f6768..b2fe3e28c3bec7 100644 --- a/Lib/test/test_gettext.py +++ b/Lib/test/test_gettext.py @@ -332,22 +332,24 @@ def _test_plural_forms(self, ngettext, gettext, x = gettext(singular) self.assertEqual(x, tsingular) + lineno = self._test_plural_forms.__code__.co_firstlineno + 12 + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, 1.0) + self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno) + self.assertEqual(x, tsingular) + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, 1.1) + self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno + 5) + self.assertEqual(x, tplural) + if numbers_only: - lineno = self._test_plural_forms.__code__.co_firstlineno + 9 - with self.assertWarns(DeprecationWarning) as cm: - x = ngettext(singular, plural, 1.0) - self.assertEqual(cm.filename, __file__) - self.assertEqual(cm.lineno, lineno + 4) - self.assertEqual(x, tsingular) - with self.assertWarns(DeprecationWarning) as cm: - x = ngettext(singular, plural, 1.1) - self.assertEqual(cm.filename, __file__) - self.assertEqual(cm.lineno, lineno + 9) - self.assertEqual(x, tplural) with self.assertRaises(TypeError): ngettext(singular, plural, None) else: - x = ngettext(singular, plural, None) + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, None) self.assertEqual(x, tplural) def test_plural_forms(self): diff --git a/Misc/NEWS.d/next/Library/2023-10-08-18-38-09.gh-issue-88434.2Q_IkG.rst b/Misc/NEWS.d/next/Library/2023-10-08-18-38-09.gh-issue-88434.2Q_IkG.rst new file mode 100644 index 00000000000000..9722be251bfcad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-08-18-38-09.gh-issue-88434.2Q_IkG.rst @@ -0,0 +1,3 @@ +Emit deprecation warning for non-integer numbers in :mod:`gettext` functions +and methods that consider plural forms even if the translation was not +found.