List populated on first use.
| 69 | |
| 70 | |
| 71 | class LazyList(list): |
| 72 | """List populated on first use.""" |
| 73 | |
| 74 | _props = [ |
| 75 | '__str__', '__repr__', '__unicode__', |
| 76 | '__hash__', '__sizeof__', '__cmp__', |
| 77 | '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', |
| 78 | 'append', 'count', 'index', 'extend', 'insert', 'pop', 'remove', |
| 79 | 'reverse', 'sort', '__add__', '__radd__', '__iadd__', '__mul__', |
| 80 | '__rmul__', '__imul__', '__contains__', '__len__', '__nonzero__', |
| 81 | '__getitem__', '__setitem__', '__delitem__', '__iter__', |
| 82 | '__reversed__', '__getslice__', '__setslice__', '__delslice__'] |
| 83 | |
| 84 | def __new__(cls, fill_iter=None): |
| 85 | |
| 86 | if fill_iter is None: |
| 87 | return list() |
| 88 | |
| 89 | # We need a new class as we will be dynamically messing with its |
| 90 | # methods. |
| 91 | class LazyList(list): |
| 92 | pass |
| 93 | |
| 94 | fill_iter = [fill_iter] |
| 95 | |
| 96 | def lazy(name): |
| 97 | def _lazy(self, *args, **kw): |
| 98 | _fill_lock.acquire() |
| 99 | try: |
| 100 | if len(fill_iter) > 0: |
| 101 | list.extend(self, fill_iter.pop()) |
| 102 | for method_name in cls._props: |
| 103 | delattr(LazyList, method_name) |
| 104 | finally: |
| 105 | _fill_lock.release() |
| 106 | return getattr(list, name)(self, *args, **kw) |
| 107 | return _lazy |
| 108 | |
| 109 | for name in cls._props: |
| 110 | setattr(LazyList, name, lazy(name)) |
| 111 | |
| 112 | new_list = LazyList() |
| 113 | return new_list |
| 114 | |
| 115 | # Not all versions of Python declare the same magic methods. |
| 116 | # Filter out properties that don't exist in this version of Python |