We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Issue running tests
```
[mboisson@build-node easybuild-framework]$ python -O -m test.framework.suite test_update
INFO: This is (based on) vsc.install.shared_setup 0.10.17
Traceback (most recent call last):
  File "/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/mboisson/git/easybuild-framework/test/framework/suite.py", line 44, in <module>
    import test.framework.asyncprocess as a
  File "/home/mboisson/git/easybuild-framework/test/framework/asyncprocess.py", line 34, in <module>
    from test.framework.utilities import EnhancedTestCase
  File "/home/mboisson/git/easybuild-framework/test/framework/utilities.py", line 71, in <module>
    go = EasyBuildOptions(go_useconfigfiles=False)
  File "easybuild/tools/options.py", line 246, in __init__
    super(EasyBuildOptions, self).__init__(*args, **kwargs)
  File "/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/site-packages/vsc/utils/generaloption.py", line 982, in __init__
    self.main_options()
  File "/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/site-packages/vsc/utils/generaloption.py", line 1058, in main_options
    fn()
  File "easybuild/tools/options.py", line 493, in config_options
    'choice', 'store', DEFAULT_REPOSITORY, sorted(avail_repositories().keys())),
  File "easybuild/tools/repository/repository.py", line 152, in avail_repositories
    raise EasyBuildError("avail_repositories: FileRepository missing from list of repositories")
easybuild.tools.build_log.EasyBuildError: 'avail_repositories: FileRepository missing from list of repositories'
``` 

