Chandler logo

Serializing Chandler 1.0 DataΒΆ

chandler.sharing.legacy_model provides the EIM Records used by Chandler 1.0 for sharing to Cosmo and for dump/reload.

>>> from chandler.core import Item
>>> from chandler.sharing import legacy_model, eim, eimml
>>> from chandler.sharing.eim import Inherit, RecordSet as rs, NoChange as nc, Diff
>>> import datetime, decimal

Serialize and deserialize entire record sets using EIMMLSerializer:

>>> sample = '''<?xml version='1.0' encoding='UTF-8'?>
...
... <eim:collection name="foo" uuid="9501de14-1dc9-40d4-a7d4-f289feff8214" xmlns:eim="http://osafoundation.org/eim/0">
...   <eim:recordset uuid="8501de14-1dc9-40d4-a7d4-f289feff8214">
...     <item:record xmlns:item="http://osafoundation.org/eim/item/0">
...       <item:uuid eim:type="text" eim:key="true"><![CDATA[8501de14-1dc9-40d4-a7d4-f289feff8214]]></item:uuid>
...       <item:title eim:type="text"><![CDATA[Welcome to Cosmo]]></item:title>
...       <item:triage eim:type="text">100 123456789.12 1</item:triage>
...       <item:createdOn eim:type="decimal"><![CDATA[1164803131]]></item:createdOn>
...       <item:hasBeenSent eim:type="integer">0</item:hasBeenSent>
...       <item:needsReply eim:type="integer">0</item:needsReply>
...       <item:read eim:type="integer">0</item:read>
...     </item:record>
...     <modby:record xmlns:modby="http://osafoundation.org/eim/modifiedBy/0">
...       <modby:uuid eim:type="text" eim:key="true"><![CDATA[8501de14-1dc9-40d4-a7d4-f289feff8214]]></modby:uuid>
...       <modby:userid eim:type="text"><![CDATA[foo@example.com]]></modby:userid>
...       <modby:timestamp eim:type="decimal"><![CDATA[1164803132]]></modby:timestamp>
...       <modby:action eim:type="integer">500</modby:action>
...     </modby:record>
...     <note:record xmlns:note="http://osafoundation.org/eim/note/0">
...       <note:uuid eim:type="text" eim:key="true"><![CDATA[8501de14-1dc9-40d4-a7d4-f289feff8214]]></note:uuid>
...       <note:body eim:type="clob">This is the body\nsecond line</note:body>
...       <note:icalUid eim:type="text"><![CDATA[1e2d48c0-d66b-494c-bb33-c3d75a1ba66b]]></note:icalUid>
...       <note:icalProperties eim:type="text" />
...       <note:icalParameters eim:type="text" />
...       <note:icalExtra eim:type="text" />
...     </note:record>
...     <event:record xmlns:event="http://osafoundation.org/eim/event/0">
...       <event:uuid eim:type="text" eim:key="true"><![CDATA[8501de14-1dc9-40d4-a7d4-f289feff8214]]></event:uuid>
...       <event:dtstart eim:type="text"><![CDATA[20061130T140000]]></event:dtstart>
...       <event:duration eim:type="text"><![CDATA[PT1H]]></event:duration>
...       <event:location eim:type="text"><![CDATA[San Jose]]></event:location>
...       <event:rrule eim:type="text"><![CDATA[FREQ=WEEKLY]]></event:rrule>
...       <event:exrule eim:type="text" />
...       <event:rdate eim:type="text" />
...       <event:exdate eim:type="text" />
...       <event:status eim:type="text"><![CDATA[CONFIRMED]]></event:status>
...       <event:lastPastOccurrence eim:type="decimal" />
...     </event:record>
...   </eim:recordset>
... </eim:collection>'''

>>> recordSets, extra = eimml.EIMMLSerializer.deserialize(sample)

>>> sample_uuid = '8501de14-1dc9-40d4-a7d4-f289feff8214'
>>> expectedRecordSets = {sample_uuid:
...     Diff([legacy_model.ItemRecord(sample_uuid,
...             u'Welcome to Cosmo', u'100 123456789.12 1', decimal.Decimal("1164803131"), 0, 0, 0),
...           legacy_model.ModifiedByRecord(sample_uuid,
...             'foo@example.com', decimal.Decimal("1164803132"), 500),
...           legacy_model.NoteRecord(sample_uuid,
...             'This is the body\nsecond line', u'1e2d48c0-d66b-494c-bb33-c3d75a1ba66b', None, None, None),
...           legacy_model.EventRecord(sample_uuid,
...             u'20061130T140000', u'PT1H', u'San Jose', u'FREQ=WEEKLY', None, None, None, u'CONFIRMED', None)
...     ])}


>>> recordSets == expectedRecordSets
True

>>> extra
{'name': 'foo', 'uuid': '9501de14-1dc9-40d4-a7d4-f289feff8214'}

>>> text = eimml.EIMMLSerializer.serialize(recordSets, name="foo")

>>> recordSets, extra = eimml.EIMMLSerializer.deserialize(text)
>>> recordSets == expectedRecordSets
True

>>> extra
{'name': 'foo'}

Fields with empty strings are serialized with an empty=”true” attribute on their element:

