From 9db81af5981882f6dcbc53825e43dcec756b22ff Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Wed, 5 Dec 2012 23:42:54 +0100 Subject: [PATCH 01/11] Remove a few unused keywords --- src/sugar3/activity/bundlebuilder.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/sugar3/activity/bundlebuilder.py b/src/sugar3/activity/bundlebuilder.py index 1450ec24..7e541526 100644 --- a/src/sugar3/activity/bundlebuilder.py +++ b/src/sugar3/activity/bundlebuilder.py @@ -64,10 +64,9 @@ def list_files(base_dir, ignore_dirs=None, ignore_files=None): class Config(object): - def __init__(self, source_dir=None, dist_dir=None, dist_name=None): - self.source_dir = source_dir or os.getcwd() - self.dist_dir = dist_dir or os.path.join(self.source_dir, 'dist') - self.dist_name = dist_name + def __init__(self): + self.source_dir = os.getcwd() + self.dist_dir = os.path.join(self.source_dir, 'dist') self.bundle = None self.version = None self.activity_name = None @@ -90,12 +89,8 @@ class Config(object): self.bundle_name = reduce(operator.add, self.activity_name.split()) self.bundle_root_dir = self.bundle_name + '.activity' self.tar_root_dir = '%s-%s' % (self.bundle_name, self.version) - - if self.dist_name: - self.xo_name = self.tar_name = self.dist_name - else: - self.xo_name = '%s-%s.xo' % (self.bundle_name, self.version) - self.tar_name = '%s-%s.tar.bz2' % (self.bundle_name, self.version) + self.xo_name = '%s-%s.xo' % (self.bundle_name, self.version) + self.tar_name = '%s-%s.tar.bz2' % (self.bundle_name, self.version) class Builder(object): From 07d593fe524ee0c358021f2599a8f00690dd81a1 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 00:09:41 +0100 Subject: [PATCH 02/11] Rework the install to use git files Instead of installing everything except a few ignored files. This is consistent with the other packagers. --- src/sugar3/activity/bundlebuilder.py | 50 +++++++++++++--------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/sugar3/activity/bundlebuilder.py b/src/sugar3/activity/bundlebuilder.py index 7e541526..68774360 100644 --- a/src/sugar3/activity/bundlebuilder.py +++ b/src/sugar3/activity/bundlebuilder.py @@ -97,6 +97,7 @@ class Builder(object): def __init__(self, config): self.config = config + self.locale_dir = os.path.join(self.config.source_dir, 'locale') def build(self): self.build_locale() @@ -108,10 +109,8 @@ class Builder(object): logging.warn('Missing po/ dir, cannot build_locale') return - locale_dir = os.path.join(self.config.source_dir, 'locale') - - if os.path.exists(locale_dir): - shutil.rmtree(locale_dir) + if os.path.exists(self.locale_dir): + shutil.rmtree(self.locale_dir) for f in os.listdir(po_dir): if not f.endswith('.po') or f == 'pseudo.po': @@ -140,10 +139,8 @@ class Builder(object): f.write('summary = %s\n' % translated_summary) f.close() - def get_files(self): - allfiles = list_files(self.config.source_dir, - IGNORE_DIRS, IGNORE_FILES) - return allfiles + def get_locale_files(self): + return list_files(self.locale_dir, IGNORE_DIRS, IGNORE_FILES) class Packager(object): @@ -195,10 +192,9 @@ class XOPackager(Packager): for f in self.get_files_in_git(): bundle_zip.write(os.path.join(self.config.source_dir, f), os.path.join(self.config.bundle_root_dir, f)) - locale_dir = os.path.join(self.config.source_dir, 'locale') - locale_files = list_files(locale_dir, IGNORE_DIRS, IGNORE_FILES) - for f in locale_files: - bundle_zip.write(os.path.join(locale_dir, f), + + for f in self.builder.get_locale_files(): + bundle_zip.write(os.path.join(self.builder.locale_dir, f), os.path.join(self.config.bundle_root_dir, 'locale', f)) @@ -220,19 +216,11 @@ class SourcePackager(Packager): tar.close() -class Installer(object): - IGNORES = ['po/*', 'MANIFEST', 'AUTHORS'] - +class Installer(Packager): def __init__(self, builder): self.config = builder.config self.builder = builder - def should_ignore(self, f): - for pattern in self.IGNORES: - if fnmatch(f, pattern): - return True - return False - def install(self, prefix): self.builder.build() @@ -240,13 +228,21 @@ class Installer(object): self.config.bundle_root_dir) source_to_dest = {} - for f in self.builder.get_files(): - if self.should_ignore(f): - pass - elif f.startswith('locale/') and f.endswith('.mo'): - source_to_dest[f] = os.path.join(prefix, 'share', f) + + for f in self.get_files_in_git(): + source_path = os.path.join(self.config.source_dir, f) + dest_path = os.path.join(activity_path, f) + source_to_dest[source_path] = dest_path + + for f in self.builder.get_locale_files(): + source_path = os.path.join(self.builder.locale_dir, f) + + if source_path.endswith(".mo"): + dest_path = os.path.join(prefix, 'share', 'locale', f) else: - source_to_dest[f] = os.path.join(activity_path, f) + dest_path = os.path.join(activity_path, 'locale', f) + + source_to_dest[source_path] = dest_path for source, dest in source_to_dest.items(): print 'Install %s to %s.' % (source, dest) From c5f30a9fbe059bda46e663821e16c70bfaeb469f Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 00:14:14 +0100 Subject: [PATCH 03/11] Support out of source directory builds It works similarly to automake. The current working directory is used as build directory. --- src/sugar3/activity/bundlebuilder.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sugar3/activity/bundlebuilder.py b/src/sugar3/activity/bundlebuilder.py index 68774360..995b0ad6 100644 --- a/src/sugar3/activity/bundlebuilder.py +++ b/src/sugar3/activity/bundlebuilder.py @@ -64,9 +64,10 @@ def list_files(base_dir, ignore_dirs=None, ignore_files=None): class Config(object): - def __init__(self): - self.source_dir = os.getcwd() - self.dist_dir = os.path.join(self.source_dir, 'dist') + def __init__(self, source_dir): + self.source_dir = source_dir + self.build_dir = os.getcwd() + self.dist_dir = os.path.join(self.build_dir, 'dist') self.bundle = None self.version = None self.activity_name = None @@ -97,7 +98,7 @@ class Builder(object): def __init__(self, config): self.config = config - self.locale_dir = os.path.join(self.config.source_dir, 'locale') + self.locale_dir = os.path.join(self.config.build_dir, 'locale') def build(self): self.build_locale() @@ -119,7 +120,7 @@ class Builder(object): file_name = os.path.join(po_dir, f) lang = f[:-3] - localedir = os.path.join(self.config.source_dir, 'locale', lang) + localedir = os.path.join(self.config.build_dir, 'locale', lang) mo_path = os.path.join(localedir, 'LC_MESSAGES') if not os.path.isdir(mo_path): os.makedirs(mo_path) @@ -218,7 +219,7 @@ class SourcePackager(Packager): class Installer(Packager): def __init__(self, builder): - self.config = builder.config + Packager.__init__(self, builder.config) self.builder = builder def install(self, prefix): @@ -328,6 +329,8 @@ def cmd_genpot(config, args): print 'Usage: %prog genpot' return + os.chdir(config.source_dir) + po_path = os.path.join(config.source_dir, 'po') if not os.path.isdir(po_path): os.mkdir(po_path) @@ -394,7 +397,8 @@ def start(): parser.disable_interspersed_args() (options_, args) = parser.parse_args() - config = Config() + source_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + config = Config(source_dir) try: globals()['cmd_' + args[0]](config, args[1:]) From 148655635f0b59a19eb2c658086f004af1c4ab64 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 18:21:03 +0100 Subject: [PATCH 04/11] Add a make target for tests We are running the existing test_mime.py. All the other tests which are not unit tests but more examples of code one can run interactively are moved to the example directory. --- Makefile.am | 6 ++++ {tests/graphics => examples}/buttons.py | 0 .../graphics => examples}/cellrenderericon.py | 0 {tests/graphics => examples}/common.py | 0 {tests/graphics => examples}/customdestroy.py | 0 .../graphics => examples}/gtktreesensitive.py | 0 {tests/graphics => examples}/iconbadges.py | 0 {tests/graphics => examples}/iconcache.py | 0 {tests/graphics => examples}/iconwidget.py | 0 {tests/graphics => examples}/intro.py | 0 {tests/graphics => examples}/progress.py | 0 {tests/graphics => examples}/tabs.py | 0 {tests/graphics => examples}/ticket2855.py | 0 {tests/graphics => examples}/ticket2999.py | 0 {tests/graphics => examples}/ticket3000.py | 0 .../graphics => examples}/toolbarpalettes.py | 0 {tests/graphics => examples}/toolbuttons.py | 0 {tests/graphics => examples}/tray.py | 0 tests/lib/runall.py | 28 ------------------- tests/{lib => }/test_mime.py | 0 20 files changed, 6 insertions(+), 28 deletions(-) rename {tests/graphics => examples}/buttons.py (100%) rename {tests/graphics => examples}/cellrenderericon.py (100%) rename {tests/graphics => examples}/common.py (100%) rename {tests/graphics => examples}/customdestroy.py (100%) rename {tests/graphics => examples}/gtktreesensitive.py (100%) rename {tests/graphics => examples}/iconbadges.py (100%) rename {tests/graphics => examples}/iconcache.py (100%) rename {tests/graphics => examples}/iconwidget.py (100%) rename {tests/graphics => examples}/intro.py (100%) rename {tests/graphics => examples}/progress.py (100%) rename {tests/graphics => examples}/tabs.py (100%) rename {tests/graphics => examples}/ticket2855.py (100%) rename {tests/graphics => examples}/ticket2999.py (100%) rename {tests/graphics => examples}/ticket3000.py (100%) rename {tests/graphics => examples}/toolbarpalettes.py (100%) rename {tests/graphics => examples}/toolbuttons.py (100%) rename {tests/graphics => examples}/tray.py (100%) delete mode 100644 tests/lib/runall.py rename tests/{lib => }/test_mime.py (100%) diff --git a/Makefile.am b/Makefile.am index 86a095c4..763c25ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,3 +12,9 @@ EXTRA_DIST = \ intltool-extract.in SUBDIRS = bin src po + +check: test + +test: + cd $(top_srcdir)/tests && \ + python -m unittest discover diff --git a/tests/graphics/buttons.py b/examples/buttons.py similarity index 100% rename from tests/graphics/buttons.py rename to examples/buttons.py diff --git a/tests/graphics/cellrenderericon.py b/examples/cellrenderericon.py similarity index 100% rename from tests/graphics/cellrenderericon.py rename to examples/cellrenderericon.py diff --git a/tests/graphics/common.py b/examples/common.py similarity index 100% rename from tests/graphics/common.py rename to examples/common.py diff --git a/tests/graphics/customdestroy.py b/examples/customdestroy.py similarity index 100% rename from tests/graphics/customdestroy.py rename to examples/customdestroy.py diff --git a/tests/graphics/gtktreesensitive.py b/examples/gtktreesensitive.py similarity index 100% rename from tests/graphics/gtktreesensitive.py rename to examples/gtktreesensitive.py diff --git a/tests/graphics/iconbadges.py b/examples/iconbadges.py similarity index 100% rename from tests/graphics/iconbadges.py rename to examples/iconbadges.py diff --git a/tests/graphics/iconcache.py b/examples/iconcache.py similarity index 100% rename from tests/graphics/iconcache.py rename to examples/iconcache.py diff --git a/tests/graphics/iconwidget.py b/examples/iconwidget.py similarity index 100% rename from tests/graphics/iconwidget.py rename to examples/iconwidget.py diff --git a/tests/graphics/intro.py b/examples/intro.py similarity index 100% rename from tests/graphics/intro.py rename to examples/intro.py diff --git a/tests/graphics/progress.py b/examples/progress.py similarity index 100% rename from tests/graphics/progress.py rename to examples/progress.py diff --git a/tests/graphics/tabs.py b/examples/tabs.py similarity index 100% rename from tests/graphics/tabs.py rename to examples/tabs.py diff --git a/tests/graphics/ticket2855.py b/examples/ticket2855.py similarity index 100% rename from tests/graphics/ticket2855.py rename to examples/ticket2855.py diff --git a/tests/graphics/ticket2999.py b/examples/ticket2999.py similarity index 100% rename from tests/graphics/ticket2999.py rename to examples/ticket2999.py diff --git a/tests/graphics/ticket3000.py b/examples/ticket3000.py similarity index 100% rename from tests/graphics/ticket3000.py rename to examples/ticket3000.py diff --git a/tests/graphics/toolbarpalettes.py b/examples/toolbarpalettes.py similarity index 100% rename from tests/graphics/toolbarpalettes.py rename to examples/toolbarpalettes.py diff --git a/tests/graphics/toolbuttons.py b/examples/toolbuttons.py similarity index 100% rename from tests/graphics/toolbuttons.py rename to examples/toolbuttons.py diff --git a/tests/graphics/tray.py b/examples/tray.py similarity index 100% rename from tests/graphics/tray.py rename to examples/tray.py diff --git a/tests/lib/runall.py b/tests/lib/runall.py deleted file mode 100644 index ae1bb3ae..00000000 --- a/tests/lib/runall.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# 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 unittest - -import test_mime - -runner = unittest.TextTestRunner() -loader = unittest.TestLoader() - -suite = unittest.TestSuite() -suite.addTest(loader.loadTestsFromModule(test_mime)) - -runner.run(suite) diff --git a/tests/lib/test_mime.py b/tests/test_mime.py similarity index 100% rename from tests/lib/test_mime.py rename to tests/test_mime.py From f66fbe4c082761a55e4ded4a6422d598b37560ea Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 22:19:28 +0100 Subject: [PATCH 05/11] Add tests for bundlebuilder --- Makefile.am | 8 +- po/POTFILES.skip | 1 + tests/data/sample.activity/activity.py | 8 + .../activity/activity-sample.svg | 26 +++ .../sample.activity/activity/activity.info | 7 + tests/data/sample.activity/po/Sample.pot | 26 +++ tests/data/sample.activity/po/es.po | 26 +++ tests/data/sample.activity/setup.py | 5 + tests/test_bundlebuilder.py | 164 ++++++++++++++++++ 9 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 tests/data/sample.activity/activity.py create mode 100644 tests/data/sample.activity/activity/activity-sample.svg create mode 100644 tests/data/sample.activity/activity/activity.info create mode 100644 tests/data/sample.activity/po/Sample.pot create mode 100644 tests/data/sample.activity/po/es.po create mode 100755 tests/data/sample.activity/setup.py create mode 100644 tests/test_bundlebuilder.py diff --git a/Makefile.am b/Makefile.am index 763c25ca..2240471f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,9 @@ ACLOCAL_AMFLAGS = -I m4 DISTCHECK_CONFIGURE_FLAGS = --enable-introspection +TESTS_TMPDIR=$(abs_builddir)/tests-tmp +TESTS_PYTHONPATH=$(abs_srcdir)/src:$(PYTHONPATH) + DISTCLEANFILES = \ intltool-extract \ intltool-merge \ @@ -17,4 +20,7 @@ check: test test: cd $(top_srcdir)/tests && \ - python -m unittest discover + mkdir -p $(TESTS_TMPDIR) && \ + TMPDIR=$(TESTS_TMPDIR) PYTHONPATH=$(TESTS_PYTHONPATH) \ + python -m unittest discover && \ + rm -rf $(TESTS_TMPDIR) diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 8dd3dfef..3eea3717 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -4,3 +4,4 @@ src/sugar3/eggdesktopfile.c src/sugar3/eggsmclient.c src/sugar3/gsm-xsmp.c +tests/data/sample.activity/activity.py diff --git a/tests/data/sample.activity/activity.py b/tests/data/sample.activity/activity.py new file mode 100644 index 00000000..97d3c986 --- /dev/null +++ b/tests/data/sample.activity/activity.py @@ -0,0 +1,8 @@ +from gettext import gettext as _ + +from sugar3.activity import activity + +class SampleActivity(activity.Activity): + def __init__(self, handle): + activity.Activity.__init__(self, handle) + self._text = _("Text string") diff --git a/tests/data/sample.activity/activity/activity-sample.svg b/tests/data/sample.activity/activity/activity-sample.svg new file mode 100644 index 00000000..8da7c63b --- /dev/null +++ b/tests/data/sample.activity/activity/activity-sample.svg @@ -0,0 +1,26 @@ + + +]> + + + + + + + + + + + + + + diff --git a/tests/data/sample.activity/activity/activity.info b/tests/data/sample.activity/activity/activity.info new file mode 100644 index 00000000..4cf7f755 --- /dev/null +++ b/tests/data/sample.activity/activity/activity.info @@ -0,0 +1,7 @@ +[Activity] +name = Sample +activity_version = 1 +bundle_id = org.sugarlabs.Sample +exec = sugar-activity activity.SampleActivity +icon = activity-sample +license = GPLv2+ diff --git a/tests/data/sample.activity/po/Sample.pot b/tests/data/sample.activity/po/Sample.pot new file mode 100644 index 00000000..0cee3579 --- /dev/null +++ b/tests/data/sample.activity/po/Sample.pot @@ -0,0 +1,26 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-12-06 20:10+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: activity/activity.info:2 +msgid "Sample" +msgstr "" + +#: activity.py:8 +msgid "Text string" +msgstr "" diff --git a/tests/data/sample.activity/po/es.po b/tests/data/sample.activity/po/es.po new file mode 100644 index 00000000..a1a6adb6 --- /dev/null +++ b/tests/data/sample.activity/po/es.po @@ -0,0 +1,26 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-12-06 20:10+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: activity/activity.info:2 +msgid "Sample" +msgstr "" + +#: activity.py:8 +msgid "Text string" +msgstr "" diff --git a/tests/data/sample.activity/setup.py b/tests/data/sample.activity/setup.py new file mode 100755 index 00000000..ad218b21 --- /dev/null +++ b/tests/data/sample.activity/setup.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +from sugar3.activity import bundlebuilder + +bundlebuilder.start() diff --git a/tests/test_bundlebuilder.py b/tests/test_bundlebuilder.py new file mode 100644 index 00000000..687b8c6f --- /dev/null +++ b/tests/test_bundlebuilder.py @@ -0,0 +1,164 @@ +# Copyright (C) 2012, Daniel Narvaez +# +# 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 shutil +import subprocess +import tempfile +import tarfile +import zipfile + +tests_dir = os.path.dirname(__file__) +data_dir = os.path.join(tests_dir, "data") + +class TestGit(unittest.TestCase): + _source_files = ["activity.py", + "setup.py", + "po/Sample.pot", + "po/es.po", + "activity/activity.info", + "activity/activity-sample.svg"] + + _activity_locale_files = ["locale/es/activity.linfo"] + + _share_locale_files = ["locale/es/LC_MESSAGES/org.sugarlabs.Sample.mo"] + + def _create_repo(self): + cwd = os.getcwd() + path = tempfile.mkdtemp() + os.chdir(path) + + subprocess.check_call(["git", "init"]) + subprocess.check_call(["git", "config", "user.name", "Test Test"]) + subprocess.check_call(["git", "config", "user.email", "test@test.org"]) + + for source in self._source_files: + source_path = os.path.join(data_dir, "sample.activity", source) + dest_path = os.path.join(path, source) + + try: + os.makedirs(os.path.dirname(dest_path)) + except OSError: + pass + + shutil.copyfile(source_path, dest_path) + shutil.copymode(source_path, dest_path) + + subprocess.check_call(["git", "add", source]) + + subprocess.check_call(["git", "commit", "-m", "Initial commit", "-a"]) + + os.chdir(cwd) + + return path + + def _strip_root_dir(self, paths): + return [path[path.find("/") + 1:] for path in paths] + + def _test_dist_xo(self, source_path, build_path): + cwd = os.getcwd() + os.chdir(build_path) + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "dist_xo"]) + + xo_path = os.path.join(build_path, "dist", "Sample-1.xo") + filenames = zipfile.ZipFile(xo_path).namelist() + + stripped_filenames = self._strip_root_dir(filenames) + expected = self._source_files[:] + expected.extend(self._share_locale_files) + expected.extend(self._activity_locale_files) + self.assertItemsEqual(stripped_filenames, expected) + + os.chdir(cwd) + + def _test_dist_source(self, source_path, build_path): + cwd = os.getcwd() + os.chdir(build_path) + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "dist_source"]) + + xo_path = os.path.join(build_path, "dist", "Sample-1.tar.bz2") + filenames = tarfile.open(name=xo_path, mode="r:bz2").getnames() + + stripped_filenames = self._strip_root_dir(filenames) + self.assertItemsEqual(stripped_filenames, self._source_files) + + os.chdir(cwd) + + def _test_install(self, source_path, build_path): + install_path = tempfile.mkdtemp() + + cwd = os.getcwd() + os.chdir(build_path) + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "install", "--prefix", install_path]) + + filenames = [] + activity_dir = os.path.join(install_path, "share", + "sugar", "activities", "Sample.activity") + for root, dirs, files in os.walk(activity_dir): + rel_root = root[len(activity_dir) + 1:] + filenames.extend([os.path.join(rel_root, name) for name in files]) + + expected = self._source_files[:] + expected.extend(self._activity_locale_files) + + self.assertItemsEqual(filenames, expected) + + filenames = [] + share_dir = os.path.join(install_path, "share") + locale_dir = os.path.join(share_dir, "locale") + for root, dirs, files in os.walk(locale_dir): + rel_root = root[len(share_dir) + 1:] + for name in files: + if "org.sugarlabs.Sample" in name: + filenames.append(os.path.join(rel_root, name)) + + self.assertItemsEqual(filenames, self._share_locale_files) + + os.chdir(cwd) + + def test_dist_xo_in_source(self): + repo_path = self._create_repo() + self._test_dist_xo(repo_path, repo_path) + + def test_dist_xo_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_dist_xo(repo_path, build_path) + + def test_dist_source_in_source(self): + repo_path = self._create_repo() + self._test_dist_source(repo_path, repo_path) + + def test_dist_source_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_dist_source(repo_path, build_path) + + def test_install_in_source(self): + repo_path = self._create_repo() + self._test_install(repo_path, repo_path) + + def test_install_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_install(repo_path, build_path) From ac153f3cdc94369cf5900093e52d7b232f550183 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 23:03:21 +0100 Subject: [PATCH 06/11] Add test for the build command --- tests/test_bundlebuilder.py | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/test_bundlebuilder.py b/tests/test_bundlebuilder.py index 687b8c6f..fc99fda4 100644 --- a/tests/test_bundlebuilder.py +++ b/tests/test_bundlebuilder.py @@ -37,6 +37,11 @@ class TestGit(unittest.TestCase): _share_locale_files = ["locale/es/LC_MESSAGES/org.sugarlabs.Sample.mo"] + def _get_all_locale_files(self): + expected = self._share_locale_files[:] + expected.extend(self._activity_locale_files) + return expected + def _create_repo(self): cwd = os.getcwd() path = tempfile.mkdtemp() @@ -81,8 +86,7 @@ class TestGit(unittest.TestCase): stripped_filenames = self._strip_root_dir(filenames) expected = self._source_files[:] - expected.extend(self._share_locale_files) - expected.extend(self._activity_locale_files) + expected.extend(self._get_all_locale_files()) self.assertItemsEqual(stripped_filenames, expected) os.chdir(cwd) @@ -102,6 +106,24 @@ class TestGit(unittest.TestCase): os.chdir(cwd) + def _test_build(self, source_path, build_path): + cwd = os.getcwd() + os.chdir(build_path) + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "build"]) + + locale_path = os.path.join(build_path, "locale") + + filenames = [] + for root, dirs, files in os.walk(locale_path): + rel_root = root[len(build_path) + 1:] + filenames.extend([os.path.join(rel_root, name) for name in files]) + + self.assertItemsEqual(filenames, self._get_all_locale_files()) + + os.chdir(cwd) + def _test_install(self, source_path, build_path): install_path = tempfile.mkdtemp() @@ -162,3 +184,12 @@ class TestGit(unittest.TestCase): repo_path = self._create_repo() build_path = tempfile.mkdtemp() self._test_install(repo_path, build_path) + + def test_build_in_source(self): + repo_path = self._create_repo() + self._test_build(repo_path, repo_path) + + def test_build_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_build(repo_path, build_path) From 617c11a078cf4225dd591dffc67e6b495291aae0 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 23:11:13 +0100 Subject: [PATCH 07/11] Add test for the genpot command --- tests/test_bundlebuilder.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_bundlebuilder.py b/tests/test_bundlebuilder.py index fc99fda4..d8292817 100644 --- a/tests/test_bundlebuilder.py +++ b/tests/test_bundlebuilder.py @@ -123,6 +123,20 @@ class TestGit(unittest.TestCase): self.assertItemsEqual(filenames, self._get_all_locale_files()) os.chdir(cwd) + + def _test_genpot(self, source_path, build_path): + cwd = os.getcwd() + os.chdir(build_path) + + pot_path = os.path.join(source_path, "po", "Sample.pot") + os.unlink(pot_path) + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "genpot"]) + + self.assertTrue(os.path.exists(pot_path)) + + os.chdir(cwd) def _test_install(self, source_path, build_path): install_path = tempfile.mkdtemp() @@ -193,3 +207,12 @@ class TestGit(unittest.TestCase): repo_path = self._create_repo() build_path = tempfile.mkdtemp() self._test_build(repo_path, build_path) + + def test_genpot_in_source(self): + repo_path = self._create_repo() + self._test_genpot(repo_path, repo_path) + + def test_genpot_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_genpot(repo_path, build_path) From 65560b0b945e0104a7b7be79bbcd1ba20004f32b Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 23:20:14 +0100 Subject: [PATCH 08/11] Add a SUGAR_ACTIVITIES_PATH environment variable Useful for tests but perhaps for other stuff too. --- src/sugar3/env.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sugar3/env.py b/src/sugar3/env.py index e681f4f7..23bb0ab0 100644 --- a/src/sugar3/env.py +++ b/src/sugar3/env.py @@ -51,8 +51,8 @@ def get_logs_path(path=None): def get_user_activities_path(): - return os.path.expanduser('~/Activities') - + return os.environ.get("SUGAR_ACTIVITIES_PATH", + os.path.expanduser('~/Activities')) def get_user_library_path(): return os.path.expanduser('~/Library') From 5ad6c4e23662ae2f2cb8c40f75166b963b115d13 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Thu, 6 Dec 2012 23:21:02 +0100 Subject: [PATCH 09/11] Add test for dev command --- tests/test_bundlebuilder.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test_bundlebuilder.py b/tests/test_bundlebuilder.py index d8292817..46a02a1d 100644 --- a/tests/test_bundlebuilder.py +++ b/tests/test_bundlebuilder.py @@ -124,6 +124,23 @@ class TestGit(unittest.TestCase): os.chdir(cwd) + def _test_dev(self, source_path, build_path): + activities_path = tempfile.mkdtemp() + + cwd = os.getcwd() + os.chdir(build_path) + + os.environ["SUGAR_ACTIVITIES_PATH"] = activities_path + + setup_path = os.path.join(source_path, "setup.py") + subprocess.call([setup_path, "dev"]) + + activity_py_path = os.path.join(activities_path, "Sample.activity", + "activity.py") + self.assertTrue(os.path.exists(activity_py_path)) + + os.chdir(cwd) + def _test_genpot(self, source_path, build_path): cwd = os.getcwd() os.chdir(build_path) @@ -208,6 +225,15 @@ class TestGit(unittest.TestCase): build_path = tempfile.mkdtemp() self._test_build(repo_path, build_path) + def test_dev_in_source(self): + repo_path = self._create_repo() + self._test_genpot(repo_path, repo_path) + + def test_dev_out_of_source(self): + repo_path = self._create_repo() + build_path = tempfile.mkdtemp() + self._test_dev(repo_path, build_path) + def test_genpot_in_source(self): repo_path = self._create_repo() self._test_genpot(repo_path, repo_path) From e6397cf2db5159b006717ba146639c80f99c4c40 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Fri, 7 Dec 2012 16:53:50 +0100 Subject: [PATCH 10/11] Some initial infrastructure for UI tests The uitree module exposes the at-spi tree. We can use it to do functional tests of the UI, by checking if the expected widgets exists, clicking them etc. A simple example of how this can be used is in the test, which runs a window and check that it has the expected button. --- configure.ac | 1 + src/sugar3/Makefile.am | 9 ++- src/sugar3/test/Makefile.am | 4 + src/sugar3/test/__init__.py | 0 src/sugar3/test/uitree.py | 153 ++++++++++++++++++++++++++++++++++++ tests/test_uitree.py | 52 ++++++++++++ 6 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 src/sugar3/test/Makefile.am create mode 100644 src/sugar3/test/__init__.py create mode 100644 src/sugar3/test/uitree.py create mode 100644 tests/test_uitree.py diff --git a/configure.ac b/configure.ac index fefb8e80..b55db4d5 100644 --- a/configure.ac +++ b/configure.ac @@ -53,5 +53,6 @@ src/sugar3/event-controller/Makefile src/sugar3/presence/Makefile src/sugar3/datastore/Makefile src/sugar3/dispatch/Makefile +src/sugar3/test/Makefile po/Makefile.in ]) diff --git a/src/sugar3/Makefile.am b/src/sugar3/Makefile.am index ddea9c85..24ef9aa1 100644 --- a/src/sugar3/Makefile.am +++ b/src/sugar3/Makefile.am @@ -1,4 +1,11 @@ -SUBDIRS = activity bundle event-controller graphics presence datastore dispatch +SUBDIRS = activity \ + bundle \ + event-controller \ + graphics \ + presence \ + datastore \ + dispatch \ + test sugardir = $(pythondir)/sugar3 sugar_PYTHON = \ diff --git a/src/sugar3/test/Makefile.am b/src/sugar3/test/Makefile.am new file mode 100644 index 00000000..0748c137 --- /dev/null +++ b/src/sugar3/test/Makefile.am @@ -0,0 +1,4 @@ +sugardir = $(pythondir)/sugar3/test +sugar_PYTHON = \ + __init__.py \ + uitree.py diff --git a/src/sugar3/test/__init__.py b/src/sugar3/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/sugar3/test/uitree.py b/src/sugar3/test/uitree.py new file mode 100644 index 00000000..34611a44 --- /dev/null +++ b/src/sugar3/test/uitree.py @@ -0,0 +1,153 @@ +# Copyright (C) 2012, Daniel Narvaez +# +# 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 + +""" +UNSTABLE. +""" + +import time + +from gi.repository import Atspi + +Atspi.set_timeout(-1, -1) + +def get_root(): + return Node(Atspi.get_desktop(0)) + +def _retry_find(func): + def wrapped(*args, **kwargs): + result = None + n_retries = 1 + + while n_retries <= 10: + print "Try %d, name=%s role_name=%s" % \ + (n_retries, + kwargs.get("name", None), + kwargs.get("role_name", None)) + + result = func(*args, **kwargs) + expect_none = kwargs.get("expect_none", False) + if (not expect_none and result) or \ + (expect_none and not result): + return result + + time.sleep(5) + n_retries = n_retries + 1 + + get_root().dump() + + return result + + return wrapped + +class Node: + def __init__(self, accessible): + self._accessible = accessible + + def dump(self): + self._crawl_accessible(self, 0) + + def do_action(self, name): + for i in range(self._accessible.get_n_actions()): + if Atspi.Action.get_name(self._accessible, i) == name: + self._accessible.do_action(i) + + def click(self, button=1): + point = self._accessible.get_position(Atspi.CoordType.SCREEN) + Atspi.generate_mouse_event(point.x, point.y, "b%sc" % button) + + @property + def name(self): + return self._accessible.get_name() + + @property + def role_name(self): + return self._accessible.get_role_name() + + @property + def text(self): + return Atspi.Text.get_text(self._accessible, 0, -1) + + def get_children(self): + children = [] + + for i in range(self._accessible.get_child_count()): + child = self._accessible.get_child_at_index(i) + + # We sometimes get none children from atspi + if child is not None: + children.append(Node(child)) + + return children + + @_retry_find + def find_children(self, name=None, role_name=None): + def predicate(node): + return self._predicate(node, name, role_name) + + descendants = [] + self._find_all_descendants(self, predicate, descendants) + if not descendants: + return [] + + return descendants + + @_retry_find + def find_child(self, name=None, role_name=None, expect_none=False): + def predicate(node): + return self._predicate(node, name, role_name) + + node = self._find_descendant(self, predicate) + if node is None: + return None + + return node + + def __str__(self): + return "[%s | %s]" % (self.name, self.role_name) + + def _predicate(self, node, name, role_name): + if name is not None and name != node.name: + return False + + if role_name is not None and role_name != node.role_name: + return False + + return True + + def _find_descendant(self, node, predicate): + if predicate(node): + return node + + for child in node.get_children(): + descendant = self._find_descendant(child, predicate) + if descendant is not None: + return descendant + + return None + + def _find_all_descendants(self, node, predicate, matches): + if predicate(node): + matches.append(node) + + for child in node.get_children(): + self._find_all_descendants(child, predicate, matches) + + def _crawl_accessible(self, node, depth): + print " " * depth + str(node) + + for child in node.get_children(): + self._crawl_accessible(child, depth + 1) diff --git a/tests/test_uitree.py b/tests/test_uitree.py new file mode 100644 index 00000000..d640e10d --- /dev/null +++ b/tests/test_uitree.py @@ -0,0 +1,52 @@ +# Copyright (C) 2012, Daniel Narvaez +# +# 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 sys +import subprocess +import unittest + +from sugar3.test import uitree + +class TestUITree(unittest.TestCase): + def test_tree(self): + process = subprocess.Popen(["python", __file__, "show_window1"]) + + try: + root = uitree.get_root() + window = root.find_child(name="window1", role_name="frame") + button = window.find_child(name="button1", role_name="push button") + finally: + process.terminate() + + self.assertIsNotNone(button) + +def show_window1(): + from gi.repository import Gtk + from gi.repository import GLib + + window = Gtk.Window() + window.set_title("window1") + + button = Gtk.Button(label="button1") + window.add(button) + button.show() + + window.show() + + Gtk.main() + +if __name__ == '__main__': + globals()[sys.argv[1]]() From 6202d4d5cc0d0872bc6989ddbff1f2be652504cd Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Sun, 9 Dec 2012 15:29:45 +0100 Subject: [PATCH 11/11] Bind xdgmime in SugarExt And use it in the sugar3.mime modules. This allows to get rid of the pygtk generated sugarbase module, along with the wrapping code. Also add more cases to test_time to make sure everything is still working. --- configure.ac | 5 -- src/sugar3/Makefile.am | 75 ++++++++++---------------- src/sugar3/_sugarbaseext.defs | 33 ------------ src/sugar3/_sugarbaseext.override | 88 ------------------------------- src/sugar3/_sugarbaseextmodule.c | 40 -------------- src/sugar3/mime.py | 11 ++-- src/sugar3/xdgmime.c | 12 +++++ tests/data/mime.svg | 3 ++ tests/test_mime.py | 21 ++++++-- 9 files changed, 65 insertions(+), 223 deletions(-) delete mode 100644 src/sugar3/_sugarbaseext.defs delete mode 100644 src/sugar3/_sugarbaseext.override delete mode 100644 src/sugar3/_sugarbaseextmodule.c create mode 100644 tests/data/mime.svg diff --git a/configure.ac b/configure.ac index b55db4d5..d7efc06f 100644 --- a/configure.ac +++ b/configure.ac @@ -18,14 +18,9 @@ AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal]) AM_PATH_PYTHON AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)]) -AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no) - PKG_CHECK_MODULES(EXT, gtk+-3.0 gdk-3.0 gdk-pixbuf-2.0 sm ice alsa librsvg-2.0 xfixes xi x11) -PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` -AC_SUBST(PYGTK_DEFSDIR) - GLIB_MKENUMS=`$PKG_CONFIG glib-2.0 --variable=glib_mkenums` AC_SUBST(GLIB_MKENUMS) diff --git a/src/sugar3/Makefile.am b/src/sugar3/Makefile.am index 24ef9aa1..650bf8ec 100644 --- a/src/sugar3/Makefile.am +++ b/src/sugar3/Makefile.am @@ -18,11 +18,28 @@ sugar_PYTHON = \ session.py \ util.py +XDG_MIME_SOURCES = \ + xdgmime.c \ + xdgmime.h \ + xdgmimealias.c \ + xdgmimealias.h \ + xdgmimecache.c \ + xdgmimecache.h \ + xdgmimeglob.c \ + xdgmimeglob.h \ + xdgmimeint.c \ + xdgmimeint.h \ + xdgmimemagic.c \ + xdgmimemagic.h \ + xdgmimeparent.c \ + xdgmimeparent.h + lib_LTLIBRARIES = libsugarext.la -libsugarext_la_CFLAGS = \ - -DHAVE_ALSA \ - $(EXT_CFLAGS) \ +libsugarext_la_CFLAGS = \ + -DHAVE_ALSA \ + -DXDG_PREFIX=sugar_mime \ + $(EXT_CFLAGS) \ $(WARN_CFLAGS) libsugarext_la_LDFLAGS = $(LDADD) @@ -62,51 +79,12 @@ libsugarext_la_SOURCES = \ sugar-key-grabber.c \ sugar-key-grabber.h \ sugar-wm.c \ - sugar-wm.h - -sugar_LTLIBRARIES = _sugarbaseext.la - -_sugarbaseext_la_CFLAGS = \ - -DXDG_PREFIX=sugar_mime \ - $(WARN_CFLAGS) \ - $(EXT_CFLAGS) \ - $(PYTHON_INCLUDES) + $(XDG_MIME_SOURCES) BUILT_SOURCES = \ sugar-marshal.c \ sugar-marshal.h -_sugarbaseext_la_LDFLAGS = -module -avoid-version -_sugarbaseext_la_LIBADD = $(EXT_LIBS) -_sugarbaseext_la_SOURCES = \ - _sugarbaseextmodule.c \ - xdgmime.c \ - xdgmime.h \ - xdgmimealias.c \ - xdgmimealias.h \ - xdgmimecache.c \ - xdgmimecache.h \ - xdgmimeglob.c \ - xdgmimeglob.h \ - xdgmimeint.c \ - xdgmimeint.h \ - xdgmimemagic.c \ - xdgmimemagic.h \ - xdgmimeparent.c \ - xdgmimeparent.h - -nodist__sugarbaseext_la_SOURCES = _sugarbaseext.c - -_sugarbaseext.c: _sugarbaseext.defs _sugarbaseext.override - -.defs.c: - (cd $(srcdir)\ - && $(PYGTK_CODEGEN) \ - --override $*.override \ - --prefix py$* $*.defs) > gen-$*.c \ - && cp gen-$*.c $*.c \ - && rm -f gen-$*.c - sugar-marshal.c: sugar-marshal.list $(GLIB_GENMARSHAL) --prefix=sugar_marshal \ $(srcdir)/sugar-marshal.list --header --body > sugar-marshal.c @@ -115,12 +93,14 @@ sugar-marshal.h: sugar-marshal.list $(GLIB_GENMARSHAL) --prefix=sugar_marshal \ $(srcdir)/sugar-marshal.list --header > sugar-marshal.h -CLEANFILES = $(BUILT_SOURCES) _sugarbaseext.c -EXTRA_DIST = sugar-marshal.list _sugarbaseext.override _sugarbaseext.defs +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = sugar-marshal.list -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = SugarExt-1.0.gir -INTROSPECTION_SCANNER_ARGS = --identifier-prefix=Sugar --symbol-prefix=sugar \ +INTROSPECTION_SCANNER_ARGS = \ + -D XDG_PREFIX=sugar_mime \ + --identifier-prefix=Sugar --symbol-prefix=sugar \ --identifier-prefix=EggSM --symbol-prefix=egg_sm \ --identifier-prefix=Gsm --symbol-prefix=gsm \ --identifier-prefix=Acme --symbol-prefix=acme \ @@ -149,7 +129,8 @@ SugarExt_1_0_gir_FILES = \ sugar-grid.c \ sugar-grid.h \ sugar-wm.c \ - sugar-wm.h + sugar-wm.h \ + $(XDG_MIME_SOURCES) SugarExt_1_0_gir_INCLUDES = Gtk-3.0 Gdk-3.0 SugarExt_1_0_gir_PACKAGES = gtk+-3.0 gdk-3.0 diff --git a/src/sugar3/_sugarbaseext.defs b/src/sugar3/_sugarbaseext.defs deleted file mode 100644 index 893219a5..00000000 --- a/src/sugar3/_sugarbaseext.defs +++ /dev/null @@ -1,33 +0,0 @@ -; functions - -(define-function get_mime_type_from_file_name - (c-name "sugar_mime_get_mime_type_from_file_name") - (return-type "const-char*") - (parameters - '("const-char*" "filename") - ) -) - -(define-function get_mime_type_for_file - (c-name "sugar_mime_get_mime_type_for_file") - (return-type "const-char*") - (parameters - '("const-char*" "filename") - ) -) - -(define-function list_mime_parents - (c-name "sugar_mime_list_mime_parents") - (return-type "char**") - (parameters - '("const-char*" "mime") - ) -) - -(define-function uri_list_extract_uris - (c-name "g_uri_list_extract_uris") - (return-type "gchar**") - (parameters - '("const-char*" "uri_list") - ) -) diff --git a/src/sugar3/_sugarbaseext.override b/src/sugar3/_sugarbaseext.override deleted file mode 100644 index 18356a9d..00000000 --- a/src/sugar3/_sugarbaseext.override +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -%% -headers -#include -#include -#include "xdgmime.h" -%% -modulename _sugarext -%% -ignore-glob - *_get_type - _* -%% -override sugar_mime_get_mime_type_for_file kwargs -static PyObject * -_wrap_sugar_mime_get_mime_type_for_file(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "filename", NULL }; - char *filename; - const char *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_mime_type_for_file", kwlist, &filename)) - return NULL; - - ret = sugar_mime_get_mime_type_for_file(filename, NULL); - - if (ret) - return PyString_FromString(ret); - Py_INCREF(Py_None); - return Py_None; -} -%% -override sugar_mime_list_mime_parents kwargs -static PyObject * -_wrap_sugar_mime_list_mime_parents(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "mime_type", NULL }; - char *mime_type; - char **parents, **tmp; - int i = 0, j; - PyObject *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:list_mime_parents", kwlist, &mime_type)) - return NULL; - - parents = (char **)sugar_mime_list_mime_parents(mime_type); - if (!parents) - return PyTuple_New(0); - - tmp = parents; - while (*tmp) - tmp++, i++; - - ret = PyTuple_New(i); - for (j = 0; j < i; j++) - PyTuple_SetItem(ret, j, PyString_FromString(parents[j])); - - return ret; -} -%% -override g_uri_list_extract_uris kwargs -static PyObject * -_wrap_g_uri_list_extract_uris(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "uri_list", NULL }; - char *uri_list; - char **uris, **tmp; - int i = 0, j; - PyObject *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:uri_list_extract_uris", kwlist, &uri_list)) - return NULL; - - uris = (char **)g_uri_list_extract_uris(uri_list); - if (!uris) - return PyTuple_New(0); - - tmp = uris; - while (*tmp) - tmp++, i++; - - ret = PyTuple_New(i); - for (j = 0; j < i; j++) - PyTuple_SetItem(ret, j, PyString_FromString(uris[j])); - - return ret; -} -%% diff --git a/src/sugar3/_sugarbaseextmodule.c b/src/sugar3/_sugarbaseextmodule.c deleted file mode 100644 index 57fb1395..00000000 --- a/src/sugar3/_sugarbaseextmodule.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* include this first, before NO_IMPORT_PYGOBJECT is defined */ -#include - -extern PyMethodDef py_sugarbaseext_functions[]; - -DL_EXPORT(void) -init_sugarbaseext(void) -{ - PyObject *m, *d; - - m = Py_InitModule ("_sugarbaseext", py_sugarbaseext_functions); - d = PyModule_GetDict (m); - - if (PyErr_Occurred ()) { - Py_FatalError ("can't initialise module _sugarext"); - } -} diff --git a/src/sugar3/mime.py b/src/sugar3/mime.py index be9b5ebb..a9046e7e 100644 --- a/src/sugar3/mime.py +++ b/src/sugar3/mime.py @@ -25,10 +25,11 @@ import os import logging import gettext +from gi.repository import GLib from gi.repository import GdkPixbuf from gi.repository import Gio -from sugar3 import _sugarbaseext +from gi.repository import SugarExt _ = lambda msg: gettext.dgettext('sugar-base', msg) @@ -123,7 +124,7 @@ def get_for_file(file_name): file_name = os.path.realpath(file_name) - mime_type = _sugarbaseext.get_mime_type_for_file(file_name) + mime_type = SugarExt.mime_get_mime_type_for_file(file_name, None) if mime_type == 'application/octet-stream': if _file_looks_like_text(file_name): return 'text/plain' @@ -134,7 +135,7 @@ def get_for_file(file_name): def get_from_file_name(file_name): - return _sugarbaseext.get_mime_type_from_file_name(file_name) + return SugarExt.mime_get_mime_type_from_file_name(file_name) def get_mime_icon(mime_type): @@ -154,7 +155,7 @@ def get_mime_description(mime_type): def get_mime_parents(mime_type): - return _sugarbaseext.list_mime_parents(mime_type) + return SugarExt.mime_list_mime_parents(mime_type) def get_primary_extension(mime_type): @@ -254,7 +255,7 @@ def choose_most_significant(mime_types): def split_uri_list(uri_list): - return _sugarbaseext.uri_list_extract_uris(uri_list) + return GLib.uri_list_extract_uris(uri_list) def _file_looks_like_text(file_name): diff --git a/src/sugar3/xdgmime.c b/src/sugar3/xdgmime.c index 1d2007cb..ec8a6a30 100644 --- a/src/sugar3/xdgmime.c +++ b/src/sugar3/xdgmime.c @@ -457,6 +457,13 @@ xdg_mime_get_mime_type_for_data (const void *data, return XDG_MIME_TYPE_UNKNOWN; } +/** + * sugar_mime_get_mime_type_for_file: + * @file_name: the file path + * @statbuf: (allow-none) + * + * Returns: (transfer none): the mime type. + */ const char * xdg_mime_get_mime_type_for_file (const char *file_name, struct stat *statbuf) @@ -752,6 +759,11 @@ xdg_mime_mime_type_subclass (const char *mime, return _xdg_mime_mime_type_subclass (mime, base); } +/** + * sugar_mime_list_mime_parents: + * + * Return value: (array zero-terminated=1) (transfer full): + **/ char ** xdg_mime_list_mime_parents (const char *mime) { diff --git a/tests/data/mime.svg b/tests/data/mime.svg new file mode 100644 index 00000000..d4e6db31 --- /dev/null +++ b/tests/data/mime.svg @@ -0,0 +1,3 @@ + + + diff --git a/tests/test_mime.py b/tests/test_mime.py index 417a320a..1f96046d 100644 --- a/tests/test_mime.py +++ b/tests/test_mime.py @@ -17,12 +17,27 @@ # 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 -from sugar import mime +from sugar3 import mime +tests_dir = os.path.dirname(__file__) +data_dir = os.path.join(tests_dir, "data") class TestMime(unittest.TestCase): + def test_split_uri_list(self): + self.assertSequenceEqual(mime.split_uri_list("http://one\nhttp://two"), + ("http://one", "http://two")) + + def test_get_mime_parents(self): + self.assertListEqual(mime.get_mime_parents("image/svg+xml"), + ["application/xml"]) + + def test_get_for_file(self): + self.assertEqual(mime.get_for_file(os.path.join(data_dir, "mime.svg")), + 'image/svg+xml') + def test_from_file_name(self): self.assertEqual(mime.get_from_file_name('test.pdf'), 'application/pdf') @@ -77,7 +92,3 @@ class TestMime(unittest.TestCase): 'text/plain;charset=utf-8', 'text/plain;charset=UTF-8', 'text/plain']) self.assertEqual(mime_type, 'text/plain') - - -if __name__ == '__main__': - unittest.main()