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

1from __future__ import annotations 

2 

3from importlib import import_module 

4from pathlib import Path 

5 

6import re 

7from typing import Any, cast 

8from typing import Dict 

9 

10from pendulum.utils._compat import resources 

11 

12 

13class Locale: 

14 """ 

15 Represent a specific locale. 

16 """ 

17 

18 _cache: dict[str, Locale] = {} 

19 

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] = {} 

24 

25 @classmethod 

26 def load(cls, locale: str | Locale) -> Locale: 

27 if isinstance(locale, Locale): 

28 return locale 

29 

30 locale = cls.normalize_locale(locale) 

31 if locale in cls._cache: 

32 return cls._cache[locale] 

33 

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.") 

40 

41 actual_locale = actual_locale.split("_")[0] 

42 

43 m = import_module(f"pendulum.locales.{actual_locale}.locale") 

44 

45 cls._cache[locale] = cls(locale, m.locale) 

46 

47 return cls._cache[locale] 

48 

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() 

56 

57 def get(self, key: str, default: Any | None = None) -> Any: 

58 if key in self._key_cache: 

59 return self._key_cache[key] 

60 

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 

68 

69 self._key_cache[key] = result 

70 

71 return self._key_cache[key] 

72 

73 def translation(self, key: str) -> Any: 

74 return self.get(f"translations.{key}") 

75 

76 def plural(self, number: int) -> str: 

77 return cast(str, self._data["plural"](number)) 

78 

79 def ordinal(self, number: int) -> str: 

80 return cast(str, self._data["ordinal"](number)) 

81 

82 def ordinalize(self, number: int) -> str: 

83 ordinal = self.get(f"custom.ordinal.{self.ordinal(number)}") 

84 

85 if not ordinal: 

86 return f"{number}" 

87 

88 return f"{number}{ordinal}" 

89 

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 

94 

95 return cast(Dict[str, str], {v: k for k, v in translations.items()}[value]) 

96 

97 def __repr__(self) -> str: 

98 return f"{self.__class__.__name__}('{self._locale}')"