[Blends-commit] [Git][blends-team/blends][experimental] 2 commits: Fix some problems, and refactorization of blend-gen-control

Ole Streicher gitlab at salsa.debian.org
Wed Mar 28 06:55:20 UTC 2018


Ole Streicher pushed to branch experimental at Debian Blends Team / blends


Commits:
f4c0f012 by Ole Streicher at 2018-03-28T08:46:02+02:00
Fix some problems, and refactorization of blend-gen-control

 * Don't lower Recommends to Suggests on format 1.0
 * Don't allow backslashes in Recommends/Suggests/Depends in format 1.1

- - - - -
3120dc33 by Ole Streicher at 2018-03-28T08:52:24+02:00
Update changelog for 0.6.102 release

- - - - -


2 changed files:

- debian/changelog
- devtools/blend-gen-control


Changes:

=====================================
debian/changelog
=====================================
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+blends (0.6.102) experimental; urgency=low
+
+  * blend-gen-control: Bugfixes, slight refactorization, documentation
+     - Don't lower Recommends to Suggests in format 1.0
+     - Fail on backslashes in dependency lists
+
+ -- Ole Streicher <olebole at debian.org>  Wed, 28 Mar 2018 08:49:42 +0200
+
 blends (0.6.101) experimental; urgency=low
 
   [ Andreas Tille ]


=====================================
devtools/blend-gen-control
=====================================
--- a/devtools/blend-gen-control
+++ b/devtools/blend-gen-control
@@ -40,21 +40,31 @@ from debian.deb822 import Deb822
 class Blend:
     '''Representation of a Debian Pure Blend.
     '''
-    def __init__(self, basedir = '.', suppress_empty = True):
+    def __init__(self, basedir = '.'):
         with open(os.path.join(basedir, 'debian', 'control.stub'), encoding="UTF-8") as fp:
             self.control_stub = Deb822List(Deb822.iter_paragraphs(fp))
-        self.short_name = self.control_stub[0]['Source'].split('-', 1)[-1]
+
         self.name = self.control_stub[0]['Source']
+        '''Full (package) name of the blend (``debian-astro``)'''
+
+        self.short_name = self.name.split('-', 1)[-1]
+        '''Short name of the blend (``astro``)'''
+
         self.title = 'Debian ' + self.short_name.capitalize()
-        if len(self.control_stub) > 1:
-            self.prefix = self.control_stub[1]['Package'].split('-', 1)[0]
-        else:
-            self.prefix = self.short_name
+        '''Blends title (``Debian Astro``)'''
+
+        base_deps = [ "${misc:Depends}", ]
+
+        self.prefix = self.short_name
+        '''Prefix for tasks (``astro``)'''
+
+        for pkg in self.control_stub[1:]:
+            p = pkg['Package'].split('-', 1)
+            if len(p) > 1 and p[1] == 'tasks':
+                self.prefix = p[0]
+                base_deps.append("{Package} (= ${{source:Version}})".format(**pkg))
+                break
 
-        base_deps = [
-            "${misc:Depends}",
-            "{}-tasks (= ${{source:Version}})".format(self.prefix),
-        ]
         try:
             with open(os.path.join(basedir, 'config', 'control'), encoding="UTF-8") as fp:
                 self.control_stub.append(Deb822(fp))
@@ -64,12 +74,11 @@ class Blend:
             pass
 
         self.tasks = []
-        self.suppress_empty = suppress_empty
+        '''``Task`` list'''
         for name in sorted(filter(lambda n: n[-1] != '~',
                                   os.listdir(os.path.join(basedir, 'tasks')))):
             with open(os.path.join(basedir, 'tasks', name), encoding="UTF-8") as fp:
-                task = Task(self.name, self.prefix,  name, fp,
-                            base_deps = base_deps)
+                task = Task(self,  name, fp, base_deps = base_deps)
             self.tasks.append(task)
 
     def update(self, cache):
@@ -102,24 +111,19 @@ class Blend:
             missing += task.fix_dependencies()
         return missing
 
-    @property
-    def control(self):
+    def gen_control(self):
         '''Return the task as list of ``Deb822`` objects suitable for
         ``debian/control``
         '''