Opening an issue for @boegel 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `easybuild/tools/utilities.py`
Content:
```
1 # #
2 # Copyright 2012-2019 Ghent University
3 #
4 # This file is part of EasyBuild,
5 # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
6 # with support of Ghent University (http://ugent.be/hpc),
7 # the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
8 # Flemish Research Foundation (FWO) (http://www.fwo.be/en)
9 # and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
10 #
11 # https://github.com/easybuilders/easybuild
12 #
13 # EasyBuild is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation v2.
16 #
17 # EasyBuild is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.
24 # #
25 """
26 Module with various utility functions
27 
28 :author: Kenneth Hoste (Ghent University)
29 """
30 import glob
31 import os
32 import string
33 import sys
34 from vsc.utils import fancylogger
35 
36 from easybuild.tools.build_log import EasyBuildError, print_msg
37 from easybuild.tools.config import build_option
38 
39 
40 _log = fancylogger.getLogger('tools.utilities')
41 
42 
43 # a list of all ascii characters
44 ASCII_CHARS = string.maketrans('', '')
45 # a list of all unwanted ascii characters (we only want to keep digits, letters and _)
46 UNWANTED_CHARS = ASCII_CHARS.translate(ASCII_CHARS, string.digits + string.ascii_letters + "_")
47 
48 
49 def read_environment(env_vars, strict=False):
50     """NO LONGER SUPPORTED: use read_environment from easybuild.tools.environment instead"""
51     _log.nosupport("read_environment has been moved to easybuild.tools.environment", '2.0')
52 
53 
54 def flatten(lst):
55     """Flatten a list of lists."""
56     res = []
57     for x in lst:
58         res.extend(x)
59     return res
60 
61 
62 def quote_str(val, escape_newline=False, prefer_single_quotes=False):
63     """
64     Obtain a new value to be used in string replacement context.
65 
66     For non-string values, it just returns the exact same value.
67 
68     For string values, it tries to escape the string in quotes, e.g.,
69     foo becomes 'foo', foo'bar becomes "foo'bar",
70     foo'bar"baz becomes \"\"\"foo'bar"baz\"\"\", etc.
71 
72     :param escape_newline: wrap strings that include a newline in triple quotes
73     """
74 
75     if isinstance(val, basestring):
76         # forced triple double quotes
77         if ("'" in val and '"' in val) or (escape_newline and '\n' in val):
78             return '"""%s"""' % val
79         # single quotes to escape double quote used in strings
80         elif '"' in val:
81             return "'%s'" % val
82         # if single quotes are preferred, use single quotes;
83         # unless a space or a single quote are in the string
84         elif prefer_single_quotes and "'" not in val and ' ' not in val:
85             return "'%s'" % val
86         # fallback on double quotes (required in tcl syntax)
87         else:
88             return '"%s"' % val
89     else:
90         return val
91 
92 
93 def quote_py_str(val):
94     """Version of quote_str specific for generating use in Python context (e.g., easyconfig parameters)."""
95     return quote_str(val, escape_newline=True, prefer_single_quotes=True)
96 
97 
98 def remove_unwanted_chars(inputstring):
99     """Remove unwanted characters from the given string and return a copy
100 
101     All non-letter and non-numeral characters are considered unwanted except for underscore ('_'), see UNWANTED_CHARS.
102     """
103     return inputstring.translate(ASCII_CHARS, UNWANTED_CHARS)
104 
105 
106 def import_available_modules(namespace):
107     """
108     Import all available module in the specified namespace.
109 
110     :param namespace: The namespace to import modules from.
111     """
112     modules = []
113     for path in sys.path:
114         for module in sorted(glob.glob(os.path.sep.join([path] + namespace.split('.') + ['*.py']))):
115             if not module.endswith('__init__.py'):
116                 mod_name = module.split(os.path.sep)[-1].split('.')[0]
117                 modpath = '.'.join([namespace, mod_name])
118                 _log.debug("importing module %s", modpath)
119                 try:
120                     mod = __import__(modpath, globals(), locals(), [''])
121                 except ImportError as err:
122                     raise EasyBuildError("import_available_modules: Failed to import %s: %s", modpath, err)
123                 modules.append(mod)
124     return modules
125 
126 
127 def only_if_module_is_available(modnames, pkgname=None, url=None):
128     """Decorator to guard functions/methods against missing required module with specified name."""
129     if pkgname and url is None:
130         url = 'https://pypi.python.org/pypi/%s' % pkgname
131 
132     if isinstance(modnames, basestring):
133         modnames = (modnames,)
134 
135     def wrap(orig):
136         """Decorated function, raises ImportError if specified module is not available."""
137         try:
138             imported = None
139             for modname in modnames:
140                 try:
141                     __import__(modname)
142                     imported = modname
143                     break
144                 except ImportError:
145                     pass
146 
147             if imported is None:
148                 raise ImportError("None of the specified modules %s is available" % ', '.join(modnames))
149             else:
150                 return orig
151 
152         except ImportError as err:
153             def error(*args, **kwargs):
154                 msg = "%s; required module '%s' is not available" % (err, modname)
155                 if pkgname:
156                     msg += " (provided by Python package %s, available from %s)" % (pkgname, url)
157                 elif url:
158                     msg += " (available from %s)" % url
159                 raise EasyBuildError("ImportError: %s", msg)
160             return error
161 
162     return wrap
163 
164 
165 def trace_msg(message, silent=False):
166     """Print trace message."""
167     if build_option('trace'):
168         print_msg('  >> ' + message, prefix=False)
169
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/easybuild/tools/utilities.py b/easybuild/tools/utilities.py
--- a/easybuild/tools/utilities.py
+++ b/easybuild/tools/utilities.py
@@ -111,7 +111,16 @@
     """
     modules = []
     for path in sys.path:
-        for module in sorted(glob.glob(os.path.sep.join([path] + namespace.split('.') + ['*.py']))):
+
+        cand_modpath_glob = os.path.sep.join([path] + namespace.split('.') + ['*.py'])
+
+        # if sys.path entry being considered is the empty string
+        # (which corresponds to Python packages/modules in current working directory being considered),
+        # we need to strip off / from the start of the path
+        if path == '' and cand_modpath_glob.startswith(os.path.sep):
+            cand_modpath_glob = cand_modpath_glob.lstrip(os.path.sep)
+
+        for module in sorted(glob.glob(cand_modpath_glob)):
             if not module.endswith('__init__.py'):
                 mod_name = module.split(os.path.sep)[-1].split('.')[0]
                 modpath = '.'.join([namespace, mod_name])
@@ -120,7 +129,10 @@
                     mod = __import__(modpath, globals(), locals(), [''])
                 except ImportError as err:
                     raise EasyBuildError("import_available_modules: Failed to import %s: %s", modpath, err)
-                modules.append(mod)
+
+                if mod not in modules:
+                    modules.append(mod)
+
     return modules

{"golden_diff": "diff --git a/easybuild/tools/utilities.py b/easybuild/tools/utilities.py\n--- a/easybuild/tools/utilities.py\n+++ b/easybuild/tools/utilities.py\n@@ -111,7 +111,16 @@\n     \"\"\"\n     modules = []\n     for path in sys.path:\n-        for module in sorted(glob.glob(os.path.sep.join([path] + namespace.split('.') + ['*.py']))):\n+\n+        cand_modpath_glob = os.path.sep.join([path] + namespace.split('.') + ['*.py'])\n+\n+        # if sys.path entry being considered is the empty string\n+        # (which corresponds to Python packages/modules in current working directory being considered),\n+        # we need to strip off / from the start of the path\n+        if path == '' and cand_modpath_glob.startswith(os.path.sep):\n+            cand_modpath_glob = cand_modpath_glob.lstrip(os.path.sep)\n+\n+        for module in sorted(glob.glob(cand_modpath_glob)):\n             if not module.endswith('__init__.py'):\n                 mod_name = module.split(os.path.sep)[-1].split('.')[0]\n                 modpath = '.'.join([namespace, mod_name])\n@@ -120,7 +129,10 @@\n                     mod = __import__(modpath, globals(), locals(), [''])\n                 except ImportError as err:\n                     raise EasyBuildError(\"import_available_modules: Failed to import %s: %s\", modpath, err)\n-                modules.append(mod)\n+\n+                if mod not in modules:\n+                    modules.append(mod)\n+\n     return modules\n", "issue": "Issue running tests\n```\r\n[mboisson@build-node easybuild-framework]$ python -O -m test.framework.suite test_update\r\nINFO: This is (based on) vsc.install.shared_setup 0.10.17\r\nTraceback (most recent call last):\r\n  File \"/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/runpy.py\", line 174, in _run_module_as_main\r\n    \"__main__\", fname, loader, pkg_name)\r\n  File \"/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/runpy.py\", line 72, in _run_code\r\n    exec code in run_globals\r\n  File \"/home/mboisson/git/easybuild-framework/test/framework/suite.py\", line 44, in <module>\r\n    import test.framework.asyncprocess as a\r\n  File \"/home/mboisson/git/easybuild-framework/test/framework/asyncprocess.py\", line 34, in <module>\r\n    from test.framework.utilities import EnhancedTestCase\r\n  File \"/home/mboisson/git/easybuild-framework/test/framework/utilities.py\", line 71, in <module>\r\n    go = EasyBuildOptions(go_useconfigfiles=False)\r\n  File \"easybuild/tools/options.py\", line 246, in __init__\r\n    super(EasyBuildOptions, self).__init__(*args, **kwargs)\r\n  File \"/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/site-packages/vsc/utils/generaloption.py\", line 982, in __init__\r\n    self.main_options()\r\n  File \"/cvmfs/soft.computecanada.ca/nix/store/4x0hqnpd0hfh62m3apkxmz8hz3hlsikx-python-2.7.13-env/lib/python2.7/site-packages/vsc/utils/generaloption.py\", line 1058, in main_options\r\n    fn()\r\n  File \"easybuild/tools/options.py\", line 493, in config_options\r\n    'choice', 'store', DEFAULT_REPOSITORY, sorted(avail_repositories().keys())),\r\n  File \"easybuild/tools/repository/repository.py\", line 152, in avail_repositories\r\n    raise EasyBuildError(\"avail_repositories: FileRepository missing from list of repositories\")\r\neasybuild.tools.build_log.EasyBuildError: 'avail_repositories: FileRepository missing from list of repositories'\r\n``` \r\n\r\nOpening an issue for @boegel \n", "before_files": [{"content": "# #\n# Copyright 2012-2019 Ghent University\n#\n# This file is part of EasyBuild,\n# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),\n# with support of Ghent University (http://ugent.be/hpc),\n# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),\n# Flemish Research Foundation (FWO) (http://www.fwo.be/en)\n# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).\n#\n# https://github.com/easybuilders/easybuild\n#\n# EasyBuild is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation v2.\n#\n# EasyBuild is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.\n# #\n\"\"\"\nModule with various utility functions\n\n:author: Kenneth Hoste (Ghent University)\n\"\"\"\nimport glob\nimport os\nimport string\nimport sys\nfrom vsc.utils import fancylogger\n\nfrom easybuild.tools.build_log import EasyBuildError, print_msg\nfrom easybuild.tools.config import build_option\n\n\n_log = fancylogger.getLogger('tools.utilities')\n\n\n# a list of all ascii characters\nASCII_CHARS = string.maketrans('', '')\n# a list of all unwanted ascii characters (we only want to keep digits, letters and _)\nUNWANTED_CHARS = ASCII_CHARS.translate(ASCII_CHARS, string.digits + string.ascii_letters + \"_\")\n\n\ndef read_environment(env_vars, strict=False):\n    \"\"\"NO LONGER SUPPORTED: use read_environment from easybuild.tools.environment instead\"\"\"\n    _log.nosupport(\"read_environment has been moved to easybuild.tools.environment\", '2.0')\n\n\ndef flatten(lst):\n    \"\"\"Flatten a list of lists.\"\"\"\n    res = []\n    for x in lst:\n        res.extend(x)\n    return res\n\n\ndef quote_str(val, escape_newline=False, prefer_single_quotes=False):\n    \"\"\"\n    Obtain a new value to be used in string replacement context.\n\n    For non-string values, it just returns the exact same value.\n\n    For string values, it tries to escape the string in quotes, e.g.,\n    foo becomes 'foo', foo'bar becomes \"foo'bar\",\n    foo'bar\"baz becomes \\\"\\\"\\\"foo'bar\"baz\\\"\\\"\\\", etc.\n\n    :param escape_newline: wrap strings that include a newline in triple quotes\n    \"\"\"\n\n    if isinstance(val, basestring):\n        # forced triple double quotes\n        if (\"'\" in val and '\"' in val) or (escape_newline and '\\n' in val):\n            return '\"\"\"%s\"\"\"' % val\n        # single quotes to escape double quote used in strings\n        elif '\"' in val:\n            return \"'%s'\" % val\n        # if single quotes are preferred, use single quotes;\n        # unless a space or a single quote are in the string\n        elif prefer_single_quotes and \"'\" not in val and ' ' not in val:\n            return \"'%s'\" % val\n        # fallback on double quotes (required in tcl syntax)\n        else:\n            return '\"%s\"' % val\n    else:\n        return val\n\n\ndef quote_py_str(val):\n    \"\"\"Version of quote_str specific for generating use in Python context (e.g., easyconfig parameters).\"\"\"\n    return quote_str(val, escape_newline=True, prefer_single_quotes=True)\n\n\ndef remove_unwanted_chars(inputstring):\n    \"\"\"Remove unwanted characters from the given string and return a copy\n\n    All non-letter and non-numeral characters are considered unwanted except for underscore ('_'), see UNWANTED_CHARS.\n    \"\"\"\n    return inputstring.translate(ASCII_CHARS, UNWANTED_CHARS)\n\n\ndef import_available_modules(namespace):\n    \"\"\"\n    Import all available module in the specified namespace.\n\n    :param namespace: The namespace to import modules from.\n    \"\"\"\n    modules = []\n    for path in sys.path:\n        for module in sorted(glob.glob(os.path.sep.join([path] + namespace.split('.') + ['*.py']))):\n            if not module.endswith('__init__.py'):\n                mod_name = module.split(os.path.sep)[-1].split('.')[0]\n                modpath = '.'.join([namespace, mod_name])\n                _log.debug(\"importing module %s\", modpath)\n                try:\n                    mod = __import__(modpath, globals(), locals(), [''])\n                except ImportError as err:\n                    raise EasyBuildError(\"import_available_modules: Failed to import %s: %s\", modpath, err)\n                modules.append(mod)\n    return modules\n\n\ndef only_if_module_is_available(modnames, pkgname=None, url=None):\n    \"\"\"Decorator to guard functions/methods against missing required module with specified name.\"\"\"\n    if pkgname and url is None:\n        url = 'https://pypi.python.org/pypi/%s' % pkgname\n\n    if isinstance(modnames, basestring):\n        modnames = (modnames,)\n\n    def wrap(orig):\n        \"\"\"Decorated function, raises ImportError if specified module is not available.\"\"\"\n        try:\n            imported = None\n            for modname in modnames:\n                try:\n                    __import__(modname)\n                    imported = modname\n                    break\n                except ImportError:\n                    pass\n\n            if imported is None:\n                raise ImportError(\"None of the specified modules %s is available\" % ', '.join(modnames))\n            else:\n                return orig\n\n        except ImportError as err:\n            def error(*args, **kwargs):\n                msg = \"%s; required module '%s' is not available\" % (err, modname)\n                if pkgname:\n                    msg += \" (provided by Python package %s, available from %s)\" % (pkgname, url)\n                elif url:\n                    msg += \" (available from %s)\" % url\n                raise EasyBuildError(\"ImportError: %s\", msg)\n            return error\n\n    return wrap\n\n\ndef trace_msg(message, silent=False):\n    \"\"\"Print trace message.\"\"\"\n    if build_option('trace'):\n        print_msg('  >> ' + message, prefix=False)\n", "path": "easybuild/tools/utilities.py"}], "after_files": [{"content": "# #\n# Copyright 2012-2019 Ghent University\n#\n# This file is part of EasyBuild,\n# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),\n# with support of Ghent University (http://ugent.be/hpc),\n# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),\n# Flemish Research Foundation (FWO) (http://www.fwo.be/en)\n# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).\n#\n# https://github.com/easybuilders/easybuild\n#\n# EasyBuild is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation v2.\n#\n# EasyBuild is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.\n# #\n\"\"\"\nModule with various utility functions\n\n:author: Kenneth Hoste (Ghent University)\n\"\"\"\nimport glob\nimport os\nimport string\nimport sys\nfrom vsc.utils import fancylogger\n\nfrom easybuild.tools.build_log import EasyBuildError, print_msg\nfrom easybuild.tools.config import build_option\n\n\n_log = fancylogger.getLogger('tools.utilities')\n\n\n# a list of all ascii characters\nASCII_CHARS = string.maketrans('', '')\n# a list of all unwanted ascii characters (we only want to keep digits, letters and _)\nUNWANTED_CHARS = ASCII_CHARS.translate(ASCII_CHARS, string.digits + string.ascii_letters + \"_\")\n\n\ndef read_environment(env_vars, strict=False):\n    \"\"\"NO LONGER SUPPORTED: use read_environment from easybuild.tools.environment instead\"\"\"\n    _log.nosupport(\"read_environment has been moved to easybuild.tools.environment\", '2.0')\n\n\ndef flatten(lst):\n    \"\"\"Flatten a list of lists.\"\"\"\n    res = []\n    for x in lst:\n        res.extend(x)\n    return res\n\n\ndef quote_str(val, escape_newline=False, prefer_single_quotes=False):\n    \"\"\"\n    Obtain a new value to be used in string replacement context.\n\n    For non-string values, it just returns the exact same value.\n\n    For string values, it tries to escape the string in quotes, e.g.,\n    foo becomes 'foo', foo'bar becomes \"foo'bar\",\n    foo'bar\"baz becomes \\\"\\\"\\\"foo'bar\"baz\\\"\\\"\\\", etc.\n\n    :param escape_newline: wrap strings that include a newline in triple quotes\n    \"\"\"\n\n    if isinstance(val, basestring):\n        # forced triple double quotes\n        if (\"'\" in val and '\"' in val) or (escape_newline and '\\n' in val):\n            return '\"\"\"%s\"\"\"' % val\n        # single quotes to escape double quote used in strings\n        elif '\"' in val:\n            return \"'%s'\" % val\n        # if single quotes are preferred, use single quotes;\n        # unless a space or a single quote are in the string\n        elif prefer_single_quotes and \"'\" not in val and ' ' not in val:\n            return \"'%s'\" % val\n        # fallback on double quotes (required in tcl syntax)\n        else:\n            return '\"%s\"' % val\n    else:\n        return val\n\n\ndef quote_py_str(val):\n    \"\"\"Version of quote_str specific for generating use in Python context (e.g., easyconfig parameters).\"\"\"\n    return quote_str(val, escape_newline=True, prefer_single_quotes=True)\n\n\ndef remove_unwanted_chars(inputstring):\n    \"\"\"Remove unwanted characters from the given string and return a copy\n\n    All non-letter and non-numeral characters are considered unwanted except for underscore ('_'), see UNWANTED_CHARS.\n    \"\"\"\n    return inputstring.translate(ASCII_CHARS, UNWANTED_CHARS)\n\n\ndef import_available_modules(namespace):\n    \"\"\"\n    Import all available module in the specified namespace.\n\n    :param namespace: The namespace to import modules from.\n    \"\"\"\n    modules = []\n    for path in sys.path:\n\n        cand_modpath_glob = os.path.sep.join([path] + namespace.split('.') + ['*.py'])\n\n        # if sys.path entry being considered is the empty string\n        # (which corresponds to Python packages/modules in current working directory being considered),\n        # we need to strip off / from the start of the path\n        if path == '' and cand_modpath_glob.startswith(os.path.sep):\n            cand_modpath_glob = cand_modpath_glob.lstrip(os.path.sep)\n\n        for module in sorted(glob.glob(cand_modpath_glob)):\n            if not module.endswith('__init__.py'):\n                mod_name = module.split(os.path.sep)[-1].split('.')[0]\n                modpath = '.'.join([namespace, mod_name])\n                _log.debug(\"importing module %s\", modpath)\n                try:\n                    mod = __import__(modpath, globals(), locals(), [''])\n                except ImportError as err:\n                    raise EasyBuildError(\"import_available_modules: Failed to import %s: %s\", modpath, err)\n\n                if mod not in modules:\n                    modules.append(mod)\n\n    return modules\n\n\ndef only_if_module_is_available(modnames, pkgname=None, url=None):\n    \"\"\"Decorator to guard functions/methods against missing required module with specified name.\"\"\"\n    if pkgname and url is None:\n        url = 'https://pypi.python.org/pypi/%s' % pkgname\n\n    if isinstance(modnames, basestring):\n        modnames = (modnames,)\n\n    def wrap(orig):\n        \"\"\"Decorated function, raises ImportError if specified module is not available.\"\"\"\n        try:\n            imported = None\n            for modname in modnames:\n                try:\n                    __import__(modname)\n                    imported = modname\n                    break\n                except ImportError:\n                    pass\n\n            if imported is None:\n                raise ImportError(\"None of the specified modules %s is available\" % ', '.join(modnames))\n            else:\n                return orig\n\n        except ImportError as err:\n            def error(*args, **kwargs):\n                msg = \"%s; required module '%s' is not available\" % (err, modname)\n                if pkgname:\n                    msg += \" (provided by Python package %s, available from %s)\" % (pkgname, url)\n                elif url:\n                    msg += \" (available from %s)\" % url\n                raise EasyBuildError(\"ImportError: %s\", msg)\n            return error\n\n    return wrap\n\n\ndef trace_msg(message, silent=False):\n    \"\"\"Print trace message.\"\"\"\n    if build_option('trace'):\n        print_msg('  >> ' + message, prefix=False)\n", "path": "easybuild/tools/utilities.py"}]}