Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sugar/bundle/activitybundle.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py
index 542fa00..a87d01b 100644
--- a/src/sugar/bundle/activitybundle.py
+++ b/src/sugar/bundle/activitybundle.py
@@ -21,8 +21,10 @@ UNSTABLE.
"""
from ConfigParser import ConfigParser
+import gettext
import locale
import os
+import re
import shutil
import tempfile
import logging
@@ -36,6 +38,14 @@ from sugar.bundle.bundleversion import NormalizedVersion
from sugar.bundle.bundleversion import InvalidVersionError
+_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
+
+
+class DependencyException(Exception):
+ """Required dependencies were not found."""
+ pass
+
+
class ActivityBundle(Bundle):
"""A Sugar activity bundle
@@ -63,6 +73,7 @@ class ActivityBundle(Bundle):
self._tags = None
self._activity_version = '0'
self._installation_time = os.stat(path).st_mtime
+ self._requires = []
info_file = self.get_file('activity/activity.info')
if info_file is None:
@@ -137,6 +148,11 @@ class ActivityBundle(Bundle):
(self._path, version))
self._activity_version = version
+ if cp.has_option(section, 'requires'):
+ requires = cp.get(section, 'requires')
+ for dep in requires.replace('\n', ';').split(';'):
+ self._requires.extend(_parse_condition(dep))
+
def _get_linfo_file(self):
lang = locale.getdefaultlocale()[0]
if not lang:
@@ -339,3 +355,57 @@ class ActivityBundle(Bundle):
def is_user_activity(self):
return self.get_path().startswith(env.get_user_activities_path())
+
+ def meets_restriction(self, req_name, req_version):
+ version = _parse_version(req_version)
+
+ for dep, dep_rels, dep_version, error_msg in self._requires:
+ if dep != req_name:
+ continue
+ errors = set()
+ for rel in dep_rels:
+ if cmp(version, dep_version) == rel:
+ errors.clear()
+ break
+ else:
+ errors.add(error_msg)
+ if errors:
+ error = _('Restriction was not met: %s') % ', '.join(errors)
+ raise DependencyException(error)
+
+
+def _format_version(version):
+ return '.'.join([str(i) for i in version])
+
+
+def _parse_version(version):
+ return [int(i) if i.isdigit() else 0 for i in version.strip().split('.')]
+
+
+def _parse_condition(dep):
+ match = re.split('(=|==|<|<=|>|>=|!=)\s*([0-9.]+)', dep)
+ if len(match) == 1:
+ return []
+ if len(match) != 4 or match[-1]:
+ raise MalformedBundleException(_('Malformed requires, "%s"') % dep)
+
+ result = []
+ dep = match[0].strip()
+ arg = _parse_version(match[2])
+ error_msg = '%s %s %s' % (dep, match[1], _format_version(arg))
+
+ if match[1] == '=' or match[1] == '==':
+ result.append((dep, [0, 1], arg, error_msg))
+ result.append((dep, [-1], arg[:-1] + [arg[-1] + 1], error_msg))
+ elif match[1] == '<':
+ result.append((dep, [-1], arg, error_msg))
+ elif match[1] == '<=':
+ result.append((dep, [-1, 0], arg, error_msg))
+ elif match[1] == '>':
+ result.append((dep, [1], arg, error_msg))
+ elif match[1] == '>=':
+ result.append((dep, [1, 0], arg, error_msg))
+ elif match[1] == '!=':
+ result.append((dep, [-1, 1], arg, error_msg))
+
+ return result