Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pendulum/locales/locale.py: 57%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

67 statements  

1from __future__ import annotations 

2 

3import re 

4 

5from importlib import import_module 

6from pathlib import Path 

7from typing import Any 

8from typing import ClassVar 

9from typing import Dict 

10from typing import cast 

11 

12from pendulum.utils._compat import resources 

13 

14 

15class Locale: 

16 """ 

17 Represent a specific locale. 

18 """ 

19 

20 _cache: ClassVar[dict[str, Locale]] = {} 

21 

22 def __init__(self, locale: str, data: Any) -> None: 

23 self._locale: str = locale 

24 self._data: Any = data 

25 self._key_cache: dict[str, str] = {} 

26 

27 @classmethod 

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

29 if isinstance(locale, Locale): 

30 return locale 

31 

32 locale = cls.normalize_locale(locale) 

33 if locale in cls._cache: 

34 return cls._cache[locale] 

35 

36 # Checking locale existence 

37 actual_locale = locale 

38 locale_path = cast(Path, resources.files(__package__).joinpath(actual_locale)) 

39 while not locale_path.exists(): 

40 if actual_locale == locale: 

41 raise ValueError(f"Locale [{locale}] does not exist.") 

42 

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

44 

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

46 

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

48 

49 return cls._cache[locale] 

50 

51 @classmethod 

52 def normalize_locale(cls, locale: str) -> str: 

53 m = re.match("([a-z]{2})[-_]([a-z]{2})", locale, re.I) 

54 if m: 

55 return f"{m.group(1).lower()}_{m.group(2).lower()}" 

56 else: 

57 return locale.lower() 

58 

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

60 if key in self._key_cache: 

61 return self._key_cache[key] 

62 

63 parts = key.split(".") 

64 try: 

65 result = self._data[parts[0]] 

66 for part in parts[1:]: 

67 result = result[part] 

68 except KeyError: 

69 result = default 

70 

71 self._key_cache[key] = result 

72 

73 return self._key_cache[key] 

74 

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

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

77 

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

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

80 

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

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

83 

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

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

86 

87 if not ordinal: 

88 return f"{number}" 

89 

90 return f"{number}{ordinal}" 

91 

92 def match_translation(self, key: str, value: Any) -> dict[str, str] | None: 

93 translations = self.translation(key) 

94 if value not in translations.values(): 

95 return None 

96 

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

98 

99 def __repr__(self) -> str: 

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