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 =      \
 | ||||
| 	__init__.py     \
 | ||||
| 	datastore.py    \
 | ||||
| 	dbus_helpers.py | ||||
| 	dbus_helpers.py	\
 | ||||
| 	demodata.py | ||||
| 
 | ||||
| bin_SCRIPTS = sugar-data-store | ||||
| 
 | ||||
|  | ||||
| @ -18,9 +18,15 @@ | ||||
| import os | ||||
| import dbus, dbus.glib, gobject | ||||
| import logging | ||||
| import sqlite3 | ||||
| 
 | ||||
| try: | ||||
|     from sqlite3 import dbapi2 as sqlite | ||||
| except ImportError: | ||||
|     from pysqlite2 import dbapi2 as sqlite | ||||
| 
 | ||||
| import dbus_helpers | ||||
| import string | ||||
| import demodata | ||||
| 
 | ||||
| have_sugar = False | ||||
| try: | ||||
| @ -72,12 +78,14 @@ def _get_data_as_string(data): | ||||
|         return data_str | ||||
|     elif isinstance(data, int): | ||||
|         return str(data) | ||||
|     elif isinstance(data, float): | ||||
|         return str(data) | ||||
|     elif isinstance(data, str): | ||||
|         return data | ||||
|     elif isinstance(data, unicode): | ||||
|         return str(data) | ||||
|     else: | ||||
|         raise ValueError("Unsupported data type") | ||||
|         raise ValueError("Unsupported data type: %s" % type(data)) | ||||
| 
 | ||||
| class DataStoreDBusHelper(dbus.service.Object): | ||||
|     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)) | ||||
| 
 | ||||
|     @dbus.service.method(_DS_DBUS_INTERFACE, | ||||
|                         in_signature="aya{sv}s", out_signature="o") | ||||
|     def create(self, data, prop_dict, activity_id): | ||||
|         if len(activity_id): | ||||
|             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) | ||||
|                         in_signature="a{sv}", out_signature="o") | ||||
|     def create(self, prop_dict): | ||||
|         uid = self._parent.create(prop_dict) | ||||
|         return _create_op(uid) | ||||
| 
 | ||||
|     @dbus.service.method(_DS_DBUS_INTERFACE, | ||||
| @ -116,9 +119,9 @@ class DataStoreDBusHelper(dbus.service.Object): | ||||
|         return 0 | ||||
| 
 | ||||
|     @dbus.service.method(_DS_DBUS_INTERFACE, | ||||
|                         in_signature="a{sv}", out_signature="ao") | ||||
|     def find(self, prop_dict): | ||||
|         uids = self._parent.find(prop_dict) | ||||
|                         in_signature="s", out_signature="ao") | ||||
|     def find(self, query): | ||||
|         uids = self._parent.find(query) | ||||
|         ops = [] | ||||
|         for uid in uids: | ||||
|             ops.append(_create_op(uid)) | ||||
| @ -188,13 +191,13 @@ class DataStore(object): | ||||
|         if not os.path.exists(os.path.dirname(self._dbfile)): | ||||
|             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: | ||||
|             self._ensure_table() | ||||
|         except StandardError, e: | ||||
|             logging.info("Could not access the data store.  Reason: '%s'.  Exiting..." % e) | ||||
|             os._exit(1) | ||||
|         self._dbcx.row_factory = sqlite3.Row | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         self._dbcx.close() | ||||
| @ -209,10 +212,7 @@ class DataStore(object): | ||||
|             # If table wasn't created, try to create it | ||||
|             self._dbcx.commit() | ||||
|             curs.execute('CREATE TABLE objects (' \ | ||||
|                 'uid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' \ | ||||
|                 'activity_id VARCHAR(50), ' \ | ||||
|                 'data BLOB' \ | ||||
|                 ');') | ||||
|                 'uid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);') | ||||
|             curs.execute('CREATE TABLE properties (' \ | ||||
|                 'objid INTEGER NOT NULL, '           \ | ||||
|                 'key VARCHAR(100),'                  \ | ||||
| @ -220,6 +220,7 @@ class DataStore(object): | ||||
|                 ');') | ||||
|             curs.execute('CREATE INDEX objid_idx ON properties(objid);') | ||||
|             self._dbcx.commit() | ||||
|             demodata.insert_demo_data(self) | ||||
|         del curs | ||||
| 
 | ||||
|     def get(self, uid): | ||||
| @ -243,24 +244,17 @@ class DataStore(object): | ||||
|         del curs | ||||
|         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() | ||||
|         data = _get_data_as_string(data) | ||||
|         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("INSERT INTO objects (uid) VALUES (NULL);") | ||||
|         curs.execute("SELECT last_insert_rowid();") | ||||
|         rows = curs.fetchall() | ||||
|         self._dbcx.commit() | ||||
|         last_row = rows[0] | ||||
|         uid = last_row[0] | ||||
|         for (key, value) in prop_dict.items(): | ||||
|             safe_key = key.replace("'", "''") | ||||
|             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() | ||||
|         del curs | ||||
|         return uid | ||||
| @ -274,23 +268,14 @@ class DataStore(object): | ||||
|         self._dbus_obj_helper.Updated(False, {}, True, uid=uid) | ||||
|         return 0 | ||||
| 
 | ||||
