Skip to content

Commit

Permalink
Merge pull request #5 from boegel/support_lua_modfiles
Browse files Browse the repository at this point in the history
fix @stdweird's remarks for framework PR 1060
  • Loading branch information
pforai committed Feb 12, 2015
2 parents 32ff7ed + a081dd6 commit 59882eb
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 36 deletions.
49 changes: 17 additions & 32 deletions easybuild/tools/module_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@
from vsc.utils.missing import get_subclasses

from easybuild.framework.easyconfig.easyconfig import ActiveMNS
from easybuild.tools import config
from easybuild.tools.config import build_option, get_module_syntax, install_path
from easybuild.tools.filetools import mkdir
from easybuild.tools.utilities import quote_str


MODULE_GENERATOR_CLASS_PREFIX = 'ModuleGenerator'
LUA_SYNTAX = 'Lua'
TCL_SYNTAX = 'Tcl'


_log = fancylogger.getLogger('module_generator', fname=False)
Expand All @@ -54,6 +55,7 @@ class ModuleGenerator(object):
"""
Class for generating module files.
"""
SYNTAX = None

# chars we want to escape in the generated modulefiles
CHARS_TO_ESCAPE = ["$"]
Expand Down Expand Up @@ -116,7 +118,7 @@ def set_fake(self, fake):
self.log.debug("Fake mode: using %s (instead of %s)" % (self.tmpdir, self.module_path))
self.module_path = self.tmpdir
else:
self.module_path = config.install_path('mod')
self.module_path = install_path('mod')

def module_header(self):
"""Return module header string."""
Expand All @@ -131,6 +133,7 @@ class ModuleGeneratorTcl(ModuleGenerator):
"""
Class for generating Tcl module files.
"""
SYNTAX = TCL_SYNTAX

def module_header(self):
"""Return module header string."""
Expand Down Expand Up @@ -287,6 +290,7 @@ class ModuleGeneratorLua(ModuleGenerator):
"""
Class for generating Lua module files.
"""
SYNTAX = LUA_SYNTAX

MODULE_SUFFIX = '.lua'

Expand All @@ -309,7 +313,6 @@ def get_description(self, conflict=True):

description = "%s - Homepage: %s" % (self.app.cfg['description'], self.app.cfg['homepage'])


lines = [
"local pkg = {}",
"help = [["
Expand Down Expand Up @@ -348,7 +351,6 @@ def get_description(self, conflict=True):
'homepage': self.app.cfg['homepage'],
}


return txt

def load_module(self, mod_name):
Expand Down Expand Up @@ -410,7 +412,6 @@ def use(self, paths):
use_statements.append('use("%s")' % path)
return '\n'.join(use_statements)


def set_environment(self, key, value):

"""
Expand All @@ -419,27 +420,24 @@ def set_environment(self, key, value):
# quotes are needed, to ensure smooth working of EBDEVEL* modulefiles
return 'setenv("%s", %s)\n' % (key, quote_str(value))


def msg_on_load(self, msg):
"""
Add a message that should be printed when loading the module.
"""
pass


def add_tcl_footer(self, tcltxt):
"""
Append whatever Tcl code you want to your modulefile
"""
#@todo to pass or not to pass? this should fail in the context of generating Lua modules
#@todo to pass or not to pass? this should fail in the context of generating Lua modules
pass


def set_alias(self, key, value):
"""
Generate set-alias statement in modulefile for the given key/value pair.
"""
# quotes are needed, to ensure smooth working of EBDEVEL* modulefiles
# quotes are needed, to ensure smooth working of EBDEVEL* modulefiles
return 'setalias(%s,"%s")\n' % (key, quote_str(value))

def avail_module_generators():
Expand All @@ -448,33 +446,20 @@ def avail_module_generators():
"""
class_dict = {}
for klass in get_subclasses(ModuleGenerator):
class_name = klass.__name__
if class_name.startswith(MODULE_GENERATOR_CLASS_PREFIX):
syntax = class_name[len(MODULE_GENERATOR_CLASS_PREFIX):]
class_dict.update({syntax: klass})
else:
tup = (MODULE_GENERATOR_CLASS_PREFIX, class_name)
_log.error("Invalid name for ModuleGenerator subclass, should start with %s: %s" % tup)
class_dict.update({klass.SYNTAX: klass})
return class_dict


def module_generator(app, fake=False):
"""
Return interface to modules tool (environment modules (C, Tcl), or Lmod)
Return ModuleGenerator instance that matches the selected module file syntax to be used
"""
module_syntax = get_module_syntax()
module_generator_class = avail_module_generators().get(module_syntax)
return module_generator_class(app, fake=fake)

available_mod_gens = avail_module_generators()

def return_module_loadregex(modfilepath):
"""
Return the correct regex depending on the module file type (Lua vs Tcl) in order for
to be able to figure out dependencies.
"""
if (modfilepath.endswith('.lua')):
loadregex = re.compile(r"^\s*load\(\"(\S+)\"", re.M)
else:
loadregex = re.compile(r"^\s*module\s+load\s+(\S+)", re.M)
return loadregex
if module_syntax not in available_mod_gens:
tup = (module_syntax, available_mod_gens)
_log.error("No module generator available for specified syntax '%s' (available: %s)" % tup)

module_generator_class = available_mod_gens[module_syntax]
return module_generator_class(app, fake=fake)
14 changes: 12 additions & 2 deletions easybuild/tools/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@
_log = fancylogger.getLogger('modules', fname=False)


def module_load_regex(modfilepath):
"""
Return the correct (compiled) regex to extract dependencies, depending on the module file type (Lua vs Tcl)
"""
if modfilepath.endswith('.lua'):
regex = r'^\s*load\("(\S+)"'
else:
regex = r"^\s*module\s+load\s+(\S+)"
return re.compile(regex, re.M)


class ModulesTool(object):
"""An abstract interface to a tool that deals with modules."""
# position and optionname
Expand Down Expand Up @@ -572,7 +583,7 @@ def dependencies_for(self, mod_name, depth=sys.maxint):
@param depth: recursion depth (default is sys.maxint, which should be equivalent to infinite recursion depth)
"""
modtxt = self.read_module_file(mod_name)
loadregex = return_module_loadregex(self.modulefile_path(modmod_name))
loadregex = module_load_regex(self.modulefile_path(mod_name))
mods = loadregex.findall(modtxt)

if depth > 0:
Expand Down Expand Up @@ -833,7 +844,6 @@ def available(self, mod_name=None):

def update(self):
"""Update after new modules were added."""
return
spider_cmd = os.path.join(os.path.dirname(self.cmd), 'spider')
cmd = [spider_cmd, '-o', 'moduleT', os.environ['MODULEPATH']]
self.log.debug("Running command '%s'..." % ' '.join(cmd))
Expand Down
5 changes: 3 additions & 2 deletions easybuild/tools/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@
from easybuild.tools.docs import FORMAT_RST, FORMAT_TXT, avail_easyconfig_params
from easybuild.tools.github import HAVE_GITHUB_API, HAVE_KEYRING, fetch_github_token
from easybuild.tools.modules import avail_modules_tools
from easybuild.tools.module_generator import avail_module_generators
from easybuild.tools.module_generator import LUA_SYNTAX, avail_module_generators
from easybuild.tools.module_naming_scheme import GENERAL_CLASS
from easybuild.tools.module_naming_scheme.utilities import avail_module_naming_schemes
from easybuild.tools.modules import Lmod
from easybuild.tools.ordereddict import OrderedDict
from easybuild.tools.toolchain.utilities import search_toolchain
from easybuild.tools.repository.repository import avail_repositories
Expand Down Expand Up @@ -398,7 +399,7 @@ def postprocess(self):
if not HAVE_GITHUB_API:
self.log.error("Required support for using GitHub API is not available (see warnings).")

if self.options.module_syntax == 'Lua' and self.options.modules_tool !='Lmod':
if self.options.module_syntax == LUA_SYNTAX and self.options.modules_tool != Lmod.__name__:
self.log.error("Generating Lua module files requires Lmod as modules tool.")

# make sure a GitHub token is available when it's required
Expand Down

0 comments on commit 59882eb

Please sign in to comment.