Collection of named entities
Project description
Dolmen collection offers a collection implementation which permits to manipulate named elements: arrange order, extract part of the collection, enforce a type of component and add new ones easily.
It originated from zeam.form where it was used to implement forms as collections of fields, actions and widgets.
API description
Components
First let’s see the component, that is elements taking parts in collections:
>>> from dolmen.collection.components import Component >>> c1 = Component(u'The Sun', 'sun') >>> c1 <Component The Sun> >>> c1.identifier 'sun' >>> c1.title u'The Sun'
It correctly implement IComponent:
>>> from zope.interface.verify import verifyObject >>> from dolmen.collection import interfaces >>> verifyObject(interfaces.IComponent, c1) True
Actually you can create a component without an id, and even using a unicode title:
>>> c2 = Component(u'Moon') >>> c2 <Component Moon> >>> c2.identifier 'moon' >>> c2.title u'Moon'
Or a number (it won’t be converted to string. Like this, this support Zope translation messages):
>>> c69 = Component(69) >>> c69.title 69
If by doing so, the title contain spaces, they will be replaced by -. If UTF-8 character are included, the identifiant will be encoded:
>>> c3 = Component(u'Some lost planet') >>> c3.identifier 'some-lost-planet' >>> c4 = Component(u'État du désir') >>> c4.identifier 'c383c2897461742d64752d64c383c2a9736972'
Spaces are normalized:
>>> c5 = Component(' Some unappropriate spacing ') >>> c5.identifier 'some-unappropriate-spacing'
You can clone a component and change its identifier:
>>> c3clone = c3.clone('new-world') >>> c3clone <Component Some lost planet> >>> c3clone.identifier 'new-world' >>> c3clone is c3 False
But you can keep the old one as well:
>>> c4clone = c4.clone() >>> c4clone.identifier 'c383c2897461742d64752d64c383c2a9736972' >>> c4clone is c4 False
Collection
Collection are simple objects, implementing ICollection:
>>> from dolmen.collection.components import Collection >>> s1 = Collection() >>> s1 <Collection> >>> len(s1) 0 >>> verifyObject(interfaces.ICollection, s1) True
Adding components to a collection
Now we can put components in a collection, and list it back in the same order:
>>> s1.append(c1) >>> list(s1) [<Component The Sun>] >>> s1.append(c2) >>> list(s1) [<Component The Sun>, <Component Moon>]
But you can’t add twice the same component:
>>> s1.append(c1) Traceback (most recent call last): ... ValueError: (u'Duplicate identifier', 'sun')
And this need to be a component:
>>> s1.append('home') Traceback (most recent call last): ... TypeError: (u'Invalid type', 'home')
You create a collection with components or collection as argument:
>>> s2 = Collection(Component('Jupiter'), Component('Saturn')) >>> list(s2) [<Component Jupiter>, <Component Saturn>] >>> len(s2) 2 >>> list(Collection(s2, Component('Uranus'))) [<Component Jupiter>, <Component Saturn>, <Component Uranus>] >>> Collection(42) Traceback (most recent call last): ... TypeError: (u'Invalid type', 42)
You can add collections. You will receive a copy with all components. Components will ordered as the addition is:
>>> s3 = s1 + s2 >>> s3 <Collection> >>> s3 is s1 False >>> list(s3) [<Component The Sun>, <Component Moon>, <Component Jupiter>, <Component Saturn>] >>> len(s3) 4 >>> list(s2 + s1) [<Component Jupiter>, <Component Saturn>, <Component The Sun>, <Component Moon>]
You can extend a collection. It work pretty much like the construtor:
>>> s3.extend(Component('Venus'), Component('Uranus')) >>> list(s3) [<Component The Sun>, <Component Moon>, <Component Jupiter>, <Component Saturn>, <Component Venus>, <Component Uranus>] >>> s3.extend('Kitty') Traceback (most recent call last): ... TypeError: (u'Invalid type', 'Kitty')
You can copy a collection:
>>> s3copy = s3.copy() >>> list(s3copy) == list(s3) True >>> s3copy is s3 False
You can remove all elements from a collection:
>>> len(s1) 2 >>> s1.clear() >>> len(s1) 0
Retriving components from a collection
You can retrieve one element of the collection:
>>> s3.get('moon') <Component Moon> >>> s3.get('uranus') <Component Uranus> >>> s3.get('me') Traceback (most recent call last): ... KeyError: 'me' >>> s3.get('me', default=42) 42
And dictionnary like access works:
>>> s3['uranus'] <Component Uranus> >>> s3['venus'] <Component Venus> >>> s3['somewhere'] Traceback (most recent call last): ... KeyError: 'somewhere'
You can get all components ids:
>>> s3.keys() ['sun', 'moon', 'jupiter', 'saturn', 'venus', 'uranus']
You can test if a component id is in the collection:
>>> 'moon' in s3 True >>> 'earth' in s3 False
You can get a new collection with some of the components of the first one:
>>> s4 = s3.select('venus', 'uranus') >>> s4 is s3 False >>> list(s4) [<Component Venus>, <Component Uranus>] >>> s4.keys() ['venus', 'uranus']
Or the other way around some components of a collection:
>>> s5 = s3.omit('sun', 'moon') >>> s5 is s3 False >>> list(s5) [<Component Jupiter>, <Component Saturn>, <Component Venus>, <Component Uranus>]
Sorting components in a collection
The Collection sort call works as the standard python list’s one:
>>> s5.sort() >>> print list(s5) [<Component Jupiter>, <Component Saturn>, <Component Uranus>, <Component Venus>]
We can use the standard arguments (cmp, key and reverse):
>>> s5.sort(reverse=True) >>> print list(s5) [<Component Venus>, <Component Uranus>, <Component Saturn>, <Component Jupiter>] >>> s5.sort(reverse=True, key=lambda el: el.identifier[-1:]) >>> print list(s5) [<Component Venus>, <Component Uranus>, <Component Jupiter>, <Component Saturn>] >>> def myLengthSort(a1, a2): ... return cmp(len(a1), len(a2)) >>> s5.sort(reverse=True, key=lambda el: el.identifier, cmp=myLengthSort) >>> print list(s5) [<Component Jupiter>, <Component Uranus>, <Component Saturn>, <Component Venus>]
The collection can be reversed too, as standard lists:
>>> s5.reverse() >>> print list(s5) [<Component Venus>, <Component Saturn>, <Component Uranus>, <Component Jupiter>]
It is possible to order the components of a Collection using a given list of ids and the sort_components cmp function:
>>> from dolmen.collection import sort_components >>> s5.sort(sort_components(['uranus', 'venus', 'jupiter'])) >>> print list(s5) [<Component Uranus>, <Component Venus>, <Component Jupiter>, <Component Saturn>]
The keys are sorted in the process:
>>> print s5.keys() ['uranus', 'venus', 'jupiter', 'saturn']
Successive sortings will leave unspecified fields at their relative places:
>>> s5.sort(sort_components(['saturn', 'uranus'])) >>> print list(s5) [<Component Saturn>, <Component Uranus>, <Component Venus>, <Component Jupiter>]
We can also revert the sorting, as the standard python behavior:
>>> s5.sort(sort_components(['uranus', 'venus']), reverse=True) >>> print list(s5) [<Component Saturn>, <Component Jupiter>, <Component Venus>, <Component Uranus>]
Errors are raised if the provided list is malformed or smaller than 2 elements:
>>> s5.sort(sort_components(['uranus'])) Traceback (most recent call last): ... ValueError: Please provide a list of, at least, two component identifiers. >>> s5.sort(sort_components('something')) Traceback (most recent call last): ... ValueError: Please provide a valid list or tuple of component identifiers.
The behavior, if unknow ids are provided, is unchanged:
>>> s5.sort(sort_components(['venus', 'uranus', 'cardassia', 'bajor'])) >>> print list(s5) [<Component Venus>, <Component Uranus>, <Component Saturn>, <Component Jupiter>]
Parameters on collections
You can provides extra parameters on collections that will be set as attributes on the object:
>>> s6 = Collection(s2, name=u'me', city=u'rotterdam') >>> s6 <Collection> >>> list(s6) [<Component Jupiter>, <Component Saturn>] >>> s6.name u'me' >>> s6.city u'rotterdam'
Those attributes are kept if you use the operations select, omit or copy:
>>> s6copy = s6.copy() >>> s6copy.name u'me' >>> s6copy.city u'rotterdam' >>> s6omit = s6.omit('jupiter') >>> s6omit.name u'me' >>> s6omit.city u'rotterdam' >>> s6select = s6.select('jupiter') >>> s6select.name u'me' >>> s6select.city u'rotterdam'
Changes
0.1 (2011-04-13)
Initial release.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.