-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FSL - Improve configuration choice #1498
Conversation
easybuild/easyblocks/f/fsl.py
Outdated
|
||
for patch in self.patches: | ||
try: | ||
for line in open(patch['path'], 'r'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod Please use the read_file
function from filetools
easybuild/easyblocks/f/fsl.py
Outdated
for patch in self.patches: | ||
try: | ||
for line in open(patch['path'], 'r'): | ||
if all(regex.match(line) for regex in [systype_regex, diff_regex]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there are only two, this is probably clearer:
if systype_regex.match(line) and diff_regex.match(line):
But, is there a specific reason why both regex's can't be joined in a single regex?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason they are separate is because I use systype_regex
twice and only once in conjunction with diff_regex
. Hence I preferred to split them like that instead of having systype_regex
being a subset of diff_regex
(i.e. avoid copy/paste).
easybuild/easyblocks/f/fsl.py
Outdated
try: | ||
for line in open(patch['path'], 'r'): | ||
if all(regex.match(line) for regex in [systype_regex, diff_regex]): | ||
matches = [m.group(0) for l in line.split('/') for m in [systype_regex.search(l)] if m] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, why use a list if you're only considering systype_regex
? Ah, because you need a handle for the match (m
)... It looks a bit weird like this, probably better roll this out for the sake of clarity:
for part in line.split('/'):
res = systype_regex.search(part)
if res:
patched_cfgs.append(res.group(0))
easybuild/easyblocks/f/fsl.py
Outdated
matches = [m.group(0) for l in line.split('/') for m in [systype_regex.search(l)] if m] | ||
patched_cfgs.extend(matches) | ||
except OSError, err: | ||
raise EasyBuildError("Unable to open patch file: %s", patch['path']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No more need for the the try
/except
when you use read_file
easybuild/easyblocks/f/fsl.py
Outdated
cfgdir = os.path.join(self.fsldir, "config") | ||
try: | ||
if not best_cfg: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try
is still relevant here, os.listdir
may throw an OSError
easybuild/easyblocks/f/fsl.py
Outdated
cfgs = os.listdir(cfgdir) | ||
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] | ||
|
||
self.log.debug("Best matching config dir for %s is %s" % (fslmachtype, best_cfg)) | ||
|
||
# Prepare config | ||
# Either use patched config or copy closest match | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod Please use copy_file
or copy_dir
below (and then there's no need for the try
here
easybuild/easyblocks/f/fsl.py
Outdated
raise EasyBuildError("Unable to open patch file: %s", patch['path']) | ||
|
||
if patched_cfgs: | ||
if patched_cfgs[1:] == patched_cfgs[:-1]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not check for len(patched_cfgs) == 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would work in the first if
statement. In the second I am checking that all strings in patched_cfgs
are the same, which means that the patch targets only one configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, then please clarify with a comment above this line, that's not clear at all :)
easybuild/easyblocks/f/fsl.py
Outdated
if patched_cfgs: | ||
if patched_cfgs[1:] == patched_cfgs[:-1]: | ||
best_cfg = patched_cfgs[0] | ||
self.log.debug("Found patched config dir: %s" % (best_cfg)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.log.debug("...", best_cfg)
easybuild/easyblocks/f/fsl.py
Outdated
self.log.debug("Found patched config dir: %s" % (best_cfg)) | ||
else: | ||
dirs = ', '.join(patched_cfgs) | ||
raise EasyBuildError("Patch files are editing multiple config dirs: %s", dirs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's OK to pass the raw patched_cfgs
in the error message imho
@vanzod I quickly ran into trouble when trying this with an old FSL easyconfig (
So this will need a version check... |
@vanzod It looks like this can only work with FSL 5.0.10 & newer (works with |
easybuild/easyblocks/f/fsl.py
Outdated
cfgs = os.listdir(cfgdir) | ||
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] | ||
self.log.debug("Best matching config dir for %s is %s" % (fslmachtype, best_cfg)) | ||
except OSError, err: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SyntaxError: invalid syntax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be except OSError as err:
easybuild/easyblocks/f/fsl.py
Outdated
systype_regex = re.compile("^diff.*config\/(.*(apple|gnu|i686|linux|spark)(?:(?!\/).)*)", re.M) | ||
|
||
patched_cfgs = [] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank line contains whitespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod The hound is merciless...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that
easybuild/easyblocks/f/fsl.py
Outdated
systype_regex = re.compile("^diff.*config\/(.*(apple|gnu|i686|linux|spark)(?:(?!\/).)*)", re.M) | ||
|
||
patched_cfgs = [] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod The hound is merciless...
easybuild/easyblocks/f/fsl.py
Outdated
cfgs = os.listdir(cfgdir) | ||
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] | ||
self.log.debug("Best matching config dir for %s is %s" % (fslmachtype, best_cfg)) | ||
except OSError, err: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be except OSError as err:
easybuild/easyblocks/f/fsl.py
Outdated
patched_cfgs.extend([i[0] for i in res]) | ||
|
||
# Check that at least one config has been found | ||
if len(patched_cfgs) != 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if patched_cfgs:
is fine here
easybuild/easyblocks/f/fsl.py
Outdated
# Check that at least one config has been found | ||
if len(patched_cfgs) != 0: | ||
# Check that a single config has been patched | ||
if patched_cfgs[1:] == patched_cfgs[:-1]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod This hurts my brain... How about using nub
from vsc.utils.missing
and change this to:
if len(nub(patched_cfgs)) == 1:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that. I did not know about nub
easybuild/easyblocks/f/fsl.py
Outdated
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] | ||
self.log.debug("Best matching config dir for %s is %s" % (fslmachtype, best_cfg)) | ||
except OSError, err: | ||
raise EasyBuildError("Unable to access configurations directory: %s", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include value of cfgdir
in error message please
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] | ||
self.log.debug("Best matching config dir for %s is %s" % (fslmachtype, best_cfg)) | ||
except OSError as err: | ||
raise EasyBuildError("Unable to access configuration directory: %s", cfgdir, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod You have a %s
missing here, this is going to result in a crash rather than an error message, should be:
raise EasyBuildError("Unable to access configuration directory %s: %s", cfgdir, err)
self.log.debug("Copied %s to %s" % (srcdir, tgtdir)) | ||
except OSError, err: | ||
raise EasyBuildError("Failed to copy closest matching config dir: %s", err) | ||
if not best_cfg: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hitting this now:
File "/tmp/eb-EdQY9x/included-easyblocks/easybuild/easyblocks/fsl.py", line 95, in configure_step
if not best_cfg:
UnboundLocalError: local variable 'best_cfg' referenced before assignment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like I have accidentally deleted the definition of best_cfg
during the refactoring
easybuild/easyblocks/f/fsl.py
Outdated
|
||
patched_cfgs = [] | ||
best_cfg = None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank line contains whitespace
easybuild/easyblocks/f/fsl.py
Outdated
systype_regex = re.compile("^diff.*config\/(.*(apple|gnu|i686|linux|spark)(?:(?!\/).)*)", re.M) | ||
|
||
patched_cfgs = [] | ||
best_cfg = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod This needs to go outside of this if
clause to ensure it's always defined for old FSL versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. Sloppy brain
Tests with existing easyconfigs are under way... |
raise EasyBuildError("Failed to copy closest matching config dir: %s", err) | ||
if not best_cfg: | ||
cfgs = os.listdir(cfgdir) | ||
best_cfg = difflib.get_close_matches(fslmachtype, cfgs)[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vanzod This whole block is now below the if
for FSL 5.0.10 or newer, while it wasn't before. That makes this change backward incompatible, resulting in breaking the installation of FSL-5.0.9-intel-2016a.eb
for example...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, no, it's not... But there still seems to be a problem with FSL-5.0.9-intel-2016a.eb
(will re-check).
Good to go, thanks @vanzod! |
FSL
build relies on an internal check and a script to identify the appropriate configuration to use. Since the available configurations are for relatively old compilers, the current easyblock usesdifflib.get_close_matches
to identify the closest configuration and copies the directory containing it into a new one named after the configuration targeted byFSL
. In certain cases the guessed closest configuration is not the same as the one at which required patches are applied, resulting in a build failure.This easyblock change uses the patch files as first source of information to guess the target directory and rolls back to
difflib.get_close_matches
only if no target configuration is found in the patches.