From a8b5521aad78ab52ba40c585deb615081dbbabcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Thu, 12 Feb 2026 18:55:34 +0800 Subject: [PATCH 1/8] chore: remove Windows 95 locale fall back code path detect exception for Windows getdefaultlocale, once any of required constant was unavaliable, fall back to POSIX behaviour. --- Lib/locale.py | 13 +++++++------ Modules/_localemodule.c | 11 ----------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index dea3ee55cf4d24..d26ad85cc112a9 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -570,13 +570,14 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): 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 + # add other platform-specific processing here, if # necessary... - return code, encoding + # for Windows, for any reason if the code was + # not avaliable, fall back to POSIX behaviour + if sys.platform == "win32" and code is None: + pass + else: + return code, encoding # fall back on POSIX behaviour import os diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 7174eebd0c94de..b224173276d3e2 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -555,17 +555,6 @@ _locale__getdefaultlocale_impl(PyObject *module) 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); From 4ba8dcb3fba76fb26c4add66205eaf732f6b8f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Sun, 22 Feb 2026 01:30:59 +0800 Subject: [PATCH 2/8] chore: raises `OSError` if getting locale info failed --- Lib/locale.py | 10 ++++------ Modules/_localemodule.c | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index d26ad85cc112a9..6993a72df4ad3f 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -557,6 +557,9 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): 1766. code and encoding can be None in case the values cannot be determined. + Raises OSError on Windows if failed to get locale info (unlikely + to happen on modern Windows). + """ return _getdefaultlocale(envvars) @@ -572,12 +575,7 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): else: # add other platform-specific processing here, if # necessary... - # for Windows, for any reason if the code was - # not avaliable, fall back to POSIX behaviour - if sys.platform == "win32" and code is None: - pass - else: - return code, encoding + return code, encoding # fall back on POSIX behaviour import os diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index b224173276d3e2..be90dc62f33342 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -29,6 +29,7 @@ This software comes with no warranty. Use at your own risk. # define WIN32_LEAN_AND_MEAN # endif # include +# include "pyerrors.h" // PyErr_SetFromWindowsErr() #endif PyDoc_STRVAR(locale__doc__, "Support for POSIX locales."); @@ -556,8 +557,8 @@ _locale__getdefaultlocale_impl(PyObject *module) } /* cannot determine the language code (very unlikely) */ - Py_INCREF(Py_None); - return Py_BuildValue("Os", Py_None, encoding); + /* if any of GetLocaleInfoA above failed */ + return PyErr_SetFromWindowsErr(0); } #endif From 8f1e79a81268e95d1cd124363a5ecd696c49a4ff Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 17:34:55 +0000 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst diff --git a/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst b/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst new file mode 100644 index 00000000000000..2214409afb359a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst @@ -0,0 +1,2 @@ +Removed Windows 95 compatibility code from :func:`_locale._getdefaultlocale`. +Instead, if ``LOCALE_SISO639LANGNAME`` or ``LOCALE_SISO3166CTRYNAME`` cannot be retrieved, an :class:`OSError` is raised. From 65fe62513b3f6d6479af9cce10b8486cac464d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= <34085039+mokurin000@users.noreply.github.com> Date: Sun, 22 Feb 2026 11:17:53 +0800 Subject: [PATCH 4/8] fix: don't expose implementation detail --- Lib/locale.py | 5 +++-- .../Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index 6993a72df4ad3f..ee95c8d6cf2879 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -557,8 +557,7 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): 1766. code and encoding can be None in case the values cannot be determined. - Raises OSError on Windows if failed to get locale info (unlikely - to happen on modern Windows). + Returns `None` on Windows if failed to get locale info. """ @@ -572,6 +571,8 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): code, encoding = _locale._getdefaultlocale() except (ImportError, AttributeError): pass + except OSError: + return None else: # add other platform-specific processing here, if # necessary... diff --git a/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst b/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst index 2214409afb359a..1babcbfd8e678a 100644 --- a/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst +++ b/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst @@ -1,2 +1 @@ -Removed Windows 95 compatibility code from :func:`_locale._getdefaultlocale`. -Instead, if ``LOCALE_SISO639LANGNAME`` or ``LOCALE_SISO3166CTRYNAME`` cannot be retrieved, an :class:`OSError` is raised. +Removed Windows 95 compatibility for :func:`locale.getdefaultlocale`. From 4cad82336a00c28aded3f4c80e76ee211db1cd53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Thu, 26 Feb 2026 17:16:32 +0800 Subject: [PATCH 5/8] fix: don't silently ignore `WindowsError` Also, `pyerrors.h` was included through `Python.h`, removing it --- Lib/locale.py | 5 +++-- Modules/_localemodule.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index ee95c8d6cf2879..9747ecb05fb107 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -571,8 +571,9 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): code, encoding = _locale._getdefaultlocale() except (ImportError, AttributeError): pass - except OSError: - return None + except OSError as e: + if sys.platform == "win32" and isinstance(e, WindowsError): + raise else: # add other platform-specific processing here, if # necessary... diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index be90dc62f33342..e8ba6b49826137 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -29,7 +29,6 @@ This software comes with no warranty. Use at your own risk. # define WIN32_LEAN_AND_MEAN # endif # include -# include "pyerrors.h" // PyErr_SetFromWindowsErr() #endif PyDoc_STRVAR(locale__doc__, "Support for POSIX locales."); From 32c7bef128be097392326e2497ab5752f6bce2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Thu, 26 Feb 2026 17:21:42 +0800 Subject: [PATCH 6/8] docs: fix outdated documentation --- Lib/locale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/locale.py b/Lib/locale.py index 9747ecb05fb107..5528f57f93fc33 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -557,7 +557,7 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): 1766. code and encoding can be None in case the values cannot be determined. - Returns `None` on Windows if failed to get locale info. + On Windows, raise a `WindowsError` if retrieving the locale fails. """ From 7c9b9fe17521297f50d059ff4a0187e0e3275b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Fri, 27 Feb 2026 02:17:51 +0800 Subject: [PATCH 7/8] chore: remove exception raising for backword compatibility --- Lib/locale.py | 5 ----- Modules/_localemodule.c | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index 5528f57f93fc33..72e3bcfd3333ce 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -557,8 +557,6 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): 1766. code and encoding can be None in case the values cannot be determined. - On Windows, raise a `WindowsError` if retrieving the locale fails. - """ return _getdefaultlocale(envvars) @@ -571,9 +569,6 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): code, encoding = _locale._getdefaultlocale() except (ImportError, AttributeError): pass - except OSError as e: - if sys.platform == "win32" and isinstance(e, WindowsError): - raise else: # add other platform-specific processing here, if # necessary... diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index e8ba6b49826137..b224173276d3e2 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -556,8 +556,8 @@ _locale__getdefaultlocale_impl(PyObject *module) } /* cannot determine the language code (very unlikely) */ - /* if any of GetLocaleInfoA above failed */ - return PyErr_SetFromWindowsErr(0); + Py_INCREF(Py_None); + return Py_BuildValue("Os", Py_None, encoding); } #endif From 583c63a9cf81c149c4a8db64c9bd20f7b07f0910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AF=E5=87=9B?= Date: Fri, 27 Feb 2026 02:20:33 +0800 Subject: [PATCH 8/8] docs: minify diff lines --- Lib/locale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/locale.py b/Lib/locale.py index 72e3bcfd3333ce..e7382796905ebd 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -570,7 +570,7 @@ def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): except (ImportError, AttributeError): pass else: - # add other platform-specific processing here, if + # ...add other platform-specific processing here, if # necessary... return code, encoding