[Dextrose] [PATCH sugar-toolkit 2/2] Parse activity dependencies

Aleksey Lim alsroot at member.fsf.org
Wed Jan 12 09:37:09 EST 2011


It is a mimic of sweets' requires tag that will be used only for sugar
dependency. Full functional dependency tracking will come with sweets support
implementation in the shell.

The format for requires optin in activity.info:
  requires = sugar (=|==|<|<=|>|>=) version [; ...]
---
 src/sugar/bundle/activitybundle.py |   70 ++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py
index b2548a4..ac1d558 100644
--- a/src/sugar/bundle/activitybundle.py
+++ b/src/sugar/bundle/activitybundle.py
@@ -26,6 +26,8 @@ import os
 import tempfile
 import logging
 import shutil
+import gettext
+import re
 
 from sugar import env
 from sugar import util
@@ -33,6 +35,14 @@ from sugar.bundle.bundle import Bundle, \
     MalformedBundleException, NotInstalledException
 
 
+_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
+
+
+class DependencyException(Exception):
+    """Required dependencies were not found."""
+    pass
+
+
 class ActivityBundle(Bundle):
     """A Sugar activity bundle
 
@@ -60,6 +70,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:
@@ -129,6 +140,11 @@ class ActivityBundle(Bundle):
                     'Activity bundle %s has invalid version number %s' %
                     (self._path, 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:
@@ -331,3 +347,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
-- 
1.7.3.4



More information about the Dextrose mailing list