diff --git a/src/humanize/i18n.py b/src/humanize/i18n.py index 55f809f..3eb4097 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,14 @@ } -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: + package = __spec__ and __spec__.parent + if not 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 +50,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..f3721c9 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__spec__() -> 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_none__spec__(monkeypatch: pytest.MonkeyPatch) -> None: i18n = importlib.import_module("humanize.i18n") - i18n.__file__ = None + monkeypatch.setattr(i18n, "__spec__", None) 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, "__spec__") 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__spec__( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: i18n = importlib.import_module("humanize.i18n") - i18n.__file__ = None + monkeypatch.setattr(i18n, "__spec__", None) 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__spec__( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: i18n = importlib.import_module("humanize.i18n") - del i18n.__file__ + monkeypatch.delattr(i18n, "__spec__") with pytest.raises(Exception) as excinfo: i18n.activate("ru_RU")