-        tasks = list(filter(lambda task: task.is_metapackage
-                            and (not self.suppress_empty
-                                 or len(task.recommends) > 0
-                                 or len(task.dependencies) > 0),
-                            self.tasks))
+        tasks = list(filter(lambda task: task.is_metapackage, self.tasks))
 
         # Create the special 'all' task recommending all tasks that
         # shall be installed by default
         all_task = Task(
-            self.name, self.prefix, "all",
+            self, "all",
             '''Description: Default selection of tasks for {task.title}
-            This package is part of the {task.title} Pure Blend and installs all
-            tasks for a default installation of this blend.'''.format(task=self),
+This package is part of the {task.title} Pure Blend and installs all
+tasks for a default installation of this blend.'''.format(task=self),
             base_deps = ['${misc:Depends}'])
         for task in tasks:
             if task.install:
@@ -131,42 +135,23 @@ class Blend:
         if len(all_task.recommends) > 0:
             tasks.insert(0, all_task)
 
-        return Deb822List(self.control_stub + [ task.control for task in tasks ])
+        return Deb822List(self.control_stub
+                          + [ task.gen_control() for task in tasks ])
 
-    @property
-    def task_desc(self):
+    def gen_task_desc(self, udeb = False):
         '''Return the task as list of ``Deb822`` objects suitable for
         ``blends-task.desc``
         '''
-        tasks = list(filter(lambda task:
-                            task.is_metapackage
-                            and task.is_leaf
-                            and (not self.suppress_empty
-                                 or len(task.recommends) > 0
-                                 or len(task.dependencies) > 0),
+        tasks = list(filter(lambda task: task.is_metapackage and task.is_leaf,
                             self.tasks))
 
-        header = Deb822({
+        header = [ Deb822({
             'Task': self.name,
             'Relevance':  '7',
             'Section': self.name,
             'Description': '{} Pure Blend\n .'.format(self.title),
-        })
-        return Deb822List([ header ] + [ task.task_desc for task in tasks ])
-
-    @property
-    def udeb_task_desc(self):
-        '''Return the task as list of ``Deb822`` objects suitable for
-        ``blends-task.desc`` in case the blend uses udebs
-        '''
-        tasks = list(filter(lambda task:
-                            task.is_metapackage
-                            and task.is_leaf
-                            and (not self.suppress_empty
-                                 or len(task.recommends) > 0
-                                 or len(task.dependencies) > 0),
-                            self.tasks))
-        return Deb822List([ task.udeb_task_desc for task in tasks ])
+        }) ] if not udeb else []
+        return Deb822List(header + [ task.gen_task_desc(udeb) for task in tasks ])
 
 
 class Task:
@@ -175,9 +160,7 @@ class Task:
     The Version class contains all information related to a
     specific package version of a blends task.
 
-    :param blend: Name of the blend
-
-    :param prefix: Prefix for the package name
+    :param blend: ``Blend`` object, or Blend name
 
     :param name: Name of the task
 
@@ -198,7 +181,7 @@ class Task:
     Example:
 
     >>> with open('education') as fp:
-    ...     task = Task('debian-astro', 'astro', 'education', fp)
+    ...     task = Task('debian-astro', 'education', fp)
     >>> print(task.name)
     education
     >>> print(task.package_name)
@@ -223,16 +206,33 @@ class Task:
     xtide
 
     '''
-    def __init__(self, blend, prefix, name, sequence, base_deps = None):
-        self.blend = blend
-        self.prefix = prefix
+    def __init__(self, blend, name, sequence, base_deps = None):
+        if isinstance(blend, str):
+            self.blend = blend
+            '''Blend name'''
+
+            self.prefix = blend[len('debian-'):] if blend.startswith('debian-') else blend
+            '''Metapackage prefix'''
+        else:
+            self.blend = blend.name
+            self.prefix = blend.prefix
+
         self.name = name
+        '''Task name'''
+
         self.content = Deb822List(Deb822.iter_paragraphs(sequence))
+        '''Deb822List content of the task'''
+
         self.header = self.content[0]
+        '''Deb822 header'''
+
         self.base_deps = base_deps or []
+        '''Base dependencies'''
 
         # Check for the format version, and upgrade if not actual
         self.format_upgraded = False
+        '''``True`` if the format was upgraded from an older version'''
+
         if 'Format' in self.header:
             self.format_version = self.header['Format'].strip().rsplit('/', 1)[-1]
         else:
@@ -241,6 +241,7 @@ class Task:
             self.content = Task.upgrade_from_1_0(self.content)
             self.format_upgraded = True
 
+        # Create package dependencies
         dep_types = ["Depends", "Recommends", "Suggests"]
         dep_attrs = [ "dependencies", "recommends", "suggests" ]
         for dep_type, dep_attr in zip(dep_types, dep_attrs):
@@ -248,6 +249,10 @@ class Task:
                 *(list(Dependency(dep_type, s.strip(), par)
                        for s in par.get(dep_type, '').split(",") if s)
                   for par in self.content[1:]))))
+        self.enhances = [
+            Dependency('Enhances', s.strip(), self.header)
+            for s in self.header.get('Enhances', '').split(",") if s
+        ]
 
     @property
     def install(self):
@@ -309,13 +314,6 @@ class Task:
         return self.header.get('Architecture', 'all')
 
     @property