>>> records = { sample_uuid: Diff([legacy_model.NoteRecord(sample_uuid, '', u'1e2d48c0-d66b-494c-bb33-c3d75a1ba66b', None, None, None)])}
>>> text = eimml.EIMMLSerializer.serialize(records)
>>> text
'<?xml version=\'1.0\' encoding=\'UTF-8\'?><ns0:collection xmlns:ns0="http://osafoundation.org/eim/0"><ns0:recordset uuid="8501de14-1dc9-40d4-a7d4-f289feff8214"><ns1:record xmlns:ns1="http://osafoundation.org/eim/note/0"><ns1:uuid ns0:key="true" ns0:type="text">8501de14-1dc9-40d4-a7d4-f289feff8214</ns1:uuid><ns1:body empty="true" ns0:type="clob" /><ns1:icalUid ns0:type="text">1e2d48c0-d66b-494c-bb33-c3d75a1ba66b</ns1:icalUid><ns1:icalProperties ns0:type="text" /><ns1:icalParameters ns0:type="text" /><ns1:icalExtra ns0:type="text" /></ns1:record></ns0:recordset></ns0:collection>'
>>> newRecords, extra = eimml.EIMMLSerializer.deserialize(text)
>>> records == newRecords
True

Any records in a recordset’s exclusions are serialized as deletions:

>>> recordDeletion = { sample_uuid: Diff(set([]), set([legacy_model.ItemRecord(sample_uuid, u'Welcome to Cosmo', u'100 123456789.12 1', decimal.Decimal("1164803131"), 0, 0, 0)]))}
>>> text = eimml.EIMMLSerializer.serialize(recordDeletion)
>>> text
'<?xml version=\'1.0\' encoding=\'UTF-8\'?><ns0:collection xmlns:ns0="http://osafoundation.org/eim/0"><ns0:recordset uuid="8501de14-1dc9-40d4-a7d4-f289feff8214"><ns1:record ns0:deleted="true" xmlns:ns1="http://osafoundation.org/eim/item/0"><ns1:uuid ns0:key="true" ns0:type="text">8501de14-1dc9-40d4-a7d4-f289feff8214</ns1:uuid></ns1:record></ns0:recordset></ns0:collection>'

To indicate that item has been deleted, pass None instead of a recordset:

>>> itemDeletion = { sample_uuid : None }
>>> text = eimml.EIMMLSerializer.serialize(itemDeletion)
>>> text
'<?xml version=\'1.0\' encoding=\'UTF-8\'?><ns0:collection xmlns:ns0="http://osafoundation.org/eim/0"><ns0:recordset uuid="8501de14-1dc9-40d4-a7d4-f289feff8214" ns0:deleted="true" /></ns0:collection>'

There is a special value, Inherit, which gets serialized as missing=”true”:

>>> missing = { sample_uuid: Diff([legacy_model.NoteRecord(sample_uuid, Inherit, u'1e2d48c0-d66b-494c-bb33-c3d75a1ba66b', None, None, None)])}
>>> text = eimml.EIMMLSerializer.serialize(missing)
>>> imported, extra = eimml.EIMMLSerializer.deserialize(text)
>>> imported
{'8501de14-1dc9-40d4-a7d4-f289feff8214': Diff(set([NoteRecord(u'8501de14-1dc9-40d4-a7d4-f289feff8214', Inherit, u'1e2d48c0-d66b-494c-bb33-c3d75a1ba66b', None, None, None)]), set([]))}

Records can be sorted by their dependencies. To make a record type dependent on another, make one of the first record type’s fields’ type be the field of another. For instance, NoteRecord’s uuid field = eim.key(ItemRecord.uuid):

>>> r1 = legacy_model.ItemRecord('1', None, nc, nc, nc, nc, nc)
>>> r2 = legacy_model.NoteRecord('1', None, nc, nc, nc, nc)
>>> r3 = legacy_model.EventRecord('1', None, nc, nc, nc, nc, nc, nc, nc, nc)
>>> r4 = legacy_model.DisplayAlarmRecord('1', nc, None, nc, nc)
>>> list(eim.sort_records( [r3, r1, r4, r2] ))
[ItemRecord(u'1', None, NoChange, NoChange, NoChange, NoChange, NoChange), NoteRecord(u'1', None, NoChange, NoChange, NoChange, NoChange), EventRecord(u'1', None, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange), DisplayAlarmRecord(u'1', NoChange, None, NoChange, NoChange)]

Sorting works even if not all record types are represented:

>>> list(eim.sort_records( [r3, r1, r4] ))
[ItemRecord(u'1', None, NoChange, NoChange, NoChange, NoChange, NoChange), EventRecord(u'1', None, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange), DisplayAlarmRecord(u'1', NoChange, None, NoChange, NoChange)]

>>> list(eim.sort_records( [r4, r3] ))
[EventRecord(u'1', None, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange, NoChange), DisplayAlarmRecord(u'1', NoChange, None, NoChange, NoChange)]

>>> sortedSets = {'1': rs([r4, r1, r3])}
>>> eimml.EIMMLSerializer.serialize(sortedSets)
'<?xml version=\'1.0\' encoding=\'UTF-8\'?><ns0:collection xmlns:ns0="http://osafoundation.org/eim/0"><ns0:recordset uuid="1"><ns1:record xmlns:ns1="http://osafoundation.org/eim/item/0"><ns1:uuid ns0:key="true" ns0:type="text">1</ns1:uuid><ns1:title ns0:type="text" /></ns1:record><ns1:record xmlns:ns1="http://osafoundation.org/eim/event/0"><ns1:uuid ns0:key="true" ns0:type="text">1</ns1:uuid><ns1:dtstart ns0:type="text" /></ns1:record><ns1:record xmlns:ns1="http://osafoundation.org/eim/displayAlarm/0"><ns1:uuid ns0:key="true" ns0:type="text">1</ns1:uuid><ns1:trigger ns0:type="text" /></ns1:record></ns0:recordset></ns0:collection>'

Previous topic

EIM - Extensible Information Model

Next topic

Translator

This Page

Quick search