diff --git a/src/sugar3/bundle/__init__.py b/src/sugar3/bundle/__init__.py index 85ebcede..d0237931 100644 --- a/src/sugar3/bundle/__init__.py +++ b/src/sugar3/bundle/__init__.py @@ -14,3 +14,37 @@ # License along with this library; if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. + +import os + +from gi.repository import Gio + +from sugar3.bundle.activitybundle import ActivityBundle +from sugar3.bundle.contentbundle import ContentBundle + + +def bundle_from_archive(path, mime_type=None): + """ + Return an appropriate Bundle object for a given file path. + The bundle type is identified by mime_type, which is guessed if not + provided. + """ + if mime_type is None: + mime_type, certainty = Gio.content_type_guess(path, data=None) + if mime_type == ActivityBundle.MIME_TYPE: + return ActivityBundle(path) + elif mime_type == ContentBundle.MIME_TYPE: + return ContentBundle(path) + return None + + +def bundle_from_dir(path): + """ + Return an appropriate Bundle object for a given directory containing + an unzipped bundle. + """ + if os.path.exists(os.path.join(path, 'activity', 'activity.info')): + return ActivityBundle(path) + elif os.path.exists(os.path.join(path, 'library', 'library.info')): + return ContentBundle(path) + return None diff --git a/src/sugar3/bundle/activitybundle.py b/src/sugar3/bundle/activitybundle.py index ed1c503c..bc58cd8d 100644 --- a/src/sugar3/bundle/activitybundle.py +++ b/src/sugar3/bundle/activitybundle.py @@ -226,10 +226,6 @@ class ActivityBundle(Bundle): raise NotInstalledException return os.path.join(self._path, 'icons') - def get_path(self): - """Get the activity bundle path.""" - return self._path - def get_name(self): """Get the activity user-visible name.""" return self._name @@ -287,9 +283,8 @@ class ActivityBundle(Bundle): """Get whether there should be a visible launcher for the activity""" return self._show_launcher - def install(self, install_dir=None): - if install_dir is None: - install_dir = env.get_user_activities_path() + def install(self): + install_dir = env.get_user_activities_path() self._unzip(install_dir) @@ -348,7 +343,9 @@ class ActivityBundle(Bundle): os.unlink(dst) os.symlink(src, dst) - def uninstall(self, install_path, force=False, delete_profile=False): + def uninstall(self, force=False, delete_profile=False): + install_path = self.get_path() + if os.path.islink(install_path): # Don't remove the actual activity dir if it's a symbolic link # because we may be removing user data. diff --git a/src/sugar3/bundle/contentbundle.py b/src/sugar3/bundle/contentbundle.py index 30cd7e15..190156f7 100644 --- a/src/sugar3/bundle/contentbundle.py +++ b/src/sugar3/bundle/contentbundle.py @@ -26,8 +26,7 @@ import os import urllib from sugar3 import env -from sugar3.bundle.bundle import Bundle, NotInstalledException, \ - MalformedBundleException +from sugar3.bundle.bundle import Bundle, MalformedBundleException from sugar3.bundle.bundleversion import NormalizedVersion from sugar3.bundle.bundleversion import InvalidVersionError @@ -185,6 +184,10 @@ class ContentBundle(Bundle): def get_activity_start(self): return self._activity_start + def get_icon(self): + # To be implemented later + return None + def _run_indexer(self): xdg_data_dirs = os.getenv('XDG_DATA_DIRS', '/usr/local/share/:/usr/share/') @@ -215,29 +218,17 @@ class ContentBundle(Bundle): # needs rethinking while fixing ContentBundle support return self._library_version - def is_installed(self): - if self._zip_file is None: - return True - elif os.path.isdir(self.get_root_dir()): - return ContentBundle(self.get_root_dir()).get_library_version() \ - == self.get_library_version() - else: - return False - def install(self): - # TODO ignore passed install_path argument - # needs rethinking while fixing ContentBundle support install_path = env.get_user_library_path() self._unzip(install_path) self._run_indexer() return self.get_root_dir() - def uninstall(self): - if self._zip_file is None: - if not self.is_installed(): - raise NotInstalledException - install_dir = self._path - else: - install_dir = os.path.join(self.get_root_dir()) + def uninstall(self, force=False, delete_profile=False): + install_dir = self._path self._uninstall(install_dir) self._run_indexer() + + def is_user_activity(self): + # All content bundles are installed in user storage + return True diff --git a/src/sugar3/graphics/objectchooser.py b/src/sugar3/graphics/objectchooser.py index f025363c..3f74c5cd 100644 --- a/src/sugar3/graphics/objectchooser.py +++ b/src/sugar3/graphics/objectchooser.py @@ -125,8 +125,12 @@ class ObjectChooser(object): else: what_filter = self._what_filter - self._chooser_id = journal.ChooseObjectWithFilter( - self._parent_xid, what_filter, self._filter_type) + if self._filter_type is None: + self._chooser_id = journal.ChooseObject( + self._parent_xid, what_filter) + else: + self._chooser_id = journal.ChooseObjectWithFilter( + self._parent_xid, what_filter, self._filter_type) Gdk.threads_leave() try: diff --git a/tests/data/sample.content/index.html b/tests/data/sample.content/index.html new file mode 100644 index 00000000..e69de29b diff --git a/tests/data/sample.content/library/library.info b/tests/data/sample.content/library/library.info new file mode 100644 index 00000000..fb372df7 --- /dev/null +++ b/tests/data/sample.content/library/library.info @@ -0,0 +1,10 @@ +[Library] +name = sample +long_name = sample +global_name = org.sugarlabs.samplecontent +library_version = 1 +host_version = 1 +l10n = false +locale = en +license = CC-BY 2.0 +category = media diff --git a/tests/test_bundle.py b/tests/test_bundle.py new file mode 100644 index 00000000..45257fe6 --- /dev/null +++ b/tests/test_bundle.py @@ -0,0 +1,49 @@ +# Copyright (C) 2013, 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 + +import os +import unittest +import subprocess + +from sugar3.bundle import bundle_from_dir, bundle_from_archive +from sugar3.bundle.activitybundle import ActivityBundle +from sugar3.bundle.contentbundle import ContentBundle + +tests_dir = os.path.dirname(__file__) +data_dir = os.path.join(tests_dir, "data") +SAMPLE_ACTIVITY_PATH = os.path.join(data_dir, 'sample.activity') +SAMPLE_CONTENT_PATH = os.path.join(data_dir, 'sample.content') + + +class TestBundle(unittest.TestCase): + def test_bundle_from_dir(self): + bundle = bundle_from_dir(SAMPLE_ACTIVITY_PATH) + self.assertIsInstance(bundle, ActivityBundle) + bundle = bundle_from_dir(SAMPLE_CONTENT_PATH) + self.assertIsInstance(bundle, ContentBundle) + + def test_activity_bundle_from_archive(self): + os.chdir(SAMPLE_ACTIVITY_PATH) + subprocess.check_call(["./setup.py", "dist_xo"]) + xo_path = os.path.join(".", "dist", "Sample-1.xo") + bundle = bundle_from_archive(xo_path) + self.assertIsInstance(bundle, ActivityBundle) + + def test_content_bundle_from_archive(self): + os.chdir(data_dir) + subprocess.check_call(["zip", "-r", "sample-1.xol", "sample.content"]) + bundle = bundle_from_archive("./sample-1.xol") + self.assertIsInstance(bundle, ContentBundle)