-    def enhances(self):
-        '''Return the task name this task is an enhancement of,
-        or `None`.
-        '''
-        return self.header.get('Enhances')
-
-    @property
     def tests(self):
         '''Return all tests for this task when included in tasksel
         '''
@@ -335,13 +333,12 @@ class Task:
                              self.recommends,
                              self.suggests)))
 
-    @property
-    def control(self):
+    def gen_control(self):
         '''Return the task as ``Deb822`` object suitable for ``debian/control``
 
         >>> with open('education') as fp:
-        ...     task = Task('debian-astro', 'astro', 'education', fp)
-        >>> print(task.control.dump())
+        ...     task = Task('debian-astro', 'education', fp)
+        >>> print(task.gen_control().dump())
         Package: astro-education
         Section: metapackages
         Architecture: all
@@ -377,13 +374,15 @@ class Task:
             "\n ".join(self.description.replace("\n\n", "\n.\n").split("\n"))
         return d
 
-    @property
-    def task_desc(self):
+    def gen_task_desc(self, udeb = False):
         '''Return the task as ``Deb822`` object suitable for ``blends-task.desc``.
 
+        :parameter udeb: if ``True``, generate ```blends-task.desc``
+                         suitable for udebs
+
         >>> with open('education') as fp:
-        ...     task = Task('debian-astro', 'astro', 'education', fp)
-        >>> print(task.task_desc.dump())
+        ...     task = Task('debian-astro', 'education', fp)
+        >>> print(task.gen_task_desc().dump())
         Task: astro-education
         Parent: debian-astro
         Section: debian-astro
@@ -395,17 +394,7 @@ class Task:
         Key:
          astro-education
         <BLANKLINE>
-        '''
-        return self._get_task_desc(udeb = False)
-
-    @property
-    def udeb_task_desc(self):
-        '''Return the task as ``Deb822`` object suitable for ``blends-task.desc``
-        in case the blend uses udebs
-
-        >>> with open('education') as fp:
-        ...     task = Task('debian-astro', 'astro', 'education', fp)
-        >>> print(task.udeb_task_desc.dump())
+        >>> print(task.gen_task_desc(udeb=True).dump())
         Task: astro-education
         Section: debian-astro
         Description: Educational astronomy applications
@@ -422,10 +411,8 @@ class Task:
          gravit
          starplot
         <BLANKLINE>
-        '''
-        return self._get_task_desc(udeb = True)
 
-    def _get_task_desc(self, udeb = False):
+        '''
         d = Deb822()
         d['Task'] = self.package_name
         if not udeb:
@@ -436,7 +423,8 @@ class Task:
         if udeb:
             d['Relevance'] = '10'
         if self.enhances:
-            d['Enhances'] = self.enhances
+            d['Enhances'] = ', '.join(sorted(d.name for d in itertools.chain(
+                *self.enhances)))
         for key, value in self.tests.items():
             d['Test-' + key] = value
         d['Key'] = '\n {}'.format(self.package_name)
@@ -458,7 +446,7 @@ class Task:
 
         >>> import apt
         >>> with open('education') as fp:
-        ...     task = Task('debian-astro', 'astro', 'education', fp)
+        ...     task = Task('debian-astro', 'education', fp)
         >>> dep = task.recommends[1][0]
         >>> print(dep.name + ": ", dep.summary)
         starplot:  None
@@ -485,7 +473,7 @@ class Task:
 
         >>> import apt
         >>> with open('education') as fp:
-        ...     task = Task('debian-astro', 'astro', 'education', fp)
+        ...     task = Task('debian-astro', 'education', fp)
         >>> for dep in task.recommends:
         ...     print(dep.rawstr)
         celestia-gnome | celestia-glut
@@ -508,17 +496,17 @@ class Task:
         celestia-gnome | celestia-glut
         '''
         missing = list()
-        for dep in self.recommends[:]:
-            sdep = Dependency("Suggests")
-            for odep in dep[:]:
-                if len(odep.target_versions) == 0:
-                    dep.remove(odep)
-                    sdep.append(odep)
-                    missing.append(odep)
-            if len(dep) == 0:
-                self.recommends.remove(dep)
-            if len(sdep) > 0:
-                self.suggests.append(sdep)
+        for recommended in self.recommends[:]:
+            suggested = Dependency("Suggests")
+            for dep in recommended[:]:
+                if len(dep.target_versions) == 0:
+                    recommended.remove(dep)
+                    suggested.append(dep)
+                    missing.append(dep)
+            if len(recommended) == 0:
+                self.recommends.remove(recommended)
+            if len(suggested) > 0:
+                self.suggests.append(suggested)
         return missing
 
     @staticmethod
@@ -529,9 +517,7 @@ class Task:
         for p in content[1:]:
             q = []
             for key, value in p.items():
-                if key == 'Recommends':
-                    key = 'Suggests'
-                elif key == 'Depends':
+                if key == 'Depends' and 'Recommends' not in p:
                     key = 'Recommends'
                 # Remove backslashes, which are not DEB822 compliant
                 value = re.sub(r'\s*\\', '', value)
@@ -546,7 +532,7 @@ class Dependency(list):
     Example:
 
     >>> with open('education') as fp:
-    ...     task = Task('debian-astro', 'astro', 'education', fp)
+    ...     task = Task('debian-astro', 'education', fp)
     >>> dep = task.recommends[0]
     >>> print(dep.rawstr)
     celestia-gnome | celestia-glut
@@ -586,7 +572,7 @@ class BaseDependency:
     Example:
 
     >>> with open('education') as fp:
-    ...     task = Task('debian-astro', 'astro', 'education', fp)
+    ...     task = Task('debian-astro', 'education', fp)
     >>> dep = task.recommends[2][0]
     >>> print(dep.rawstr)
     gravit
@@ -604,6 +590,10 @@ class BaseDependency:
     '''
 
     def __init__(self, s, content = None):
+        r = re.compile(r'([a-z0-9][a-z0-9+-\.]+)')
+        m = r.match(s)
+        if m is None or m.string != s:
+            raise ValueError('"{}" is not a valid package name'.format(s))
         self.name = s
         self.content = content or dict()
         self.target_versions = []
@@ -681,10 +671,10 @@ class Deb822List(list):
     def dump(self, fd=None, encoding=None, text_mode=False):
         '''Dump the the contents in the original format
 
-        If ``fd`` is ``None``, returns a ``unicode`` object.
-        Otherwise, ``fd`` is assumed to be a ``file``-like object, and
-        this method will write the data to it instead of returning a
-        ``unicode`` object.
+        If ``fd`` is ``None``, returns a ``str`` object. Otherwise,
+        ``fd`` is assumed to be a ``file``-like object, and this
+        method will write the data to it instead of returning an
+        ``str`` object.
 
         If ``fd`` is not ``None`` and ``text_mode`` is ``False``, the
         data will be encoded to a byte string before writing to the
@@ -784,7 +774,7 @@ if __name__ == '__main__':
     if args.release == "current":
         args.release = None
 
-    blend = Blend(basedir=args.dir, suppress_empty = args.suppressempty)
+    blend = Blend(basedir=args.dir)
 
     # For better performance, remove all tasks that will not create metapackages
     for task in blend.tasks[:]:
@@ -794,6 +784,11 @@ if __name__ == '__main__':
     blend += aptcache(args.release)
     missing = blend.fix_dependencies()
 
+    if args.suppressempty:
+        for task in blend.tasks[:]:
+            if len(task.recommends) == 0 and len(task.dependencies) > 0:
+                blend.tasks.remove(task)
+
     if missing and args.missing:
         missing = sorted(set(d.name for d in missing))
         print('Missing {} packages downgraded to `suggests`:\n  '
@@ -811,21 +806,13 @@ if __name__ == '__main__':
     if args.gencontrol:
         with open(os.path.join(args.dir,'debian', 'control'), 'w') as fp:
             fp.write('# This file is autogenerated. Do not edit!\n')
-            blend.control.dump(fp, text_mode=True)
+            blend.gen_control().dump(fp, text_mode=True)
 
-    if args.taskdesc and not args.udebs:
+    if args.taskdesc:
         with open(os.path.join(args.dir,'{}-tasks.desc'.format(blend.name)), 'w') as fp:
-            blend.task_desc.dump(fp, text_mode=True)
-
-    if args.taskdesc and args.udebs:
-        with open(os.path.join(args.dir,'{}-tasks.desc'.format(blend.name)), 'w') as fp:
-            blend.udeb_task_desc.dump(fp, text_mode=True)
-
-    upgraded_tasks = []
-    for task in blend.tasks:
-        if task.format_upgraded:
-            upgraded_tasks.append(task)
+            blend.gen_task_desc(udeb = args.udebs).dump(fp, text_mode=True)
 
+    upgraded_tasks = list(filter(lambda task: task.format_upgraded, blend.tasks))
     if upgraded_tasks:
         if args.upgrade_tasks:
             print('Upgrading {} tasks from format version {}'



View it on GitLab: https://salsa.debian.org/blends-team/blends/compare/35533d90964cefe5fc75983e6b4fe6200302201b...3120dc33c3d0eedee3533dfdd415f4464b06e40c

---
View it on GitLab: https://salsa.debian.org/blends-team/blends/compare/35533d90964cefe5fc75983e6b4fe6200302201b...3120dc33c3d0eedee3533dfdd415f4464b06e40c
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/blends-commit/attachments/20180328/a6afa734/attachment-0001.html>


More information about the Blends-commit mailing list