From 53b2edf352731f45436e4a6fe8ea08c922a4dbd8 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 26 Oct 2018 21:13:21 +0300 Subject: [PATCH 1/7] bpo-33710: Deprecate l*gettext() and related functions in the gettext module. They return encoded bytes and are Python 2 artifacts. --- Doc/library/gettext.rst | 22 ++- Doc/whatsnew/3.8.rst | 18 ++ Lib/gettext.py | 95 ++++++++-- Lib/test/test_gettext.py | 162 ++++++++++++------ .../2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst | 4 + 5 files changed, 234 insertions(+), 67 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst diff --git a/Doc/library/gettext.rst b/Doc/library/gettext.rst index 93748a2e47268d..0a9456abe146c7 100644 --- a/Doc/library/gettext.rst +++ b/Doc/library/gettext.rst @@ -53,6 +53,8 @@ class-based API instead. and :func:`ldngettext` functions. If *codeset* is omitted, then the current binding is returned. + .. deprecated-removed:: 3.8 3.10 + .. function:: textdomain(domain=None) @@ -112,9 +114,9 @@ class-based API instead. Unicode strings instead, since most Python applications will want to manipulate human readable text as strings instead of bytes. Further, it's possible that you may get unexpected Unicode-related exceptions - if there are encoding problems with the translated strings. It is - possible that the ``l*()`` functions will be deprecated in future Python - versions due to their inherent problems and limitations. + if there are encoding problems with the translated strings. + + .. deprecated-removed:: 3.8 3.10 Note that GNU :program:`gettext` also defines a :func:`dcgettext` method, but @@ -192,6 +194,9 @@ class can also install themselves in the built-in namespace as the function .. versionchanged:: 3.3 :exc:`IOError` used to be raised instead of :exc:`OSError`. + .. deprecated-removed:: 3.8 3.10 + The *codeset* parameter. + .. function:: install(domain, localedir=None, codeset=None, names=None) @@ -212,6 +217,9 @@ class can also install themselves in the built-in namespace as the function builtins namespace, so it is easily accessible in all modules of your application. + .. deprecated-removed:: 3.8 3.10 + The *codeset* parameter. + The :class:`NullTranslations` class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -272,6 +280,8 @@ are the methods of :class:`!NullTranslations`: These methods should be avoided in Python 3. See the warning for the :func:`lgettext` function. + .. deprecated-removed:: 3.8 3.10 + .. method:: info() @@ -288,11 +298,15 @@ are the methods of :class:`!NullTranslations`: Return the encoding used to return translated messages in :meth:`.lgettext` and :meth:`.lngettext`. + .. deprecated-removed:: 3.8 3.10 + .. method:: set_output_charset(charset) Change the encoding used to return translated messages. + .. deprecated-removed:: 3.8 3.10 + .. method:: install(names=None) @@ -393,6 +407,8 @@ unexpected, or if other problems occur while reading the file, instantiating a These methods should be avoided in Python 3. See the warning for the :func:`lgettext` function. + .. deprecated-removed:: 3.8 3.10 + Solaris message catalog support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index a09492137e779e..e218807dd0aa6e 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -295,6 +295,24 @@ Deprecated versions. :class:`~ast.Constant` should be used instead. (Contributed by Serhiy Storchaka in :issue:`32892`.) +* Functions :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, + :func:`~gettext.lngettext` and :func:`~gettext.ldngettext` in the + :mod:`gettext` module and corresponding methods of the + :class:`~gettext.NullTranslations` and :class:`~GNUTranslations` classes. + They return encoded bytes, and it's possible that you may get unexpected + Unicode-related exceptions if there are encoding problems with the + translated strings. It's much better to use alternatives which return + Unicode strings in Python 3. Further, they were broken for long time. + + Function :func:`~gettext.bind_textdomain_codeset`, methods + :meth:`~gettext.NullTranslations.output_charset` and + :meth:`~gettext.NullTranslations.set_output_charset`, and the *codeset* + parameter of functions :func:`~gettext.translation` and + :func:`~gettext.install` are also depreted, since they are only used for + for ``l*gettext()`` functions. + + (Contributed by Serhiy Storchaka in :issue:`33710`.) + Removed ======= diff --git a/Lib/gettext.py b/Lib/gettext.py index 4c3b80b0239b0a..920742cabe8836 100644 --- a/Lib/gettext.py +++ b/Lib/gettext.py @@ -274,8 +274,14 @@ def gettext(self, message): return message def lgettext(self, message): + import warnings + warnings.warn('lgettext() is deprecated, use gettext() instead', + DeprecationWarning, 2) if self._fallback: - return self._fallback.lgettext(message) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\blgettext\b.*', + DeprecationWarning) + return self._fallback.lgettext(message) if self._output_charset: return message.encode(self._output_charset) return message.encode(locale.getpreferredencoding()) @@ -289,8 +295,14 @@ def ngettext(self, msgid1, msgid2, n): return msgid2 def lngettext(self, msgid1, msgid2, n): + import warnings + warnings.warn('lngettext() is deprecated, use ngettext() instead', + DeprecationWarning, 2) if self._fallback: - return self._fallback.lngettext(msgid1, msgid2, n) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\blngettext\b.*', + DeprecationWarning) + return self._fallback.lngettext(msgid1, msgid2, n) if n == 1: tmsg = msgid1 else: @@ -306,9 +318,15 @@ def charset(self): return self._charset def output_charset(self): + import warnings + warnings.warn('output_charset() is deprecated', + DeprecationWarning, 2) return self._output_charset def set_output_charset(self, charset): + import warnings + warnings.warn('set_output_charset() is deprecated', + DeprecationWarning, 2) self._output_charset = charset def install(self, names=None): @@ -424,6 +442,9 @@ def _parse(self, fp): transidx += 8 def lgettext(self, message): + import warnings + warnings.warn('lgettext() is deprecated, use gettext() instead', + DeprecationWarning, 2) missing = object() tmsg = self._catalog.get(message, missing) if tmsg is missing: @@ -435,6 +456,9 @@ def lgettext(self, message): return tmsg.encode(locale.getpreferredencoding()) def lngettext(self, msgid1, msgid2, n): + import warnings + warnings.warn('lngettext() is deprecated, use ngettext() instead', + DeprecationWarning, 2) try: tmsg = self._catalog[(msgid1, self.plural(n))] except KeyError: @@ -510,9 +534,10 @@ def find(domain, localedir=None, languages=None, all=False): # a mapping between absolute .mo file path and Translation object _translations = {} +_unspecified = ['unspecified'] def translation(domain, localedir=None, languages=None, - class_=None, fallback=False, codeset=None): + class_=None, fallback=False, codeset=_unspecified): if class_ is None: class_ = GNUTranslations mofiles = find(domain, localedir, languages, all=True) @@ -538,8 +563,15 @@ def translation(domain, localedir=None, languages=None, # are not used. import copy t = copy.copy(t) - if codeset: - t.set_output_charset(codeset) + if codeset is not _unspecified: + import warnings + warnings.warn('parameter codeset is deprecated', + DeprecationWarning, 2) + if codeset: + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\bset_output_charset\b.*', + DeprecationWarning) + t.set_output_charset(codeset) if result is None: result = t else: @@ -547,7 +579,7 @@ def translation(domain, localedir=None, languages=None, return result -def install(domain, localedir=None, codeset=None, names=None): +def install(domain, localedir=None, codeset=_unspecified, names=None): t = translation(domain, localedir, fallback=True, codeset=codeset) t.install(names) @@ -576,6 +608,9 @@ def bindtextdomain(domain, localedir=None): def bind_textdomain_codeset(domain, codeset=None): + import warnings + warnings.warn('bind_textdomain_codeset() is deprecated', + DeprecationWarning, 2) global _localecodesets if codeset is not None: _localecodesets[domain] = codeset @@ -584,24 +619,31 @@ def bind_textdomain_codeset(domain, codeset=None): def dgettext(domain, message): try: - t = translation(domain, _localedirs.get(domain, None), - codeset=_localecodesets.get(domain)) + t = translation(domain, _localedirs.get(domain, None)) except OSError: return message return t.gettext(message) def ldgettext(domain, message): + import warnings + warnings.warn('ldgettext() is deprecated, use dgettext() instead', + DeprecationWarning, 2) codeset = _localecodesets.get(domain) try: - t = translation(domain, _localedirs.get(domain, None), codeset=codeset) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\bparameter codeset\b.*', + DeprecationWarning) + t = translation(domain, _localedirs.get(domain, None), codeset=codeset) except OSError: return message.encode(codeset or locale.getpreferredencoding()) - return t.lgettext(message) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\blgettext\b.*', + DeprecationWarning) + return t.lgettext(message) def dngettext(domain, msgid1, msgid2, n): try: - t = translation(domain, _localedirs.get(domain, None), - codeset=_localecodesets.get(domain)) + t = translation(domain, _localedirs.get(domain, None)) except OSError: if n == 1: return msgid1 @@ -610,28 +652,49 @@ def dngettext(domain, msgid1, msgid2, n): return t.ngettext(msgid1, msgid2, n) def ldngettext(domain, msgid1, msgid2, n): + import warnings + warnings.warn('ldngettext() is deprecated, use dngettext() instead', + DeprecationWarning, 2) codeset = _localecodesets.get(domain) try: - t = translation(domain, _localedirs.get(domain, None), codeset=codeset) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\bparameter codeset\b.*', + DeprecationWarning) + t = translation(domain, _localedirs.get(domain, None), codeset=codeset) except OSError: if n == 1: tmsg = msgid1 else: tmsg = msgid2 return tmsg.encode(codeset or locale.getpreferredencoding()) - return t.lngettext(msgid1, msgid2, n) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\blngettext\b.*', + DeprecationWarning) + return t.lngettext(msgid1, msgid2, n) def gettext(message): return dgettext(_current_domain, message) def lgettext(message): - return ldgettext(_current_domain, message) + import warnings + warnings.warn('lgettext() is deprecated, use gettext() instead', + DeprecationWarning, 2) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\bldgettext\b.*', + DeprecationWarning) + return ldgettext(_current_domain, message) def ngettext(msgid1, msgid2, n): return dngettext(_current_domain, msgid1, msgid2, n) def lngettext(msgid1, msgid2, n): - return ldngettext(_current_domain, msgid1, msgid2, n) + import warnings + warnings.warn('lngettext() is deprecated, use ngettext() instead', + DeprecationWarning, 2) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'.*\bldngettext\b.*', + DeprecationWarning) + return ldngettext(_current_domain, msgid1, msgid2, n) # dcgettext() has been deemed unnecessary and is not implemented. diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py index b5ed05eab7bbe1..bbad1028dcd89c 100644 --- a/Lib/test/test_gettext.py +++ b/Lib/test/test_gettext.py @@ -1,5 +1,6 @@ import os import base64 +import contextlib import gettext import locale import unittest @@ -461,116 +462,174 @@ def setUp(self): GettextBaseTest.setUp(self) self.mofile = MOFILE + @contextlib.contextmanager + def assertDeprecated(self, name): + with self.assertWarnsRegex(DeprecationWarning, + fr'^{name}\(\) is deprecated'): + yield + def test_lgettext(self): lgettext = gettext.lgettext ldgettext = gettext.ldgettext - self.assertEqual(lgettext('mullusk'), b'bacon') - self.assertEqual(lgettext('spam'), b'spam') - self.assertEqual(ldgettext('gettext', 'mullusk'), b'bacon') - self.assertEqual(ldgettext('gettext', 'spam'), b'spam') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('mullusk'), b'bacon') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('spam'), b'spam') + with self.assertDeprecated('ldgettext'): + self.assertEqual(ldgettext('gettext', 'mullusk'), b'bacon') + with self.assertDeprecated('ldgettext'): + self.assertEqual(ldgettext('gettext', 'spam'), b'spam') def test_lgettext_2(self): with open(self.mofile, 'rb') as fp: t = gettext.GNUTranslations(fp) lgettext = t.lgettext - self.assertEqual(lgettext('mullusk'), b'bacon') - self.assertEqual(lgettext('spam'), b'spam') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('mullusk'), b'bacon') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('spam'), b'spam') def test_lgettext_bind_textdomain_codeset(self): lgettext = gettext.lgettext ldgettext = gettext.ldgettext - saved_codeset = gettext.bind_textdomain_codeset('gettext') + with self.assertDeprecated('bind_textdomain_codeset'): + saved_codeset = gettext.bind_textdomain_codeset('gettext') try: - gettext.bind_textdomain_codeset('gettext', 'utf-16') - self.assertEqual(lgettext('mullusk'), 'bacon'.encode('utf-16')) - self.assertEqual(lgettext('spam'), 'spam'.encode('utf-16')) - self.assertEqual(ldgettext('gettext', 'mullusk'), 'bacon'.encode('utf-16')) - self.assertEqual(ldgettext('gettext', 'spam'), 'spam'.encode('utf-16')) + with self.assertDeprecated('bind_textdomain_codeset'): + gettext.bind_textdomain_codeset('gettext', 'utf-16') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('mullusk'), 'bacon'.encode('utf-16')) + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('spam'), 'spam'.encode('utf-16')) + with self.assertDeprecated('ldgettext'): + self.assertEqual(ldgettext('gettext', 'mullusk'), 'bacon'.encode('utf-16')) + with self.assertDeprecated('ldgettext'): + self.assertEqual(ldgettext('gettext', 'spam'), 'spam'.encode('utf-16')) finally: del gettext._localecodesets['gettext'] - gettext.bind_textdomain_codeset('gettext', saved_codeset) + with self.assertDeprecated('bind_textdomain_codeset'): + gettext.bind_textdomain_codeset('gettext', saved_codeset) def test_lgettext_output_encoding(self): with open(self.mofile, 'rb') as fp: t = gettext.GNUTranslations(fp) lgettext = t.lgettext - t.set_output_charset('utf-16') - self.assertEqual(lgettext('mullusk'), 'bacon'.encode('utf-16')) - self.assertEqual(lgettext('spam'), 'spam'.encode('utf-16')) + with self.assertDeprecated('set_output_charset'): + t.set_output_charset('utf-16') + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('mullusk'), 'bacon'.encode('utf-16')) + with self.assertDeprecated('lgettext'): + self.assertEqual(lgettext('spam'), 'spam'.encode('utf-16')) def test_lngettext(self): lngettext = gettext.lngettext ldngettext = gettext.ldngettext - x = lngettext('There is %s file', 'There are %s files', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 1) self.assertEqual(x, b'Hay %s fichero') - x = lngettext('There is %s file', 'There are %s files', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 2) self.assertEqual(x, b'Hay %s ficheros') - x = lngettext('There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 1) self.assertEqual(x, b'There is %s directory') - x = lngettext('There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 2) self.assertEqual(x, b'There are %s directories') - x = ldngettext('gettext', 'There is %s file', 'There are %s files', 1) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s file', 'There are %s files', 1) self.assertEqual(x, b'Hay %s fichero') - x = ldngettext('gettext', 'There is %s file', 'There are %s files', 2) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s file', 'There are %s files', 2) self.assertEqual(x, b'Hay %s ficheros') - x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 1) self.assertEqual(x, b'There is %s directory') - x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 2) self.assertEqual(x, b'There are %s directories') def test_lngettext_2(self): with open(self.mofile, 'rb') as fp: t = gettext.GNUTranslations(fp) lngettext = t.lngettext - x = lngettext('There is %s file', 'There are %s files', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 1) self.assertEqual(x, b'Hay %s fichero') - x = lngettext('There is %s file', 'There are %s files', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 2) self.assertEqual(x, b'Hay %s ficheros') - x = lngettext('There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 1) self.assertEqual(x, b'There is %s directory') - x = lngettext('There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 2) self.assertEqual(x, b'There are %s directories') def test_lngettext_bind_textdomain_codeset(self): lngettext = gettext.lngettext ldngettext = gettext.ldngettext - saved_codeset = gettext.bind_textdomain_codeset('gettext') + with self.assertDeprecated('bind_textdomain_codeset'): + saved_codeset = gettext.bind_textdomain_codeset('gettext') try: - gettext.bind_textdomain_codeset('gettext', 'utf-16') - x = lngettext('There is %s file', 'There are %s files', 1) + with self.assertDeprecated('bind_textdomain_codeset'): + gettext.bind_textdomain_codeset('gettext', 'utf-16') + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 1) self.assertEqual(x, 'Hay %s fichero'.encode('utf-16')) - x = lngettext('There is %s file', 'There are %s files', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 2) self.assertEqual(x, 'Hay %s ficheros'.encode('utf-16')) - x = lngettext('There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 1) self.assertEqual(x, 'There is %s directory'.encode('utf-16')) - x = lngettext('There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 2) self.assertEqual(x, 'There are %s directories'.encode('utf-16')) - x = ldngettext('gettext', 'There is %s file', 'There are %s files', 1) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s file', 'There are %s files', 1) self.assertEqual(x, 'Hay %s fichero'.encode('utf-16')) - x = ldngettext('gettext', 'There is %s file', 'There are %s files', 2) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s file', 'There are %s files', 2) self.assertEqual(x, 'Hay %s ficheros'.encode('utf-16')) - x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 1) self.assertEqual(x, 'There is %s directory'.encode('utf-16')) - x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('ldngettext'): + x = ldngettext('gettext', 'There is %s directory', 'There are %s directories', 2) self.assertEqual(x, 'There are %s directories'.encode('utf-16')) finally: del gettext._localecodesets['gettext'] - gettext.bind_textdomain_codeset('gettext', saved_codeset) + with self.assertDeprecated('bind_textdomain_codeset'): + gettext.bind_textdomain_codeset('gettext', saved_codeset) def test_lngettext_output_encoding(self): with open(self.mofile, 'rb') as fp: t = gettext.GNUTranslations(fp) lngettext = t.lngettext - t.set_output_charset('utf-16') - x = lngettext('There is %s file', 'There are %s files', 1) + with self.assertDeprecated('set_output_charset'): + t.set_output_charset('utf-16') + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 1) self.assertEqual(x, 'Hay %s fichero'.encode('utf-16')) - x = lngettext('There is %s file', 'There are %s files', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s file', 'There are %s files', 2) self.assertEqual(x, 'Hay %s ficheros'.encode('utf-16')) - x = lngettext('There is %s directory', 'There are %s directories', 1) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 1) self.assertEqual(x, 'There is %s directory'.encode('utf-16')) - x = lngettext('There is %s directory', 'There are %s directories', 2) + with self.assertDeprecated('lngettext'): + x = lngettext('There is %s directory', 'There are %s directories', 2) self.assertEqual(x, 'There are %s directories'.encode('utf-16')) + def test_output_encoding(self): + with open(self.mofile, 'rb') as fp: + t = gettext.GNUTranslations(fp) + with self.assertDeprecated('set_output_charset'): + t.set_output_charset('utf-16') + with self.assertDeprecated('output_charset'): + self.assertEqual(t.output_charset(), 'utf-16') + class GNUTranslationParsingTest(GettextBaseTest): def test_plural_form_error_issue17898(self): @@ -642,6 +701,16 @@ def test_cache(self): self.assertEqual(len(gettext._translations), 2) self.assertEqual(t.__class__, DummyGNUTranslations) + # Test deprecated parameter codeset + with self.assertWarnsRegex(DeprecationWarning, 'parameter codeset'): + t = gettext.translation('gettext', self.localedir, + class_=DummyGNUTranslations, + codeset='utf-16') + self.assertEqual(len(gettext._translations), 2) + self.assertEqual(t.__class__, DummyGNUTranslations) + with self.assertWarns(DeprecationWarning): + self.assertEqual(t.output_charset(), 'utf-16') + class MiscTestCase(unittest.TestCase): def test__all__(self): @@ -649,11 +718,8 @@ def test__all__(self): support.check__all__(self, gettext, blacklist=blacklist) -def test_main(): - support.run_unittest(__name__) - if __name__ == '__main__': - test_main() + unittest.main() # For reference, here's the .po file used to created the GNU_MO_DATA above. diff --git a/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst b/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst new file mode 100644 index 00000000000000..a1132d13f663f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst @@ -0,0 +1,4 @@ +Deprecated ``l*gettext()`` functions and methods in the :mod:`gettext` +module. They return encoded bytes instead of Unicode strings and are +artifacts from Python 2 times. Deprecated also functions and methods related +to setting the charset for ``l*gettext()`` functions and methods. From 9521b19b3a88b5acda64f7c5ddcd26fbdc87c4bd Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Oct 2018 21:55:06 +0300 Subject: [PATCH 2/7] Update Doc/whatsnew/3.8.rst Co-Authored-By: serhiy-storchaka --- Doc/whatsnew/3.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index e218807dd0aa6e..71247ccb5010c9 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -295,7 +295,7 @@ Deprecated versions. :class:`~ast.Constant` should be used instead. (Contributed by Serhiy Storchaka in :issue:`32892`.) -* Functions :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, +* The following functions are deprecated: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, :func:`~gettext.lngettext` and :func:`~gettext.ldngettext` in the :mod:`gettext` module and corresponding methods of the :class:`~gettext.NullTranslations` and :class:`~GNUTranslations` classes. From e96180ee3a31cb7964cf9d9d2febe7dbd55b24ad Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Oct 2018 21:55:13 +0300 Subject: [PATCH 3/7] Update Doc/whatsnew/3.8.rst Co-Authored-By: serhiy-storchaka --- Doc/whatsnew/3.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 71247ccb5010c9..076bd3a7299301 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -299,7 +299,7 @@ Deprecated :func:`~gettext.lngettext` and :func:`~gettext.ldngettext` in the :mod:`gettext` module and corresponding methods of the :class:`~gettext.NullTranslations` and :class:`~GNUTranslations` classes. - They return encoded bytes, and it's possible that you may get unexpected + They return encoded bytes, and it's possible that you will get unexpected Unicode-related exceptions if there are encoding problems with the translated strings. It's much better to use alternatives which return Unicode strings in Python 3. Further, they were broken for long time. From 319c4d5d09eb42bee55b0b168706f7ad7bdd78fb Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Oct 2018 21:55:20 +0300 Subject: [PATCH 4/7] Update Doc/whatsnew/3.8.rst Co-Authored-By: serhiy-storchaka --- Doc/whatsnew/3.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 076bd3a7299301..f83fd563c4cf1b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -302,7 +302,7 @@ Deprecated They return encoded bytes, and it's possible that you will get unexpected Unicode-related exceptions if there are encoding problems with the translated strings. It's much better to use alternatives which return - Unicode strings in Python 3. Further, they were broken for long time. + Unicode strings in Python 3. These functions have been broken for a long time. Function :func:`~gettext.bind_textdomain_codeset`, methods :meth:`~gettext.NullTranslations.output_charset` and From 18a83d7cd2effebb4f715289245add73336ed667 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Oct 2018 21:55:29 +0300 Subject: [PATCH 5/7] Update Doc/whatsnew/3.8.rst Co-Authored-By: serhiy-storchaka --- Doc/whatsnew/3.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index f83fd563c4cf1b..490fa2573043f0 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -308,7 +308,7 @@ Deprecated :meth:`~gettext.NullTranslations.output_charset` and :meth:`~gettext.NullTranslations.set_output_charset`, and the *codeset* parameter of functions :func:`~gettext.translation` and - :func:`~gettext.install` are also depreted, since they are only used for + :func:`~gettext.install` are also deprecated, since they are only used for for ``l*gettext()`` functions. (Contributed by Serhiy Storchaka in :issue:`33710`.) From 0ed09ef8dc95afaba50d45686767f360b6375b5f Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Oct 2018 21:57:20 +0300 Subject: [PATCH 6/7] Update Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst Co-Authored-By: serhiy-storchaka --- .../next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst b/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst index a1132d13f663f4..25f0f875808384 100644 --- a/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst +++ b/Misc/NEWS.d/next/Library/2018-10-26-21-12-55.bpo-33710.Q5oXc6.rst @@ -1,4 +1,4 @@ Deprecated ``l*gettext()`` functions and methods in the :mod:`gettext` module. They return encoded bytes instead of Unicode strings and are -artifacts from Python 2 times. Deprecated also functions and methods related +artifacts from Python 2 times. Also deprecated functions and methods related to setting the charset for ``l*gettext()`` functions and methods. From c93dd56e2ca7c55a42f5b286c740d3172c877d3b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 26 Oct 2018 22:04:51 +0300 Subject: [PATCH 7/7] Update 3.8.rst --- Doc/whatsnew/3.8.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 490fa2573043f0..05b7d235cee800 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -295,10 +295,9 @@ Deprecated versions. :class:`~ast.Constant` should be used instead. (Contributed by Serhiy Storchaka in :issue:`32892`.) -* The following functions are deprecated: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, - :func:`~gettext.lngettext` and :func:`~gettext.ldngettext` in the - :mod:`gettext` module and corresponding methods of the - :class:`~gettext.NullTranslations` and :class:`~GNUTranslations` classes. +* The following functions and methods are deprecated in the :mod:`gettext` + module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, + :func:`~gettext.lngettext` and :func:`~gettext.ldngettext`. They return encoded bytes, and it's possible that you will get unexpected Unicode-related exceptions if there are encoding problems with the translated strings. It's much better to use alternatives which return @@ -309,7 +308,7 @@ Deprecated :meth:`~gettext.NullTranslations.set_output_charset`, and the *codeset* parameter of functions :func:`~gettext.translation` and :func:`~gettext.install` are also deprecated, since they are only used for - for ``l*gettext()`` functions. + for the ``l*gettext()`` functions. (Contributed by Serhiy Storchaka in :issue:`33710`.)