|     def find(self, prop_dict): | ||||
|         query = "SELECT objid FROM properties" | ||||
|         subquery = "" | ||||
|         for (key, value) in prop_dict.items(): | ||||
|             safe_key = key.replace("'", "''") | ||||
|             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, value) | ||||
|             if len(subquery) > 0: | ||||
|                 subquery += " OR " | ||||
|             subquery += substr | ||||
|         if len(subquery): | ||||
|             query += " WHERE (%s)" % subquery | ||||
|         query += ";" | ||||
|     def find(self, query): | ||||
|         sql_query = "SELECT DISTINCT(objid) FROM properties" | ||||
|         if query: | ||||
|             # TODO: parse the query for avoiding sql injection attacks. | ||||
|             sql_query += " WHERE (%s)" % query | ||||
|         sql_query += ";" | ||||
|         curs = self._dbcx.cursor() | ||||
|         curs.execute(query) | ||||
|         curs.execute(sql_query) | ||||
|         rows = curs.fetchall() | ||||
|         self._dbcx.commit() | ||||
|         # FIXME: ensure that each properties.objid has a match in objects.uid | ||||
| @ -314,7 +299,8 @@ class DataStore(object): | ||||
|         del curs | ||||
|         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): | ||||
|         curs = self._dbcx.cursor() | ||||
|         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) | ||||
| 
 | ||||
|         for (key, value) in prop_dict.items(): | ||||
|             safe_key = key.replace("'", "''") | ||||
|             value = _get_data_as_string(value) | ||||
|             if not len(value): | ||||
|                 # 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: | ||||
|                 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: | ||||
|                     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: | ||||
|                     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() | ||||
|         del curs | ||||
|         self._dbus_obj_helper.Updated(False, {}, False, uid=uid) | ||||
| @ -360,10 +345,11 @@ class DataStore(object): | ||||
|         subquery = "" | ||||
|         if len(keys) > 0: | ||||
|             for key in keys: | ||||
|                 if len(subquery) > 0: | ||||
|                 if not subquery: | ||||
|                     subquery += " AND (" | ||||
|                 else: | ||||
|                     subquery += " OR " | ||||
|                 safe_key = key.replace("'", "''") | ||||
|                 subquery += "key='%s'" % safe_key | ||||
|                 subquery += "key='%s'" % key | ||||
|             subquery += ")" | ||||
|         query += subquery + ");" | ||||
|         curs = self._dbcx.cursor() | ||||
| @ -374,7 +360,7 @@ class DataStore(object): | ||||
|         for row in rows: | ||||
|             conv_key = row['key'].replace("''", "'") | ||||
|             prop_dict[conv_key] = row['value'] | ||||
|         prop_dict['uid'] = str(uid) | ||||
|         prop_dict['handle'] = str(uid) | ||||
|         del curs | ||||
|         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 | ||||
| 
 | ||||
| _VIDEO_WIDTH = 640 | ||||
| _VIDEO_HEIGHT = 480 | ||||
| 
 | ||||
| _VIDEO_WIDTH = units.points_to_pixels(160) | ||||
| _VIDEO_HEIGHT = units.points_to_pixels(120) | ||||
| 
 | ||||
| class IntroImage(gtk.EventBox): | ||||
|     __gtype_name__ = "IntroImage" | ||||
|  | ||||
| @ -21,6 +21,7 @@ class ActivityHandle(object): | ||||
|     def __init__(self, activity_id): | ||||
|         self.activity_id = activity_id | ||||
|         self.pservice_id = None | ||||
|         self.object_id = None | ||||
|         self.uri = None | ||||
| 
 | ||||
|     def get_presence_service(self): | ||||
| @ -34,6 +35,8 @@ class ActivityHandle(object): | ||||
|         result = { 'activity_id' : self.activity_id } | ||||
|         if self.pservice_id: | ||||
|             result['pservice_id'] = self.pservice_id | ||||
|         if self.object_id: | ||||
|             result['object_id'] = self.object_id | ||||
|         if self.uri: | ||||
|             result['uri'] = self.uri | ||||
| 
 | ||||
| @ -43,6 +46,8 @@ def create_from_dict(handle_dict): | ||||
|     result = ActivityHandle(handle_dict['activity_id']) | ||||
|     if handle_dict.has_key('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'): | ||||
|         result.uri = handle_dict['uri'] | ||||
| 
 | ||||
|  | ||||
| @ -13,10 +13,101 @@ | ||||
| # 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 | ||||
| import logging | ||||
| 
 | ||||
| import dbus | ||||
| import dbus.glib | ||||
| import gobject | ||||
| 
 | ||||
| import dbus, dbus.glib, gobject | ||||
| 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): | ||||
|     def __init__(self): | ||||
|         self._cache = {} | ||||
| @ -39,9 +130,6 @@ class ObjectCache(object): | ||||
|             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): | ||||
| 
 | ||||
|  | ||||
| @ -96,7 +96,8 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem): | ||||
|             return self._value | ||||
| 
 | ||||
|     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._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 | ||||
| DATE=`date +%Y%m%d` | ||||
| RELEASE=2.34 | ||||
| RELEASE=2.36 | ||||
| TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2 | ||||
| 
 | ||||
| rm sugar-$VERSION.tar.bz2 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Dan Williams
						Dan Williams