Lynn Rees avatar Lynn Rees committed 3de8e16 Merge

Comments (0)

Files changed (3)

 from collections import Mapping, Sequence, MutableMapping
 
 from stuf.six import items, strings, keys, values
-from stuf.utils import clsname, lazy, recursive_repr
+from stuf.utils import clsname, lazy, recursive_repr, exhaust, imap
 
 __all__ = ['corestuf', 'directstuf', 'wrapstuf', 'writestuf', 'writewrapstuf']
 
         ))
 
     @classmethod
-    def _build(cls, iterable, _map=map, _is=isinstance, _list=list):
+    def _build(cls, iterable, _map=imap, _is=isinstance, _list=exhaust):
         kind = cls._map
         # add class to handle potential nested objects of the same class
         kw = kind()
                     update(arg)
                 except (ValueError, TypeError):
                     pass
-            _list(map(_coro, iterable))
+            _list(_map(_coro, iterable))
         return kw
 
     @classmethod
                     future[key] = value
             else:
                 future[key] = value
-        list(m(_coro, _i(past)))
+        exhaust(m(_coro, _i(past)))
         return cls._postpopulate(future)
 
     @classmethod
 from collections import Mapping, Sequence, defaultdict, namedtuple
 
 from stuf.six import items, keys, values
-from stuf.utils import OrderedDict, getter, imap
+from stuf.utils import OrderedDict, getter, imap, exhaust
 from stuf.base import directstuf, wrapstuf, writewrapstuf
 
 __all__ = ('defaultstuf', 'fixedstuf', 'frozenstuf', 'orderedstuf', 'stuf')
         directstuf.__init__(self, *args, **kw)
 
     @classmethod
-    def _build(cls, default, iterable, _map=imap, _list=list):
+    def _build(cls, default, iterable, _map=imap, _list=exhaust):
         kind = cls._map
         # add class to handle potential nested objects of the same class
         kw = kind(default)
                     future[key] = value
             else:
                 future[key] = value
-        list(_map(_coro, _items(past)))
+        exhaust(_map(_coro, _items(past)))
 
     def _prepopulate(self, *args, **kw):
         kw.update(self._build(self.default_factory, args))
         return default
 
 
+def exhaust(iterable, exception=StopIteration, _next=next):
+    '''
+    call next on an iterator until it's exhausted
+
+    @param iterable: an iterable to exhaust
+    '''
+    try:
+        while True:
+            next(iterable)
+    except exception:
+        pass
+
+
 def deleter(this, key):
     '''
     delete an attribute
         return default
 
 
+def iterexcept(func, exception):
+    '''
+    call a function repeatedly until an exception is raised
+
+    Converts a call-until-exception interface to an iterator interface. Like
+    `__builtin__.iter(func, sentinel)` but uses an exception instead of a
+    sentinel to end the loop.
+    '''
+    try:
+        while True:
+            yield func()
+    except exception:
+        pass
+
+
 def lru(this, maxsize=100):
     '''
     least-recently-used cache decorator from Raymond Hettinger
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.