Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
commit
7b11487995
@ -9,7 +9,8 @@ sugardir = $(pkgdatadir)/services/datastore
|
|||||||
sugar_PYTHON = \
|
sugar_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
datastore.py \
|
datastore.py \
|
||||||
dbus_helpers.py
|
dbus_helpers.py \
|
||||||
|
demodata.py
|
||||||
|
|
||||||
bin_SCRIPTS = sugar-data-store
|
bin_SCRIPTS = sugar-data-store
|
||||||
|
|
||||||
|
@ -18,9 +18,15 @@
|
|||||||
import os
|
import os
|
||||||
import dbus, dbus.glib, gobject
|
import dbus, dbus.glib, gobject
|
||||||
import logging
|
import logging
|
||||||
import sqlite3
|
|
||||||
|
try:
|
||||||
|
from sqlite3 import dbapi2 as sqlite
|
||||||
|
except ImportError:
|
||||||
|
from pysqlite2 import dbapi2 as sqlite
|
||||||
|
|
||||||
import dbus_helpers
|
import dbus_helpers
|
||||||
import string
|
import string
|
||||||
|
import demodata
|
||||||
|
|
||||||
have_sugar = False
|
have_sugar = False
|
||||||
try:
|
try:
|
||||||
@ -72,12 +78,14 @@ def _get_data_as_string(data):
|
|||||||
return data_str
|
return data_str
|
||||||
elif isinstance(data, int):
|
elif isinstance(data, int):
|
||||||
return str(data)
|
return str(data)
|
||||||
|
elif isinstance(data, float):
|
||||||
|
return str(data)
|
||||||
elif isinstance(data, str):
|
elif isinstance(data, str):
|
||||||
return data
|
return data
|
||||||
elif isinstance(data, unicode):
|
elif isinstance(data, unicode):
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported data type")
|
raise ValueError("Unsupported data type: %s" % type(data))
|
||||||
|
|
||||||
class DataStoreDBusHelper(dbus.service.Object):
|
class DataStoreDBusHelper(dbus.service.Object):
|
||||||
def __init__(self, parent, bus_name):
|
def __init__(self, parent, bus_name):
|
||||||
@ -98,14 +106,9 @@ class DataStoreDBusHelper(dbus.service.Object):
|
|||||||
return _create_op(self._parent.get_activity_object(activity_id))
|
return _create_op(self._parent.get_activity_object(activity_id))
|
||||||
|
|
||||||
@dbus.service.method(_DS_DBUS_INTERFACE,
|
@dbus.service.method(_DS_DBUS_INTERFACE,
|
||||||
in_signature="aya{sv}s", out_signature="o")
|
in_signature="a{sv}", out_signature="o")
|
||||||
def create(self, data, prop_dict, activity_id):
|
def create(self, prop_dict):
|
||||||
if len(activity_id):
|
uid = self._parent.create(prop_dict)
|
||||||
if not validate_activity_id(activity_id):
|
|
||||||
raise ValueError("invalid activity id")
|
|
||||||
else:
|
|
||||||
activity_id = None
|
|
||||||
uid = self._parent.create(data, prop_dict, activity_id)
|
|
||||||
return _create_op(uid)
|
return _create_op(uid)
|
||||||
|
|
||||||
@dbus.service.method(_DS_DBUS_INTERFACE,
|
@dbus.service.method(_DS_DBUS_INTERFACE,
|
||||||
@ -116,9 +119,9 @@ class DataStoreDBusHelper(dbus.service.Object):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
@dbus.service.method(_DS_DBUS_INTERFACE,
|
@dbus.service.method(_DS_DBUS_INTERFACE,
|
||||||
in_signature="a{sv}", out_signature="ao")
|
in_signature="s", out_signature="ao")
|
||||||
def find(self, prop_dict):
|
def find(self, query):
|
||||||
uids = self._parent.find(prop_dict)
|
uids = self._parent.find(query)
|
||||||
ops = []
|
ops = []
|
||||||
for uid in uids:
|
for uid in uids:
|
||||||
ops.append(_create_op(uid))
|
ops.append(_create_op(uid))
|
||||||
@ -188,13 +191,13 @@ class DataStore(object):
|
|||||||
if not os.path.exists(os.path.dirname(self._dbfile)):
|
if not os.path.exists(os.path.dirname(self._dbfile)):
|
||||||
os.makedirs(os.path.dirname(self._dbfile), 0755)
|
os.makedirs(os.path.dirname(self._dbfile), 0755)
|
||||||
|
|
||||||
self._dbcx = sqlite3.connect(self._dbfile, timeout=3)
|
self._dbcx = sqlite.connect(self._dbfile, timeout=3)
|
||||||
|
self._dbcx.row_factory = sqlite.Row
|
||||||
try:
|
try:
|
||||||
self._ensure_table()
|
self._ensure_table()
|
||||||
except StandardError, e:
|
except StandardError, e:
|
||||||
logging.info("Could not access the data store. Reason: '%s'. Exiting..." % e)
|
logging.info("Could not access the data store. Reason: '%s'. Exiting..." % e)
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
self._dbcx.row_factory = sqlite3.Row
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self._dbcx.close()
|
self._dbcx.close()
|
||||||
@ -209,10 +212,7 @@ class DataStore(object):
|
|||||||
# If table wasn't created, try to create it
|
# If table wasn't created, try to create it
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
curs.execute('CREATE TABLE objects (' \
|
curs.execute('CREATE TABLE objects (' \
|
||||||
'uid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' \
|
'uid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);')
|
||||||
'activity_id VARCHAR(50), ' \
|
|
||||||
'data BLOB' \
|
|
||||||
');')
|
|
||||||
curs.execute('CREATE TABLE properties (' \
|
curs.execute('CREATE TABLE properties (' \
|
||||||
'objid INTEGER NOT NULL, ' \
|
'objid INTEGER NOT NULL, ' \
|
||||||
'key VARCHAR(100),' \
|
'key VARCHAR(100),' \
|
||||||
@ -220,6 +220,7 @@ class DataStore(object):
|
|||||||
');')
|
');')
|
||||||
curs.execute('CREATE INDEX objid_idx ON properties(objid);')
|
curs.execute('CREATE INDEX objid_idx ON properties(objid);')
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
|
demodata.insert_demo_data(self)
|
||||||
del curs
|
del curs
|
||||||
|
|
||||||
def get(self, uid):
|
def get(self, uid):
|
||||||
@ -243,24 +244,17 @@ class DataStore(object):
|
|||||||
del curs
|
del curs
|
||||||
raise NotFoundError("Object for activity %s was not found." % activity_id)
|
raise NotFoundError("Object for activity %s was not found." % activity_id)
|
||||||
|
|
||||||
def create(self, data, prop_dict=None, activity_id=None):
|
def create(self, prop_dict):
|
||||||
curs = self._dbcx.cursor()
|
curs = self._dbcx.cursor()
|
||||||
data = _get_data_as_string(data)
|
curs.execute("INSERT INTO objects (uid) VALUES (NULL);")
|
||||||
logging.debug(type(data))
|
|
||||||
logging.debug(data)
|
|
||||||
if not activity_id:
|
|
||||||
curs.execute("INSERT INTO objects (uid, data) VALUES (NULL, ?);", (data,))
|
|
||||||
else:
|
|
||||||
curs.execute("INSERT INTO objects (uid, data, activity_id) VALUES (NULL, ?, ?);", (data, activity_id))
|
|
||||||
curs.execute("SELECT last_insert_rowid();")
|
curs.execute("SELECT last_insert_rowid();")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
last_row = rows[0]
|
last_row = rows[0]
|
||||||
uid = last_row[0]
|
uid = last_row[0]
|
||||||
for (key, value) in prop_dict.items():
|
for (key, value) in prop_dict.items():
|
||||||
safe_key = key.replace("'", "''")
|
|
||||||
value = _get_data_as_string(value)
|
value = _get_data_as_string(value)
|
||||||
curs.execute("INSERT INTO properties (objid, key, value) VALUES (?, ?, ?);", (uid, safe_key, value))
|
curs.execute("INSERT INTO properties (objid, key, value) VALUES (?, ?, ?);", (uid, key, value))
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
del curs
|
del curs
|
||||||
return uid
|
return uid
|
||||||
@ -274,23 +268,14 @@ class DataStore(object):
|
|||||||
self._dbus_obj_helper.Updated(False, {}, True, uid=uid)
|
self._dbus_obj_helper.Updated(False, {}, True, uid=uid)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def find(self, prop_dict):
|
def find(self, query):
|
||||||
query = "SELECT objid FROM properties"
|
sql_query = "SELECT DISTINCT(objid) FROM properties"
|
||||||
subquery = ""
|
if query:
|
||||||
for (key, value) in prop_dict.items():
|
# TODO: parse the query for avoiding sql injection attacks.
|
||||||
safe_key = key.replace("'", "''")
|
sql_query += " WHERE (%s)" % query
|
||||||
value = _get_data_as_string(value)
|
sql_query += ";"
|
||||||
if not len(value):
|
|
||||||
raise ValueError("Property values must not be blank.")
|
|
||||||
substr = "(key='%s' AND value='%s')" % (safe_key, value)
|
|
||||||
if len(subquery) > 0:
|
|
||||||
subquery += " OR "
|
|
||||||
subquery += substr
|
|
||||||
if len(subquery):
|
|
||||||
query += " WHERE (%s)" % subquery
|
|
||||||
query += ";"
|
|
||||||
curs = self._dbcx.cursor()
|
curs = self._dbcx.cursor()
|
||||||
curs.execute(query)
|
curs.execute(sql_query)
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
# FIXME: ensure that each properties.objid has a match in objects.uid
|
# FIXME: ensure that each properties.objid has a match in objects.uid
|
||||||
@ -314,7 +299,8 @@ class DataStore(object):
|
|||||||
del curs
|
del curs
|
||||||
self._dbus_obj_helper.Updated(True, {}, False, uid=uid)
|
self._dbus_obj_helper.Updated(True, {}, False, uid=uid)
|
||||||
|
|
||||||
_reserved_keys = ["uid", "objid", "data", "created", "modified"]
|
_reserved_keys = ["handle", "objid", "data", "created", "modified",
|
||||||
|
"object-type", "file-path"]
|
||||||
def set_properties(self, uid, prop_dict):
|
def set_properties(self, uid, prop_dict):
|
||||||
curs = self._dbcx.cursor()
|
curs = self._dbcx.cursor()
|
||||||
curs.execute('SELECT uid FROM objects WHERE uid=?;', (uid,))
|
curs.execute('SELECT uid FROM objects WHERE uid=?;', (uid,))
|
||||||
@ -329,17 +315,16 @@ class DataStore(object):
|
|||||||
raise ValueError("key %s is a reserved key." % key)
|
raise ValueError("key %s is a reserved key." % key)
|
||||||
|
|
||||||
for (key, value) in prop_dict.items():
|
for (key, value) in prop_dict.items():
|
||||||
safe_key = key.replace("'", "''")
|
|
||||||
value = _get_data_as_string(value)
|
value = _get_data_as_string(value)
|
||||||
if not len(value):
|
if not len(value):
|
||||||
# delete the property
|
# delete the property
|
||||||
curs.execute("DELETE FROM properties WHERE (objid=? AND key=?);", (uid, safe_key))
|
curs.execute("DELETE FROM properties WHERE (objid=? AND key=?);", (uid, key))
|
||||||
else:
|
else:
|
||||||
curs.execute("SELECT objid FROM properties WHERE (objid=? AND key=?);", (uid, safe_key))
|
curs.execute("SELECT objid FROM properties WHERE (objid=? AND key=?);", (uid, key))
|
||||||
if len(curs.fetchall()) > 0:
|
if len(curs.fetchall()) > 0:
|
||||||
curs.execute("UPDATE properties SET value=? WHERE (objid=? AND key=?);", (value, uid, safe_key))
|
curs.execute("UPDATE properties SET value=? WHERE (objid=? AND key=?);", (value, uid, key))
|
||||||
else:
|
else:
|
||||||
curs.execute("INSERT INTO properties (objid, key, value) VALUES (?, ?, ?);", (uid, safe_key, value))
|
curs.execute("INSERT INTO properties (objid, key, value) VALUES (?, ?, ?);", (uid, key, value))
|
||||||
self._dbcx.commit()
|
self._dbcx.commit()
|
||||||
del curs
|
del curs
|
||||||
self._dbus_obj_helper.Updated(False, {}, False, uid=uid)
|
self._dbus_obj_helper.Updated(False, {}, False, uid=uid)
|
||||||
@ -360,10 +345,11 @@ class DataStore(object):
|
|||||||
subquery = ""
|
subquery = ""
|
||||||
if len(keys) > 0:
|
if len(keys) > 0:
|
||||||
for key in keys:
|
for key in keys:
|
||||||
if len(subquery) > 0:
|
if not subquery:
|
||||||
|
subquery += " AND ("
|
||||||
|
else:
|
||||||
subquery += " OR "
|
subquery += " OR "
|
||||||
safe_key = key.replace("'", "''")
|
subquery += "key='%s'" % key
|
||||||
subquery += "key='%s'" % safe_key
|
|
||||||
subquery += ")"
|
subquery += ")"
|
||||||
query += subquery + ");"
|
query += subquery + ");"
|
||||||
curs = self._dbcx.cursor()
|
curs = self._dbcx.cursor()
|
||||||
@ -374,7 +360,7 @@ class DataStore(object):
|
|||||||
for row in rows:
|
for row in rows:
|
||||||
conv_key = row['key'].replace("''", "'")
|
conv_key = row['key'].replace("''", "'")
|
||||||
prop_dict[conv_key] = row['value']
|
prop_dict[conv_key] = row['value']
|
||||||
prop_dict['uid'] = str(uid)
|
prop_dict['handle'] = str(uid)
|
||||||
del curs
|
del curs
|
||||||
return prop_dict
|
return prop_dict
|
||||||
|
|
||||||
|
65
services/datastore/demodata.py
Normal file
65
services/datastore/demodata.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
def insert_demo_data(data_store):
|
||||||
|
home_dir = os.path.expanduser('~')
|
||||||
|
journal_dir = os.path.join(home_dir, "Journal")
|
||||||
|
if not os.path.exists(journal_dir):
|
||||||
|
os.makedirs(journal_dir, 0755)
|
||||||
|
|
||||||
|
data = [
|
||||||
|
{ 'file-path' : os.path.join(journal_dir, 'fishes_in_the_sea.rtf'),
|
||||||
|
'object-type' : 'text',
|
||||||
|
'date' : str(time.time() - 100000),
|
||||||
|
'title' : 'Fishes in the Sea',
|
||||||
|
'preview' : 'There are many fishes in the sea, and not only...',
|
||||||
|
'icon' : 'theme:object-text',
|
||||||
|
'icon-color' : '#C2B00C,#785C78',
|
||||||
|
'keep' : '0',
|
||||||
|
'buddies' : str([ { 'name' : 'Marco',
|
||||||
|
'color' : '#C2B00C,#785C78' },
|
||||||
|
{ 'name' : 'Dan',
|
||||||
|
'color' : '#75C228,#3A6E3A' } ])
|
||||||
|
},
|
||||||
|
{ 'file-path' : os.path.join(journal_dir, 'my_cat_and_my_fishes.rtf'),
|
||||||
|
'object-type' : 'text',
|
||||||
|
'date' : str(time.time() - 200000),
|
||||||
|
'title' : 'My cat and my fishes',
|
||||||
|
'preview' : "Don't know why, but my cat looks to like my fishe...",
|
||||||
|
'icon' : 'theme:object-text',
|
||||||
|
'icon-color' : '#C2B00C,#785C78',
|
||||||
|
'keep' : '1',
|
||||||
|
'buddies' : str([ { 'name' : 'Eben',
|
||||||
|
'color' : '#C2B00C,#785C78' },
|
||||||
|
{ 'name' : 'Dan',
|
||||||
|
'color' : '#75C228,#3A6E3A' } ])
|
||||||
|
},
|
||||||
|
{ 'file-path' : os.path.join(journal_dir, 'cat_browsing.hist'),
|
||||||
|
'object-type' : 'link',
|
||||||
|
'date' : str(time.time() - 300000),
|
||||||
|
'title' : 'About cats',
|
||||||
|
'preview' : "http://en.wikipedia.org/wiki/Cat",
|
||||||
|
'icon' : 'theme:object-link',
|
||||||
|
'icon-color' : '#C2B00C,#785C78',
|
||||||
|
'keep' : '0',
|
||||||
|
'buddies' : str([ { 'name' : 'Dan',
|
||||||
|
'color' : '#C2B00C,#785C78' },
|
||||||
|
{ 'name' : 'Tomeu',
|
||||||
|
'color' : '#75C228,#3A6E3A' } ])
|
||||||
|
},
|
||||||
|
{ 'file-path' : os.path.join(journal_dir, 'our_school.jpeg'),
|
||||||
|
'object-type' : 'picture',
|
||||||
|
'date' : str(time.time() - 400000),
|
||||||
|
'title' : 'Our school',
|
||||||
|
'preview' : "Our school",
|
||||||
|
'icon' : 'theme:object-image',
|
||||||
|
'icon-color' : '#C2B00C,#785C78',
|
||||||
|
'keep' : '0',
|
||||||
|
'buddies' : str([ { 'name' : 'Marco',
|
||||||
|
'color' : '#C2B00C,#785C78' },
|
||||||
|
{ 'name' : 'Eben',
|
||||||
|
'color' : '#75C228,#3A6E3A' } ])
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for obj in data:
|
||||||
|
data_store.create(obj)
|
@ -32,9 +32,8 @@ from sugar.graphics import iconbutton
|
|||||||
|
|
||||||
import colorpicker
|
import colorpicker
|
||||||
|
|
||||||
_VIDEO_WIDTH = 640
|
_VIDEO_WIDTH = units.points_to_pixels(160)
|
||||||
_VIDEO_HEIGHT = 480
|
_VIDEO_HEIGHT = units.points_to_pixels(120)
|
||||||
|
|
||||||
|
|
||||||
class IntroImage(gtk.EventBox):
|
class IntroImage(gtk.EventBox):
|
||||||
__gtype_name__ = "IntroImage"
|
__gtype_name__ = "IntroImage"
|
||||||
|
@ -21,6 +21,7 @@ class ActivityHandle(object):
|
|||||||
def __init__(self, activity_id):
|
def __init__(self, activity_id):
|
||||||
self.activity_id = activity_id
|
self.activity_id = activity_id
|
||||||
self.pservice_id = None
|
self.pservice_id = None
|
||||||
|
self.object_id = None
|
||||||
self.uri = None
|
self.uri = None
|
||||||
|
|
||||||
def get_presence_service(self):
|
def get_presence_service(self):
|
||||||
@ -34,6 +35,8 @@ class ActivityHandle(object):
|
|||||||
result = { 'activity_id' : self.activity_id }
|
result = { 'activity_id' : self.activity_id }
|
||||||
if self.pservice_id:
|
if self.pservice_id:
|
||||||
result['pservice_id'] = self.pservice_id
|
result['pservice_id'] = self.pservice_id
|
||||||
|
if self.object_id:
|
||||||
|
result['object_id'] = self.object_id
|
||||||
if self.uri:
|
if self.uri:
|
||||||
result['uri'] = self.uri
|
result['uri'] = self.uri
|
||||||
|
|
||||||
@ -43,6 +46,8 @@ def create_from_dict(handle_dict):
|
|||||||
result = ActivityHandle(handle_dict['activity_id'])
|
result = ActivityHandle(handle_dict['activity_id'])
|
||||||
if handle_dict.has_key('pservice_id'):
|
if handle_dict.has_key('pservice_id'):
|
||||||
result.pservice_id = handle_dict['pservice_id']
|
result.pservice_id = handle_dict['pservice_id']
|
||||||
|
if handle_dict.has_key('object_id'):
|
||||||
|
result.object_id = handle_dict['object_id']
|
||||||
if handle_dict.has_key('uri'):
|
if handle_dict.has_key('uri'):
|
||||||
result.uri = handle_dict['uri']
|
result.uri = handle_dict['uri']
|
||||||
|
|
||||||
|
@ -13,10 +13,101 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
import dbus.glib
|
||||||
|
import gobject
|
||||||
|
|
||||||
import dbus, dbus.glib, gobject
|
|
||||||
from sugar import util
|
from sugar import util
|
||||||
|
|
||||||
|
DS_DBUS_SERVICE = "org.laptop.sugar.DataStore"
|
||||||
|
DS_DBUS_INTERFACE = "org.laptop.sugar.DataStore"
|
||||||
|
DS_DBUS_PATH = "/org/laptop/sugar/DataStore"
|
||||||
|
|
||||||
|
_bus = dbus.SessionBus()
|
||||||
|
_data_store = dbus.Interface(_bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH),
|
||||||
|
DS_DBUS_INTERFACE)
|
||||||
|
|
||||||
|
class DataStoreObject:
|
||||||
|
def __init__(self, metadata, file_path=None, handle=None):
|
||||||
|
self._metadata = metadata
|
||||||
|
self._file_path = file_path
|
||||||
|
self._handle = handle
|
||||||
|
|
||||||
|
def get_metadata(self):
|
||||||
|
return self._metadata
|
||||||
|
|
||||||
|
def get_file_path(self):
|
||||||
|
return self._file_path
|
||||||
|
|
||||||
|
def set_file_path(self, file_path):
|
||||||
|
self._file_path = file_path
|
||||||
|
|
||||||
|
def get_handle(self):
|
||||||
|
return self._handle
|
||||||
|
|
||||||
|
def get_object_type(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
class Text(DataStoreObject):
|
||||||
|
def get_object_type(self):
|
||||||
|
return 'text'
|
||||||
|
|
||||||
|
class Picture(DataStoreObject):
|
||||||
|
def get_object_type(self):
|
||||||
|
return 'picture'
|
||||||
|
|
||||||
|
class Link(DataStoreObject):
|
||||||
|
def get_object_type(self):
|
||||||
|
return 'link'
|
||||||
|
|
||||||
|
def _read_from_object_path(object_path):
|
||||||
|
dbus_object = _bus.get_object(DS_DBUS_SERVICE, object_path)
|
||||||
|
metadata = dbus_object.get_properties(dbus.Dictionary({}, signature='sv'))
|
||||||
|
|
||||||
|
object_type = metadata['object-type']
|
||||||
|
file_path = metadata['file-path']
|
||||||
|
handle = metadata['handle']
|
||||||
|
|
||||||
|
del metadata['object-type']
|
||||||
|
del metadata['file-path']
|
||||||
|
del metadata['handle']
|
||||||
|
|
||||||
|
if object_type == 'text':
|
||||||
|
return Text(metadata, file_path, handle)
|
||||||
|
elif object_type == 'picture':
|
||||||
|
return Picture(metadata, file_path, handle)
|
||||||
|
elif object_type == 'link':
|
||||||
|
return Link(metadata, file_path, handle)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError('Unknown object type.')
|
||||||
|
|
||||||
|
def read(handle):
|
||||||
|
object_path = _data_store.get(handle)
|
||||||
|
return _read_from_object_path(object_path)
|
||||||
|
|
||||||
|
def write(obj):
|
||||||
|
metadata = obj.get_metadata().copy()
|
||||||
|
metadata['file-path'] = obj.get_file_path()
|
||||||
|
metadata['object-type'] = obj.get_object_type()
|
||||||
|
logging.debug(str(metadata))
|
||||||
|
object_path = _data_store.create(dbus.Dictionary(metadata))
|
||||||
|
dbus_object = _bus.get_object(DS_DBUS_SERVICE, object_path)
|
||||||
|
return dbus_object.get_properties(['handle'])['handle']
|
||||||
|
|
||||||
|
def find(query):
|
||||||
|
object_paths = _data_store.find(query)
|
||||||
|
objects = []
|
||||||
|
for object_path in object_paths:
|
||||||
|
objects.append(_read_from_object_path(object_path))
|
||||||
|
return objects
|
||||||
|
|
||||||
|
def delete(handle):
|
||||||
|
pass
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
class ObjectCache(object):
|
class ObjectCache(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._cache = {}
|
self._cache = {}
|
||||||
@ -39,9 +130,6 @@ class ObjectCache(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
DS_DBUS_SERVICE = "org.laptop.sugar.DataStore"
|
|
||||||
DS_DBUS_INTERFACE = "org.laptop.sugar.DataStore"
|
|
||||||
DS_DBUS_PATH = "/org/laptop/sugar/DataStore"
|
|
||||||
|
|
||||||
class DSObject(gobject.GObject):
|
class DSObject(gobject.GObject):
|
||||||
|
|
||||||
|
@ -96,7 +96,8 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
|
|||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def add_item(self, menu_item):
|
def add_item(self, menu_item):
|
||||||
if not self._value:
|
if self._value == None:
|
||||||
|
logging.debug('Setting default value to: ' + menu_item.props.label)
|
||||||
self._value = menu_item.props.action_id
|
self._value = menu_item.props.action_id
|
||||||
self._canvas_text.props.text = menu_item.props.label
|
self._canvas_text.props.text = menu_item.props.label
|
||||||
|
|
||||||
|
50
tests/test-datastore2.py
Executable file
50
tests/test-datastore2.py
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright (C) 2006, One Laptop Per Child
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
from sugar.datastore import datastore
|
||||||
|
from sugar.datastore.datastore import Text
|
||||||
|
|
||||||
|
# Write a text object
|
||||||
|
metadata = { 'date' : 1000900000,
|
||||||
|
'title' : 'Thai history',
|
||||||
|
'preview' : 'The subject of thai history...',
|
||||||
|
'icon-color' : '#C2B00C,#785C78',
|
||||||
|
}
|
||||||
|
text = Text(metadata)
|
||||||
|
f = open("/tmp/hello.txt", 'w')
|
||||||
|
try:
|
||||||
|
f.write('The subject of thai history blah blah blah, blah blah blah and blah.')
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
text.set_file_path(f.name)
|
||||||
|
handle = datastore.write(text)
|
||||||
|
|
||||||
|
# Read back that object
|
||||||
|
thing = datastore.read(handle)
|
||||||
|
metadata = thing.get_metadata()
|
||||||
|
print metadata
|
||||||
|
|
||||||
|
file_path = thing.get_file_path()
|
||||||
|
f = open(file_path)
|
||||||
|
try:
|
||||||
|
print f.read()
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# Retrieve all the objects
|
||||||
|
objects = datastore.find('')
|
||||||
|
for obj in objects:
|
||||||
|
print obj.get_metadata()['title']
|
@ -1,6 +1,6 @@
|
|||||||
VERSION=0.63
|
VERSION=0.63
|
||||||
DATE=`date +%Y%m%d`
|
DATE=`date +%Y%m%d`
|
||||||
RELEASE=2.34
|
RELEASE=2.36
|
||||||
TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2
|
TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2
|
||||||
|
|
||||||
rm sugar-$VERSION.tar.bz2
|
rm sugar-$VERSION.tar.bz2
|
||||||
|
Loading…
Reference in New Issue
Block a user