changeset 13:368650dc3423 trunk

Extended and documented `LazyProxy`.
author cmlenz
date Thu, 31 May 2007 10:27:47 +0000
parents e6ba3e878b10
children fc8b5515af7c
files babel/util.py scripts/import_cldr.py
diffstat 2 files changed, 83 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
Copyright (C) 2012-2017 Edgewall Software