Skip to content

Commit 193921c

Browse files
authored
Merge pull request #1 from boegel/clean_module_generator
sync with develop
2 parents 0b61642 + c2b7795 commit 193921c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1473
-382
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ env:
77
- LMOD_VERSION=5.8 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
88
- LMOD_VERSION=6.6.3
99
- LMOD_VERSION=6.6.3 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
10-
- LMOD_VERSION=7.1
11-
- LMOD_VERSION=7.1 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
10+
- LMOD_VERSION=7.4
11+
- LMOD_VERSION=7.4 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1212
- ENV_MOD_VERSION=3.2.10 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesC TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1313
- ENV_MOD_TCL_VERSION=1.147 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesTcl TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1414
matrix:
@@ -43,7 +43,7 @@ before_install:
4343
# pydot (dep for python-graph-dot) 1.2.0 and more recent doesn't work with Python 2.6
4444
- if [ "x$TRAVIS_PYTHON_VERSION" == 'x2.6' ]; then pip install pydot==1.1.0; else pip install pydot; fi
4545
# optional Python packages for EasyBuild
46-
- pip install autopep8 GC3Pie pep8 python-graph-dot python-hglib PyYAML
46+
- pip install autopep8 GC3Pie pycodestyle python-graph-dot python-hglib PyYAML
4747
# git config is required to make actual git commits (cfr. tests for GitRepository)
4848
- git config --global user.name "Travis CI"
4949
- git config --global user.email "[email protected]"

RELEASE_NOTES

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,48 @@ For more detailed information, please see the git log.
33

44
These release notes can also be consulted at http://easybuild.readthedocs.org/en/latest/Release_notes.html.
55

