Example #1
0
def check_easyconfigs_style(easyconfigs, verbose=False):
    """
    Check the given list of easyconfigs for style
    :param: easyconfigs list of file paths to easyconfigs
    :param: verbose print our statistics and be verbose about the errors and warning
    :return: the number of warnings and errors
    """
    # importing autopep8 changes some pep8 functions.
    # We reload it to be sure to get the real pep8 functions.
    if 'pycodestyle' in sys.modules:
        reload(pycodestyle)
    else:
        reload(pep8)

    # register the extra checks before using pep8:
    # any function in this module starting with `_eb_check_` will be used.
    cands = globals()
    for check_function in sorted([
            cands[f] for f in cands
            if callable(cands[f]) and f.startswith(EB_CHECK)
    ]):
        _log.debug("Adding custom style check %s", check_function)
        register_check(check_function)

    styleguide = StyleGuide(quiet=False, config_file=None)
    options = styleguide.options
    # we deviate from standard pep8 and allow 120 chars
    # on a line: the default of 79 is too narrow.
    options.max_line_length = MAX_LINE_LENGTH
    # we ignore some tests
    # note that W291 has been replaced by our custom W299
    options.ignore = (
        'W291',  # replaced by W299
    )
    options.verbose = int(verbose)

    result = styleguide.check_files(easyconfigs)

    if verbose:
        result.print_statistics()

    return result.total_errors
