From 927ae13aec406cd3d3f67d6e10a8ef1f253a0a80 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sun, 24 Aug 2008 12:33:58 +0000 Subject: Merge branch 'master' of git+ssh://benzea@dev.laptop.org/git/sugar-toolkit --- (limited to 'src/sugar') diff --git a/src/sugar/activity/bundlebuilder.py b/src/sugar/activity/bundlebuilder.py index b8f87a7..75d6d89 100644 --- a/src/sugar/activity/bundlebuilder.py +++ b/src/sugar/activity/bundlebuilder.py @@ -51,7 +51,21 @@ 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 + self.bundle = None + self.version = None + self.activity_name = None + self.bundle_id = None + self.bundle_name = None + self.bundle_root_dir = None + self.tar_root_dir = None + self.xo_name = None + self.tar_name = None + + self.update() + + def update(self): self.bundle = bundle = ActivityBundle(self.source_dir) self.version = bundle.get_activity_version() self.activity_name = bundle.get_name() @@ -59,14 +73,9 @@ class Config(object): self.bundle_name = reduce(lambda x, y:x+y, self.activity_name.split()) self.bundle_root_dir = self.bundle_name + '.activity' self.tar_root_dir = '%s-%d' % (self.bundle_name, self.version) - - if dist_dir: - self.dist_dir = dist_dir - else: - self.dist_dir = os.path.join(self.source_dir, 'dist') - if dist_name: - self.xo_name = self.tar_name = dist_name + if self.dist_name: + self.xo_name = self.tar_name = self.dist_name else: self.xo_name = '%s-%d.xo' % (self.bundle_name, self.version) self.tar_name = '%s-%d.tar.bz2' % (self.bundle_name, self.version) @@ -118,6 +127,12 @@ class Packager(object): if not os.path.exists(self.config.dist_dir): os.mkdir(self.config.dist_dir) + def _list_files(self): + ignore_dirs = ['dist', '.git'] + ignore_files = ['.gitignore', 'MANIFEST', '*.pyc', '*~', '*.bak'] + + return list_files(self.config.source_dir, ignore_dirs, ignore_files) + class BuildPackager(Packager): def get_files(self): files = self.config.bundle.get_files() @@ -128,20 +143,22 @@ class BuildPackager(Packager): files = self.config.bundle.get_files() return files - - def _list_useful_files(self): - ignore_dirs = ['dist', '.git'] - ignore_files = ['.gitignore', 'MANIFEST', '*.pyc', '*~', '*.bak'] - - return list_files(self.config.source_dir, ignore_dirs, ignore_files) + + def _check_manifest(self): + missing_files = [] + + allfiles = self._list_files() + for path in allfiles: + if path not in self.config.bundle.manifest: + missing_files.append(path) + + return missing_files def fix_manifest(self): manifest = self.config.bundle.manifest - allfiles = self._list_useful_files() - for path in allfiles: - if path not in manifest: - manifest.append(path) + for path in self._check_manifest(): + manifest.append(path) f = open(os.path.join(self.config.source_dir, "MANIFEST"), "wb") for line in manifest: @@ -157,15 +174,22 @@ class XOPackager(BuildPackager): bundle_zip = zipfile.ZipFile(self.package_path, 'w', zipfile.ZIP_DEFLATED) + missing_files = self._check_manifest() + if missing_files: + logging.warn('These files are not included in the manifest ' \ + 'and will not be present in the bundle:\n\n' + + '\n'.join(missing_files) + + '\n\nUse fix_manifest if you want to add them.') + for f in self.get_files(): bundle_zip.write(os.path.join(self.config.source_dir, f), os.path.join(self.config.bundle_root_dir, f)) bundle_zip.close() -class SourcePackager(BuildPackager): +class SourcePackager(Packager): def __init__(self, config): - BuildPackager.__init__(self, config) + Packager.__init__(self, config) self.package_path = os.path.join(self.config.dist_dir, self.config.tar_name) @@ -174,7 +198,7 @@ class SourcePackager(BuildPackager): cwd=self.config.source_dir) if git_ls.wait(): # Fall back to filtered list - return self._list_useful_files() + return self._list_files() return [path.strip() for path in git_ls.stdout.readlines()] @@ -191,6 +215,7 @@ setup.py build - build generated files \n\ setup.py dev - setup for development \n\ setup.py dist_xo - create a xo bundle package \n\ setup.py dist_source - create a tar source package \n\ +setup.py fix_manifest - add missing files to the manifest \n\ setup.py install [dirname] - install the bundle \n\ setup.py uninstall [dirname] - uninstall the bundle \n\ setup.py genpot - generate the gettext pot file \n\ @@ -218,6 +243,13 @@ def cmd_dist_xo(config, options, args): packager = XOPackager(config) packager.package() +def cmd_fix_manifest(config, options, args): + builder = Builder(config) + builder.build() + + packager = XOPackager(config) + packager.fix_manifest() + def cmd_dist(config, options, args): logging.warn("dist deprecated, use dist_xo.") cmd_dist_xo(config, options, args) @@ -309,6 +341,8 @@ def cmd_release(config, options, args): f.write(info) f.close() + config.update() + news_path = os.path.join(config.source_dir, 'NEWS') if os.environ.has_key('SUGAR_NEWS'): diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py index 5f29a69..be997cc 100644 --- a/src/sugar/bundle/activitybundle.py +++ b/src/sugar/bundle/activitybundle.py @@ -205,13 +205,13 @@ class ActivityBundle(Bundle): def get_locale_path(self): """Get the locale path inside the (installed) activity bundle.""" - if not self._unpacked: + if self._zip_file is not None: raise NotInstalledException return os.path.join(self._path, 'locale') def get_icons_path(self): """Get the icons path inside the (installed) activity bundle.""" - if not self._unpacked: + if self._zip_file is not None: raise NotInstalledException return os.path.join(self._path, 'icons') @@ -237,7 +237,7 @@ class ActivityBundle(Bundle): def get_icon(self): """Get the activity icon name""" icon_path = os.path.join('activity', self._icon + '.svg') - if self._unpacked: + if self._zip_file is None: return os.path.join(self._path, icon_path) else: icon_data = self.get_file(icon_path).read() @@ -365,7 +365,7 @@ class ActivityBundle(Bundle): raise RegistrationException def uninstall(self, force=False): - if self._unpacked: + if self._zip_file is None: install_path = self._path else: if not self.is_installed(): diff --git a/src/sugar/bundle/bundle.py b/src/sugar/bundle/bundle.py index 3b12932..0319b9e 100644 --- a/src/sugar/bundle/bundle.py +++ b/src/sugar/bundle/bundle.py @@ -19,6 +19,7 @@ import os import logging +import shutil import StringIO import zipfile @@ -59,9 +60,9 @@ class Bundle: self._zip_root_dir = None if os.path.isdir(self._path): - self._unpacked = True + self._zip_file = None else: - self._unpacked = False + self._zip_file = zipfile.ZipFile(self._path) self._check_zip_bundle() # manifest = self._get_file(self._infodir + '/contents') @@ -72,9 +73,12 @@ class Bundle: # if signature is None: # raise MalformedBundleException('No signature file') + def __del__(self): + if self._zip_file is not None: + self._zip_file.close() + def _check_zip_bundle(self): - zip_file = zipfile.ZipFile(self._path) - file_names = zip_file.namelist() + file_names = self._zip_file.namelist() if len(file_names) == 0: raise MalformedBundleException('Empty zip file') @@ -99,48 +103,42 @@ class Bundle: def get_file(self, filename): f = None - if self._unpacked: + if self._zip_file is None: path = os.path.join(self._path, filename) try: f = open(path,"rb") except IOError: return None else: - zip_file = zipfile.ZipFile(self._path) path = os.path.join(self._zip_root_dir, filename) try: - data = zip_file.read(path) + data = self._zip_file.read(path) f = StringIO.StringIO(data) except KeyError: logging.debug('%s not found.' % filename) - zip_file.close() return f def is_file(self, filename): - if self._unpacked: + if self._zip_file is None: path = os.path.join(self._path, filename) return os.path.isfile(path) else: - zip_file = zipfile.ZipFile(self._path) path = os.path.join(self._zip_root_dir, filename) try: - zip_file.getinfo(path) + self._zip_file.getinfo(path) except KeyError: return False - finally: - zip_file.close() return True def is_dir(self, filename): - if self._unpacked: + if self._zip_file is None: path = os.path.join(self._path, filename) return os.path.isdir(path) else: - zip_file = zipfile.ZipFile(self._path) path = os.path.join(self._zip_root_dir, filename, "") - for f in zip_file.namelist(): + for f in self._zip_file.namelist(): if f.startswith(path): return True return False @@ -150,7 +148,7 @@ class Bundle: return self._path def _unzip(self, install_dir): - if self._unpacked: + if self._zip_file is None: raise AlreadyInstalledException if not os.path.isdir(install_dir): @@ -163,10 +161,13 @@ class Bundle: # FIXME: use manifest if os.spawnlp(os.P_WAIT, 'unzip', 'unzip', '-o', self._path, '-x', 'mimetype', '-d', install_dir): + # clean up install dir after failure + shutil.rmtree(install_dir, ignore_errors=True) + # indicate failure. raise ZipExtractException def _zip(self, bundle_path): - if not self._unpacked: + if self._zip_file is not None: raise NotInstalledException raise NotImplementedError diff --git a/src/sugar/bundle/contentbundle.py b/src/sugar/bundle/contentbundle.py index f99c13a..389fd70 100644 --- a/src/sugar/bundle/contentbundle.py +++ b/src/sugar/bundle/contentbundle.py @@ -195,7 +195,7 @@ class ContentBundle(Bundle): return "file://" + urllib.pathname2url(self.get_start_path()) def is_installed(self): - if self._unpacked: + if self._zip_file is None: return True elif os.path.isdir(self.get_root_dir()): return True @@ -207,7 +207,7 @@ class ContentBundle(Bundle): self._run_indexer() def uninstall(self): - if self._unpacked: + if self._zip_file is None: if not self.is_installed(): raise NotInstalledException install_dir = self._path diff --git a/src/sugar/graphics/toolbutton.py b/src/sugar/graphics/toolbutton.py index bf392c8..715e7a9 100644 --- a/src/sugar/graphics/toolbutton.py +++ b/src/sugar/graphics/toolbutton.py @@ -65,6 +65,12 @@ class ToolButton(gtk.ToolButton): self.set_icon(icon_name) self.connect('clicked', self.__button_clicked_cb) + self.get_child().connect('can-activate-accel', + self.__button_can_activate_accel_cb) + + def __button_can_activate_accel_cb(self, button, signal_id): + # Accept activation via accelerators regardless of this widget's state + return True def set_tooltip(self, tooltip): """ Set a simple palette with just a single label. diff --git a/src/sugar/util.py b/src/sugar/util.py index 955f4c8..c365dce 100644 --- a/src/sugar/util.py +++ b/src/sugar/util.py @@ -16,6 +16,7 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +import os import time import sha import random @@ -23,7 +24,6 @@ import binascii import gettext _ = lambda msg: gettext.dgettext('sugar-toolkit', msg) -_ngettext = lambda m1, m2, n: gettext.dngettext('sugar-toolkit', m1, m2, n) def printable_hash(in_hash): """Convert binary hash data into printable characters.""" @@ -217,6 +217,9 @@ del ngettext # End of plurals hack +# gettext perfs hack (#7959) +_i18n_timestamps_cache = LRU(60) + def timestamp_to_elapsed_string(timestamp, max_levels=2): levels = 0 time_period = '' @@ -229,8 +232,17 @@ def timestamp_to_elapsed_string(timestamp, max_levels=2): if levels > 0: time_period += COMMA - time_period += _ngettext(name_singular, name_plural, - elapsed_units) % elapsed_units + key = ''.join((os.environ['LANG'], name_singular, + str(elapsed_units))) + if key in _i18n_timestamps_cache: + time_period += _i18n_timestamps_cache[key] + else: + translation = gettext.dngettext('sugar-toolkit', + name_singular, + name_plural, + elapsed_units) % elapsed_units + _i18n_timestamps_cache[key] = translation + time_period += translation elapsed_seconds -= elapsed_units * factor -- cgit v0.9.1