Repository: easybuilders/easybuild-easyblocks

Issue:
OpenFOAM easyblock fails when using Python 3
```
$ eb OpenFOAM-v1606+-foss-2018b.eb
...
ERROR: Traceback (most recent call last):
  File "/home/kehoste/easybuild-framework/easybuild/main.py", line 112, in build_and_install_software
    (ec_res['success'], app_log, err) = build_and_install_one(ec, init_env)
  File "/home/kehoste/easybuild-framework/easybuild/framework/easyblock.py", line 3046, in build_and_install_one
    result = app.run_all_steps(run_test_cases=run_test_cases)
  File "/home/kehoste/easybuild-framework/easybuild/framework/easyblock.py", line 2954, in run_all_steps
    self.run_step(step_name, step_methods)
  File "/home/kehoste/easybuild-framework/easybuild/framework/easyblock.py", line 2824, in run_step
    step_method(self)()
  File "/home/kehoste/easybuild-easyblocks/easybuild/easyblocks/o/openfoam.py", line 151, in configure_step
    if LooseVersion(self.version) < LooseVersion('3.0'):
  File "/usr/lib64/python3.6/distutils/version.py", line 52, in __lt__
    c = self._cmp(other)
  File "/usr/lib64/python3.6/distutils/version.py", line 337, in _cmp
    if self.version < other.version:
TypeError: '<' not supported between instances of 'str' and 'int'
```


Discussion:

Resolving patch:
diff --git a/easybuild/easyblocks/o/openfoam.py b/easybuild/easyblocks/o/openfoam.py
--- a/easybuild/easyblocks/o/openfoam.py
+++ b/easybuild/easyblocks/o/openfoam.py
@@ -67,8 +67,12 @@ def __init__(self, *args, **kwargs):
         self.openfoamdir = None
         self.thrdpartydir = None
 
+        # version may start with 'v' for some variants of OpenFOAM
+        # we need to strip this off to avoid problems when comparing LooseVersion instances in Python 3
+        self.looseversion = LooseVersion(self.version.lstrip('v'))
+
         if 'extend' in self.name.lower():
-            if LooseVersion(self.version) >= LooseVersion('3.0'):
+            if self.looseversion >= LooseVersion('3.0'):
                 self.openfoamdir = 'foam-extend-%s' % self.version
             else:
                 self.openfoamdir = 'OpenFOAM-%s-ext' % self.version
@@ -145,10 +149,10 @@ def configure_step(self):
                 extra_flags = '-fuse-ld=bfd'
 
             # older versions of OpenFOAM-Extend require -fpermissive
-            if 'extend' in self.name.lower() and LooseVersion(self.version) < LooseVersion('2.0'):
+            if 'extend' in self.name.lower() and self.looseversion < LooseVersion('2.0'):
                 extra_flags += ' -fpermissive'
 
-            if LooseVersion(self.version) < LooseVersion('3.0'):
+            if self.looseversion < LooseVersion('3.0'):
                 extra_flags += ' -fno-delete-null-pointer-checks'
 
         elif comp_fam == toolchain.INTELCOMP:  # @UndefinedVariable
@@ -166,13 +170,13 @@ def configure_step(self):
             regex_subs = [(r"^(setenv|export) WM_THIRD_PARTY_USE_.*[ =].*$", r"# \g<0>")]
 
             # this does not work for OpenFOAM Extend lower than 2.0
-            if 'extend' not in self.name.lower() or LooseVersion(self.version) >= LooseVersion('2.0'):
+            if 'extend' not in self.name.lower() or self.looseversion >= LooseVersion('2.0'):
                 key = "WM_PROJECT_VERSION"
                 regex_subs += [(r"^(setenv|export) %s=.*$" % key, r"export %s=%s #\g<0>" % (key, self.version))]
 
             WM_env_var = ['WM_COMPILER', 'WM_MPLIB', 'WM_THIRD_PARTY_DIR']
             # OpenFOAM >= 3.0.0 can use 64 bit integers