Example #2
0
    def tearDown(self):
        """Clean up after running testcase."""
        super(EnhancedTestCase, self).tearDown()

        self.log.info("Cleaning up for test %s", self.id())

        # go back to where we were before
        os.chdir(self.cwd)

        # restore original environment
        modify_env(os.environ, self.orig_environ, verbose=False)

        self.allow_deprecated_behaviour()

        # restore original Python search path
        sys.path = self.orig_sys_path
        import easybuild.easyblocks
        reload(easybuild.easyblocks)
        import easybuild.easyblocks.generic
        reload(easybuild.easyblocks.generic)

        # remove any log handlers that were added (so that log files can be effectively removed)
        log = fancylogger.getLogger(fname=False)
        new_log_handlers = [
            h for h in log.handlers if h not in self.orig_log_handlers
        ]
        for log_handler in new_log_handlers:
            log_handler.close()
            log.removeHandler(log_handler)

        # cleanup test tmp dir
        try:
            shutil.rmtree(self.test_prefix)
        except (OSError, IOError):
            pass

        # restore original 'parent' tmpdir
        for var in ['TMPDIR', 'TEMP', 'TMP']:
            os.environ[var] = self.orig_tmpdir

        # reset to make sure tempfile picks up new temporary directory to use
        tempfile.tempdir = None
    def setUp(self):
        """Set up testcase."""
        super(EnhancedTestCase, self).setUp()

        # make sure option parser doesn't pick up any cmdline arguments/options
        while len(sys.argv) > 1:
            sys.argv.pop()

        # keep track of log handlers
        log = fancylogger.getLogger(fname=False)
        self.orig_log_handlers = log.handlers[:]

        log.info("setting up test %s" % self.id())

        self.orig_tmpdir = tempfile.gettempdir()
        # use a subdirectory for this test (which we can clean up easily after the test completes)
        self.test_prefix = set_tmpdir()

        self.log = fancylogger.getLogger(self.__class__.__name__, fname=False)
        fd, self.logfile = tempfile.mkstemp(suffix='.log', prefix='eb-test-')
        os.close(fd)
        self.cwd = os.getcwd()

        # keep track of original environment to restore
        self.orig_environ = copy.deepcopy(os.environ)

        # keep track of original environment/Python search path to restore
        self.orig_sys_path = sys.path[:]

        testdir = os.path.dirname(os.path.abspath(__file__))

        self.test_sourcepath = os.path.join(testdir, 'sandbox', 'sources')
        os.environ['EASYBUILD_SOURCEPATH'] = self.test_sourcepath
        os.environ['EASYBUILD_PREFIX'] = self.test_prefix
        self.test_buildpath = tempfile.mkdtemp()
        os.environ['EASYBUILD_BUILDPATH'] = self.test_buildpath
        self.test_installpath = tempfile.mkdtemp()
        os.environ['EASYBUILD_INSTALLPATH'] = self.test_installpath

        # make sure that the tests only pick up easyconfigs provided with the tests
        os.environ['EASYBUILD_ROBOT_PATHS'] = os.path.join(testdir, 'easyconfigs', 'test_ecs')

        # make sure no deprecated behaviour is being triggered (unless intended by the test)
        self.orig_current_version = eb_build_log.CURRENT_VERSION
        self.disallow_deprecated_behaviour()

        init_config()

        import easybuild
        # try to import easybuild.easyblocks(.generic) packages
        # it's OK if it fails here, but important to import first before fiddling with sys.path
        try:
            import easybuild.easyblocks
            import easybuild.easyblocks.generic
        except ImportError:
            pass

        # add sandbox to Python search path, update namespace packages
        sys.path.append(os.path.join(testdir, 'sandbox'))

        # required to make sure the 'easybuild' dir in the sandbox is picked up;
        # this relates to the other 'reload' statements below
        reload(easybuild)

        # required to 'reset' easybuild.tools.module_naming_scheme namespace
        reload(easybuild.tools)
        reload(easybuild.tools.module_naming_scheme)

        # remove any entries in Python search path that seem to provide easyblocks (except the sandbox)
        for path in sys.path[:]:
            if os.path.exists(os.path.join(path, 'easybuild', 'easyblocks', '__init__.py')):
                if not os.path.samefile(path, os.path.join(testdir, 'sandbox')):
                    sys.path.remove(path)

        # hard inject location to (generic) test easyblocks into Python search path
        # only prepending to sys.path is not enough due to 'pkgutil.extend_path' in easybuild/easyblocks/__init__.py
        easybuild.__path__.insert(0, os.path.join(testdir, 'sandbox', 'easybuild'))
        import easybuild.easyblocks
        test_easyblocks_path = os.path.join(testdir, 'sandbox', 'easybuild', 'easyblocks')
        easybuild.easyblocks.__path__.insert(0, test_easyblocks_path)
        reload(easybuild.easyblocks)

        import easybuild.easyblocks.generic
        test_easyblocks_path = os.path.join(test_easyblocks_path, 'generic')
        easybuild.easyblocks.generic.__path__.insert(0, test_easyblocks_path)
        reload(easybuild.easyblocks.generic)

        # save values of $PATH & $PYTHONPATH, so they can be restored later
        # this is important in case EasyBuild was installed as a module, since that module may be unloaded,
        # for example due to changes to $MODULEPATH in case EasyBuild was installed in a module hierarchy
        # cfr. https://github.com/easybuilders/easybuild-framework/issues/1685
        self.env_path = os.environ.get('PATH')
        self.env_pythonpath = os.environ.get('PYTHONPATH')

        self.modtool = modules_tool()
        self.reset_modulepath([os.path.join(testdir, 'modules')])
        reset_module_caches()
Example #4
0
 def setUp(self):
     """Prepare for running a config test."""
     reload(eboptions)
     super(EasyBuildConfigTest, self).setUp()
     self.tmpdir = tempfile.mkdtemp()
