1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
"""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()
|