Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pendulum/locales/locale.py: 55%
65 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:11 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:11 +0000
1from __future__ import annotations
3from importlib import import_module
4from pathlib import Path
6import re
7from typing import Any, cast
8from typing import Dict
10from pendulum.utils._compat import resources
13class Locale:
14 """
15 Represent a specific locale.
16 """
18 _cache: dict[str, Locale] = {}
20 def __init__(self, locale: str, data: Any) -> None:
21 self._locale: str = locale
22 self._data: Any = data
23 self._key_cache: dict[str, str] = {}
25 @classmethod
26 def load(cls, locale: str | Locale) -> Locale:
27 if isinstance(locale, Locale):
28 return locale
30 locale = cls.normalize_locale(locale)
31 if locale in cls._cache:
32 return cls._cache[locale]
34 # Checking locale existence
35 actual_locale = locale
36 locale_path = cast(Path, resources.files(__package__).joinpath(actual_locale))
37 while not locale_path.exists():
38 if actual_locale == locale:
39 raise ValueError(f"Locale [{locale}] does not exist.")
41 actual_locale = actual_locale.split("_")[0]
43 m = import_module(f"pendulum.locales.{actual_locale}.locale")
45 cls._cache[locale] = cls(locale, m.locale)
47 return cls._cache[locale]
49 @classmethod
50 def normalize_locale(cls, locale: str) -> str:
51 m = re.match("([a-z]{2})[-_]([a-z]{2})", locale, re.I)
52 if m:
53 return f"{m.group(1).lower()}_{m.group(2).lower()}"
54 else:
55 return locale.lower()
57 def get(self, key: str, default: Any | None = None) -> Any:
58 if key in self._key_cache:
59 return self._key_cache[key]
61 parts = key.split(".")
62 try:
63 result = self._data[parts[0]]
64 for part in parts[1:]:
65 result = result[part]
66 except KeyError:
67 result = default
69 self._key_cache[key] = result
71 return self._key_cache[key]
73 def translation(self, key: str) -> Any:
74 return self.get(f"translations.{key}")
76 def plural(self, number: int) -> str:
77 return cast(str, self._data["plural"](number))
79 def ordinal(self, number: int) -> str:
80 return cast(str, self._data["ordinal"](number))
82 def ordinalize(self, number: int) -> str:
83 ordinal = self.get(f"custom.ordinal.{self.ordinal(number)}")
85 if not ordinal:
86 return f"{number}"
88 return f"{number}{ordinal}"
90 def match_translation(self, key: str, value: Any) -> dict[str, str] | None:
91 translations = self.translation(key)
92 if value not in translations.values():
93 return None
95 return cast(Dict[str, str], {v: k for k, v in translations.items()}[value])
97 def __repr__(self) -> str:
98 return f"{self.__class__.__name__}('{self._locale}')"