◐ Shell
reader mode source ↗
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
2 changes: 1 addition & 1 deletion Doc/deprecations/pending-removal-in-3.15.rst
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ Pending removal in Python 3.15

* :class:`locale`:

* The :func:`~locale.getdefaultlocale` function
has been deprecated since Python 3.11.
Its removal was originally planned for Python 3.13 (:gh:`90817`),
but has been postponed to Python 3.15.
Expand Down
3 changes: 1 addition & 2 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1113,8 +1113,7 @@ conflict.
components running in the same process (such as the GNU ``readline``
library), the updated setting is also seen in subprocesses (regardless of
whether or not those processes are running a Python interpreter), as well as
in operations that query the environment rather than the current C locale
(such as Python's own :func:`locale.getdefaultlocale`).

Configuring one of these locales (either explicitly or via the above
implicit locale coercion) automatically enables the ``surrogateescape``
Expand Down
4 changes: 2 additions & 2 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ Standard Library
* :func:`!importlib.resources.read_text`
* :func:`!importlib.resources.path`

* The :func:`locale.getdefaultlocale` function is deprecated and will be
removed in Python 3.15. Use :func:`locale.setlocale`,
:func:`locale.getpreferredencoding(False) <locale.getpreferredencoding>` and
:func:`locale.getlocale` functions instead.
Expand Down Expand Up @@ -2080,7 +2080,7 @@ Porting notes for the C API are

* :mod:`calendar`: The :class:`calendar.LocaleTextCalendar` and
:class:`calendar.LocaleHTMLCalendar` classes now use
:func:`locale.getlocale`, instead of using :func:`locale.getdefaultlocale`,
if no locale is specified.
(Contributed by Victor Stinner in :issue:`46659`.)

Expand Down
8 changes: 8 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ Deprecated
Removed
=======

platform
--------

Expand Down
74 changes: 5 additions & 69 deletions Lib/locale.py
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@

# Yuck: LC_MESSAGES is non-standard: can't tell whether it exists before
# trying the import. So __all__ is also fiddled at the end of the file.
__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error",
"setlocale", "localeconv", "strcoll", "strxfrm",
"str", "atof", "atoi", "format_string", "currency",
"normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY",
Expand Down Expand Up @@ -521,69 +521,6 @@ def _build_localename(localetuple):
raise TypeError('Locale must be None, a string, or an iterable of '
'two strings -- language code, encoding.') from None

def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')):

""" Tries to determine the default locale settings and returns
them as tuple (language code, encoding).

According to POSIX, a program which has not called
setlocale(LC_ALL, "") runs using the portable 'C' locale.
Calling setlocale(LC_ALL, "") lets it use the default locale as
defined by the LANG variable. Since we don't want to interfere
with the current locale setting we thus emulate the behavior
in the way described above.

To maintain compatibility with other platforms, not only the
LANG variable is tested, but a list of variables given as
envvars parameter. The first found to be defined will be
used. envvars defaults to the search path used in GNU gettext;
it must always contain the variable name 'LANG'.

Except for the code 'C', the language code corresponds to RFC
1766. code and encoding can be None in case the values cannot
be determined.

"""

import warnings
warnings._deprecated(
"locale.getdefaultlocale",
"{name!r} is deprecated and slated for removal in Python {remove}. "
"Use setlocale(), getencoding() and getlocale() instead.",
remove=(3, 15))
return _getdefaultlocale(envvars)


def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')):
try:
# check if it's supported by the _locale module
import _locale
code, encoding = _locale._getdefaultlocale()
except (ImportError, AttributeError):
pass
else:
# make sure the code/encoding values are valid
if sys.platform == "win32" and code and code[:2] == "0x":
# map windows language identifier to language name
code = windows_locale.get(int(code, 0))
# ...add other platform-specific processing here, if
# necessary...
return code, encoding

# fall back on POSIX behaviour
import os
lookup = os.environ.get
for variable in envvars:
localename = lookup(variable,None)
if localename:
if variable == 'LANGUAGE':
localename = localename.split(':')[0]
break
else:
localename = 'C'
return _parse_localename(localename)


def getlocale(category=LC_CTYPE):

""" Returns the current setting for the given locale category as
Expand Down Expand Up @@ -1728,12 +1665,11 @@ def _init_categories(categories=categories):
_init_categories()
del categories['LC_ALL']

print('Locale defaults as determined by getdefaultlocale():')
print('-'*72)
lang, enc = getdefaultlocale()
print('Language: ', lang or '(undefined)')
print('Encoding: ', enc or '(undefined)')
print()

print('Locale settings on startup:')
print('-'*72)
Expand Down
24 changes: 0 additions & 24 deletions Lib/test/test_locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,30 +483,6 @@ def test_japanese(self):


class TestMiscellaneous(unittest.TestCase):
def test_defaults_UTF8(self):
# Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is
# valid. Furthermore LC_CTYPE=UTF is used by the UTF-8 locale coercing
# during interpreter startup (on macOS).
import _locale

self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8'))

if hasattr(_locale, '_getdefaultlocale'):
orig_getlocale = _locale._getdefaultlocale
del _locale._getdefaultlocale
else:
orig_getlocale = None

try:
with os_helper.EnvironmentVarGuard() as env:
env.unset('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')
env.set('LC_CTYPE', 'UTF-8')

with check_warnings(('', DeprecationWarning)):
self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8'))
finally:
if orig_getlocale is not None:
_locale._getdefaultlocale = orig_getlocale

def test_getencoding(self):
# Invoke getencoding to make sure it does not cause exceptions.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
47 changes: 0 additions & 47 deletions Modules/_localemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,50 +444,6 @@ _locale_strxfrm_impl(PyObject *module, PyObject *str)
}
#endif

#if defined(MS_WINDOWS)

/*[clinic input]
_locale._getdefaultlocale

[clinic start generated code]*/

static PyObject *
_locale__getdefaultlocale_impl(PyObject *module)
/*[clinic end generated code: output=e6254088579534c2 input=003ea41acd17f7c7]*/
{
char encoding[20];
char locale[100];

PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP());

if (GetLocaleInfoA(LOCALE_USER_DEFAULT,
LOCALE_SISO639LANGNAME,
locale, sizeof(locale))) {
Py_ssize_t i = strlen(locale);
locale[i++] = '_';
if (GetLocaleInfoA(LOCALE_USER_DEFAULT,
LOCALE_SISO3166CTRYNAME,
locale+i, (int)(sizeof(locale)-i)))
return Py_BuildValue("ss", locale, encoding);
}

/* If we end up here, this windows version didn't know about
ISO639/ISO3166 names (it's probably Windows 95). Return the
Windows language identifier instead (a hexadecimal number) */

locale[0] = '0';
locale[1] = 'x';
if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
locale+2, sizeof(locale)-2)) {
return Py_BuildValue("ss", locale, encoding);
}

/* cannot determine the language code (very unlikely) */
Py_INCREF(Py_None);
return Py_BuildValue("Os", Py_None, encoding);
}
#endif

#ifdef HAVE_LANGINFO_H
#define LANGINFO(X, Y) {#X, X, Y}
static struct langinfo_constant{
Expand Down Expand Up @@ -899,9 +855,6 @@ static struct PyMethodDef PyLocale_Methods[] = {
#ifdef HAVE_WCSXFRM
_LOCALE_STRXFRM_METHODDEF
#endif
#if defined(MS_WINDOWS)
_LOCALE__GETDEFAULTLOCALE_METHODDEF
#endif
#ifdef HAVE_LANGINFO_H
_LOCALE_NL_LANGINFO_METHODDEF
#endif
Expand Down
27 changes: 1 addition & 26 deletions Modules/clinic/_localemodule.c.h
Toggle all file notes Toggle all file annotations