import os
import re
-__all__ = ['default_locale', 'extended_glob', 'lazy']
+__all__ = ['default_locale', 'extended_glob', 'LazyProxy']
__docformat__ = 'restructuredtext en'
-def default_locale(kind):
+def default_locale(kind=None):
"""Returns the default locale for a given category, based on environment
variables.
``LANG``)
:rtype: `str`
"""
- for name in (kind, 'LC_ALL', 'LANG'):
+ for name in filter(None, (kind, 'LC_ALL', 'LANG')):
locale = os.getenv(name)
if locale is not None:
return locale
if regex.match(filepath):
yield filepath
-def lazy(func):
- """Return a new function that lazily evaluates another function.
+class LazyProxy(object):
+ """Class for proxy objects that delegate to a specified function to evaluate
+ the actual object.
- >>> lazystr = lazy(str)
- >>> ls = lazystr('foo')
- >>> print ls
- foo
+ >>> def greeting(name='world'):
+ ... return 'Hello, %s!' % name
+ >>> lazy_greeting = LazyProxy(greeting, name='Joe')
+ >>> print lazy_greeting
+ Hello, Joe!
+ >>> u' ' + lazy_greeting
+ u' Hello, Joe!'
+ >>> u'(%s)' % lazy_greeting
+ u'(Hello, Joe!)'
- :param func: the function to wrap
- :return: a lazily-evaluated version of the function
- :rtype: ``function``
- """
- def newfunc(*args, **kwargs):
- return LazyProxy(func, *args, **kwargs)
- return newfunc
-
-
-class LazyProxy(object):
- """
+ This can be used, for example, to implement lazy translation functions that
+ delay the actual translation until the string is actually used. The
+ rationale for such behavior is that the locale of the user may not always
+ be available. In web applications, you only know the locale when processing
+ a request.
+
+ The proxy implementation attempts to be as complete as possible, so that
+ the lazy objects should mostly work as expected, for example for sorting:
- >>> lazystr = LazyProxy(str, 'bar')
- >>> print lazystr
- bar
- >>> u'foo' + lazystr
- u'foobar'
+ >>> greetings = [
+ ... LazyProxy(greeting, 'world'),
+ ... LazyProxy(greeting, 'Joe'),
+ ... LazyProxy(greeting, 'universe'),
+ ... ]
+ >>> greetings.sort()
+ >>> for greeting in greetings:
+ ... print greeting
+ Hello, Joe!
+ Hello, universe!
+ Hello, world!
"""
+ __slots__ = ['_func', '_args', '_kwargs', '_value']
def __init__(self, func, *args, **kwargs):
- self.func = func
- self.args = args
- self.kwargs = kwargs
- self._value = None
+ # Avoid triggering our own __setattr__ implementation
+ object.__setattr__(self, '_func', func)
+ object.__setattr__(self, '_args', args)
+ object.__setattr__(self, '_kwargs', kwargs)
+ object.__setattr__(self, '_value', None)
def value(self):
if self._value is None:
- self._value = self.func(*self.args, **self.kwargs)
+ value = self._func(*self._args, **self._kwargs)
+ object.__setattr__(self, '_value', value)
return self._value
value = property(value)
+ def __contains__(self, key):
+ return key in self.value
+
+ def __nonzero__(self):
+ return bool(self.value)
+
+ def __dir__(self):
+ return dir(self.value)
+
+ def __iter__(self):
+ return iter(self.value)
+
+ def __len__(self):
+ return len(self.value)
+
def __str__(self):
return str(self.value)
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)
- def __cmp__(self, other):
- return cmp(self.value, other)
+ def __lt__(self, other):
+ return self.value < other
- def __rcmp__(self, other):
- return other + self.value
+ def __le__(self, other):
+ return self.value <= other
def __eq__(self, other):
return self.value == other
-# def __delattr__(self, name):
-# delattr(self.value, name)
-#
-# def __getattr__(self, name):
-# return getattr(self.value, name)
-#
-# def __setattr__(self, name, value):
-# setattr(self.value, name, value)
+ def __ne__(self, other):
+ return self.value != other
+
+ def __gt__(self, other):
+ return self.value > other
+
+ def __ge__(self, other):
+ return self.value >= other
+
+ def __delattr__(self, name):
+ delattr(self.value, name)
+
+ def __getattr__(self, name):
+ return getattr(self.value, name)
+
+ def __setattr__(self, key, value):
+ setattr(self.value, name, value)
def __delitem__(self, key):
- del self.value[name]
+ del self.value[key]
def __getitem__(self, key):
- return self.value[name]
+ return self.value[key]
def __setitem__(self, key, value):
self.value[name] = value