Example #5
0
    def test_XDG_CONFIG_env_vars(self):
        """Test effect of XDG_CONFIG* environment variables on default configuration."""
        self.purge_environment()

        xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
        xdg_config_dirs = os.environ.get('XDG_CONFIG_DIRS')

        cfg_template = '\n'.join([
            '[config]',
            'prefix=%s',
        ])

        homedir = os.path.join(self.test_prefix, 'homedir', '.config')
        mkdir(os.path.join(homedir, 'easybuild'), parents=True)
        write_file(os.path.join(homedir, 'easybuild', 'config.cfg'),
                   cfg_template % '/home')

        dir1 = os.path.join(self.test_prefix, 'dir1')
        mkdir(os.path.join(dir1, 'easybuild.d'), parents=True)
        write_file(os.path.join(dir1, 'easybuild.d', 'foo.cfg'),
                   cfg_template % '/foo')
        write_file(os.path.join(dir1, 'easybuild.d', 'bar.cfg'),
                   cfg_template % '/bar')

        dir2 = os.path.join(self.test_prefix, 'dir2')  # empty on purpose
        mkdir(os.path.join(dir2, 'easybuild.d'), parents=True)

        dir3 = os.path.join(self.test_prefix, 'dir3')
        mkdir(os.path.join(dir3, 'easybuild.d'), parents=True)
        write_file(os.path.join(dir3, 'easybuild.d', 'foobarbaz.cfg'),
                   cfg_template % '/foobarbaz')

        # set $XDG_CONFIG_DIRS to non-existing dir to isolate ourselves from possible system-wide config files
        os.environ[
            'XDG_CONFIG_DIRS'] = '/there/should/be/no/such/directory/we/hope'

        # only $XDG_CONFIG_HOME set (to existing path)
        os.environ['XDG_CONFIG_HOME'] = homedir
        cfg_files = [os.path.join(homedir, 'easybuild', 'config.cfg')]
        reload(eboptions)
        eb_go = eboptions.parse_options(args=[])
        self.assertEqual(eb_go.options.configfiles, cfg_files)
        self.assertEqual(eb_go.options.prefix, '/home')

        # $XDG_CONFIG_HOME set, one directory listed in $XDG_CONFIG_DIRS
        os.environ['XDG_CONFIG_DIRS'] = dir1
        cfg_files = [
            os.path.join(dir1, 'easybuild.d', 'bar.cfg'),
            os.path.join(dir1, 'easybuild.d', 'foo.cfg'),
            os.path.join(homedir, 'easybuild',
                         'config.cfg'),  # $XDG_CONFIG_HOME goes last
        ]
        reload(eboptions)
        eb_go = eboptions.parse_options(args=[])
        self.assertEqual(eb_go.options.configfiles, cfg_files)
        self.assertEqual(eb_go.options.prefix, '/home')  # last cfgfile wins

        # $XDG_CONFIG_HOME not set, multiple directories listed in $XDG_CONFIG_DIRS
        del os.environ['XDG_CONFIG_HOME']  # unset, so should become default
        os.environ['XDG_CONFIG_DIRS'] = os.pathsep.join([dir1, dir2, dir3])
        cfg_files = [
            os.path.join(dir1, 'easybuild.d', 'bar.cfg'),
            os.path.join(dir1, 'easybuild.d', 'foo.cfg'),
            os.path.join(dir3, 'easybuild.d', 'foobarbaz.cfg'),
        ]
        reload(eboptions)
        eb_go = eboptions.parse_options(args=[])
        # note: there may be a config file in $HOME too, so don't use a strict comparison
        self.assertEqual(cfg_files, eb_go.options.configfiles[:3])

        # $XDG_CONFIG_HOME set to non-existing directory, multiple directories listed in $XDG_CONFIG_DIRS
        os.environ['XDG_CONFIG_HOME'] = os.path.join(self.test_prefix,
                                                     'nosuchdir')
        cfg_files = [
            os.path.join(dir1, 'easybuild.d', 'bar.cfg'),
            os.path.join(dir1, 'easybuild.d', 'foo.cfg'),
            os.path.join(dir3, 'easybuild.d', 'foobarbaz.cfg'),
        ]
        reload(eboptions)
        eb_go = eboptions.parse_options(args=[])
        self.assertEqual(eb_go.options.configfiles, cfg_files)
        self.assertEqual(eb_go.options.prefix,
                         '/foobarbaz')  # last cfgfile wins

        # restore $XDG_CONFIG env vars to original state
        if xdg_config_home is None:
            del os.environ['XDG_CONFIG_HOME']
        else:
            os.environ['XDG_CONFIG_HOME'] = xdg_config_home

        if xdg_config_dirs is None:
            del os.environ['XDG_CONFIG_DIRS']
        else:
            os.environ['XDG_CONFIG_DIRS'] = xdg_config_dirs
        reload(eboptions)