Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormike <michael.jmontcalm@gmail.com>2009-10-06 18:12:44 (GMT)
committer mike <michael.jmontcalm@gmail.com>2009-10-06 18:12:44 (GMT)
commit30c560204da219cf40ef3e2344a68b9d015d4d41 (patch)
treebc49bcd055ba1b42d9c9439c4569959a6a400c22
parent940057bee6fb1ae0912e376f731a493fb964c6f2 (diff)
LP 444777 : Adding the Store Proxy interface and equivalent tests
-rw-r--r--tests/storetests.py107
-rw-r--r--tutorius/store.py175
2 files changed, 282 insertions, 0 deletions
diff --git a/tests/storetests.py b/tests/storetests.py
new file mode 100644
index 0000000..da20c00
--- /dev/null
+++ b/tests/storetests.py
@@ -0,0 +1,107 @@
+# Copyright (C) 2009, Tutorius.org
+#
+# 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
+
+import unittest
+
+from sugar.tutorius.store import *
+
+g_tutorial_id = '114db454-b2a1-11de-8cfc-001f5bf747dc'
+g_other_id = '47efc6ee-b2a3-11de-8cfc-001f5bf747dc'
+
+class StoreProxyTest(unittest.TestCase):
+ def setUp(self):
+ self.store = StoreProxy()
+
+ def tearDown(self):
+ pass
+
+ def test_get_categories(self):
+ categories = self.store.get_categories()
+
+ assert isinstance(categories, list), "categories should be a list"
+
+ def test_get_tutorials(self):
+ self.store.get_tutorials()
+
+ def test_get_tutorial_collection(self):
+ collection_list = self.store.get_tutorial_collection('top5_rating')
+
+ assert isinstance(collection_list, list), "get_tutorial_collection should return a list"
+
+ def test_get_latest_version(self):
+ version_dict = self.store.get_latest_version([])
+
+ assert isinstance(version_dict, dict)
+
+ def test_download_tutorial(self):
+ tutorial = self.store.download_tutorial(g_tutorial_id)
+
+ assert tutorial is not None
+
+ def test_login(self):
+ assert self.store.login("unknown_user", "random_password")
+
+ def test_register_new_user(self):
+ user_info = {
+ 'name' : "Albert",
+ 'last_name' : "The Tester",
+ 'location' : 'Mozambique',
+ 'email' : 'albertthetester@mozambique.org'
+ }
+
+ assert self.store.register_new_user(user_info)
+
+
+class StoreProxyLoginTest(unittest.TestCase):
+ def setUp(self):
+ self.store = StoreProxy()
+ self.store.login("unknown_user", "random_password")
+
+ def tearDown(self):
+ session_id = self.store.get_session_id()
+
+ if session_id is not None:
+ self.store.close_session()
+
+ def test_close_session(self):
+ assert self.store.close_session()
+
+ def test_get_session_id(self):
+ session_id = self.store.get_session_id()
+
+ assert session_id is not None
+
+ def test_rate(self):
+ assert self.store.rate(5, g_tutorial_id)
+
+ def test_publish(self):
+ # TODO : We need to send in a real tutorial loaded from
+ # the Vault
+ assert self.store.publish(['This should be a real tutorial...'])
+
+ def test_unpublish(self):
+ # TODO : We need to send in a real tutorial loaded from
+ # the Vault
+ self.store.publish([g_tutorial_id, 'Fake tutorial'])
+
+ assert self.store.unpublish(g_tutorial_id)
+
+ def test_update_published_tutorial(self):
+ # TODO : Run these tests with files from the Vault
+ self.store.publish([g_tutorial_id, 'Fake tutorial'])
+
+ assert self.store.update_published_tutorial(g_tutorial_id, [g_tutorial_id, 'This is an updated tutorial'])
+
diff --git a/tutorius/store.py b/tutorius/store.py
new file mode 100644
index 0000000..dfd6fca
--- /dev/null
+++ b/tutorius/store.py
@@ -0,0 +1,175 @@
+# Copyright (C) 2009, Tutorius.org
+#
+# 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
+
+import urllib
+
+class StoreProxy(object):
+ """
+ Implements a communication channel with the Tutorius Store, where tutorials
+ are shared from around the world. This proxy is meant to offer a one-stop
+ shop to implement all the requests that could be made to the Store.
+ """
+
+ def get_categories(self):
+ """
+ Returns all the categories registered in the store. Categories are used to
+ classify tutorials according to a theme. (e.g. Mathematics, History, etc...)
+
+ @return The list of category names stored on the server.
+ """
+ raise NotImplementerError("get_categories() not implemented")
+
+ def get_tutorials(self, keywords=None, category=None, startIndex=0, numResults=10, sortBy='name'):
+ """
+ Returns the list of tutorials that correspond to the given search criteria.
+
+ @param keywords The list of keywords that should be matched inside the tutorial title
+ or description. If None, the search will not filter the results
+ according to the keywords.
+ @param category The category in which to restrict the search.
+ @param startIndex The index in the result set from which to return results. This is
+ used to allow applications to fetch results one set at a time.
+ @param numResults The max number of results that can be returned
+ @param sortBy The field on which to sort the results
+ @return A list of tutorial meta-data that corresponds to the query
+ """
+ raise NotImplementedError("get_tutorials() not implemented")
+
+ def get_tutorial_collection(self, collection_name):
+ """
+ Returns a list of tutorials corresponding to the given collection name.
+ Collections can be groups like '5 most downloaded' or 'Top 10 ratings'.
+
+ @param collection_name The name of the collection from which we want the
+ meta-data
+ @return A list of tutorial meta-data corresponding to the given group
+ """
+ raise NotImplementedError("get_tutorial_collection() not implemented... yet!")
+
+ def get_latest_version(self, tutorial_id_list):
+ """
+ Returns the latest version number on the server, for each tutorial ID
+ in the list.
+
+ @param tutorial_id_list The list of tutorial IDs from which we want to
+ known the latest version number.
+ @return A dictionary having the tutorial ID as the key and the version
+ as the value.
+ """
+ raise NotImplementedError("get_latest_version() not implemented")
+
+ def download_tutorial(self, tutorial_id, version=None):
+ """
+ Fetches the tutorial file from the server and returns the
+
+ @param tutorial_id The tutorial that we want to get
+ @param version The version number that we want to download. If None,
+ the latest version will be downloaded.
+ @return The downloaded file itself (an in-memory representation of the file,
+ not a path to it on the disk)
+
+ TODO : We should decide if we're saving to disk or in mem.
+ """
+ raise NotImplementedError("downloadTutorial() not implemented")
+
+ def login(self, username, password):
+ """
+ Logs in the user on the store and saves the login status in the proxy
+ state. After a successful logon, the operation requiring a login will
+ be successful.
+
+ @param username
+ @param password
+ @return True if the login was successful, False otherwise
+ """
+ raise NotImplementedError("login() not implemented yet")
+
+ def close_session(self):
+ """
+ Ends the user's session on the server and changes the state of the proxy
+ to disallow the calls to the store that requires to be logged in.
+
+ @return True if the user was disconnected, False otherwise
+ """
+ raise NotImplementedError("close_session() not implemented yet")
+
+ def get_session_id(self):
+ """
+ Gives the current session ID cached in the Store Proxy, or returns
+ None is the user is not logged yet.
+
+ @return The current session's ID, or None if the user is not logged
+ """
+ raise NotImplementedError("get_session_id() not implemented yet")
+
+ def rate(self, value, tutorial_store_id):
+ """
+ Sends a rating for the given tutorial.
+
+ This function requires the user to be logged in.
+
+ @param value The value of the rating. It must be an integer with a value
+ from 1 to 5.
+ @param tutorial_store_id The ID of the tutorial that was rated
+ @return True if the rating was sent to the Store, False otherwise.
+ """
+ raise NotImplementedError("rate() not implemented")
+
+ def publish(self, tutorial):
+ """
+ Sends a tutorial to the store.
+
+ This function requires the user to be logged in.
+
+ @param tutorial The tutorial file to be sent. Note that this is the
+ content itself and not the path to the file.
+ @return True if the tutorial was sent correctly, False otherwise.
+ """
+ raise NotImplemetedError("publish() not implemented")
+
+ def unpublish(self, tutorial_store_id):
+ """
+ Removes a tutorial from the server. The user in the current session
+ needs to be the creator for it to be unpublished. This will remove
+ the file from the server and from all its collections and categories.
+
+ This function requires the user to be logged in.
+
+ @param tutorial_store_id The ID of the tutorial to be removed
+ @return True if the tutorial was properly removed from the server
+ """
+ raise NotImplementedError("unpublish() not implemeted")
+
+ def update_published_tutorial(self, tutorial_id, tutorial):
+ """
+ Sends the new content for the tutorial with the given ID.
+
+ This function requires the user to be logged in.
+
+ @param tutorial_id The ID of the tutorial to be updated
+ @param tutorial The bundled tutorial file content (not a path!)
+ @return True if the tutorial was sent and updated, False otherwise
+ """
+ raise NotImplementedError("update_published_tutorial() not implemented yet")
+
+ def register_new_user(self, user_info):
+ """
+ Creates a new user from the given user information.
+
+ @param user_info A structure containing all the data required to do a login.
+ @return True if the new account was created, false otherwise
+ """
+ raise NotImplementedError("register_new_user() not implemented")