6+
v3.1.2 (March 20th 2017)
7+
------------------------
8+
9+
bugfix release
10+
- fix broken packaging support by fixing ``run_cmd`` bug with ``shell=False`` (#2153)
11+
- minor enhancements, including:
12+
- implement change_dir function in filetools module (#2155)
13+
- use checker_state in trailing whitespace style check + add dedicated test (#2160, #2169)
14+
- consider both pycodestyle and pep8 Python modules in style checks (#2161)
15+
- make bootstrap script aware various modules-related $EASYBUILD_* environment variables (#2170)
16+
- various bug fixes, including:
17+
- interpret statements that extend $MODULEPATH in modpath_extensions_for method (#2104)
18+
- also fixes inclusion of superfluous load statements in modules installed in user HMNS module tree (cfr. #2172)
19+
- take into account that $PATH or $PYTHONPATH may be empty when running tests (#2149)
20+
- handle duplicates in --include-* (#2151)
21+
- exclude dependencies of dependencies that extend $MODULEPATH (#2152)
22+
- add ld.bfd to RPATH wrappers (#2156)
23+
- fix test_vsc_location, vsc.__file__ may not be available when vsc is installed as a namespace package (#2159)
24+
- fix reported problems with scripts & docs tests (#2164)
25+
- fix --try-software-version using non-greedy matching + lookahead assertion, add test for tweak_one (#2166)
26+
- avoid creating empty modulefile directories when using modaltsoftname (#2168)
27+
- fix fftw_libs for MKL without interface libraries (#2171)
28+
29+
30+
v3.1.1 (March 7th 2017)
31+
-----------------------
32+
33+
bugfix release
34+
- minor enhancements, including:
35+
- print more useful error message when no compiler-specific optarch flag is defined (#1950)
36+
- add ec parameter to expand_toolchain_load() (#2103)
37+
- clarify unstable/closed PR warning message (#2129)
38+
- various bug fixes, including:
39+
- ensure that $EBEXTSLIST* is also included in generated module under --module-only (#2112)
40+
- fix formatting issues in generated documentation for --list-software and --avail-easyconfig-licenses (#2121)
41+
- fix problem with backticks in description breaking 'fpm' packaging command (#2124)
42+
- replace --enable-new-dtags with --disable-new-dtags instead of removing it in RPATH wrapper script (#2131)
43+
- only perform is_short_modname_for sanity check in det_short_module_name if modaltsoftname is available (#2138)
44+
- fix logic in make_module_dep w.r.t. excluding loads for toolchain & toolchain components (#2140)
45+
- skip test_check_style if pep8 is not available (#2142)
46+
47+
648
v3.1.0 (February 3rd 2017)
749
--------------------------
850

easybuild/framework/easyblock.py

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
from easybuild.tools.config import install_path, log_path, package_path, source_paths
6666
from easybuild.tools.environment import restore_env, sanitize_env
6767
from easybuild.tools.filetools import DEFAULT_CHECKSUM
68-
from easybuild.tools.filetools import adjust_permissions, apply_patch, convert_name, derive_alt_pypi_url
68+
from easybuild.tools.filetools import adjust_permissions, apply_patch, change_dir, convert_name, derive_alt_pypi_url
6969
from easybuild.tools.filetools import compute_checksum, download_file, encode_class_name, extract_file
7070
from easybuild.tools.filetools import is_alt_pypi_url, mkdir, move_logs, read_file, remove_file, rmtree2, write_file
7171
from easybuild.tools.filetools import verify_checksum, weld_paths
@@ -912,21 +912,23 @@ def make_module_dep(self, unload_info=None):
912912
913913
:param unload_info: dictionary with full module names as keys and module name to unload first as corr. value
914914
"""
915-
deps = []
916915
mns = ActiveMNS()
917916
unload_info = unload_info or {}
918917

919-
# include load statements for toolchain, either directly or for toolchain dependencies
918+
# include toolchain as first dependency to load
919+
tc_mod = None
920920
if self.toolchain.name != DUMMY_TOOLCHAIN_NAME:
921-
if mns.expand_toolchain_load():
922-
mod_names = self.toolchain.toolchain_dep_mods
923-
deps.extend(mod_names)
924-
self.log.debug("Adding toolchain components as module dependencies: %s" % mod_names)
925-
else:
926-
deps.append(self.toolchain.det_short_module_name())
927-
self.log.debug("Adding toolchain %s as a module dependency" % deps[-1])
921+
tc_mod = self.toolchain.det_short_module_name()
922+
self.log.debug("Toolchain to load in generated module (before excluding any deps): %s", tc_mod)
923+
924+
# expand toolchain into toolchain components if desired
925+
tc_dep_mods = None
926+
if mns.expand_toolchain_load(ec=self.cfg):
927+
tc_dep_mods = self.toolchain.toolchain_dep_mods
928+
self.log.debug("Toolchain components to load in generated module (before excluding any): %s", tc_dep_mods)
928929

929930
# include load/unload statements for dependencies
931+
deps = []
930932
self.log.debug("List of deps considered to load in generated module: %s", self.toolchain.dependencies)
931933
for dep in self.toolchain.dependencies:
932934
if dep['build_only']:
@@ -935,35 +937,52 @@ def make_module_dep(self, unload_info=None):
935937
modname = dep['short_mod_name']
936938
self.log.debug("Adding %s as a module dependency" % modname)
937939
deps.append(modname)
938-
939940
self.log.debug("List of deps to load in generated module (before excluding any): %s", deps)
940941

941942
# exclude dependencies that extend $MODULEPATH and form the path to the top of the module tree (if any)
942943
full_mod_subdir = os.path.join(self.installdir_mod, self.mod_subdir)
943944
init_modpaths = mns.det_init_modulepaths(self.cfg)
944945
top_paths = [self.installdir_mod] + [os.path.join(self.installdir_mod, p) for p in init_modpaths]
946+
947+
all_deps = [d for d in [tc_mod] + (tc_dep_mods or []) + deps if d is not None]
945948
excluded_deps = self.modules_tool.path_to_top_of_module_tree(top_paths, self.cfg.short_mod_name,
946-
full_mod_subdir, deps)
949+
full_mod_subdir, all_deps)
950+
951+
# if the toolchain is excluded, so should the toolchain components
952+
if tc_mod in excluded_deps and tc_dep_mods:
953+
excluded_deps.extend(tc_dep_mods)
954+
947955
self.log.debug("List of excluded deps: %s", excluded_deps)
948956

949-
# load modules that open up the module tree before checking deps of deps (in reverse order)
950-
self.modules_tool.load(excluded_deps[::-1])
957+
# expand toolchain into toolchain components if desired
958+
if tc_dep_mods is not None:
959+
deps = tc_dep_mods + deps
960+
elif tc_mod is not None:
961+
deps = [tc_mod] + deps
951962

963+
# filter dependencies to avoid including loads for toolchain or toolchain components that extend $MODULEPATH
964+
# with location to where this module is being installed (full_mod_subdir);
965+
# if the modules that extend $MODULEPATH are not loaded this module is not available, so there is not
966+
# point in loading them again (in fact, it may cause problems when reloading this module due to a load storm)
952967
deps = [d for d in deps if d not in excluded_deps]
953-
for dep in excluded_deps:
954-
excluded_dep_deps = dependencies_for(dep, self.modules_tool)
955-
self.log.debug("List of dependencies for excluded dependency %s: %s" % (dep, excluded_dep_deps))
968+
969+
# load modules that open up the module tree before checking deps of deps (in reverse order)
970+
self.modules_tool.load(excluded_deps[::-1])
971+
972+
for excluded_dep in excluded_deps:
973+
excluded_dep_deps = dependencies_for(excluded_dep, self.modules_tool)
974+
self.log.debug("List of dependencies for excluded dependency %s: %s" % (excluded_dep, excluded_dep_deps))
956975
deps = [d for d in deps if d not in excluded_dep_deps]
957976

958-
self.log.debug("List of retained deps to load in generated module: %s" % deps)
959-
recursive_unload = self.cfg['recursive_module_unload']
977+
self.log.debug("List of retained deps to load in generated module: %s", deps)
960978

979+
# include load statements for retained dependencies
961980
loads = []
962981
for dep in deps:
963982
unload_modules = []
964983
if dep in unload_info:
965984
unload_modules.append(unload_info[dep])
966-
loads.append(self.module_generator.load_module(dep, recursive_unload=recursive_unload,
985+
loads.append(self.module_generator.load_module(dep, recursive_unload=self.cfg['recursive_module_unload'],
967986
unload_modules=unload_modules))
968987

969988
# Force unloading any other modules
@@ -1111,10 +1130,7 @@ def make_module_req(self):
11111130

11121131
lines = []
11131132
if os.path.isdir(self.installdir):
1114-
try:
1115-
os.chdir(self.installdir)
1116-
except OSError, err:
1117-
raise EasyBuildError("Failed to change to %s: %s", self.installdir, err)
1133+
change_dir(self.installdir)
11181134

11191135
lines.append('\n')
11201136

@@ -1143,10 +1159,7 @@ def make_module_req(self):
11431159
lines.append(self.module_generator.prepend_paths(key, paths))
11441160
if self.dry_run:
11451161
self.dry_run_msg('')
1146-
try:
1147-
os.chdir(self.orig_workdir)
1148-
except OSError, err:
1149-
raise EasyBuildError("Failed to change back to %s: %s", self.orig_workdir, err)
1162+
change_dir(self.orig_workdir)
11501163

11511164
return ''.join(lines)
11521165

@@ -1332,11 +1345,8 @@ def guess_start_dir(self):
13321345

13331346
self.log.info("Using %s as start dir", self.cfg['start_dir'])
13341347

1335-
try:
1336-
os.chdir(self.cfg['start_dir'])
1337-
self.log.debug("Changed to real build directory %s (start_dir)" % self.cfg['start_dir'])
1338-
except OSError, err:
1339-
raise EasyBuildError("Can't change to real build directory %s: %s", self.cfg['start_dir'], err)
1348+
change_dir(self.cfg['start_dir'])
1349+
self.log.debug("Changed to real build directory %s (start_dir)", self.cfg['start_dir'])
13401350

13411351
def handle_iterate_opts(self):
13421352
"""Handle options relevant during iterated part of build/install procedure."""
@@ -1509,13 +1519,13 @@ def fetch_step(self, skip_checksums=False):
15091519
# create parent dirs in install and modules path already
15101520
# this is required when building in parallel
15111521
mod_symlink_paths = ActiveMNS().det_module_symlink_paths(self.cfg)
1512-
parent_subdir = os.path.dirname(self.install_subdir)
1522+
mod_subdir = os.path.dirname(ActiveMNS().det_full_module_name(self.cfg))
15131523
pardirs = [
15141524
self.installdir,
1515-
os.path.join(self.installdir_mod, parent_subdir),
1525+
os.path.join(self.installdir_mod, mod_subdir),
15161526
]
15171527
for mod_symlink_path in mod_symlink_paths:
1518-
pardirs.append(os.path.join(install_path('mod'), mod_symlink_path, parent_subdir))
1528+
pardirs.append(os.path.join(install_path('mod'), mod_symlink_path, mod_subdir))
15191529

15201530
self.log.info("Checking dirs that need to be created: %s" % pardirs)
15211531
for pardir in pardirs:
@@ -1707,7 +1717,7 @@ def extensions_step(self, fetch=False):
17071717
print_msg("installing extension %s %s (%d/%d)..." % tup, silent=self.silent)
17081718

17091719
# always go back to original work dir to avoid running stuff from a dir that no longer exists
1710-
os.chdir(self.orig_workdir)
1720+
change_dir(self.orig_workdir)
17111721

17121722
cls, inst = None, None
17131723
class_name = encode_class_name(ext['name'])
@@ -1717,7 +1727,8 @@ def extensions_step(self, fetch=False):
17171727
try:
17181728
# no error when importing class fails, in case we run into an existing easyblock
17191729
# with a similar name (e.g., Perl Extension 'GO' vs 'Go' for which 'EB_Go' is available)
1720-
cls = get_easyblock_class(None, name=ext['name'], default_fallback=False, error_on_failed_import=False)
1730+
cls = get_easyblock_class(None, name=ext['name'], error_on_failed_import=False,
1731+
error_on_missing_easyblock=False)
17211732
self.log.debug("Obtained class %s for extension %s" % (cls, ext['name']))
17221733
if cls is not None:
17231734
inst = cls(self, ext)
@@ -2033,10 +2044,7 @@ def _sanity_check_step(self, custom_paths=None, custom_commands=None, extension=
20332044

20342045
# chdir to installdir (better environment for running tests)
20352046
if os.path.isdir(self.installdir):
2036-
try:
2037-
os.chdir(self.installdir)
2038-
except OSError, err:
2039-
raise EasyBuildError("Failed to move to installdir %s: %s", self.installdir, err)
2047+
change_dir(self.installdir)
20402048

20412049
# run sanity check commands
20422050
for command in commands:
@@ -2074,6 +2082,18 @@ def _sanity_check_step(self, custom_paths=None, custom_commands=None, extension=
20742082
else:
20752083
self.log.debug("Sanity check passed!")
20762084

2085+
def _set_module_as_default(self):
2086+
"""
2087+
Defining default module Version
2088+
2089+
sets the default module version except if we are in dry run.
2090+
"""
2091+
if self.dry_run:
2092+
dry_run_msg("Marked %s v%s as default version" % (self.name, self.version))
2093+
else:
2094+
mod_folderpath = os.path.dirname(self.module_generator.get_module_filepath())
2095+
self.module_generator.set_as_default(mod_folderpath, self.version)
2096+
20772097
def cleanup_step(self):
20782098
"""
20792099
Cleanup leftover mess: remove/clean build directory
@@ -2082,11 +2102,12 @@ def cleanup_step(self):
20822102
cleanup_builddir is False, otherwise we remove the installation
20832103
"""
20842104
if not self.build_in_installdir and build_option('cleanup_builddir'):
2085-
try:
2086-
os.chdir(self.orig_workdir) # make sure we're out of the dir we're removing
20872105

2088-
self.log.info("Cleaning up builddir %s (in %s)" % (self.builddir, os.getcwd()))
2106+
# make sure we're out of the dir we're removing
2107+
change_dir(self.orig_workdir)
2108+
self.log.info("Cleaning up builddir %s (in %s)", self.builddir, os.getcwd())
20892109

2110+
try:
20902111
rmtree2(self.builddir)
20912112
base = os.path.dirname(self.builddir)
20922113

@@ -2137,7 +2158,6 @@ def make_module_step(self, fake=False):
21372158
self.dry_run_msg("Generating module file %s, with contents:\n", mod_filepath)
21382159
for line in txt.split('\n'):
21392160
self.dry_run_msg(' ' * 4 + line)
2140-
21412161
else:
21422162
write_file(mod_filepath, txt)
21432163
self.log.info("Module file %s written: %s", mod_filepath, txt)
@@ -2162,6 +2182,9 @@ def make_module_step(self, fake=False):
21622182
if not fake:
21632183
self.make_devel_module()
21642184

2185+
if build_option('set_default_module'):
2186+
self._set_module_as_default()
2187+
21652188
return modpath
21662189

21672190
def permissions_step(self):
@@ -2218,7 +2241,7 @@ def test_cases_step(self):
22182241
Run provided test cases.
22192242
"""
22202243
for test in self.cfg['tests']:
2221-
os.chdir(self.orig_workdir)
2244+
change_dir(self.orig_workdir)
22222245
if os.path.isabs(test):
22232246
path = test
22242247
else:
@@ -2514,7 +2537,7 @@ def build_and_install_one(ecdict, init_env):
25142537
ended = 'ended'
25152538

25162539
# make sure we're back in original directory before we finish up
2517-
os.chdir(cwd)
2540+
change_dir(cwd)
25182541

25192542
application_log = None
25202543

@@ -2709,7 +2732,7 @@ def perform_step(step, obj, method, logfile):
27092732
start_time = time.time()
27102733

27112734
# start with a clean slate
2712-
os.chdir(base_dir)
2735+
change_dir(base_dir)
27132736
restore_env(base_env)
27142737
sanitize_env()
27152738

0 commit comments

Comments
 (0)