From ff870da2b772c338922731fc67f25bc5e807e217 Mon Sep 17 00:00:00 2001 From: Daniel Gillet Date: Sun, 22 Sep 2024 16:52:03 +0200 Subject: [PATCH] Fix i18n _get_default_locale_path Fixes #105 Use importlib.resources available since Python 3.9 to find the location of the locale folder containing the translations. --- src/humanize/i18n.py | 21 ++++++++++++--------- tests/test_i18n.py | 22 +++++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/humanize/i18n.py b/src/humanize/i18n.py index 55f809f..09757d9 100644 --- a/src/humanize/i18n.py +++ b/src/humanize/i18n.py @@ -3,7 +3,9 @@ from __future__ import annotations import gettext as gettext_module -import os.path +import importlib.resources +import os +import pathlib from threading import local __all__ = ["activate", "deactivate", "decimal_separator", "thousands_separator"] @@ -32,14 +34,13 @@ } -def _get_default_locale_path() -> str | None: - try: - if __file__ is None: - return None - return os.path.join(os.path.dirname(__file__), "locale") - except NameError: +def _get_default_locale_path() -> pathlib.Path | None: + if __package__ == "": return None + with importlib.resources.as_file(importlib.resources.files(__package__)) as pkg: + return pkg / "locale" + def get_translation() -> gettext_module.NullTranslations: try: @@ -48,14 +49,16 @@ def get_translation() -> gettext_module.NullTranslations: return _TRANSLATIONS[None] -def activate(locale: str, path: str | None = None) -> gettext_module.NullTranslations: +def activate( + locale: str, path: str | os.PathLike[str] | None = None +) -> gettext_module.NullTranslations: """Activate internationalisation. Set `locale` as current locale. Search for locale in directory `path`. Args: locale (str): Language name, e.g. `en_GB`. - path (str): Path to search for locales. + path (str | pathlib.Path): Path to search for locales. Returns: dict: Translations. diff --git a/tests/test_i18n.py b/tests/test_i18n.py index 004b3f5..fdc18b5 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -156,20 +156,20 @@ def test_ordinal_genders( humanize.i18n.deactivate() -def test_default_locale_path_defined__file__() -> None: +def test_default_locale_path_defined__package__() -> None: i18n = importlib.import_module("humanize.i18n") assert i18n._get_default_locale_path() is not None -def test_default_locale_path_null__file__() -> None: +def test_default_locale_path_null__package__(monkeypatch: pytest.MonkeyPatch) -> None: i18n = importlib.import_module("humanize.i18n") - i18n.__file__ = None + monkeypatch.setattr(i18n, "__package__", "") assert i18n._get_default_locale_path() is None -def test_default_locale_path_undefined__file__() -> None: +def test_default_locale_path_undefined__file__(monkeypatch: pytest.MonkeyPatch) -> None: i18n = importlib.import_module("humanize.i18n") - del i18n.__file__ + monkeypatch.delattr(i18n, "__package__") assert i18n._get_default_locale_path() is None @@ -179,17 +179,21 @@ class TestActivate: " 'locale' folder. You need to pass the path explicitly." ) - def test_default_locale_path_null__file__(self) -> None: + def test_default_locale_path_null__package__( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: i18n = importlib.import_module("humanize.i18n") - i18n.__file__ = None + monkeypatch.setattr(i18n, "__package__", "") with pytest.raises(Exception) as excinfo: i18n.activate("ru_RU") assert str(excinfo.value) == self.expected_msg - def test_default_locale_path_undefined__file__(self) -> None: + def test_default_locale_path_undefined__file__( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: i18n = importlib.import_module("humanize.i18n") - del i18n.__file__ + monkeypatch.delattr(i18n, "__package__") with pytest.raises(Exception) as excinfo: i18n.activate("ru_RU")