From 7ab0b60b10c6f3adbb7b376b018dbea5f94da29a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 1 Mar 2007 11:53:43 -0500 Subject: [PATCH] Update data store to new dbus-python bindings API and sqlite3 --- services/datastore/datastore.py | 56 +++++++++---------- services/datastore/dbus_helpers.py | 83 +++++++++++++++++------------ services/datastore/sugar-data-store | 5 +- 3 files changed, 77 insertions(+), 67 deletions(-) diff --git a/services/datastore/datastore.py b/services/datastore/datastore.py index aa03035a..295a0430 100644 --- a/services/datastore/datastore.py +++ b/services/datastore/datastore.py @@ -18,7 +18,7 @@ import os import dbus, dbus.glib, gobject import logging -import sqlite +import sqlite3 import dbus_helpers import string @@ -131,36 +131,36 @@ class ObjectDBusHelper(dbus_helpers.FallbackObject): dbus_helpers.FallbackObject.__init__(self, bus_name, _DS_OBJECT_OBJECT_PATH) @dbus_helpers.method(_DS_OBJECT_DBUS_INTERFACE, - in_signature="", out_signature="ay", dbus_message_keyword="dbus_message") - def get_data(self, dbus_message=None): - if not dbus_message: - raise RuntimeError("Need the dbus message.") - uid = _get_uid_from_op(dbus_message.get_path()) + in_signature="", out_signature="ay", object_path_keyword="dbus_object_path") + def get_data(self, dbus_object_path=None): + if not dbus_object_path: + raise RuntimeError("Need the dbus object path.") + uid = _get_uid_from_op(dbus_object_path) return self._parent.get_data(uid) @dbus_helpers.method(_DS_OBJECT_DBUS_INTERFACE, - in_signature="ay", out_signature="i", dbus_message_keyword="dbus_message") - def set_data(self, data, dbus_message=None): - if not dbus_message: - raise RuntimeError("Need the dbus message.") - uid = _get_uid_from_op(dbus_message.get_path()) + in_signature="ay", out_signature="i", object_path_keyword="dbus_object_path") + def set_data(self, data, dbus_object_path=None): + if not dbus_object_path: + raise RuntimeError("Need the dbus object path.") + uid = _get_uid_from_op(dbus_object_path) self._parent.set_data(uid, data) return 0 @dbus_helpers.method(_DS_OBJECT_DBUS_INTERFACE, - in_signature="as", out_signature="a{sv}", dbus_message_keyword="dbus_message") - def get_properties(self, keys, dbus_message=None): - if not dbus_message: - raise RuntimeError("Need the dbus message.") - uid = _get_uid_from_op(dbus_message.get_path()) + in_signature="as", out_signature="a{sv}", object_path_keyword="dbus_object_path") + def get_properties(self, keys, dbus_object_path=None): + if not dbus_object_path: + raise RuntimeError("Need the dbus object path.") + uid = _get_uid_from_op(dbus_object_path) return self._parent.get_properties(uid, keys) @dbus_helpers.method(_DS_OBJECT_DBUS_INTERFACE, - in_signature="a{sv}", out_signature="i", dbus_message_keyword="dbus_message") - def set_properties(self, prop_dict, dbus_message=None): - if not dbus_message: - raise RuntimeError("Need the dbus message.") - uid = _get_uid_from_op(dbus_message.get_path()) + in_signature="a{sv}", out_signature="i", object_path_keyword="dbus_object_path") + def set_properties(self, prop_dict, dbus_object_path=None): + if not dbus_object_path: + raise RuntimeError("Need the dbus object path.") + uid = _get_uid_from_op(dbus_object_path) self._parent.set_properties(uid, prop_dict) return 0 @@ -188,7 +188,7 @@ class DataStore(object): if not os.path.exists(os.path.dirname(self._dbfile)): os.makedirs(os.path.dirname(self._dbfile), 0755) - self._dbcx = sqlite.connect(self._dbfile, encoding="utf-8", timeout=3) + self._dbcx = sqlite3.connect(self._dbfile, timeout=3) try: self._ensure_table() except StandardError, e: @@ -244,7 +244,7 @@ class DataStore(object): def create(self, data, prop_dict=None, activity_id=None): curs = self._dbcx.cursor() - data = sqlite.encode(_get_data_as_string(data)) + data = sqlite3.encode(_get_data_as_string(data)) if not activity_id: curs.execute("INSERT INTO objects (uid, data) VALUES (NULL, '%s');" % data) else: @@ -256,7 +256,7 @@ class DataStore(object): uid = last_row[0] for (key, value) in prop_dict.items(): safe_key = key.replace("'", "''") - value = sqlite.encode(_get_data_as_string(value)) + value = sqlite3.encode(_get_data_as_string(value)) curs.execute("INSERT INTO properties (objid, key, value) VALUES (%d, '%s', '%s');" % (uid, safe_key, value)) self._dbcx.commit() del curs @@ -279,7 +279,7 @@ class DataStore(object): value = _get_data_as_string(value) if not len(value): raise ValueError("Property values must not be blank.") - substr = "(key='%s' AND value='%s')" % (safe_key, sqlite.encode(value)) + substr = "(key='%s' AND value='%s')" % (safe_key, sqlite3.encode(value)) if len(subquery) > 0: subquery += " OR " subquery += substr @@ -305,7 +305,7 @@ class DataStore(object): if len(res) <= 0: del curs raise NotFoundError("Object %d was not found." % uid) - data = sqlite.encode(_get_data_as_string(data)) + data = sqlite3.encode(_get_data_as_string(data)) curs.execute("UPDATE objects SET data='%s' WHERE uid=%d;" % (data, uid)) self._dbcx.commit() del curs @@ -332,7 +332,7 @@ class DataStore(object): # delete the property curs.execute("DELETE FROM properties WHERE (objid=%d AND key='%s');" % (uid, safe_key)) else: - enc_value = sqlite.encode(value) + enc_value = sqlite3.encode(value) curs.execute("SELECT objid FROM properties WHERE (objid=%d AND key='%s');" % (uid, safe_key)) if len(curs.fetchall()) > 0: curs.execute("UPDATE properties SET value='%s' WHERE (objid=%d AND key='%s');" % (enc_value, uid, safe_key)) @@ -371,7 +371,7 @@ class DataStore(object): prop_dict = {} for row in rows: conv_key = row['key'].replace("''", "'") - prop_dict[conv_key] = sqlite.decode(row['value']) + prop_dict[conv_key] = sqlite3.decode(row['value']) prop_dict['uid'] = str(uid) del curs return prop_dict diff --git a/services/datastore/dbus_helpers.py b/services/datastore/dbus_helpers.py index 391e2017..f35958e8 100644 --- a/services/datastore/dbus_helpers.py +++ b/services/datastore/dbus_helpers.py @@ -18,11 +18,12 @@ # Mostly taken from dbus-python's service.py import dbus +import _dbus_bindings from dbus import service import inspect -def method(dbus_interface, in_signature=None, out_signature=None, async_callbacks=None, sender_keyword=None, dbus_message_keyword=None): - dbus._util._validate_interface_or_name(dbus_interface) +def method(dbus_interface, in_signature=None, out_signature=None, async_callbacks=None, sender_keyword=None, utf8_strings=False, byte_arrays=False, object_path_keyword=None): + _dbus_bindings.validate_interface_name(dbus_interface) def decorator(func): args = inspect.getargspec(func)[0] @@ -39,18 +40,17 @@ def method(dbus_interface, in_signature=None, out_signature=None, async_callback if sender_keyword: args.remove(sender_keyword) - if dbus_message_keyword: - args.remove(dbus_message_keyword) + if object_path_keyword: + args.remove(object_path_keyword) if in_signature: - in_sig = tuple(dbus.dbus_bindings.Signature(in_signature)) + in_sig = tuple(_dbus_bindings.Signature(in_signature)) if len(in_sig) > len(args): raise ValueError, 'input signature is longer than the number of arguments taken' elif len(in_sig) < len(args): raise ValueError, 'input signature is shorter than the number of arguments taken' - func._dbus_message_keyword = dbus_message_keyword func._dbus_is_method = True func._dbus_async_callbacks = async_callbacks func._dbus_interface = dbus_interface @@ -58,27 +58,28 @@ def method(dbus_interface, in_signature=None, out_signature=None, async_callback func._dbus_out_signature = out_signature func._dbus_sender_keyword = sender_keyword func._dbus_args = args + func._dbus_get_args_options = {'byte_arrays': byte_arrays, + 'utf8_strings': utf8_strings} + func._dbus_object_path_keyword = object_path_keyword return func return decorator + def fallback_signal(dbus_interface, signature=None, ignore_args=None): - dbus._util._validate_interface_or_name(dbus_interface) + _dbus_bindings.validate_interface_name(dbus_interface) def decorator(func): def emit_signal(self, *args, **keywords): obj_path = func(self, *args, **keywords) - message = dbus.dbus_bindings.Signal(obj_path, dbus_interface, func.__name__) - iter = message.get_iter(True) + message = _dbus_bindings.SignalMessage(obj_path, dbus_interface, func.__name__) if emit_signal._dbus_signature: - signature = tuple(dbus.dbus_bindings.Signature(emit_signal._dbus_signature)) - for (arg, sig) in zip(args, signature): - iter.append_strict(arg, sig) + message.append(signature=emit_signal._dbus_signature, + *args) else: - for arg in args: - iter.append(arg) + message.append(*args) - self._connection.send(message) + self._connection.send_message(message) temp_args = inspect.getargspec(func)[0] temp_args.pop(0) @@ -89,7 +90,7 @@ def fallback_signal(dbus_interface, signature=None, ignore_args=None): args.append(arg) if signature: - sig = tuple(dbus.dbus_bindings.Signature(signature)) + sig = tuple(_dbus_bindings.Signature(signature)) if len(sig) > len(args): raise ValueError, 'signal signature is longer than the number of arguments provided' @@ -112,14 +113,28 @@ class FallbackObject(dbus.service.Object): Just inherit from Object and provide a list of methods to share across the Bus """ - def __init__(self, bus_name, fallback_object_path): + + def __init__(self, conn=None, fallback_object_path=None, bus_name=None): + if fallback_object_path is None: + raise TypeError('The fallback_object_path argument is required') + + if isinstance(conn, dbus.service.BusName): + # someone's using the old API; don't gratuitously break them + bus_name = conn + conn = bus_name.get_bus() + elif conn is None: + # someone's using the old API but naming arguments, probably + if bus_name is None: + raise TypeError('Either conn or bus_name is required') + conn = bus_name.get_bus() + self._object_path = fallback_object_path - self._name = bus_name - self._bus = bus_name.get_bus() + self._name = bus_name + self._bus = conn self._connection = self._bus.get_connection() - self._connection.register_fallback(fallback_object_path, self._unregister_cb, self._message_cb) + self._connection._register_object_path(fallback_object_path, self._message_cb, self._unregister_cb, fallback=True) def _message_cb(self, connection, message): try: @@ -129,12 +144,11 @@ class FallbackObject(dbus.service.Object): (candidate_method, parent_method) = dbus.service._method_lookup(self, method_name, interface_name) # set up method call parameters - args = message.get_args_list() + args = message.get_args_list(**parent_method._dbus_get_args_options) keywords = {} - # iterate signature into list of complete types - if parent_method._dbus_out_signature: - signature = tuple(dbus.dbus_bindings.Signature(parent_method._dbus_out_signature)) + if parent_method._dbus_out_signature is not None: + signature = _dbus_bindings.Signature(parent_method._dbus_out_signature) else: signature = None @@ -148,8 +162,8 @@ class FallbackObject(dbus.service.Object): if parent_method._dbus_sender_keyword: keywords[parent_method._dbus_sender_keyword] = message.get_sender() - if parent_method._dbus_message_keyword: - keywords[parent_method._dbus_message_keyword] = message + if parent_method._dbus_object_path_keyword: + keywords[parent_method._dbus_object_path_keyword] = message.get_object_path() # call method retval = candidate_method(self, *args, **keywords) @@ -161,17 +175,18 @@ class FallbackObject(dbus.service.Object): # otherwise we send the return values in a reply. if we have a # signature, use it to turn the return value into a tuple as # appropriate - if parent_method._dbus_out_signature: + if signature is not None: + signature_tuple = tuple(signature) # if we have zero or one return values we want make a tuple # for the _method_reply_return function, otherwise we need # to check we're passing it a sequence - if len(signature) == 0: + if len(signature_tuple) == 0: if retval == None: retval = () else: raise TypeError('%s has an empty output signature but did not return None' % method_name) - elif len(signature) == 1: + elif len(signature_tuple) == 1: retval = (retval,) else: if operator.isSequenceType(retval): @@ -183,7 +198,6 @@ class FallbackObject(dbus.service.Object): # no signature, so just turn the return into a tuple and send it as normal else: - signature = None if retval == None: retval = () else: @@ -194,11 +208,10 @@ class FallbackObject(dbus.service.Object): # send error reply dbus.service._method_reply_error(connection, message, exception) - @method('org.freedesktop.DBus.Introspectable', in_signature='', out_signature='s', dbus_message_keyword="dbus_message") - def Introspect(self, dbus_message=None): + @method('org.freedesktop.DBus.Introspectable', in_signature='', out_signature='s', object_path_keyword="dbus_object_path") + def Introspect(self, dbus_object_path=None): reflection_data = '\n' - op = dbus_message.get_path() - reflection_data += '\n' % (op) + reflection_data += '\n' % (dbus_object_path) interfaces = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__] for (name, funcs) in interfaces.iteritems(): @@ -217,6 +230,6 @@ class FallbackObject(dbus.service.Object): return reflection_data def __repr__(self): - return '' % (self._fallback_object_path, self._name, id(self)) + return '' % (self._object_path, self._name, id(self)) __str__ = __repr__ diff --git a/services/datastore/sugar-data-store b/services/datastore/sugar-data-store index 63449524..b4a728bd 100755 --- a/services/datastore/sugar-data-store +++ b/services/datastore/sugar-data-store @@ -28,9 +28,6 @@ sys.path.insert(0, env.get_services_dir()) logger.start('data-store') logging.info('Starting the data store...') -try: - from datastore import datastore -except ImportError: - import datastore +from datastore import datastore datastore.main()