Module speaklater
[hide private]
[frames] | no frames]

Source Code for Module speaklater

  1  # -*- coding: utf-8 -*- 
  2  r""" 
  3      speaklater 
  4      ~~~~~~~~~~ 
  5   
  6      A module that provides lazy strings for translations.  Basically you 
  7      get an object that appears to be a string but changes the value every 
  8      time the value is evaluated based on a callable you provide. 
  9   
 10      For example you can have a global `lazy_gettext` function that returns 
 11      a lazy string with the value of the current set language. 
 12   
 13      Example: 
 14   
 15      >>> from speaklater import make_lazy_string, text_type 
 16      >>> sval = u'Hello World' 
 17      >>> string = make_lazy_string(lambda: sval) 
 18   
 19      This lazy string will evaluate to the value of the `sval` variable. 
 20   
 21      >>> string 
 22      l'Hello World' 
 23      >>> text_type(string) == u'Hello World' 
 24      True 
 25      >>> string.upper() == u'HELLO WORLD' 
 26      True 
 27   
 28      If you change the value, the lazy string will change as well: 
 29   
 30      >>> sval = u'Hallo Welt' 
 31      >>> string.upper() == u'HALLO WELT' 
 32      True 
 33   
 34      This is especially handy when combined with a thread local and gettext 
 35      translations or dicts of translatable strings: 
 36   
 37      >>> from speaklater import make_lazy_gettext 
 38      >>> from threading import local 
 39      >>> l = local() 
 40      >>> l.translations = {u'Yes': 'Ja'} 
 41      >>> lazy_gettext = make_lazy_gettext(lambda: l.translations.get) 
 42      >>> yes = lazy_gettext(u'Yes') 
 43      >>> print(yes) 
 44      Ja 
 45      >>> l.translations[u'Yes'] = u'Si' 
 46      >>> print(yes) 
 47      Si 
 48   
 49      Lazy strings are no real strings so if you pass this sort of string to 
 50      a function that performs an instance check, it will fail.  In that case 
 51      you have to explicitly convert it with `unicode` and/or `string` depending 
 52      on what string type the lazy string encapsulates. 
 53   
 54      To check if a string is lazy, you can use the `is_lazy_string` function: 
 55   
 56      >>> from speaklater import is_lazy_string 
 57      >>> is_lazy_string(u'yes') 
 58      False 
 59      >>> is_lazy_string(yes) 
 60      True 
 61   
 62      New in version 1.4: python >= 3.3 (and also 2.6 and 2.7) support, 
 63                          repr(lazystring) is l"foo" on py2 and py3 - no "u" on py2! 
 64   
 65      New in version 1.2: It's now also possible to pass keyword arguments to 
 66      the callback used with `make_lazy_string`. 
 67   
 68      :copyright: (c) 2010 by Armin Ronacher. 
 69      :license: BSD, see LICENSE for more details. 
 70  """ 
 71   
 72  import sys 
 73   
 74  PY2 = sys.version_info[0] == 2 
 75  _identity = lambda x: x 
 76   
 77  if not PY2: 
 78      text_type = str 
 79      implements_to_string = _identity 
 80      implements_bool = _identity 
 81  else: 
 82      text_type = unicode 
83 84 - def implements_to_string(cls):
85 cls.__unicode__ = cls.__str__ 86 cls.__str__ = lambda x: x.__unicode__().encode('utf-8') 87 return cls
88
89 - def implements_bool(cls):
90 cls.__nonzero__ = cls.__bool__ 91 del cls.__bool__ 92 return cls
93
94 95 -def is_lazy_string(obj):
96 """Checks if the given object is a lazy string.""" 97 return isinstance(obj, _LazyString)
98
99 100 -def make_lazy_string(__func, *args, **kwargs):
101 """Creates a lazy string by invoking func with args.""" 102 return _LazyString(__func, args, kwargs)
103
104 105 -def make_lazy_gettext(lookup_func):
106 """Creates a lazy gettext function dispatches to a gettext 107 function as returned by `lookup_func`. 108 109 Example: 110 111 >>> translations = {u'Yes': u'Ja'} 112 >>> lazy_gettext = make_lazy_gettext(lambda: translations.get) 113 >>> x = lazy_gettext(u'Yes') 114 >>> x 115 l'Ja' 116 >>> translations[u'Yes'] = u'Si' 117 >>> x 118 l'Si' 119 """ 120 def lazy_gettext(string): 121 if is_lazy_string(string): 122 return string 123 return make_lazy_string(lookup_func(), string)
124 return lazy_gettext 125
126 127 @implements_bool 128 @implements_to_string 129 -class _LazyString(object):
130 """Class for strings created by a function call. 131 132 The proxy implementation attempts to be as complete as possible, so that 133 the lazy objects should mostly work as expected, for example for sorting. 134 """ 135 __slots__ = ('_func', '_args', '_kwargs') 136
137 - def __init__(self, func, args, kwargs):
138 self._func = func 139 self._args = args 140 self._kwargs = kwargs
141 142 value = property(lambda x: x._func(*x._args, **x._kwargs)) 143
144 - def __contains__(self, key):
145 return key in self.value
146
147 - def __bool__(self):
148 return bool(self.value)
149
150 - def __dir__(self):
151 return dir(text_type)
152
153 - def __iter__(self):
154 return iter(self.value)
155
156 - def __len__(self):
157 return len(self.value)
158
159 - def __str__(self):
160 return text_type(self.value)
161
162 - def __add__(self, other):
163 return self.value + other
164
165 - def __radd__(self, other):
166 return other + self.value
167
168 - def __mod__(self, other):
169 return self.value % other
170
171 - def __rmod__(self, other):
172 return other % self.value
173
174 - def __mul__(self, other):
175 return self.value * other
176
177 - def __rmul__(self, other):
178 return other * self.value
179
180 - def __lt__(self, other):
181 return self.value < other
182
183 - def __le__(self, other):
184 return self.value <= other
185
186 - def __eq__(self, other):
187 return self.value == other
188
189 - def __ne__(self, other):
190 return self.value != other
191
192 - def __gt__(self, other):
193 return self.value > other
194
195 - def __ge__(self, other):
196 return self.value >= other
197
198 - def __getattr__(self, name):
199 if name == '__members__': 200 return self.__dir__() 201 return getattr(self.value, name)
202
203 - def __getstate__(self):
204 return self._func, self._args, self._kwargs
205
206 - def __setstate__(self, tup):
207 self._func, self._args, self._kwargs = tup
208
209 - def __getitem__(self, key):
210 return self.value[key]
211
212 - def __copy__(self):
213 return self
214
215 - def __repr__(self):
216 try: 217 r = repr(self.value) 218 if PY2 and r.startswith('u'): 219 r = r[1:] # make it look same as on py3 220 return 'l' + r 221 except Exception: 222 return '<%s broken>' % self.__class__.__name__
223 224 225 if __name__ == '__main__': 226 import doctest 227 doctest.testmod() 228