On Jul 15, 2005, at 8:06 AM, Johan Carlsson wrote:
Hi all,
I want to have a list of ordered sub objects (potentially if
different types) for an object.
...
Johan, something in our 'to be open sourced' bag that I can make
available as a preview (i.e., ZPL, but a static checkout rather than
access to the repo yet) *might* be what you want. I can't quite tell
from what you described.
We have an odd but surprisingly useful bird called 'listcontainer'.
It's a bit parallel to the zope.app.container framework. I attached
the README doctest for you to read. If it looks like it would be a
help, I'll make it available.
It has no UI: it's just guts.
Gary
-
listcontainer
-
The listcontainer package is a Zope-3-aware pseudo-list that generates events
upon changes and maintains linked list information on its members.
>>> from zc import listcontainer
>>> list1 = listcontainer.ListContainer()
>>> list1
[]
The listcontainer package is similar in many ways to the zope.app.container
package:
- it resembles a standard Python API (listcontainers resemble lists, and
zope.app.container objects resemble dicts);
>>> contained1 = listcontainer.Contained()
>>> contained1.id = 1 # for sorting below; id is not a requirement
>>> list1.append(contained1)
>>> contained2 = listcontainer.Contained()
>>> contained2.id = 2
>>> contained3 = listcontainer.Contained()
>>> contained3.id = 3
>>> list1.extend([contained3, contained2])
>>> list1 == [contained1, contained3, contained2]
True
>>> len(list1)
3
>>> del list1[2]
>>> list1[1] = contained2
>>> list1[3:20] = [contained3]
>>> list1 == [contained1, contained2, contained3]
True
- contained objects must provide interfaces.IContained, and know about their
parent and their place within it, a la linked lists;
>>> list1.append(2)
Traceback (most recent call last):
...
AssertionError
>>> contained1.super is contained2.super is contained1.super is list1
True
>>> contained1.previous is None
True
>>> contained1.next is contained2
True
>>> contained2.previous is contained1
True
>>> contained2.next is contained3
True
>>> contained3.previous is contained2
True
>>> contained3.next is None
True
>>> list1.pop() is contained3
True
>>> contained3.super is None and contained3.previous is None
True
>>> contained3.next is None and contained2.next is None
True
>>> del list1[0]
>>> contained1.super is None and contained1.previous is None
True
>>> contained1.next is None and contained2.previous is None
True
>>> del list1[0:1]
>>> contained2.super is None
True
>>> list1.extend([contained2, contained1])
>>> list1.insert(0, contained3)
>>> [contained3, contained2, contained1] == list1
True
>>> contained3.super is contained2.super is contained1.super is list1
True
>>> contained3.previous is None
True
>>> contained3.next is contained2
True
>>> contained2.previous is contained3
True
>>> contained2.next is contained1
True
>>> contained1.previous is contained2
True
>>> contained1.next is None
True
- contained objects may only participate in one listcontainer location at a
time--they cannot be in multiple listcontainers or be multiple times within
the same list container (although they may also be in a
zope.app.container--the packages may be used simultaneously for the same
object);
>>> list1.append(contained3)
Traceback (most recent call last):
...
RuntimeError: Cannot append item that already has a super
>>> list1[2] = contained3
Traceback (most recent call last):
...
RuntimeError: Cannot set item that already has a super
>>> list1.id = 'list1'
>>> list2 = listcontainer.ListContainer()
>>> list2.id = 'list2'
>>> list2.append(contained3)
Traceback (most recent call last):
...
RuntimeError: Cannot append item that already has a super
>>> list2[2] = contained3
Traceback (most recent call last):
...
RuntimeError: Cannot set item that already has a super
>>> list2.extend([contained3])
... # doctest: +ELLIPSIS
Traceback (most recent call last):
...
RuntimeError: ('Cannot add items that already have a super'...
>>> list1[0:0] = [contained3]
... # doctest: +ELLIPSIS
Traceback (most recent call last):
...
RuntimeError: ('Cannot add items that already have a super'...
>>> list1 == [contained3, contained2, contained1]
True
>>> list2 == []
True
- and listcontainers fire several events to alert subscribers to
membership changes. Note that events are generated iff (iff means
"if and only if") the previous link or the super link have changed
for a given item. This means that, for instance, a pop will
generate a removal event for the item and, i