summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Stepanov <penguinolog@users.noreply.github.com>2023-04-03 12:04:37 +0200
committerGitHub <noreply@github.com>2023-04-03 12:04:37 +0200
commit2d27ffc2bebc6436fc38ee3f1b3828635dc976a3 (patch)
treef8a040f1275a29732df3b32511fa39f646e41cb1
parente9080d282869392835ee579af18965aa4c633526 (diff)
downloadurwid-2d27ffc2bebc6436fc38ee3f1b3828635dc976a3.tar.gz
Use `locale.getpreferredencoding(False)` if possible (most systems) Fix #436 Fix #479 (#528)
* Handle impossibility to set locale in tests (docker container scenario) * `detect_encoding` start from non-destructive behavior (do not change locale) and restore exact locale in destructive Co-authored-by: Aleksei Stepanov <alekseis@nvidia.com>
-rw-r--r--urwid/tests/test_util.py25
-rw-r--r--urwid/util.py27
2 files changed, 39 insertions, 13 deletions
diff --git a/urwid/tests/test_util.py b/urwid/tests/test_util.py
index abe7aa5..eeae2f9 100644
--- a/urwid/tests/test_util.py
+++ b/urwid/tests/test_util.py
@@ -193,6 +193,7 @@ class RleTest(unittest.TestCase):
self.assertListEqual(rle3, [('A', 10), ('B', 20)])
self.assertListEqual(rle4, [('A', 10), ('B', 15), ('K', 1)])
+
class PortabilityTest(unittest.TestCase):
def test_locale(self):
initial = locale.getlocale()
@@ -201,8 +202,28 @@ class PortabilityTest(unittest.TestCase):
util.detect_encoding()
self.assertEqual(locale.getlocale(), (None, None))
- locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))
+ try:
+ locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))
+ except locale.Error as exc:
+ if "unsupported locale setting" not in str(exc):
+ raise
+
+ print(
+ f"Locale change impossible, probably locale not supported by system (libc ignores this error).\n"
+ f"{exc}"
+ )
+ return
+
util.detect_encoding()
self.assertEqual(locale.getlocale(), ('en_US', 'UTF-8'))
- locale.setlocale(locale.LC_ALL, initial)
+ try:
+ locale.setlocale(locale.LC_ALL, initial)
+ except locale.Error as exc:
+ if "unsupported locale setting" not in str(exc):
+ raise
+
+ print(
+ f"Locale restore impossible, probably locale not supported by system (libc ignores this error).\n"
+ f"{exc}"
+ )
diff --git a/urwid/util.py b/urwid/util.py
index 3ac4657..9def762 100644
--- a/urwid/util.py
+++ b/urwid/util.py
@@ -37,28 +37,33 @@ move_prev_char = str_util.move_prev_char
within_double_byte = str_util.within_double_byte
-def detect_encoding():
+def detect_encoding() -> str:
# Try to determine if using a supported double-byte encoding
import locale
- initial = locale.getlocale()
+
+ no_set_locale = locale.getpreferredencoding(False)
+
+ if no_set_locale != "ascii":
+ # ascii is fallback locale in case of detect failed
+
+ return no_set_locale
+
+ # Use actual `getpreferredencoding` with public API only
+ old_loc = locale.setlocale(locale.LC_CTYPE) # == getlocale, but not mangle data
try:
try:
- locale.setlocale(locale.LC_ALL, "")
+ locale.setlocale(locale.LC_CTYPE, "")
except locale.Error:
pass
- return locale.getlocale()[1] or ""
- except ValueError as e:
- # with invalid LANG value python will throw ValueError
- if e.args and e.args[0].startswith("unknown locale"):
- return ""
- else:
- raise
+ # internally call private `_get_locale_encoding`
+ return locale.getpreferredencoding(False)
finally:
try:
- locale.setlocale(locale.LC_ALL, initial)
+ locale.setlocale(locale.LC_CTYPE, old_loc)
except locale.Error:
pass
+
if 'detected_encoding' not in locals():
detected_encoding = detect_encoding()
else: