Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy_utils/i18n.py: 28%

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

74 statements  

1import sqlalchemy as sa 

2from sqlalchemy.ext.compiler import compiles 

3from sqlalchemy.ext.hybrid import hybrid_property 

4from sqlalchemy.sql.expression import ColumnElement 

5 

6from .exceptions import ImproperlyConfigured 

7 

8try: 

9 import babel 

10 import babel.dates 

11except ImportError: 

12 babel = None 

13 

14 

15def get_locale(): 

16 try: 

17 return babel.Locale('en') 

18 except AttributeError: 

19 # As babel is optional, we may raise an AttributeError accessing it 

20 raise ImproperlyConfigured( 

21 'Could not load get_locale function using Babel. Either ' 

22 'install Babel or make a similar function and override it ' 

23 'in this module.' 

24 ) 

25 

26 

27def cast_locale(obj, locale, attr): 

28 """ 

29 Cast given locale to string. Supports also callbacks that return locales. 

30 

31 :param obj: 

32 Object or class to use as a possible parameter to locale callable 

33 :param locale: 

34 Locale object or string or callable that returns a locale. 

35 """ 

36 if callable(locale): 

37 try: 

38 locale = locale(obj, attr.key) 

39 except TypeError: 

40 try: 

41 locale = locale(obj) 

42 except TypeError: 

43 locale = locale() 

44 if isinstance(locale, babel.Locale): 

45 return str(locale) 

46 return locale 

47 

48 

49class cast_locale_expr(ColumnElement): 

50 inherit_cache = False 

51 

52 def __init__(self, cls, locale, attr): 

53 self.cls = cls 

54 self.locale = locale 

55 self.attr = attr 

56 

57 

58@compiles(cast_locale_expr) 

59def compile_cast_locale_expr(element, compiler, **kw): 

60 locale = cast_locale(element.cls, element.locale, element.attr) 

61 if isinstance(locale, str): 

62 return f"'{locale}'" 

63 return compiler.process(locale) 

64 

65 

66class TranslationHybrid: 

67 def __init__(self, current_locale, default_locale, default_value=None): 

68 if babel is None: 

69 raise ImproperlyConfigured( 

70 'You need to install babel in order to use TranslationHybrid.' 

71 ) 

72 self.current_locale = current_locale 

73 self.default_locale = default_locale 

74 self.default_value = default_value 

75 

76 def getter_factory(self, attr): 

77 """ 

78 Return a hybrid_property getter function for given attribute. The 

79 returned getter first checks if object has translation for current 

80 locale. If not it tries to get translation for default locale. If there 

81 is no translation found for default locale it returns None. 

82 """ 

83 

84 def getter(obj): 

85 current_locale = cast_locale(obj, self.current_locale, attr) 

86 try: 

87 return getattr(obj, attr.key)[current_locale] 

88 except (TypeError, KeyError): 

89 default_locale = cast_locale(obj, self.default_locale, attr) 

90 try: 

91 return getattr(obj, attr.key)[default_locale] 

92 except (TypeError, KeyError): 

93 return self.default_value 

94 

95 return getter 

96 

97 def setter_factory(self, attr): 

98 def setter(obj, value): 

99 if getattr(obj, attr.key) is None: 

100 setattr(obj, attr.key, {}) 

101 locale = cast_locale(obj, self.current_locale, attr) 

102 getattr(obj, attr.key)[locale] = value 

103 

104 return setter 

105 

106 def expr_factory(self, attr): 

107 def expr(cls): 

108 cls_attr = getattr(cls, attr.key) 

109 current_locale = cast_locale_expr(cls, self.current_locale, attr) 

110 default_locale = cast_locale_expr(cls, self.default_locale, attr) 

111 return sa.func.coalesce(cls_attr[current_locale], cls_attr[default_locale]) 

112 

113 return expr 

114 

115 def __call__(self, attr): 

116 return hybrid_property( 

117 fget=self.getter_factory(attr), 

118 fset=self.setter_factory(attr), 

119 expr=self.expr_factory(attr), 

120 )