#75 legacy: Allow marking variant as addon
Merged 5 years ago by lsedlar. Opened 5 years ago by lsedlar.
lsedlar/compose-utils dependent-variants  into  master

@@ -20,7 +20,17 @@ 

      compose = productmd.compose.Compose(opts.compose)

      target = opts.path or compose.compose_path

      with open(os.path.join(target, '.composeinfo'), 'w') as f:

-         write_legacy_composeinfo(compose.info, f)

+         write_legacy_composeinfo(compose.info, f, extra_addon_list=opts.addon)

+ 

+ 

+ def parse_variant_pair(val):

+     try:

+         base, addon = val.split(":")

+         return (base, addon)

+     except Exception:

+         raise argparse.ArgumentParseError(

+             "%s is not a colon separated pair of variant IDs" % val

+         )

  

  

  if __name__ == '__main__':
@@ -29,6 +39,13 @@ 

      parser.add_argument('-p', '--path',

                          help='Directory in which to write the .composeinfo file. '

                               'Defaults to the compose subdirectory.')

+     parser.add_argument(

+         "--addon",

+         metavar="BASE_VARIANT:ADDON",

+         help="Mark variant ADDON as an addon to BASE_VARIANT",

+         type=parse_variant_pair,

+         nargs='+',

+     )

  

      opts = parser.parse_args()

      run(opts)

file modified
+18 -8
@@ -1,16 +1,22 @@ 

  # -*- coding: utf-8 -*-

  

+ from collections import defaultdict

+ from itertools import chain

+ 

  from six.moves import configparser

  

  

- def write_legacy_composeinfo(ci, file):

+ def write_legacy_composeinfo(ci, file, extra_addon_list=None):

      """Write a legacy INI-style composeinfo data into `file`."""

      conf = configparser.SafeConfigParser(dict_type=SortedDict)

      _serialize_compose(conf, ci.compose)

      _serialize_product(conf, ci.release, ci.compose)

      if ci.release.is_layered:

          _serialize_base_product(conf, ci.base_product)

-     _serialize_variants(conf, ci.variants)

+     extra_addons = defaultdict(set)

+     for base, addon in extra_addon_list or []:

+         extra_addons[base].add(addon)

+     _serialize_variants(conf, ci.variants, extra_addons=extra_addons)

      conf.write(file)

  

  
@@ -88,7 +94,7 @@ 

          _set("debuginfo", paths.debug_repository, arch)

  

  

- def _serialize_variant(conf, variant):

+ def _serialize_variant(conf, variant, extra_addons):

      section = 'variant-%s' % variant.uid

      conf.add_section(section)

  
@@ -107,19 +113,23 @@ 

  

      children = set()

      for child in variant.variants.values():

-         _serialize_variant(conf, child)

+         _serialize_variant(conf, child, set())

          children.add(child.uid)

  

+     children |= extra_addons

+ 

      if children:

          conf.set(section, 'variants', ','.join(sorted(children)))

  

  

- def _serialize_variants(conf, variants):

-     ids = sorted(variants.variants.keys())

+ def _serialize_variants(conf, variants, extra_addons):

+     ids = sorted(

+         set(variants.variants.keys()) - set(chain.from_iterable(extra_addons.values()))

+     )

      conf.set('product', 'variants', ','.join(ids))

-     for variant_id in ids:

+     for variant_id in sorted(variants.variants):

          variant = variants.variants[variant_id]

-         _serialize_variant(conf, variant)

+         _serialize_variant(conf, variant, extra_addons.get(variant_id, set()))

  

  

  class SortedDict(dict):

@@ -19,6 +19,10 @@ 

  

  By default the \fIcompose/\fR subdirectory will be used. This is where most

  consumers expect the file to be.

+ .TP

+ .BR \-\-addon = \fIBASE\fR:\fIADDON\fR

+ Mark \fIADDON\fR variant as an addon to \fIBASE\fR, even though it may not be

+ created as such. Multiple pairs be specified.

  .SH BUGS

  Please report bugs at

  .br

@@ -0,0 +1,36 @@ 

+ [compose]

+ date = 20160720

+ id = DP-1.0-20160720.t.8

+ respin = 8

+ type = test

+ 

+ [product]

+ family = Dummy Product

+ name = DP-1.0-20160720.t.8

+ short = DP

+ type = ga

+ variants = Server

+ version = 1.0

+ 

+ [variant-Client]

+ arches = s390x,x86_64

+ id = Client

+ name = Client

+ type = variant

+ uid = Client

+ 

+ [variant-Client.s390x]

+ 

+ [variant-Client.x86_64]

+ 

+ [variant-Server]

+ arches = s390x,x86_64

+ id = Server

+ name = Server

+ type = variant

+ uid = Server

+ variants = Client

+ 

+ [variant-Server.s390x]

+ 

+ [variant-Server.x86_64]

@@ -53,6 +53,26 @@ 

              expected = f.read().split()

              self.assertEqual(output.getvalue().split(), expected)

  

+     def test_write_legacy_file__extra_addon(self):

+         output = StringIO()

+         # Keep only Server variant and remove all paths for server

+         server = self.compose.info.variants['Server']

+         server.variants = {}

+         client = self.compose.info.variants['Client']

+         client.variants = {}

+         client.arches = ['s390x', 'x86_64']

+         self.compose.info.variants.variants = {'Server': server, 'Client': client}

+         for v in ('Client', 'Server'):

+             for type in self.compose.info.variants[v].paths._fields:

+                 setattr(self.compose.info.variants[v].paths, type, {})

+ 

+         # Mark Client as addon for Server.

+         write_legacy_composeinfo(self.compose.info, output, [('Server', 'Client')])

+         self.maxDiff = None

+         with open(os.path.join(BASE_PATH, 'compose', get_expected('.addon'))) as f:

+             expected = f.read().split()

+             self.assertEqual(output.getvalue().split(), expected)

+ 

  

  if __name__ == '__main__':

      unittest.main()

Even though two variants can be created as standalone variants, we may want to mark them as addons in the legacy .composeinfo to make it possible to import to Beaker.

Pull-Request has been merged by lsedlar

5 years ago