# HG changeset patch # User cmlenz # Date 1180607267 0 # Node ID b47c34d42eda5bdad6cdb5cfa25de6f21aca0b46 # Parent 29ef15a6fd75395bb5c651fb23b9214ec1de1eb8 Extended and documented `LazyProxy`. diff --git a/babel/util.py b/babel/util.py --- a/babel/util.py +++ b/babel/util.py @@ -16,10 +16,10 @@ 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. @@ -28,7 +28,7 @@ ``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 @@ -75,45 +75,72 @@ 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`` + 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: + + >>> greetings = [ + ... LazyProxy(greeting, 'world'), + ... LazyProxy(greeting, 'Joe'), + ... LazyProxy(greeting, 'universe'), + ... ] + >>> greetings.sort() + >>> for greeting in greetings: + ... print greeting + Hello, Joe! + Hello, universe! + Hello, world! """ - def newfunc(*args, **kwargs): - return LazyProxy(func, *args, **kwargs) - return newfunc - - -class LazyProxy(object): - """ - - >>> lazystr = LazyProxy(str, 'bar') - >>> print lazystr - bar - >>> u'foo' + lazystr - u'foobar' - """ + __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) @@ -141,29 +168,38 @@ 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 diff --git a/scripts/import_cldr.py b/scripts/import_cldr.py --- a/scripts/import_cldr.py +++ b/scripts/import_cldr.py @@ -104,6 +104,8 @@ elem = tree.find('//identity/territory') if elem is not None: territory = elem.attrib['type'] + else: + territory = '001' # world print>>sys.stderr, ' Territory: %r' % territory regions = territory_containment.get(territory, []) print>>sys.stderr, ' Regions: %r' % regions