Skip to content

Commit

Permalink
Merge pull request #1 from boegel/precision_140
Browse files Browse the repository at this point in the history
style and bug fixes in variables module, added initial unit test
  • Loading branch information
stdweird committed Oct 6, 2012
2 parents d73e29e + 6276d38 commit 650a1e4
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 138 deletions.
6 changes: 3 additions & 3 deletions easybuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,9 @@ def processEasyconfig(path, log, onlyBlocks=None, regtest_online=False, validate
log.debug("Adding dependency %s for app %s." % (dep, name))
package['dependencies'].append(dep)

if eb.toolkit_name() != 'dummy':
dep = (eb.toolkit_name(), eb.toolkit_version())
log.debug("Adding toolkit %s as dependency for app %s." % (dep, name))
if eb.toolchain_name() != 'dummy':
dep = (eb.toolchain_name(), eb.toolchain_version())
log.debug("Adding toolchain %s as dependency for app %s." % (dep, name))
package['dependencies'].append(dep)

del eb
Expand Down
38 changes: 19 additions & 19 deletions easybuild/framework/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ def ready2build(self):
if len(loadedmods) > 0:
self.log.warning("Loaded modules detected: %s" % loadedmods)

# Do all dependencies have a toolkit version
self.toolkit().add_dependencies(self.cfg.dependencies())
if not len(self.cfg.dependencies()) == len(self.toolkit().dependencies):
# Do all dependencies have a toolchain version
self.toolchain().add_dependencies(self.cfg.dependencies())
if not len(self.cfg.dependencies()) == len(self.toolchain().dependencies):
self.log.debug("dep %s (%s)" % (len(self.cfg.dependencies()), self.cfg.dependencies()))
self.log.debug("tk.dep %s (%s)" % (len(self.toolkit().dependencies), self.toolkit().dependencies))
self.log.error('Not all dependencies have a matching toolkit version')
self.log.debug("tk.dep %s (%s)" % (len(self.toolchain().dependencies), self.toolchain().dependencies))
self.log.error('Not all dependencies have a matching toolchain version')

# Check if the application is not loaded at the moment
(root, env_var) = get_software_root(self.name(), with_env_var=True)
Expand Down Expand Up @@ -620,7 +620,7 @@ def build(self):
- unpack sources
- patch sources
- prepare dependencies
- prepare toolkit
- prepare toolchain
- configure
- make (use parallelism?)
- test
Expand Down Expand Up @@ -913,7 +913,7 @@ def prepare(self):
"""
Pre-configure step. Set's up the builddir just before starting configure
"""
self.toolkit().prepare(self.getcfg('onlytkmod'))
self.toolchain().prepare(self.getcfg('onlytkmod'))
self.startfrom()


Expand Down Expand Up @@ -958,21 +958,21 @@ def test(self):

return out

def toolkit(self):
def toolchain(self):
"""
Toolkit used to build this Application
Toolchain used to build this Application
"""
return self.cfg.toolkit()
return self.cfg.toolchain()

def toolkit_name(self):
"""
Name of toolkit used to build this Application
Name of toolchain used to build this Application
"""
return self.cfg.toolkit_name()

def toolkit_version(self):
"""
Version of toolkit used to build this Application
Version of toolchain used to build this Application
"""
return self.cfg.toolkit_version()

Expand Down Expand Up @@ -1189,14 +1189,14 @@ def make_module_dep(self):
"""
load = unload = ''

# Load toolkit
# Load toolchain
if self.toolkit_name() != 'dummy':
load += self.moduleGenerator.loadModule(self.toolkit_name(), self.toolkit_version())
unload += self.moduleGenerator.unloadModule(self.toolkit_name(), self.toolkit_version())

# Load dependencies
builddeps = self.cfg.builddependencies()
for dep in self.toolkit().dependencies:
for dep in self.toolchain().dependencies:
if not dep in builddeps:
self.log.debug("Adding %s/%s as a module dependency" % (dep['name'], dep['tk']))
load += self.moduleGenerator.loadModule(dep['name'], dep['tk'])
Expand Down Expand Up @@ -1689,21 +1689,21 @@ def postrun(self):
"""
pass

def toolkit(self):
def toolchain(self):
"""
Toolkit used to build this package
Toolchain used to build this package
"""
return self.master.toolkit()
return self.master.toolchain()

def toolkit_name(self):
"""
Name of toolkit used to build this package
Name of toolchain used to build this package
"""
return self.master.toolkit_name()

def toolkit_version(self):
"""
Version of toolkit used to build this package
Version of toolchain used to build this package
"""
return self.master.toolkit_version()

Expand Down
62 changes: 31 additions & 31 deletions easybuild/framework/easyconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@
import os

from easybuild.tools.build_log import getLog
from easybuild.tools.toolkit import Toolkit
from easybuild.tools.toolchain.toolchain import Toolchain
from easybuild.tools.systemtools import get_shared_lib_ext
from easybuild.tools.filetools import run_cmd
from easybuild.tools.ordereddict import OrderedDict

# we use a tuple here so we can sort them based on the numbers
MANDATORY = (0, 'mandatory')
CUSTOM = (1, 'easyblock-specific')
TOOLKIT = (2, 'toolkit')
TOOLCHAIN = (2, 'toolchain')
BUILD = (3, 'build')
FILEMANAGEMENT = (4, 'file-management')
DEPENDENCIES = (5, 'dependencies')
Expand All @@ -59,16 +59,16 @@ class EasyConfig:
default_config = [
('name', [None, "Name of software", MANDATORY]),
('version', [None, "Version of software", MANDATORY]),
('toolkit', [None, 'Name and version of toolkit', MANDATORY]),
('toolchain', [None, 'Name and version of toolchain', MANDATORY]),
('description', [None, 'A short description of the software', MANDATORY]),
('homepage', [None, 'The homepage of the software', MANDATORY]),

('toolkitopts', ['', 'Extra options for compilers', TOOLKIT]),
('onlytkmod', [False, 'Boolean/string to indicate if the toolkit should only load the enviornment with module (True) or also set all other variables (False) like compiler CC etc (If string: comma separated list of variables that will be ignored). (Default: False)', TOOLKIT]),
('toolchainopts', ['', 'Extra options for compilers', TOOLCHAIN]),
('onlytcmod', [False, 'Boolean/string to indicate if the toolchain should only load the enviornment with module (True) or also set all other variables (False) like compiler CC etc (If string: comma separated list of variables that will be ignored). (Default: False)', TOOLCHAIN]),

('easybuildVersion', [None, "EasyBuild-version this spec-file was written for", BUILD]),
('versionsuffix', ['', 'Additional suffix for software version (placed after toolkit name)', BUILD]),
('versionprefix', ['', 'Additional prefix for software version (placed before version and toolkit name)',BUILD]),
('versionsuffix', ['', 'Additional suffix for software version (placed after toolchain name)', BUILD]),
('versionprefix', ['', 'Additional prefix for software version (placed before version and toolchain name)',BUILD]),
('runtest', [None, 'Indicates if a test should be run after make; should specify argument after make (for e.g.,"test" for make test) (Default: None)', BUILD]),
('preconfigopts', ['', 'Extra options pre-passed to configure.', BUILD]),
('configopts', ['', 'Extra options passed to configure (Default already has --prefix)', BUILD]),
Expand Down Expand Up @@ -132,7 +132,7 @@ def __init__(self, path, extra_options=[], validate=True):
# perform a deepcopy of the default_config found in the easybuild.tools.easyblock module
self.config = dict(copy.deepcopy(self.default_config))
self.config.update(extra_options)
self.mandatory = ['name', 'version', 'homepage', 'description', 'toolkit']
self.mandatory = ['name', 'version', 'homepage', 'description', 'toolchain']

# extend mandatory keys
for (key, value) in extra_options:
Expand All @@ -141,8 +141,8 @@ def __init__(self, path, extra_options=[], validate=True):

self.log = getLog("EasyConfig")

# store toolkit
self._toolkit = None
# store toolchain
self._toolchain = None

if not os.path.isfile(path):
self.log.error("EasyConfig __init__ expected a valid path")
Expand Down Expand Up @@ -245,42 +245,42 @@ def builddependencies(self):

return deps

def toolkit_name(self):
def toolchain_name(self):
"""
Returns toolkit name.
Returns toolchain name.
"""
return self['toolkit']['name']
return self['toolchain']['name']

def toolkit_version(self):
def toolchain_version(self):
"""
Returns toolkit name.
Returns toolchain name.
"""
return self['toolkit']['version']
return self['toolchain']['version']

def toolkit(self):
def toolchain(self):
"""
returns the Toolkit used
returns the Toolchain used
"""
if self._toolkit:
return self._toolkit
if self._toolchain:
return self._toolchain

tk = Toolkit(self.toolkit_name(), self.toolkit_version())
if self['toolkitopts']:
tk.set_options(self['toolkitopts'])
tc = Toolchain(self.toolchain_name(), self.toolchain_version())
if self['toolchainopts']:
tc.set_options(self['toolchainopts'])

self._toolkit = tk
return self._toolkit
self._toolchain = tc
return self._toolchain

def installversion(self):
"""
return the installation version name
"""
prefix, suffix = self['versionprefix'], self['versionsuffix']

if self.toolkit_name() == 'dummy':
if self.toolchain_name() == 'dummy':
name = "%s%s%s" % (prefix, self['version'], suffix)
else:
extra = "%s-%s" % (self.toolkit_name(), self.toolkit_version())
extra = "%s-%s" % (self.toolchain_name(), self.toolchain_version())
name = "%s%s-%s%s" % (prefix, self['version'], extra, suffix)

return name
Expand Down Expand Up @@ -331,7 +331,7 @@ def _parse_dependency(self, dep):
of these attributes, 'name' and 'version' are mandatory
output dict contains these attributes:
['name', 'version', 'suffix', 'dummy', 'tk']
['name', 'version', 'suffix', 'dummy', 'tc']
"""
# convert tuple to string otherwise python might complain about the formatting
self.log.debug("Parsing %s as a dependency" % str(dep))
Expand All @@ -354,8 +354,8 @@ def _parse_dependency(self, dep):
if not dependency['version']:
self.log.error('Dependency without version.')

if not 'tk' in dependency:
dependency['tk'] = self.toolkit().get_dependency_version(dependency)
if not 'tc' in dependency:
dependency['tc'] = self.toolchain().get_dependency_version(dependency)

return dependency

Expand All @@ -377,7 +377,7 @@ def sorted_categories():
"""
returns the categories in the correct order
"""
categories = [MANDATORY, CUSTOM , TOOLKIT, BUILD, FILEMANAGEMENT, DEPENDENCIES, LICENSE , PACKAGE, MODULES, OTHER]
categories = [MANDATORY, CUSTOM , TOOLCHAIN, BUILD, FILEMANAGEMENT, DEPENDENCIES, LICENSE , PACKAGE, MODULES, OTHER]
categories.sort(key = lambda c: c[0])
return categories

Expand Down
3 changes: 2 additions & 1 deletion easybuild/test/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
import easybuild.test.filetools as f
import easybuild.test.repository as r
import easybuild.test.robot as robot
import easybuild.test.variables as v

# call suite() for each module and then run them all
suite = unittest.TestSuite(map(lambda x: x.suite(), [t, r, e, mg, m, f, a, robot]))
suite = unittest.TestSuite(map(lambda x: x.suite(), [t, r, e, mg, m, f, a, robot, v]))
unittest.TextTestRunner().run(suite)
86 changes: 86 additions & 0 deletions easybuild/test/variables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
##
# Copyright 2012 Kenneth Hoste
#
# This file is part of EasyBuild,
# originally created by the HPC team of the University of Ghent (http://ugent.be/hpc).
#
# http://github.com/hpcugent/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
import os
import re

from unittest import TestCase, TestSuite
from easybuild.tools.variables import CommaList, CommandFlagList, FlagList, ListOfLists, StrList, Variables
from easybuild.tools.variables import get_linker_endgroup, get_linker_startgroup


class VariablesTest(TestCase):
""" Baseclass for easyblock testcases """

def assertErrorRegex(self, error, regex, call, *args):
""" convenience method to match regex with the error message """
try:
call(*args)
except error, err:
self.assertTrue(re.search(regex, err.msg))

def runTest(self):

class TestListOfLists(ListOfLists):
MAP_CLASS = {'FOO':CommaList}

class TestVariables(Variables):
MAP_LISTCLASS = {TestListOfLists : ['FOO']}

v = TestVariables()
self.assertEqual(str(v), "{}")

v['BAR'] = range(3)
self.assertEqual(str(v), "{'BAR': [[], [0, 1, 2]]}")
self.assertEqual(str(v['BAR']), " 0 1 2")

v['BAR'].append(StrList(range(10, 12)))
self.assertEqual(str(v['BAR']), " 0 1 2 10 11")

v.append_el('BAR', 20)
self.assertEqual(str(v['BAR']), " 0 1 2 10 11 20")

v['FOO'] = range(3)
self.assertEqual(str(v['FOO']), " 0,1,2")

le = get_linker_endgroup()
self.assertEqual(str(le), "-Wl,--end-group")

static_dynamic = {
'static': '-Bstatic',
'dynamic': '-Bdynamic'
}

ls = get_linker_startgroup(static_dynamic)
ls.toggle_static()
self.assertEqual(str(ls), "-Wl,--start-group -Wl,-Bstatic")

fs = FlagList(["foo", "bar"])
le.set_static_dynamic(static_dynamic)
le.toggle_dynamic()
all_flags = ListOfLists([ls, fs, le])
self.assertEqual(str(all_flags), "-Wl,--start-group -Wl,-Bstatic -foo -bar -Wl,--end-group -Wl,-Bdynamic")

cmd = CommandFlagList(["gcc", "bar", "baz"])
self.assertEqual(str(cmd), "gcc -bar -baz")

def suite():
""" return all the tests"""
return TestSuite([VariablesTest()])
Loading

0 comments on commit 650a1e4

Please sign in to comment.