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>'