Python to 3.13.14 - #20476
Conversation
Bump the pinned CPython version used across the project from 3.13.13 to 3.13.14. Changes: - .python-versions: update cpython-3.13.13-windows-x86_64-none to cpython-3.13.14-windows-x86_64-none - runtime-builders/synthDriverHost32/.python-version: update cpython-3.13.13-windows-x86-none to cpython-3.13.14-windows-x86-none - .github/workflows/autofix.yml: update python-version from 3.13.13 to 3.13.14 - .github/workflows/fetch-crowdin-translations.yml: update python-version from 3.13.13 to 3.13.14 - .github/workflows/testAndPublish.yml: update defaultPythonVersion and supportedPythonVersions from 3.13.13 to 3.13.14 - projectDocs/dev/createDevEnvironment.md: update documented Python version requirement from 3.13.13 to 3.13.14 Signed-off-by: dpy013 <26911141+dpy013@users.noreply.github.com>
| # check that the language codes are correctly set for the thread | ||
| self.assertEqual( | ||
| langOnly, | ||
| WINDOWS_LOCALE_ALIASES.get(langOnly, langOnly), |
There was a problem hiding this comment.
I don't think this is the correct fix.
windows_locale is being removed in Python 3.14 as per python/cpython#144738
Instead we need to remove using windows_locale and use winKernel.LCIDToLocaleName instead. This involves changing languageHandler.windowsLCIDToLocaleName, removing _LCIDS_TO_TRANSLATED_LOCALES_OVERRIDES
def windowsLCIDToLocaleName(lcid: int) -> str | None:
"""
Gets a normalized locale from a Windows LCID.
NVDA should avoid relying on LCIDs in future, as they have been deprecated by MS:
https://docs.microsoft.com/en-us/globalization/locale/locale-names
"""
localeName = LCIDS_TO_TRANSLATED_LOCALES.get(lcid)
if not localeName:
localeName = winKernel.LCIDToLocaleName(lcid)
if localeName:
return normalizeLanguage(localeName)As per reviewer feedback on PR nvaccess#20476, locale.windows_locale is being deprecated and removed in Python 3.13 (see cpython#144738). This commit removes NVDA's dependency on it in languageHandler.windowsLCIDToLocaleName. Changes: - Remove _LCIDS_TO_TRANSLATED_LOCALES_OVERRIDES (no longer needed since we're not using locale.windows_locale) - Simplify windowsLCIDToLocaleName to check LCIDS_TO_TRANSLATED_LOCALES first, then use winKernel.LCIDToLocaleName (Windows API) - Update LCIDS_TO_TRANSLATED_LOCALES docstring to reflect its new purpose - Revert WINDOWS_LOCALE_ALIASES workaround in test_languageHandler.py (no longer needed since LCIDS_TO_TRANSLATED_LOCALES already has 1170: "ckb", which correctly maps LCID 0x0492 to "ckb") This fixes the ckb locale test failure because when Windows returns LCID 0x0492 for Central Kurdish, windowsLCIDToLocaleName now checks LCIDS_TO_TRANSLATED_LOCALES first and returns "ckb" directly, matching what the test expects. References: - Python cpython#144738: python/cpython#144738 - PR nvaccess#20476 discussion: nvaccess#20476 (comment)
fix Co-authored-by: Sean Budd <seanbudd123@gmail.com>
fix Co-authored-by: Sean Budd <seanbudd123@gmail.com>
As per reviewer feedback on PR nvaccess#20476, locale.windows_locale is being deprecated and removed in Python 3.13 (see cpython#144738). This commit removes NVDA's dependency on it in languageHandler.windowsLCIDToLocaleName. Changes: - Remove _LCIDS_TO_TRANSLATED_LOCALES_OVERRIDES (no longer needed since we're not using locale.windows_locale) - Simplify windowsLCIDToLocaleName to check LCIDS_TO_TRANSLATED_LOCALES first, then use winKernel.LCIDToLocaleName (Windows API) - Update LCIDS_TO_TRANSLATED_LOCALES docstring to reflect its new purpose - Revert WINDOWS_LOCALE_ALIASES workaround in test_languageHandler.py (no longer needed since LCIDS_TO_TRANSLATED_LOCALES already has 1170: "ckb", which correctly maps LCID 0x0492 to "ckb") This fixes the ckb locale test failure because when Windows returns LCID 0x0492 for Central Kurdish, windowsLCIDToLocaleName now checks LCIDS_TO_TRANSLATED_LOCALES first and returns "ckb" directly, matching what the test expects. References: - Python cpython#144738: python/cpython#144738 - PR nvaccess#20476 discussion: nvaccess#20476 (comment)
| # NOTE: this mapping is incomplete and out of date. | ||
| # We should stop relying on it and use Windows API calls instead. | ||
| # https://github.com/python/cpython/issues/123853 | ||
| localeName = locale.windows_locale.get(lcid) |
There was a problem hiding this comment.
make sure to remove all usages of windows_locale in NVDA currently
There was a problem hiding this comment.
Pull request overview
This PR bumps NVDA’s pinned CPython version from 3.13.13 to 3.13.14 and updates Windows locale/LCID handling to account for CPython/Windows locale mapping changes (notably around Central Kurdish). It also updates SAPI voice language detection to use NVDA’s LCID-to-locale conversion instead of CPython’s locale.windows_locale.
Changes:
- Updated Python version pins to 3.13.14 across CI/workflows, runtime builder config, developer docs, and changelog.
- Updated
windowsLCIDToLocaleNameto prefer NVDA’s override mapping (LCIDS_TO_TRANSLATED_LOCALES) before calling the Windows API. - Added a Kernel32 binding for
EnumSystemLocalesExand updated unit tests to enumerate Windows locales using the Windows API; updated SAPI4/SAPI5 voice language locale mapping.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| user_docs/en/changes.md | Documents Python bump to 3.13.14 in the changelog. |
| tests/unit/test_languageHandler.py | Enumerates Windows locales via EnumSystemLocalesEx to drive locale-related tests. |
| source/winBindings/kernel32.py | Adds ctypes bindings for LOCALE_ENUMPROCEX and EnumSystemLocalesEx. |
| source/synthDrivers/sapi5.py | Uses languageHandler.windowsLCIDToLocaleName for SAPI5 voice language mapping. |
| source/languageHandler.py | Changes LCID-to-locale resolution order to prefer NVDA overrides, then Windows API. |
| source/_synthDrivers32/sapi4.py | Uses languageHandler.windowsLCIDToLocaleName for SAPI4 voice language mapping. |
| runtime-builders/synthDriverHost32/.python-version | Updates 32-bit runtime builder Python pin to 3.13.14. |
| projectDocs/dev/createDevEnvironment.md | Updates developer documentation to Python 3.13.14. |
| .python-versions | Updates main pinned CPython build to 3.13.14. |
| .github/workflows/testAndPublish.yml | Updates default/supported Python versions to 3.13.14. |
| .github/workflows/fetch-crowdin-translations.yml | Updates setup-python version to 3.13.14. |
| .github/workflows/autofix.yml | Updates setup-python version to 3.13.14. |
| if not localeName: | ||
| return True | ||
| normalizedLocale = languageHandler.normalizeLanguage(localeName) | ||
| if normalizedLocale: | ||
| windowsLangs.add(normalizedLocale) | ||
| return True |
| language = locale.windows_locale[mode.language.LanguageID] | ||
| except KeyError: | ||
| language = None | ||
| language = languageHandler.windowsLCIDToLocaleName(mode.language.LanguageID) |
| localeName = LCIDS_TO_TRANSLATED_LOCALES.get(lcid) | ||
| if not localeName: | ||
| localeName = winKernel.LCIDToLocaleName(lcid) | ||
| if localeName: |
| language = locale.windows_locale[mode.language.LanguageID] | ||
| except KeyError: | ||
| language = None | ||
| language = languageHandler.windowsLCIDToLocaleName(mode.language.LanguageID) |
There was a problem hiding this comment.
are you sure we should be using languageHandler here and not winKernel.LCIDToLocaleName? Can you explain how you tested to ensure nothing broke here?
| language = locale.windows_locale[int(v[i].getattribute("language").split(";")[0], 16)] | ||
| except KeyError: | ||
| language = None | ||
| language = languageHandler.windowsLCIDToLocaleName( |
There was a problem hiding this comment.
are you sure we should be using languageHandler here and not winKernel.LCIDToLocaleName? Can you explain how you tested to ensure nothing broke here?
|
please fix up the formatting of the PR description |
|
@dpy013 I suspect you are using AI to assist with this PR (or perhaps relying on it entirely). Regardless, please ensure you thoroughly test your changes yourself first and address Sean's questions. Thank you. |
|
"Closing this PR for now as it needs further investigation." |
In Python 3.13.13, these entries did not exist, so
ckbwas classified as an unsupported Windows language and the locale assertion intest_NVDASupportedLanguages_LanguageIsSetCorrectlywas skipped. In Python 3.13.14,ckbis now recognized by Windows (LCID0x0492), but Windows maps it toku_IQ(language codeku) rather thanckb, causing the test assertion'ckb' != 'ku'to fail.### Description of user facing changes:
None. This is an internal Python version bump and test fix with no user-facing behavior changes.
### Description of developer facing changes:
- The pinned CPython version is now 3.13.14 across all build configurations, CI workflows, and developer documentation.
WINDOWS_LOCALE_ALIASESmapping is introduced intests/unit/test_languageHandler.pyto handle cases where Windows returns a different but related language code than the one NVDA uses. Future locale mismatches can be resolved by adding entries to this dictionary.### Description of development approach:
1. Updated Python version from 3.13.13 to 3.13.14 in:
.python-versions(root, x86_64)runtime-builders/synthDriverHost32/.python-version(x86).github/workflows/autofix.yml.github/workflows/fetch-crowdin-translations.yml.github/workflows/testAndPublish.yml(defaultPythonVersionandsupportedPythonVersions)projectDocs/dev/createDevEnvironment.mdckblocale test failure by adding aWINDOWS_LOCALE_ALIASESdictionary intests/unit/test_languageHandler.pythat mapsckb→ku, and updated the thread locale assertion to useWINDOWS_LOCALE_ALIASES.get(langOnly, langOnly)instead oflangOnly.References:
Python 3.13.14
Lib/locale.pyPython 3.13.13
Lib/locale.pyMS-LCID specification
Python 3.13.14 release notes
### Testing strategy:
- CI run on
dpy013/nvdabranchpy3.13.14: all jobs pass after the fix (Build, unit tests, Pyright type check, license check, translator comments, symbols).The
WINDOWS_LOCALE_ALIASESmapping is designed to be extensible — if similar locale mismatches surface on different Windows versions, new entries can be added without modifying test logic.### Known issues with pull request:
None.
### Code Review Checklist:
action run:
https://github.com/dpy013/nvda/actions/runs/29052432147