1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
4 # This file is part of OpenAnno.
6 # OpenAnno is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 # ###################################################
22 # This file was stolen from http://home.gna.org/meals/ at 2008-07-24
25 weaklist - list implementation that store objects with weakref
31 class _CopyDocFromParentClass(type):
33 metaclass that copy, for a given class,
34 all the docstring from their parents if there are not set
37 def __init__(cls
, name
, bases
, dict):
38 for name
, method
in dict.iteritems():
40 if not method
.__doc
__:
41 method
.__doc
__ = getattr(bases
[0], name
).__doc
__
42 except AttributeError:
47 A Weak_list can store objects but without keeping them
48 alive with references couting incrementation.
50 When objects are deleted or garbage_collected, they disapear from
53 ! WARNING: du to the *magic* deletion of item, some method here
54 are not guaranted to give the right result or even to work properly.
56 This class is NOT thread safe and NOT GC safe.
58 You can have problem with:
60 - extend can add broken weakref in the list
62 - __iter__, __str__, __repr__ and __reversed can return some None
63 - all the rich comparison method
64 - count can return wrong values or outdated
65 - index can return too high values or forget to raise exceptions
66 - __get_item__ and __set_item__ are useless
68 Be also carrfull that your work with weakref, so some usual
71 >>> weak = weaklist.WeakList(weakable_class())
77 # This copy all the list's doctstring into this class's method
78 # So even if the class look undocumented, it is ! (use pydoc)
79 __metaclass__
= _CopyDocFromParentClass
84 def __init__(self
, items
=None):
86 list.__init
__(self
, self
.__iter
_over
_weakref
(items
))
91 return '[' + ', '.join((repr(i
) for i
in self
)) + ']'
94 return 'Weak_list((' + ', '.join((repr(i
) for i
in self
)) + '))'
99 def __new_weekref(self
, item
):
100 """Create a weakref with the good callback"""
101 return weakref
.ref(item
, self
.__remove
_ref
)
103 def __iter_over_weakref(self
, iterable
):
104 """For a given iterable, return an iterable generator over all weakref"""
105 return (self
.__new
_weekref
(i
) for i
in iterable
)
107 def __remove_ref(self
, ref
):
109 When an object from the list is destroy, this
110 method is call to remove it from list
113 list.remove(self
, ref
)
118 def extend(self
, iterable
):
119 iterable
= self
.__iter
_over
_weakref
(list(iterable
))
120 list.extend(self
, iterable
)
122 def append(self
, object):
123 list.append(self
, weakref
.ref(object, self
.__remove
_ref
))
125 def remove(self
, object):
126 list.remove(self
, weakref
.ref(object))
128 def count(self
, value
):
129 return list.count(self
, weakref
.ref(value
))
131 def index(self
, value
, *args
):
132 return list.index(self
, weakref
.ref(value
), *args
)
134 def pop(self
, index
=-1):
135 return list.pop(self
,index
)()
137 def sort(self
, cmp=None, key
=None, reverse
=False):
138 sortable
= list(self
)
139 sortable
.sort(cmp,key
,reverse
)
141 self
.extend(sortable
)
143 def insert(self
, index
, object):
144 list.insert(self
, index
, self
.__new
_weekref
(object))
147 ## Emulating container types
149 def __getitem__(self
, index
):
150 return list.__getitem
__(self
, index
)()
152 def __setitem__(self
, index
, value
):
153 if isinstance(index
,slice):
154 list.__setitem
__(self
, index
, self
.__iter
_over
_weakref
(value
))
156 list.__setitem
__(self
, index
, self
.__new
_weekref
(value
))
158 return iter([i() for i
in list.__iter
__(self
)])
160 def __contains__(self
, item
):
161 return list.__contains
__(self
, weakref
.ref(item
))
163 def __getslice__(self
,i
,j
):
164 return WeakList(list(self
)[i
:j
])
166 def __setslice__(self
, i
, j
, iterable
):
167 list.__setslice
__(self
, i
, j
, self
.__iter
_over
_weakref
(iterable
))
169 def __reversed__(self
):
170 return iter([i() for i
in list.__reversed
__(self
)])
173 ## Emulating numeric types
175 def __iadd__(self
, other
):
179 def __add__(self
, other
):
180 return self
.__class
__(list(self
) + list(other
))
185 def __eq__(self
, other
):
186 if isinstance(other
,WeakList
):
188 return list.__eq
__(list(self
), other
)
190 def __ge__(self
, other
):
191 if isinstance(other
,WeakList
):
193 return list.__ge
__(list(self
), other
)
195 def __le__(self
, other
):
196 if isinstance(other
,WeakList
):
199 return list.__le
__(list(self
), other
)
201 def __gt__(self
, other
):
202 if isinstance(other
,WeakList
):
205 return list.__gt
__(list(self
), other
)
207 def __ne__(self
, other
):
208 if isinstance(other
,WeakList
):
211 return list.__ne
__(list(self
), other
)
213 def __lt__(self
, other
):
214 if isinstance(other
,WeakList
):
217 return list.__lt
__(list(self
), other
)
219 ### End of WeakList class