summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzu-ping Chung <uranusjr@gmail.com>2023-01-03 07:44:22 +0800
committerTzu-ping Chung <uranusjr@gmail.com>2023-01-03 08:13:13 +0800
commit8fe656305049b0bddc372dc2e77770af52f223c4 (patch)
tree7e0df326220dcb2a0423a0ba7652847f6a5eb6e5
parent6750d847a7e3220af700a07f2f96daa4939776c4 (diff)
downloadpip-8fe656305049b0bddc372dc2e77770af52f223c4.tar.gz
Fall back to non-localized message on Windows
Windows does not implement LC_MESSAGES, and since PEP 668 is mainly designed for Linux distributions, we simply take the easier way out until someone wants an equivalent on Windows.
-rw-r--r--src/pip/_internal/exceptions.py12
-rw-r--r--tests/unit/test_exceptions.py62
2 files changed, 71 insertions, 3 deletions
diff --git a/src/pip/_internal/exceptions.py b/src/pip/_internal/exceptions.py
index 5e0559c9a..d28713ff7 100644
--- a/src/pip/_internal/exceptions.py
+++ b/src/pip/_internal/exceptions.py
@@ -703,7 +703,17 @@ class ExternallyManagedEnvironment(DiagnosticPipError):
@staticmethod
def _iter_externally_managed_error_keys() -> Iterator[str]:
- lang, _ = locale.getlocale(locale.LC_MESSAGES)
+ # LC_MESSAGES is in POSIX, but not the C standard. The most common
+ # platform that does not implement this category is Windows, where
+ # using other categories for console message localization is equally
+ # unreliable, so we fall back to the locale-less vendor message. This
+ # can always be re-evaluated when a vendor proposes a new alternative.
+ try:
+ category = locale.LC_MESSAGES
+ except AttributeError:
+ lang: Optional[str] = None
+ else:
+ lang, _ = locale.getlocale(category)
if lang is not None:
yield f"Error-{lang}"
for sep in ("-", "_"):
diff --git a/tests/unit/test_exceptions.py b/tests/unit/test_exceptions.py
index 17cccd591..6510b569e 100644
--- a/tests/unit/test_exceptions.py
+++ b/tests/unit/test_exceptions.py
@@ -492,9 +492,9 @@ class TestExternallyManagedEnvironment:
orig_getlocal = locale.getlocale
def fake_getlocale(category: int) -> Tuple[Optional[str], Optional[str]]:
- """Fake getlocale() that always report zh_Hant."""
+ """Fake getlocale() that always reports zh_Hant for LC_MESSASGES."""
result = orig_getlocal(category)
- if category == locale.LC_MESSAGES:
+ if category == getattr(locale, "LC_MESSAGES", None):
return "zh_Hant", result[1]
return result
@@ -541,6 +541,10 @@ class TestExternallyManagedEnvironment:
assert not caplog.records
assert str(exc.context) == self.default_text
+ @pytest.mark.skipif(
+ sys.platform == "win32",
+ reason="Localization disabled on Windows",
+ )
@pytest.mark.parametrize(
"config, expected",
[
@@ -594,3 +598,57 @@ class TestExternallyManagedEnvironment:
exc = ExternallyManagedEnvironment.from_config(marker)
assert not caplog.records
assert str(exc.context) == expected
+
+ @pytest.mark.skipif(
+ sys.platform != "win32",
+ reason="Non-Windows should implement localization",
+ )
+ @pytest.mark.parametrize(
+ "config",
+ [
+ pytest.param(
+ """\
+ [externally-managed]
+ Error = 最後
+ Error-en = English
+ Error-zh = 中文
+ Error-zh_Hant = 繁體
+ Error-zh_Hans = 简体
+ """,
+ id="full",
+ ),
+ pytest.param(
+ """\
+ [externally-managed]
+ Error = 最後
+ Error-en = English
+ Error-zh = 中文
+ Error-zh_Hans = 简体
+ """,
+ id="no-variant",
+ ),
+ pytest.param(
+ """\
+ [externally-managed]
+ Error = 最後
+ Error-en = English
+ """,
+ id="fallback",
+ ),
+ ],
+ )
+ def test_config_canonical_no_localization(
+ self,
+ caplog: pytest.LogCaptureFixture,
+ marker: pathlib.Path,
+ config: str,
+ ) -> None:
+ marker.write_text(
+ textwrap.dedent(config),
+ encoding="utf8",
+ )
+
+ with caplog.at_level(logging.WARNING, "pip._internal.exceptions"):
+ exc = ExternallyManagedEnvironment.from_config(marker)
+ assert not caplog.records
+ assert str(exc.context) == "最後"