You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible/test/lib/ansible_test/_internal/locale_util.py

63 lines
2.1 KiB
Python

"""Initialize locale settings. This must be imported very early in ansible-test startup."""
from __future__ import annotations
import locale
import sys
import typing as t
STANDARD_LOCALE = 'en_US.UTF-8'
"""
The standard locale used by ansible-test and its subprocesses and delegated instances.
"""
FALLBACK_LOCALE = 'C.UTF-8'
"""
The fallback locale to use when the standard locale is not available.
This was added in ansible-core 2.14 to allow testing in environments without the standard locale.
It was not needed in previous ansible-core releases since they do not verify the locale during startup.
"""
class LocaleError(SystemExit):
"""Exception to raise when locale related errors occur."""
def __init__(self, message: str) -> None:
super().__init__(f'ERROR: {message}')
def configure_locale() -> tuple[str, t.Optional[str]]:
"""Configure the locale, returning the selected locale and an optional warning."""
if (fs_encoding := sys.getfilesystemencoding()).lower() != 'utf-8':
raise LocaleError(f'ansible-test requires the filesystem encoding to be UTF-8, but "{fs_encoding}" was detected.')
candidate_locales = STANDARD_LOCALE, FALLBACK_LOCALE
errors: dict[str, str] = {}
warning: t.Optional[str] = None
configured_locale: t.Optional[str] = None
for candidate_locale in candidate_locales:
try:
locale.setlocale(locale.LC_ALL, candidate_locale)
locale.getlocale()
except (locale.Error, ValueError) as ex:
errors[candidate_locale] = str(ex)
else:
configured_locale = candidate_locale
break
if not configured_locale:
raise LocaleError('ansible-test could not initialize a supported locale:\n' +
'\n'.join(f'{key}: {value}' for key, value in errors.items()))
if configured_locale != STANDARD_LOCALE:
warning = (f'Using locale "{configured_locale}" instead of "{STANDARD_LOCALE}". '
'Tests which depend on the locale may behave unexpectedly.')
return configured_locale, warning
CONFIGURED_LOCALE, LOCALE_WARNING = configure_locale()