>>> import os >>> import tempfile >>> import time Define some helper functions >>> def test_unique(items): ... return not [True for e in items if items.count(e) > 1] >>> def to_native(value): ... if isinstance(value, list): ... return [to_native(e) for e in value] ... elif isinstance(value, dict): ... return dict([(to_native(k), to_native(v)) for k, v in value.items()]) ... elif isinstance(value, unicode): ... return unicode(value) ... elif isinstance(value, str): ... return str(value) ... return value >>> def create_temp_file(content): ... fd, file_name = tempfile.mkstemp() ... f = os.fdopen(fd, 'w') ... f.write(content) ... f.close() ... return file_name Connect to data store using DBus: >>> import dbus >>> DS_DBUS_SERVICE = 'org.silbe.GDataStore' >>> DS_DBUS_INTERFACE = 'org.silbe.GDataStore1' >>> DS_DBUS_PATH = '/org/silbe/GDataStore1' >>> bus = dbus.SessionBus() >>> ds = dbus.Interface(bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH), DS_DBUS_INTERFACE) Make sure we're starting from an empty datastore: >>> assert ds.find({}, {}) == ([], 0) Create something to play with: >>> o1_oid = ds.create({'title': 'DS test object 1', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest1'}, '') >>> assert isinstance(o1_oid, tuple) and len(o1_oid) == 2 and isinstance(o1_oid[0], basestring) and isinstance(o1_oid[1], basestring) >>> o2_oid = ds.create({'title': 'DS test object 2', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest2'}, '') >>> assert isinstance(o2_oid, tuple) and len(o2_oid) == 2 and isinstance(o2_oid[0], basestring) and isinstance(o2_oid[1], basestring) >>> o3_oid = ds.create({'title': 'DS test object 3', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest2'}, '') >>> assert isinstance(o3_oid, tuple) and len(o3_oid) == 2 and isinstance(o3_oid[0], basestring) and isinstance(o3_oid[1], basestring) >>> assert test_unique([o1_oid, o2_oid, o3_oid]) Check everything is there: >>> assert sorted(to_native(ds.find({}, {'metadata': ['title', 'activity']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 1', u'activity': 'org.sugarlabs.DataStoreTest1'}, ... {u'title': 'DS test object 2', u'activity': 'org.sugarlabs.DataStoreTest2'}, ... {u'title': 'DS test object 3', u'activity': 'org.sugarlabs.DataStoreTest2'}] >>> ds.get_data_path(*o1_oid, byte_arrays=True) dbus.ByteArray('') >>> ds.get_data_path(*o2_oid, byte_arrays=True) dbus.ByteArray('') >>> ds.get_data_path(*o3_oid, byte_arrays=True) dbus.ByteArray('') Change some metadata without creating a new version: >>> ds.change_metadata(o1_oid[0], o1_oid[1], {'title': 'DS test object 1 updated', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest1', 'tags': 'foo'}) >>> ds.change_metadata(o2_oid[0], o2_oid[1], {'title': 'DS test object 2', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest1', 'tags': 'bar baz'}) >>> ds.change_metadata(o3_oid[0], o3_oid[1], {'title': 'DS test object 2', 'mime_type': 'text/html', 'activity': 'org.sugarlabs.DataStoreTest3', 'timestamp': 10000}) >>> assert sorted(to_native(ds.find({}, {'metadata': ['title', 'activity']}, byte_arrays=True)[0])) == \ ... [{u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 1 updated'}, ... {u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 2'}, ... {u'activity': 'org.sugarlabs.DataStoreTest3', u'title': 'DS test object 2'}] >>> unicode(ds.get_metadata(*o1_oid)['title']) u'DS test object 1 updated' Retrieve metadata for a single entry, ignoring variable data: >>> d=dict(ds.get_metadata(*o3_oid, byte_arrays=True)) >>> del d['tree_id'], d['version_id'], d['timestamp'], d['creation_time'] >>> assert to_native(d) == {u'title': 'DS test object 2', u'mime_type': 'text/html', u'activity': 'org.sugarlabs.DataStoreTest3'} Find entries using "standard" metadata: >>> assert sorted(to_native(ds.find({'mime_type': ['text/plain']}, {'metadata': ['title', 'activity', 'mime_type', 'tags']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'activity': 'org.sugarlabs.DataStoreTest1', u'mime_type': 'text/plain', u'tags': 'bar baz'}, ... {u'title': 'DS test object 1 updated', u'activity': 'org.sugarlabs.DataStoreTest1', u'mime_type': 'text/plain', u'tags': 'foo'}] >>> assert sorted(to_native(ds.find({'mime_type': ['text/html']}, {'metadata': ['title', 'activity', 'mime_type', 'tags']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'mime_type': 'text/html', u'activity': 'org.sugarlabs.DataStoreTest3'}] >>> assert sorted(to_native(ds.find({'tree_id': o3_oid[0]}, {'metadata': ['title', 'activity', 'mime_type']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'mime_type': 'text/html', u'activity': 'org.sugarlabs.DataStoreTest3'}] >>> assert sorted(to_native(ds.find({'timestamp': (9000, 11000)}, {'metadata': ['title', 'activity', 'mime_type']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'mime_type': 'text/html', u'activity': 'org.sugarlabs.DataStoreTest3'}] Find entries using "non-standard" metadata (only works with dict-based queries or prefixed Xapian query strings): >>> assert sorted(to_native(ds.find({'title': 'DS test object 2'}, {'metadata': ['title', 'activity', 'mime_type', 'tags']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'mime_type': 'text/html', u'activity': 'org.sugarlabs.DataStoreTest3'}, ... {u'title': 'DS test object 2', u'activity': 'org.sugarlabs.DataStoreTest1', u'mime_type': 'text/plain', u'tags': 'bar baz'}] You can specify a (primary) sort order. Please note that the secondary sort order is undefined / implementation-dependent. >>> assert to_native(ds.find({}, {'metadata': ['title', 'activity'], 'order_by': ['+title']}, byte_arrays=True)[0]) == \ ... [{u'activity': 'org.sugarlabs.DataStoreTest3', u'title': 'DS test object 2'}, ... {u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 2'}, ... {u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 1 updated'}] >>> assert to_native(ds.find({}, {'metadata': ['title', 'activity'], 'order_by': ['-title']}, byte_arrays=True)[0]) == \ ... [{u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 1 updated'}, ... {u'activity': 'org.sugarlabs.DataStoreTest1', u'title': 'DS test object 2'}, ... {u'activity': 'org.sugarlabs.DataStoreTest3', u'title': 'DS test object 2'}] Delete an entry: >>> ds.delete(*o1_oid) >>> assert sorted(to_native(ds.find({}, {'metadata': ['title', 'activity']}, byte_arrays=True)[0])) == \ ... [{u'title': 'DS test object 2', u'activity': 'org.sugarlabs.DataStoreTest1'}, ... {u'title': 'DS test object 2', u'activity': 'org.sugarlabs.DataStoreTest3'}] Create an entry with content: >>> dog_content = 'The quick brown dog jumped over the lazy fox.' >>> dog_props = {'title': 'dog/fox story', 'mime_type': 'text/plain'} >>> dog_file_name = create_temp_file(dog_content) >>> dog_oid = ds.create(dog_props, dog_file_name) You can also pass the data as a file descriptor, useful for streaming: >>> dog2_file = tempfile.TemporaryFile() >>> dog2_file.write(dog_content) >>> dog2_file.flush() >>> dog2_file.seek(0) >>> dog2_oid = ds.create_fd({'title': 'DS test object 4', 'mime_type': 'text/plain', 'activity': 'org.sugarlabs.DataStoreTest1'}, dog2_file.fileno()) >>> dog2_file.close() Retrieve and verify the entry with content: >>> dog_retrieved = ds.get_data_path(*dog_oid, byte_arrays=True).decode('utf-8') >>> assert(file(dog_retrieved).read() == dog_content) >>> os.remove(dog_retrieved) The same using file descriptor passing: >>> dog2_retrieved_file = os.fdopen(ds.get_data_fd(*dog2_oid).take(), 'r') >>> assert(dog2_retrieved_file.read() == dog_content) Update the entry content (creates a new version): >>> dog_content_2 = 'The quick brown fox jumped over the lazy dog.' >>> dog_file_name = create_temp_file(dog_content_2) >>> dog_updated_version_id = ds.add_version(dog_oid[0], dog_oid[1], dog_props, dog_file_name) Update the entry content by passing a file descriptor: >>> dog_content_2 = 'The quick brown fox jumped over the lazy dog.' >>> dog2_file = tempfile.TemporaryFile() >>> dog2_file.write(dog_content) >>> dog2_file.flush() >>> dog2_file.seek(0) >>> dog2_updated_version_id = ds.add_version_fd(dog_oid[0], dog_oid[1], dog_props, dog2_file.fileno()) Verify updated content: >>> dog_retrieved = ds.get_data_path(dog_oid[0], dog_updated_version_id, byte_arrays=True).decode('utf-8') >>> assert(file(dog_retrieved).read() == dog_content_2) >>> os.remove(dog_retrieved) Verify old content is still accessible: >>> dog_retrieved = ds.get_data_path(*dog_oid, byte_arrays=True).decode('utf-8') >>> assert(file(dog_retrieved).read() == dog_content) >>> os.remove(dog_retrieved)