From c1156b7fa276526c3f47fc8e41085356eef10a49 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 29 Jan 2014 14:38:36 +0100 Subject: [PATCH 1/8] split default section into supported and default --- easybuild/framework/easyconfig/format/two.py | 38 ++++----- .../framework/easyconfig/format/version.py | 79 ++++++++++++------- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/easybuild/framework/easyconfig/format/two.py b/easybuild/framework/easyconfig/format/two.py index 74a0b3c45b..bd8720958d 100644 --- a/easybuild/framework/easyconfig/format/two.py +++ b/easybuild/framework/easyconfig/format/two.py @@ -108,8 +108,8 @@ def get_config_dict(self): version = self.specs.get('version', None) if version is None: # check for default version - if 'default_version' in cov.default: - version = cov.default['default_version'] + if 'version' in cov.default: + version = cov.default['version'] self.log.info("no software version specified, using default version '%s'" % version) else: self.log.error("no software version specified, no default version found") @@ -120,13 +120,13 @@ def get_config_dict(self): toolchain_name = tc_spec.get('name', None) if toolchain_name is None: # check for default toolchain - if 'default_toolchain' in cov.default: - toolchain = cov.default['default_toolchain'] - toolchain_name = toolchain.tc_name + if 'toolchain' in cov.default: + toolchain = cov.default['toolchain'] + toolchain_name = toolchain['name'] self.log.info("no toolchain name specified, using default '%s'" % toolchain_name) toolchain_version = tc_spec.get('version', None) if toolchain_version is None: - toolchain_version = toolchain.get_version_str() + toolchain_version = toolchain['version'] self.log.info("no toolchain version specified, using default '%s'" % toolchain_version) else: self.log.error("no toolchain name specified, no default toolchain found") @@ -136,23 +136,6 @@ def get_config_dict(self): if toolchain_version is None: self.log.error("Toolchain specification incomplete: name %s provided, but no version" % toolchain_name) - # add version/toolchain specifications to config dict - if isinstance(version, VersionOperator): - version = version.get_version_str() - elif not isinstance(version, basestring): - self.log.error("Found version of unexpected type: %s (%s)" % (type(version), version)) - if isinstance(toolchain_version, ToolchainVersionOperator): - toolchain_version = toolchain_version.get_version_str() - elif not isinstance(toolchain_version, basestring): - tup = (type(toolchain_version), toolchain_version) - self.log.error("Found toolchain version of unexpected type: %s (%s)" % tup) - - cfg.update({ - 'version': version, - 'toolchain': {'name': toolchain_name, 'version': toolchain_version}, - }) - self.log.debug("Config dict including version/toolchain specs: %s" % cfg) - # toolchain name is known, remove all others toolchains from parsed easyconfig before we continue # this also performs some validation, and checks for conflicts between section markers self.log.debug("sections for full parsed configobj: %s" % cov.sections) @@ -161,7 +144,14 @@ def get_config_dict(self): section_specs = cov.get_specs_for(version=version, tcname=toolchain_name, tcversion=toolchain_version) cfg.update(section_specs) + self.log.debug("Config dict after processing applicable easyconfig sections: %s" % cfg) # FIXME what about updating dict values/appending to list values? how do we allow both redefining and updating? = and +=? - self.log.debug("Final config dict: %s" % cfg) + # update config with correct version/toolchain (to avoid using values specified in default section) + cfg.update({ + 'version': version, + 'toolchain': {'name': toolchain_name, 'version': toolchain_version}, + }) + + self.log.debug("Final config dict (including correct version/toolchain): %s" % cfg) return cfg diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 04f846f86c..3728740c81 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -475,6 +475,17 @@ def parse_versop_str(self, tcversop_str): self.log.debug("toolchain versop expression '%s' parsed to '%s'" % (tcversop_str, tcversop_dict)) return tcversop_dict + def as_dict(self): + """ + Return toolchain version operator as a dictionary with name/version keys. + Returns None if translation to a dictionary is not possible (e.g. non-equals operator, missing version, ...). + """ + version = self.get_version_str() + if not None in [self.tc_name, version] and self.operator == self.OPERATOR_MAP['==']: + return {'name': self.tc_name, 'version': version} + else: + return None + class OrderedVersionOperators(object): """ @@ -566,9 +577,11 @@ class ConfigObjVersion(object): """ # TODO: add nested/recursive example to docstring - DEFAULT = 'DEFAULT' + SECTION_MARKER_DEFAULT = 'DEFAULT' + SECTION_MARKER_DEPENDENCIES = 'DEPENDENCIES' + SECTION_MARKER_SUPPORTED = 'SUPPORTED' # list of known marker types (except default) - KNOWN_MARKER_TYPES = [ToolchainVersionOperator, VersionOperator] # order matters, see parse_sections + KNOWN_VERSION_MARKER_TYPES = [ToolchainVersionOperator, VersionOperator] # order matters, see parse_sections VERSION_OPERATOR_VALUE_TYPES = { # toolchains: comma-separated list of toolchain version operators 'toolchains': ToolchainVersionOperator, @@ -586,8 +599,9 @@ def __init__(self, configobj=None): self.tcname = None self.default = {} # default section - self.sections = {} # non-default sections - self.unfiltered_sections = {} # unfiltered non-default sections + self.supported = {} # supported section + self.sections = {} # all other sections + self.unfiltered_sections = {} # unfiltered other sections self.versops = OrderedVersionOperators() self.tcversops = OrderedVersionOperators() @@ -621,13 +635,19 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): for key, value in toparse.items(): if isinstance(value, Section): self.log.debug("Enter subsection key %s value %s" % (key, value)) - # only 3 types of sectionkeys supported: VersionOperator, ToolchainVersionOperator, and DEFAULT - if key in [self.DEFAULT]: + # only supported types of section keys are: + # * DEFAULT + # * SUPPORTED + # * dependencies + # * VersionOperator or ToolchainVersionOperator (e.g. [> 2.0], [goolf > 1]) + if key in [self.SECTION_MARKER_DEFAULT, self.SECTION_MARKER_SUPPORTED]: new_key = key + elif key in [self.SECTION_MARKER_DEPENDENCIES]: + raise NotImplementedError else: # try parsing key as toolchain version operator first # try parsing as version operator if it's not a toolchain version operator - for marker_type in self.KNOWN_MARKER_TYPES: + for marker_type in self.KNOWN_VERSION_MARKER_TYPES: new_key = marker_type(key) if new_key: self.log.debug("'%s' was parsed as a %s section marker" % (key, marker_type.__name__)) @@ -710,7 +730,7 @@ def validate_and_filter_by_toolchain(self, tcname, processed=None, filtered_sect self.versops.add(key, value) filtered_sections[key] = value else: - self.log.error("Unhandled section marker type '%s', not in %s?" % (type(key), self.KNOWN_MARKER_TYPES)) + self.log.error("Unhandled section marker '%s' (type '%s')" % (key, type(key))) # recursively go deeper for (relevant) sections self.validate_and_filter_by_toolchain(tcname, processed=value, filtered_sections=filtered_sections, @@ -744,28 +764,35 @@ def parse(self, configobj): # process the configobj instance self.sections = self.parse_sections(self.configobj) - # check for defaults section - default = self.sections.pop(self.DEFAULT, {}) - known_default_keywords = ('toolchains', 'versions') - # default should only have versions and toolchains + # handle default section # no nesting - # - add DEFAULT key,values to the root of self.sections + # - add DEFAULT key-value entries to the root of self.sections # - key-value items from other sections will be deeper down # - deepest level is best match and wins, so defaults are on top level + default = self.sections.pop(self.SECTION_MARKER_DEFAULT, {}) for key, value in default.items(): - if not key in known_default_keywords: - self.log.error('Unsupported key %s in %s section' % (key, self.DEFAULT)) self.sections[key] = value + self.default = default - if 'versions' in default: + # handle supported section + # supported should only have 'versions' and 'toolchains' keys + supported = self.sections.pop(self.SECTION_MARKER_SUPPORTED, {}) + known_supported_keywords = self.VERSION_OPERATOR_VALUE_TYPES.keys() + for key, value in supported.items(): + if not key in known_supported_keywords: + self.log.error('Unsupported key %s in %s section' % (key, self.SECTION_MARKER_SUPPORTED)) + self.sections['%s' % key] = value + self.supported = supported + + if 'versions' in supported: # first of list is special: it is the default - default['default_version'] = default['versions'][0] - if 'toolchains' in default: + self.default['version'] = supported['versions'][0].get_version_str() + if 'toolchains' in supported: # first of list is special: it is the default - default['default_toolchain'] = default['toolchains'][0] + self.default['toolchain'] = supported['toolchains'][0].as_dict() - self.default = default - self.log.debug("(parse) default: %s; sections: %s" % (self.default, self.sections)) + tup = (self.default, self.supported, self.sections) + self.log.debug("(parse) default: %s; supported: %s, sections: %s" % tup) def get_specs_for(self, version=None, tcname=None, tcversion=None): """ @@ -775,13 +802,9 @@ def get_specs_for(self, version=None, tcname=None, tcversion=None): cfg = self.default.dict() else: cfg = copy.deepcopy(self.default) - # get rid of entries that are not easyconfig parameters - # FIXME these should go in a dedicated section SUPPORTED instead of DEFAULT? - for key in ['default_toolchain', 'default_version', 'toolchains', 'versions']: - cfg.pop(key) # make sure that requested version/toolchain are supported by this easyconfig - versions = [x.get_version_str() for x in self.default['versions']] + versions = [x.get_version_str() for x in self.supported['versions']] if version is None: self.log.debug("No version specified") elif version in versions: @@ -789,12 +812,12 @@ def get_specs_for(self, version=None, tcname=None, tcversion=None): else: self.log.error("Version '%s' not supported in easyconfig (only %s)" % (version, versions)) - tcnames = [tc.tc_name for tc in self.default['toolchains']] + tcnames = [tc.tc_name for tc in self.supported['toolchains']] if tcname is None: self.log.debug("Toolchain name not specified.") elif tcname in tcnames: self.log.debug("Toolchain '%s' is supported in easyconfig." % tcname) - tcversions = [tc.get_version_str() for tc in self.default['toolchains'] if tc.tc_name == tcname] + tcversions = [tc.get_version_str() for tc in self.supported['toolchains'] if tc.tc_name == tcname] if tcversion is None: self.log.debug("Toolchain version not specified.") elif tcversion in tcversions: From 5e2fe3f831a4710025e5e1b1372004b063da0958 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 29 Jan 2014 14:39:16 +0100 Subject: [PATCH 2/8] transform use of [DEFAULT] to [SUPPORTED], use default section in gzip.eb test easyconfig --- test/framework/easyconfigs/v2.0/GCC.eb | 2 +- test/framework/easyconfigs/v2.0/doesnotexist.eb | 4 +++- test/framework/easyconfigs/v2.0/gzip.eb | 7 ++++--- test/framework/easyconfigs/v2.0/toy.eb | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/test/framework/easyconfigs/v2.0/GCC.eb b/test/framework/easyconfigs/v2.0/GCC.eb index 4a9e8ced37..ece0f2bef9 100644 --- a/test/framework/easyconfigs/v2.0/GCC.eb +++ b/test/framework/easyconfigs/v2.0/GCC.eb @@ -33,7 +33,7 @@ license = GPLv3 moduleclass = 'compiler' -[DEFAULT] +[SUPPORTED] versions = 4.6.2, 4.6.3 toolchains = dummy == dummy diff --git a/test/framework/easyconfigs/v2.0/doesnotexist.eb b/test/framework/easyconfigs/v2.0/doesnotexist.eb index 7cd5fb1c4e..3cfe8a9361 100644 --- a/test/framework/easyconfigs/v2.0/doesnotexist.eb +++ b/test/framework/easyconfigs/v2.0/doesnotexist.eb @@ -23,10 +23,12 @@ source_urls = ['http://ftpmirror.gnu.org/gzip'] # make sure the gzip and gunzip binaries are available after installation sanity_check_paths = {'files': ["bin/gunzip", "bin/gzip"], 'dirs': []} -[DEFAULT] +[SUPPORTED] versions=1.0.0,>= 0.5.0 toolchains=dummy > 5,GCC == 3.0.0,ictce < 1.0 + [goolf > 1] versions=1.5.0 + [2.0.0] toolchains=dummy > 6,GCC > 4 diff --git a/test/framework/easyconfigs/v2.0/gzip.eb b/test/framework/easyconfigs/v2.0/gzip.eb index 82a6bbc8fb..ee3e1d5379 100644 --- a/test/framework/easyconfigs/v2.0/gzip.eb +++ b/test/framework/easyconfigs/v2.0/gzip.eb @@ -20,8 +20,9 @@ sanity_check_paths = { sanity_check_commands = [True, ('gzip', '--version')] -moduleclass = 'tools' - -[DEFAULT] +[SUPPORTED] versions = 1.4, 1.5 toolchains = dummy == dummy, goolf, GCC == 4.6.3, goolf == 1.4.10, ictce == 4.1.13 + +[DEFAULT] +moduleclass = tools diff --git a/test/framework/easyconfigs/v2.0/toy.eb b/test/framework/easyconfigs/v2.0/toy.eb index 15e70c4146..f8ff148e97 100644 --- a/test/framework/easyconfigs/v2.0/toy.eb +++ b/test/framework/easyconfigs/v2.0/toy.eb @@ -20,6 +20,6 @@ sanity_check_paths = { moduleclass = 'tools' -[DEFAULT] +[SUPPORTED] versions = 1.0, 0.0 toolchains = goolf == 1.4.10, dummy == dummy From c28cb86b5f12356409ba2912e7c330b4ca2419cf Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 29 Jan 2014 21:17:19 +0100 Subject: [PATCH 3/8] implement preliminary parsing of dependency specifications --- .../framework/easyconfig/format/version.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 3728740c81..357ccee5d1 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -641,9 +641,19 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): # * dependencies # * VersionOperator or ToolchainVersionOperator (e.g. [> 2.0], [goolf > 1]) if key in [self.SECTION_MARKER_DEFAULT, self.SECTION_MARKER_SUPPORTED]: + # parse value as a section, recursively new_key = key - elif key in [self.SECTION_MARKER_DEPENDENCIES]: - raise NotImplementedError + new_value = self.parse_sections(configobj, toparse=value, parent=value.parent, depth=value.depth) + + elif key == self.SECTION_MARKER_DEPENDENCIES: + new_key = 'dependencies' + new_value = [] + for dep_name, dep_spec in value.items(): + if isinstance(dep_spec, Section): + self.log.error("Unsupported nested section '%s' found in dependencies section" % dep_name) + else: + # FIXME: parse the dependency specification for version, toolchain, suffix, etc. + new_value.append((dep_name, dep_spec)) else: # try parsing key as toolchain version operator first # try parsing as version operator if it's not a toolchain version operator @@ -657,8 +667,8 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): if not new_key: self.log.error("Unsupported section marker '%s'" % key) - # parse value as a section, recursively - new_value = self.parse_sections(configobj, toparse=value, parent=value.parent, depth=value.depth) + # parse value as a section, recursively + new_value = self.parse_sections(configobj, toparse=value, parent=value.parent, depth=value.depth) else: new_key = key From dfe226ad2e894d9b91b1bbc465591a4f081a2669 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Thu, 30 Jan 2014 14:54:37 +0100 Subject: [PATCH 4/8] complete implementation of handling dependencies in format v2, works for simple (name,version) deps --- .../framework/easyconfig/format/version.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 64ca0b97b9..2cf5f3e856 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -642,8 +642,9 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): # * VersionOperator or ToolchainVersionOperator (e.g. [> 2.0], [goolf > 1]) if key in [self.SECTION_MARKER_DEFAULT, self.SECTION_MARKER_SUPPORTED]: # parse value as a section, recursively - new_key = key new_value = self.parse_sections(configobj, toparse=value, parent=value.parent, depth=value.depth) + self.log.debug('Converted %s section to new value %s' % (key, new_value)) + parsed[key] = new_value elif key == self.SECTION_MARKER_DEPENDENCIES: new_key = 'dependencies' @@ -654,6 +655,12 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): else: # FIXME: parse the dependency specification for version, toolchain, suffix, etc. new_value.append((dep_name, dep_spec)) + + self.log.debug('Converted %s section to %s, passed it to parent section (or default)' % (key, new_value)) + if isinstance(parsed, Section): + parsed.parent[new_key] = new_value + else: + parsed[self.SECTION_MARKER_DEFAULT].update({new_key: new_value}) else: # try parsing key as toolchain version operator first # try parsing as version operator if it's not a toolchain version operator @@ -670,17 +677,18 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): # parse value as a section, recursively new_value = self.parse_sections(configobj, toparse=value, parent=value.parent, depth=value.depth) - else: - new_key = key + self.log.debug('Converted key %s value %s in new key %s new value %s' % (key, value, new_key, new_value)) + parsed[new_key] = new_value + else: # simply pass down any non-special key-value items - if not new_key in special_keys: - self.log.debug('Passing down key %s with value %s' % (new_key, value)) + if not key in special_keys: + self.log.debug('Passing down key %s with value %s' % (key, value)) new_value = value # parse individual key-value assignments - elif new_key in self.VERSION_OPERATOR_VALUE_TYPES: - value_type = self.VERSION_OPERATOR_VALUE_TYPES[new_key] + elif key in self.VERSION_OPERATOR_VALUE_TYPES: + value_type = self.VERSION_OPERATOR_VALUE_TYPES[key] # list of supported toolchains/versions # first one is default if isinstance(value, basestring): @@ -693,11 +701,11 @@ def parse_sections(self, configobj, toparse=None, parent=None, depth=0): if None in new_value: self.log.error("Failed to parse '%s' as a %s" % (value, value_type.__class__.__name__)) else: - tup = (new_key, value, type(value)) + tup = (key, value, type(value)) self.log.error('Bug: supported but unknown key %s with non-string value: %s, type %s' % tup) - self.log.debug('Converted key %s value %s in new key %s new value %s' % (key, value, new_key, new_value)) - parsed[new_key] = new_value + self.log.debug("Converted value '%s' for key '%s' into new value '%s'" % (value, key, new_value)) + parsed[key] = new_value return parsed From abef4f3a49829658a4191f158deab4e10599706e Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Thu, 30 Jan 2014 14:55:06 +0100 Subject: [PATCH 5/8] add unit test easyconfig to verify parsing of dependency specs --- test/framework/easyconfigparser.py | 12 +++++++++++ test/framework/easyconfigs/v2.0/libpng.eb | 26 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 test/framework/easyconfigs/v2.0/libpng.eb diff --git a/test/framework/easyconfigparser.py b/test/framework/easyconfigparser.py index d2eefc2a68..e272630589 100644 --- a/test/framework/easyconfigparser.py +++ b/test/framework/easyconfigparser.py @@ -58,6 +58,18 @@ def test_v20_extra(self): self.assertFalse('version' in formatter.pyheader_localvars) self.assertFalse('toolchain' in formatter.pyheader_localvars) + def test_v20_deps(self): + fn = os.path.join(TESTDIRBASE, 'v2.0', 'libpng.eb') + ecp = EasyConfigParser(fn) + + ec = ecp.get_config_dict() + self.assertEqual(ec['name'], 'libpng') + # first version/toolchain listed is default + self.assertEqual(ec['version'], '1.5.10') + self.assertEqual(ec['toolchain'], {'name': 'goolf', 'version': '1.4.10'}) + + # dependencies should be parsed correctly + self.assertEqual(ec['dependencies'], [('zlib', '1.2.5')]) def suite(): """ returns all the testcases in this module """ diff --git a/test/framework/easyconfigs/v2.0/libpng.eb b/test/framework/easyconfigs/v2.0/libpng.eb new file mode 100644 index 0000000000..6db4a276a5 --- /dev/null +++ b/test/framework/easyconfigs/v2.0/libpng.eb @@ -0,0 +1,26 @@ +# EASYCONFIGFORMAT 2.0 +""" +Example easyconfig with dependencies +@author: Kenneth Hoste (UGent) +""" +name = 'libpng' + +description = "libpng is the official PNG reference library" + +toolchainopts = {'optarch': True} + +configopts = "--with-pic" + +source_urls = [SOURCEFORGE_SOURCE] +sources = [SOURCELOWER_TAR_GZ] + +[SUPPORTED] +versions = 1.5.10, 1.5.11, 1.5.13, 1.5.14, 1.6.2, 1.6.3, 1.6.6 +toolchains = goolf == 1.4.10, ictce == 4.1.13, goalf == 1.1.0-no-OFED + +[DEFAULT] +homepage = http://www.libpng.org/pub/png/libpng.html +moduleclass = lib + +[DEPENDENCIES] +zlib = 1.2.5 From 26adea385ce0d33aad9adc1c5f4175c7d7b28862 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Thu, 30 Jan 2014 15:15:29 +0100 Subject: [PATCH 6/8] fix remark w.r.t as_dict ToolchainVersionOperator method, test functionality in unit tests --- easybuild/framework/easyconfig/format/version.py | 2 +- test/framework/easyconfigversion.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 2cf5f3e856..1108304fb3 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -481,7 +481,7 @@ def as_dict(self): Returns None if translation to a dictionary is not possible (e.g. non-equals operator, missing version, ...). """ version = self.get_version_str() - if not None in [self.tc_name, version] and self.operator == self.OPERATOR_MAP['==']: + if self.operator == self.OPERATOR_MAP['==']: return {'name': self.tc_name, 'version': version} else: return None diff --git a/test/framework/easyconfigversion.py b/test/framework/easyconfigversion.py index 32accccccc..c7edb56ad5 100644 --- a/test/framework/easyconfigversion.py +++ b/test/framework/easyconfigversion.py @@ -152,13 +152,15 @@ def test_parser_toolchain_regex(self): for tc in tc_names: # test all known toolchain names # test version expressions with optional version operator ok_tests = [ - "%s >= 1.2.3" % tc, - "%s == 1.2.3" % tc, - tc, + ("%s >= 1.2.3" % tc, None), # only dict repr for == operator + ("%s == 1.2.3" % tc, {'name': tc, 'version': '1.2.3'}), + (tc, None), # only toolchain name, no dict repr (default operator is >=, version is 0.0.0) ] - for txt in ok_tests: + for txt, as_dict in ok_tests: self.assertTrue(top.regex.search(txt), "%s matches toolchain section marker regex" % txt) - self.assertTrue(ToolchainVersionOperator(txt)) + tcversop = ToolchainVersionOperator(txt) + self.assertTrue(tcversop) + self.assertEqual(tcversop.as_dict(), as_dict) # only accept known toolchain names fail_tests = [ From 0f3fbe85d9f2468b17e293bd9a10f47b81f01d6a Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Thu, 30 Jan 2014 15:20:30 +0100 Subject: [PATCH 7/8] fix minor remark --- easybuild/framework/easyconfig/format/version.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 1108304fb3..cd8ff9df7b 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -795,9 +795,8 @@ def parse(self, configobj): # handle supported section # supported should only have 'versions' and 'toolchains' keys supported = self.sections.pop(self.SECTION_MARKER_SUPPORTED, {}) - known_supported_keywords = self.VERSION_OPERATOR_VALUE_TYPES.keys() for key, value in supported.items(): - if not key in known_supported_keywords: + if not key in self.VERSION_OPERATOR_VALUE_TYPES: self.log.error('Unsupported key %s in %s section' % (key, self.SECTION_MARKER_SUPPORTED)) self.sections['%s' % key] = value self.supported = supported From 42df1df3db4ff54252001b1cae33eb6318359d66 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Thu, 30 Jan 2014 18:22:35 +0100 Subject: [PATCH 8/8] correct use of self.default and self.supported in parse method --- .../framework/easyconfig/format/version.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index cd8ff9df7b..f95f49ad4f 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -787,26 +787,24 @@ def parse(self, configobj): # - add DEFAULT key-value entries to the root of self.sections # - key-value items from other sections will be deeper down # - deepest level is best match and wins, so defaults are on top level - default = self.sections.pop(self.SECTION_MARKER_DEFAULT, {}) - for key, value in default.items(): + self.default = self.sections.pop(self.SECTION_MARKER_DEFAULT, {}) + for key, value in self.default.items(): self.sections[key] = value - self.default = default # handle supported section # supported should only have 'versions' and 'toolchains' keys - supported = self.sections.pop(self.SECTION_MARKER_SUPPORTED, {}) - for key, value in supported.items(): + self.supported = self.sections.pop(self.SECTION_MARKER_SUPPORTED, {}) + for key, value in self.supported.items(): if not key in self.VERSION_OPERATOR_VALUE_TYPES: self.log.error('Unsupported key %s in %s section' % (key, self.SECTION_MARKER_SUPPORTED)) self.sections['%s' % key] = value - self.supported = supported - if 'versions' in supported: + if 'versions' in self.supported: # first of list is special: it is the default - self.default['version'] = supported['versions'][0].get_version_str() - if 'toolchains' in supported: + self.default['version'] = self.supported['versions'][0].get_version_str() + if 'toolchains' in self.supported: # first of list is special: it is the default - self.default['toolchain'] = supported['toolchains'][0].as_dict() + self.default['toolchain'] = self.supported['toolchains'][0].as_dict() tup = (self.default, self.supported, self.sections) self.log.debug("(parse) default: %s; supported: %s, sections: %s" % tup)