-            if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0'):
+            if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion('3.0'):
                 WM_env_var.append('WM_LABEL_SIZE')
             for env_var in WM_env_var:
                 regex_subs.append((r"^(setenv|export) (?P<var>%s)[ =](?P<val>.*)$" % env_var,
@@ -241,15 +245,15 @@ def configure_step(self):
         env.setvar("WM_NCOMPPROCS", str(self.cfg['parallel']))
 
         # OpenFOAM >= 3.0.0 can use 64 bit integers
-        if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0'):
+        if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion('3.0'):
             if self.toolchain.options['i8']:
                 env.setvar("WM_LABEL_SIZE", '64')
             else:
                 env.setvar("WM_LABEL_SIZE", '32')
 
         # make sure lib/include dirs for dependencies are found
-        openfoam_extend_v3 = 'extend' in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0')
-        if LooseVersion(self.version) < LooseVersion("2") or openfoam_extend_v3:
+        openfoam_extend_v3 = 'extend' in self.name.lower() and self.looseversion >= LooseVersion('3.0')
+        if self.looseversion < LooseVersion("2") or openfoam_extend_v3:
             self.log.debug("List of deps: %s" % self.cfg.dependencies())
             for dep in self.cfg.dependencies():
                 dep_name = dep['name'].upper(),
@@ -277,7 +281,7 @@ def build_step(self):
         """Build OpenFOAM using make after sourcing script to set environment."""
 
         precmd = "source %s" % os.path.join(self.builddir, self.openfoamdir, "etc", "bashrc")
-        if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion('4.0'):
+        if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion('4.0'):
             cleancmd = "cd $WM_PROJECT_DIR && wcleanPlatform -all && cd -"
         else:
             cleancmd = "wcleanAll"
@@ -289,7 +293,7 @@ def build_step(self):
             'prebuildopts': self.cfg['prebuildopts'],
             'makecmd': os.path.join(self.builddir, self.openfoamdir, '%s'),
         }
-        if 'extend' in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0'):
+        if 'extend' in self.name.lower() and self.looseversion >= LooseVersion('3.0'):
             qa = {
                 "Proceed without compiling ParaView [Y/n]": 'Y',
                 "Proceed without compiling cudaSolvers? [Y/n]": 'Y',
@@ -333,7 +337,7 @@ def sanity_check_step(self):
         shlib_ext = get_shared_lib_ext()
 
         # OpenFOAM >= 3.0.0 can use 64 bit integers
-        if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0'):
+        if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion('3.0'):
             if self.toolchain.options['i8']:
                 int_size = 'Int64'
             else:
@@ -343,8 +347,8 @@ def sanity_check_step(self):
 
         psubdir = "linux64%sDP%s%s" % (self.wm_compiler, int_size, self.build_type)
 
-        openfoam_extend_v3 = 'extend' in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0')
-        if openfoam_extend_v3 or LooseVersion(self.version) < LooseVersion("2"):
+        openfoam_extend_v3 = 'extend' in self.name.lower() and self.looseversion >= LooseVersion('3.0')
+        if openfoam_extend_v3 or self.looseversion < LooseVersion("2"):
             toolsdir = os.path.join(self.openfoamdir, "applications", "bin", psubdir)
             libsdir = os.path.join(self.openfoamdir, "lib", psubdir)
             dirs = [toolsdir, libsdir]
@@ -365,7 +369,7 @@ def sanity_check_step(self):
         if 'extend' in self.name.lower():
             libs = [os.path.join(libsdir, "libscotchDecomp.%s" % shlib_ext),
                     os.path.join(libsdir, "libmetisDecomp.%s" % shlib_ext)]
-            if LooseVersion(self.version) < LooseVersion('3.2'):
+            if self.looseversion < LooseVersion('3.2'):
                 # Pstream should have both a dummy and a mpi one
                 libs.extend([os.path.join(libsdir, x, "libPstream.%s" % shlib_ext) for x in ["dummy", "mpi"]])
                 libs.extend([os.path.join(libsdir, "mpi", "libparMetisDecomp.%s" % shlib_ext)])
@@ -378,7 +382,7 @@ def sanity_check_step(self):
                    [os.path.join(libsdir, "libscotchDecomp.%s" % shlib_ext)] + \
                    [os.path.join(libsdir, "dummy", "libscotchDecomp.%s" % shlib_ext)]
 
-        if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion("2.3.0"):
+        if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion("2.3.0"):
             # surfaceSmooth is replaced by surfaceLambdaMuSmooth is OpenFOAM v2.3.0
             bins.remove(os.path.join(toolsdir, "surfaceSmooth"))
             bins.append(os.path.join(toolsdir, "surfaceLambdaMuSmooth"))
@@ -408,7 +412,7 @@ def make_module_extra(self, altroot=None, altversion=None):
         ]
 
         # OpenFOAM >= 3.0.0 can use 64 bit integers
-        if 'extend' not in self.name.lower() and LooseVersion(self.version) >= LooseVersion('3.0'):
+        if 'extend' not in self.name.lower() and self.looseversion >= LooseVersion('3.0'):
             if self.toolchain.options['i8']:
                 env_vars += [('WM_LABEL_SIZE', '64')]
             else:


Test patch: