Source code for sdss_install.install.modules

# License information goes here
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
# The line above will help with 2to3 support.
from sys import path, version_info
from os import environ, makedirs
from os.path import basename, exists, isdir, join
from sdss_install.utils import Module


[docs]class Modules: ''' Class for handling and preparing the installation of module files ''' def __init__(self, options=None, logger=None, product=None, directory=None, build_type=None): self.options = options self.logger = logger self.product = product self.directory = directory self.build_type = build_type self.ready = False self.dependencies = None self.built = None self.module = None def set_module(self): self.module = Module(logger=self.logger, options=self.options)
[docs] def set_ready(self): '''Set up Modules.''' self.ready = (self.logger and self.options and self.product and self.directory and self.module) if self.ready and not self.module.ready: self.ready = False self.logger.error("You do not appear to have Modules set up.")
[docs] def set_file(self, ext='.module'): '''Set product module file path.''' if self.ready: alt = "_%s" % self.options.alt_module if self.options.alt_module else "" filename = (self.product['name']+alt+ext if 'name' in self.product and ext else None) self.file = (join(self.directory['work'], 'etc', filename) if filename and 'work' in self.directory else None)
[docs] def load_dependencies(self): '''Load dependencies.''' if self.ready: self.set_dependencies() for (product, version) in self.dependencies: self.load(product=product, version=version)
[docs] def set_dependencies(self): '''Set the dependencies by looking for modules loaded in the modules file''' self.dependencies = list() if self.ready: if exists(self.file): with open(self.file) as file: lines = file.readlines() from json import dumps for product_version in [l.strip().split()[2] for l in lines if l.startswith('module load')]: self.dependencies.append(product_version.split('/', 1) if '/' in product_version else (product_version, None))
[docs] def load(self, product=None, version=None): '''Hook to module load function.''' if self.ready: if product: product_version = join( product, version) if version else product try: self.module.set_command('load', arguments=product_version) self.module.execute_command() self.logger.info( "module load %s (dependency)" % product_version) except: self.logger.warning("unable to module load %s (dependency)" % product_version) else: self.logger.error("module load command requires a " + "product [version optional]")
[docs] def set_keywords(self, build_type=None): '''Set keywords to configure module.''' if self.ready: self.keywords = dict() self.keywords['name'] = self.product['name'] self.keywords['version'] = self.product['version'] self.keywords['root'] = self.directory['root'] self.keywords['needs_bin'] = '# ' self.keywords['needs_python'] = '# ' self.keywords['needs_trunk_python'] = '# ' self.keywords['needs_ld_lib'] = '# ' self.keywords['needs_idl'] = '# ' self.keywords['pyversion'] = "python{0:d}.{1:d}".format(*version_info) if isdir(join(self.directory['work'], 'bin')): self.keywords['needs_bin'] = '' if isdir(join(self.directory['work'], 'lib')): self.keywords['needs_ld_lib'] = '' if isdir(join(self.directory['work'], 'pro')): self.keywords['needs_idl'] = '' if 'python' in self.build_type: if (self.product['is_branch'] or self.product['is_master'] or self.options.no_python_package): self.keywords['needs_trunk_python'] = '' else: self.keywords['needs_python'] = '' lib_dir = join(self.directory['install'], 'lib', self.keywords['pyversion'], 'site-packages') # # If this is a python package, # we need to manipulate the PYTHONPATH and # include the install directory # if not self.options.test: try: makedirs(lib_dir) except OSError as ose: self.logger.error(ose.strerror) self.ready = False try: newpythonpath = (lib_dir + ':' + environ['PYTHONPATH']) except KeyError: newpythonpath = lib_dir environ['PYTHONPATH'] = newpythonpath path.insert(int(path[0] == ''), lib_dir) elif isdir(join(self.directory['work'], 'python')): self.keywords['needs_trunk_python'] = '' if basename(self.options.product) == 'sdss_install': self.keywords['sdss_install_root'] = self.options.root self.keywords['sdss_install_longpath'] = '# ' elif basename(self.options.product) == 'sdss4tools': self.keywords['sdss4tools_root'] = self.options.root self.keywords['sdss4tools_longpath'] = self.options.longpath
[docs] def set_directory(self): '''Make module file installation directory.''' self.check_options() if self.ready: self.directory['modules'] = join(self.options.moduledir, self.product['name']) if self.ready and not self.options.test: if not isdir(self.directory['modules']): self.logger.info("Creating Modules directory %(modules)s" % self.directory) try: makedirs(self.directory['modules']) except OSError as ose: self.logger.error(ose.strerror) self.ready = False
[docs] def check_options(self): ''' Check for / create a modulefile directory (if there is an etc/product.module file or for the tree product) ''' if self.ready: # only check for modulefiles if the original template modulefile exists if exists(self.file) or basename(self.options.product) == 'tree': if not self.options.moduledir: # check for SDSS_GIT/SVN_MODULES environment variable first repo = 'GIT' if self.options.github else 'SVN' mod_dir = environ.get('SDSS_{0}_MODULES'.format(repo), None) # if none found, build the default modulefile path if not mod_dir: repo_type = 'github' if self.options.github else 'svn' mod_dir = join(self.options.root, repo_type, 'modulefiles') # set the modulefile directory self.options.moduledir = mod_dir # create the modulefiles directory if it doesn't exist if not self.options.test: if not isdir(self.options.moduledir): self.logger.info("Creating Modules directory {0}" .format(self.options.moduledir)) try: makedirs(self.options.moduledir) except OSError as ose: self.ready = False self.logger.error(ose.strerror)
[docs] def build(self): ''' Install the product modulefile (and versionfile if --default is specified). ''' if self.ready: if exists(self.file): self.product['modulefile'] = join(self.directory['modules'], self.product['version']) # read the modulefile template and substitute keywords with open(self.file) as file: mod = file.read().format(**self.keywords) if self.options.test: self.logger.debug(mod) else: self.logger.info("Adding module file %(modulefile)s" % self.product) # check if skipping version subdirectory mod = self._check_skip_version(mod) # write the new modulefile with open(self.product['modulefile'], 'w') as file: file.write(mod) # write the default .version file if self.options.default: versionfile = ["#%Module1.0\n", "set ModulesVersion \"%(version)s\"\n" % self.product] self.product['versionfile'] = ( join(self.directory['modules'], '.version')) with open(self.product['versionfile'], 'w') as file: file.writelines(versionfile) self.built = True elif basename(self.options.product) != 'tree': self.built = False
def _check_skip_version(self, data): ''' Check to skip the version sub-directory in the module file Checks if the version sub-directory is being skipped or not. If so, then it removes it from the modulefile data content. Parameters: data (str): The modulefile data content Returns: The modified modulefile data content ''' # do nothing if we aren't a git repo if not self.options.github: return data # do nothing if we aren't skipping the version sub-directory if not self.options.skip_git_verdirs: return data vstring = self._find_string('set PRODUCT_DIR', data) if not vstring: # return the original data if no PRODUCT_DIR can be found return data # remove the $version subdirectory from the modulefile new_vstring = vstring.replace('/$version', '') data = data.replace(vstring, new_vstring) return data @staticmethod def _find_string(data_string, data): ''' Find a substring in some data Searches for a substring in read in modulefile data. Searches from the substring up to the first "\n" entry. Parameters: data_string (str): A sub_string to search for data (str): The full string data to search in Returns: The substring ''' # find starting index vstart = data.find(data_string) # if don't find anything return empty string if vstart == -1: return '' # find ending index vend = data.find('\n', vstart) # extract the subtring vstring = data[vstart:vend] return vstring