CHECK_PROPERTY = "has_unit_tests"
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and
- logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- products_infos = [pi for pi in products_infos if not(
- src.product.product_is_native(pi[1]) or
- src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def log_step(logger, header, step):
logger.write("\r%s%s" % (header, " " * 20), 3)
src.check_config_has_application( runner.cfg )
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Print some informations
logger.write(_('Executing the check command in the build '
except NameError:
pass
-PROPERTY_EXPRESSION = "^.+:.+$"
# Define all possible option for the clean command : sat clean <options>
parser = src.options.Options()
parser.add_option('p', 'products', 'list2', 'products',
_('Optional: Products to clean. This option can be'
' passed several time to clean several products.'))
-parser.add_option('', 'properties', 'string', 'properties',
- _('Optional: Filter the products by their properties.\n\tSyntax: '
- '--properties <property>:<value>'))
-parser.add_option('s', 'sources', 'boolean', 'sources',
+parser.add_option('s', 'sources', 'boolean', 'sources',
_("Optional: Clean the product source directories."))
parser.add_option('b', 'build', 'boolean', 'build',
_("Optional: Clean the product build directories."))
parser.add_option('', 'sources_without_dev', 'boolean', 'sources_without_dev',
_("Optional: do not clean the products in development mode."))
-def get_products_list(options, cfg, logger):
- """\
- method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param config Config: The global configuration
- :param logger Logger: The logger instance to use for the display and logging
- :return: The list of (product name, product_informations).
- :rtype: List
- """
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- # if the property option was passed, filter the list
- if options.properties:
- [prop, value] = options.properties.split(":")
- products_infos = [(p_name, p_info) for
- (p_name, p_info) in products_infos
- if "properties" in p_info and
- prop in p_info.properties and
- p_info.properties[prop] == value]
-
- return products_infos
def get_source_directories(products_infos, without_dev):
"""\
# check that the command has been called with an application
src.check_config_has_application( runner.cfg )
- # Verify the --properties option
- if options.properties:
- oExpr = re.compile(PROPERTY_EXPRESSION)
- if not oExpr.search(options.properties):
- msg = _('WARNING: the "--properties" options must have the '
- 'following syntax:\n--properties <property>:<value>')
- logger.write(src.printcolors.printcWarning(msg), 1)
- logger.write("\n", 1)
- options.properties = None
-
# Get the list of products to threat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Construct the list of directories to suppress
l_dir_to_suppress = []
except NameError:
pass
-PROPERTY_EXPRESSION = "^.+:.+$"
# Define all possible option for the compile command : sat compile <options>
parser = src.options.Options()
parser.add_option('p', 'products', 'list2', 'products',
_('Optional: products to compile. This option can be'
' passed several time to compile several products.'))
-parser.add_option('', 'properties', 'string', 'properties',
- _('Optional: Filter the products by their properties.\n\tSyntax: '
- '--properties <property>:<value>'))
parser.add_option('', 'with_fathers', 'boolean', 'fathers',
_("Optional: build all necessary products to the given product (KERNEL is "
"build before building GUI)."), False)
parser.add_option('', 'clean_build_after', 'boolean', 'clean_build_after',
_('Optional: remove the build directory after successful compilation'), False)
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and
- logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- # if the property option was passed, filter the list
- if options.properties:
- [prop, value] = options.properties.split(":")
- products_infos = [(p_name, p_info) for
- (p_name, p_info) in products_infos
- if "properties" in p_info and
- prop in p_info.properties and
- p_info.properties[prop] == value]
-
-
- # get rid of fixed products
- products_infos = [pi for pi in products_infos if not(
- src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def get_children(config, p_name_p_info):
l_res = []
# check that the command has been called with an application
src.check_config_has_application( runner.cfg )
- # Verify the --properties option
- if options.properties:
- oExpr = re.compile(PROPERTY_EXPRESSION)
- if not oExpr.search(options.properties):
- msg = _('WARNING: the "--properties" options must have the '
- 'following syntax:\n--properties <property>:<value>')
- logger.write(src.printcolors.printcWarning(msg), 1)
- logger.write("\n", 1)
- options.properties = None
-
# Print some informations
logger.write(_('Executing the compile commands in the build '
'directories of the products of '
src.print_info(logger, info)
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
if options.fathers:
# Extend the list with all recursive dependencies of the given products
parser.add_option('o', 'option', 'string', 'option',
_('Optional: Option to add to the configure or cmake command.'), "")
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- products_infos = [pi for pi in products_infos if not(src.product.product_is_native(pi[1]) or src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def log_step(logger, header, step):
logger.write("\r%s%s" % (header, " " * 20), 3)
src.check_config_has_application( runner.cfg )
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Print some informations
logger.write(_('Configuring the sources of the application %s\n') %
parser.add_option('o', 'option', 'string', 'option',
_('Optional: Option to add to the make command.'), "")
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and
- logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- products_infos = [pi for pi in products_infos if not(
- src.product.product_is_native(pi[1]) or
- src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def log_step(logger, header, step):
logger.write("\r%s%s" % (header, " " * 20), 3)
src.check_config_has_application( runner.cfg )
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Print some informations
logger.write(_('Executing the make command in the build '
_('Optional: products to install. This option can be'
' passed several time to install several products.'))
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- products_infos = [pi for pi in products_infos if not(src.product.product_is_native(pi[1]) or src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def log_step(logger, header, step):
logger.write("\r%s%s" % (header, " " * 20), 3)
src.check_config_has_application( runner.cfg )
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Print some informations
logger.write(_('Executing the make install command in the build directories of the application %s\n') %
parser.add_option('p', 'products', 'list2', 'products',
_('Optional: products to get the sources. This option can be'
' passed several time to get the sources of several products.'))
-parser.add_option('', 'properties', 'string', 'properties',
- _('Optional: Filter the products by their properties.\n\tSyntax: '
- '--properties <property>:<value>'))
def apply_patch(config, product_info, max_product_name_len, logger):
'''The method called to apply patches on a product
# check that the command has been called with an application
src.check_config_has_application( runner.cfg )
- # Verify the --properties option
- if options.properties:
- oExpr = re.compile(prepare.PROPERTY_EXPRESSION)
- if not oExpr.search(options.properties):
- msg = _('WARNING: the "--properties" options must have the '
- 'following syntax:\n--properties <property>:<value>')
- logger.write(src.printcolors.printcWarning(msg), 1)
- logger.write("\n", 1)
- options.properties = None
-
# Print some informations
logger.write('Patching sources of the application %s\n' %
src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
logger.write("\n", 2, False)
# Get the products list with products informations regarding the options
- products_infos = prepare.get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Get the maximum name length in order to format the terminal display
max_product_name_len = 1
import src
import src.debug as DBG
-PROPERTY_EXPRESSION = "^.+:.+$"
# Define all possible option for prepare command : sat prepare <options>
parser = src.options.Options()
parser.add_option('p', 'products', 'list2', 'products',
_('Optional: products to prepare. This option can be'
' passed several time to prepare several products.'))
-parser.add_option('', 'properties', 'string', 'properties',
- _('Optional: Filter the products by their properties.\n\tSyntax: '
- '--properties <property>:<value>'))
-parser.add_option('f', 'force', 'boolean', 'force',
+parser.add_option('f', 'force', 'boolean', 'force',
_("Optional: force to prepare the products in development mode."))
parser.add_option('', 'force_patch', 'boolean', 'force_patch',
_("Optional: force to apply patch to the products in development mode."))
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param config Config: The global configuration
- :param logger Logger: The logger instance to use for the display and logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- # if the property option was passed, filter the list
- if options.properties:
- [prop, value] = options.properties.split(":")
- products_infos = [(p_name, p_info) for
- (p_name, p_info) in products_infos
- if "properties" in p_info and
- prop in p_info.properties and
- p_info.properties[prop] == value]
-
- return products_infos
def find_products_already_getted(l_products):
'''function that returns the list of products that have an existing source
# check that the command has been called with an application
src.check_config_has_application( runner.cfg )
- # Verify the --properties option
- if options.properties:
- oExpr = re.compile(PROPERTY_EXPRESSION)
- if not oExpr.search(options.properties):
- msg = _('WARNING: the "--properties" options must have the '
- 'following syntax:\n--properties <property>:<value>')
- logger.write(src.printcolors.printcWarning(msg), 1)
- logger.write("\n", 1)
- options.properties = None
-
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Construct the arguments to pass to the clean, source and patch commands
args_appli = runner.cfg.VARS.application + " " # useful whitespace
'if you want this option to work.\n\tThe $MAKE_OPTIONS has to be '
'used.'), 0)
-def get_products_list(options, cfg, logger):
- '''method that gives the product list with their informations from
- configuration regarding the passed options.
-
- :param options Options: The Options instance that stores the commands
- arguments
- :param cfg Config: The global configuration
- :param logger Logger: The logger instance to use for the display and
- logging
- :return: The list of (product name, product_informations).
- :rtype: List
- '''
- # Get the products to be prepared, regarding the options
- if options.products is None:
- # No options, get all products sources
- products = cfg.APPLICATION.products
- else:
- # if option --products, check that all products of the command line
- # are present in the application.
- products = options.products
- for p in products:
- if p not in cfg.APPLICATION.products:
- raise src.SatException(_("Product %(product)s "
- "not defined in application %(application)s") %
- { 'product': p, 'application': cfg.VARS.application} )
-
- # Construct the list of tuple containing
- # the products name and their definition
- products_infos = src.product.get_products_infos(products, cfg)
-
- products_infos = [pi for pi in products_infos if not(
- src.product.product_is_native(pi[1]) or
- src.product.product_is_fixed(pi[1]))]
-
- return products_infos
def log_step(logger, header, step):
logger.write("\r%s%s" % (header, " " * 20), 3)
src.check_config_has_application( runner.cfg )
# Get the list of products to treat
- products_infos = get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Print some informations
logger.write(_('Executing the script in the build '
parser.add_option('p', 'products', 'list2', 'products',
_('Optional: products from which to get the sources. This option can be'
' passed several time to get the sources of several products.'))
-parser.add_option('', 'properties', 'string', 'properties',
- _('Optional: Filter the products by their properties.\n\tSyntax: '
- '--properties <property>:<value>'))
def get_source_for_dev(config, product_info, source_dir, logger, pad):
'''The method called if the product is in development mode
# check that the command has been called with an application
src.check_config_has_application( runner.cfg )
- # Verify the --properties option
- if options.properties:
- oExpr = re.compile(prepare.PROPERTY_EXPRESSION)
- if not oExpr.search(options.properties):
- msg = _('WARNING: the "--properties" options must have the '
- 'following syntax:\n--properties <property>:<value>')
- logger.write(src.printcolors.printcWarning(msg), 1)
- logger.write("\n", 1)
- options.properties = None
-
# Print some informations
logger.write(_('Getting sources of the application %s\n') %
src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
logger.write("\n", 2, False)
# Get the products list with products informations regarding the options
- products_infos = prepare.get_products_list(options, runner.cfg, logger)
+ products_infos = src.product.get_products_list(options, runner.cfg, logger)
# Call to the function that gets all the sources
good_result, results = get_all_product_sources(runner.cfg,
import getopt
import sys
+import re
import pprint as PP
from . import printcolors
"""
# The options field stocks all options of a command
# in a list that contains dicts
+ self.PROPERTY_EXPRESSION = "^.+:.+$"
self.options = []
# The list of available option type
- self.availableOptions = "noboolean boolean string int float long list list2 level".split()
+ self.availableOptions = "noboolean boolean string int float long list list2 level properties".split()
self.noArgOptions = "noboolean boolean".split()
self.default = None
self.results = {}
option['result'] = default
self.options.append(option)
+
+ # add option properties unconditionaly if 'products' option added
+ if [shortName, longName] == ["p", "products"]:
+ self.add_option('', 'properties', 'properties', 'properties',
+ _('Optional: Filter the products by their properties.\n\tSyntax: '
+ '--properties <property>:<value>'))
+
+
def getDetailOption(self, option):
"""
if option['result'] is None:
option['result'] = list()
option['result'] = self.filterList2(opt[1])
+ elif optionType == "properties":
+ option['result'] = self.filterProperties(opt[1])
optResult.__setattr__(option['destName'], option['result'])
# free the option in order to be able to make
option['result'] = None
self.results = {"optlist": optlist, "optResult": optResult, "args": args, "argList": argList}
- DBG.write("results", self.results)
+ DBG.write("results", self.results, True)
return optResult, args
def filterLevel(self, aLevel):
aList = [i for i in aList if i != ""] # split old list leadin "," as ",KERNEL,ETC..."
return aList
+ def filterProperties(self, aStr):
+ """
+ filter properties values
+
+ example:
+ >> sat -v 9 prepare $TRG -p KERNEL --properties is_SALOME_module:yes
+ """
+ msg = _('The "--properties" option must have the following syntax:\n--properties <property>:<value>')
+ oExpr = re.compile(self.PROPERTY_EXPRESSION)
+ if not oExpr.search(aStr):
+ raise Exception(msg)
+ res = aStr.split(":")
+ if len(res) != 2:
+ raise Exception(msg)
+ return res
def __repr__(self):
- """
- repr for only self.options and self.results (if present)
- """
- aDict = {'options': self.options, 'results': self.results}
- aStr = PP.pformat(aDict)
- res = "%s(\n %s\n)" % (self.__class__.__name__, aStr[1:-1])
- return res
+ """
+ repr for only self.options and self.results (if present)
+ """
+ aDict = {'options': self.options, 'results': self.results}
+ aStr = PP.pformat(aDict)
+ res = "%s(\n %s\n)" % (self.__class__.__name__, aStr[1:-1])
+ return res
def __str__(self):
- """
- str for only resume expected self.options
- """
- #aDict = [(k["longName"], k["shortName", k["helpString"]) for k in self.options}
- #aList = [(k, self.options[k]) for k in sorted(self.options.keys())]
- aDict = {}
- for o in self.options:
- aDict[o["longName"]] = (o["shortName"], o["helpString"])
- aStr = PP.pformat(aDict)
- res = "%s(\n %s)" % (self.__class__.__name__, aStr[1:-1])
- return res
+ """
+ str for only resume expected self.options
+ """
+ #aDict = [(k["longName"], k["shortName", k["helpString"]) for k in self.options}
+ #aList = [(k, self.options[k]) for k in sorted(self.options.keys())]
+ aDict = {}
+ for o in self.options:
+ aDict[o["longName"]] = (o["shortName"], o["helpString"])
+ aStr = PP.pformat(aDict)
+ res = "%s(\n %s)" % (self.__class__.__name__, aStr[1:-1])
+ return res
def debug_write(self):
- DBG.write("options and results", self, True)
+ DBG.write("options and results", self, True)
import os
import re
+import pprint as PP
import src
import src.debug as DBG
if prod_info is not None:
products_infos.append((prod, prod_info))
else:
- msg = _("The %s product has no definition "
- "in the configuration.") % prod
+ msg = _("The %s product has no definition in the configuration.") % prod
raise src.SatException(msg)
return products_infos
+
+def get_products_list(options, cfg, logger):
+ """
+ method that gives the product list with their informations from
+ configuration regarding the passed options.
+
+ :param options Options: The Options instance that stores the commands arguments
+ :param cfg Config: The global configuration
+ :param logger Logger: The logger instance to use for the display and logging
+ :return: The list of (product name, product_informations).
+ :rtype: List
+ """
+ # Get the products to be prepared, regarding the options
+ if options.products is None:
+ # No options, get all products sources
+ products = cfg.APPLICATION.products
+ else:
+ # if option --products, check that all products of the command line
+ # are present in the application.
+ products = options.products
+ for p in products:
+ if p not in cfg.APPLICATION.products:
+ raise src.SatException(_("Product %(product)s "
+ "not defined in application %(application)s") %
+ { 'product': p, 'application': cfg.VARS.application} )
+
+ # Construct the list of tuple containing
+ # the products name and their definition
+ resAll = src.product.get_products_infos(products, cfg)
+
+ # if the property option was passed, filter the list
+ if options.properties: # existing properties
+ ok = []
+ ko = []
+ res =[]
+ prop, value = options.properties # for example 'is_SALOME_module', 'yes'
+ for p_name, p_info in resAll:
+ try:
+ if p_info.properties[prop] == value:
+ res.append((p_name, p_info))
+ ok.append(p_name)
+ else:
+ ko.append(p_name)
+ except:
+ ok.append(p_name)
+
+ if len(ok) != len(resAll):
+ logger.trace("on properties %s\n products accepted:\n %s\n products rejected:\n %s\n" %
+ (options.properties, PP.pformat(sorted(ok)), PP.pformat(sorted(ko))))
+ else:
+ logger.warning("properties %s\n seems useless with no products rejected" %
+ (options.properties))
+ else:
+ res = resAll # not existing properties as all accepted
+
+
+ ok = []
+ ko = []
+ products_infos = []
+ for p_name, p_info in res:
+ try:
+ if src.product.product_is_native(p_info) or src.product.product_is_fixed(p_info):
+ ko.append(p_name)
+ else:
+ products_infos.append((p_name, p_info))
+ ok.append(p_name)
+ except:
+ msg = "problem on 'is_native' or 'is_fixed' for product %s" % p_name
+ raise Exception(msg)
+
+ if len(ko) > 0:
+ logger.warning("on is_native or is_fixed\n products accepted:\n %s\n products rejected:\n %s\n" %
+ (PP.pformat(sorted(ok)), PP.pformat(sorted(ko))))
+
+ logger.debug("products selected:\n %s\n" % PP.pformat(sorted(ok)))
+
+ return res
+
+
def get_product_dependencies(config, product_info):
"""\
Get recursively the list of products that are