We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
EB_PYTHON startup behaviour
The documentation at https://easybuild.readthedocs.io/en/latest/Python-2-3-compatibility.html?#controlling-which-python-command-easybuild-will-use-via-eb-python suggests that one can control which version of Python EasyBuild will use by setting EB_PYTHON.

Since https://github.com/easybuilders/easybuild-easyblocks/commit/40b76bef5a1f4f149e0c13cce913c051b54da5a3 running `module load EasyBuild` will now overwrite any existing EB_PYTHON environment variable.

While it is still possible to configure EB_PYTHON after running `module load EasyBuild`, it is no longer possible to configure EB_PYTHON first (e.g. in one's shell startup), since it is overwritten when EasyBuild loads.

If this is the desired behaviour then it should be documented. If this is not the desired behaviour, then it is a bug.

--- 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/easyblocks/e/easybuildmeta.py`
Content:
```
1 # #
2 # Copyright 2013-2020 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 EasyBuild support for installing EasyBuild, implemented as an easyblock
27 
28 @author: Kenneth Hoste (UGent)
29 """
30 import copy
31 import os
32 import re
33 from distutils.version import LooseVersion
34 
35 from easybuild.easyblocks.generic.pythonpackage import PythonPackage
36 from easybuild.tools.build_log import EasyBuildError
37 from easybuild.tools.filetools import read_file
38 from easybuild.tools.modules import get_software_root_env_var_name
39 from easybuild.tools.py2vs3 import OrderedDict
40 from easybuild.tools.utilities import flatten
41 
42 
43 # note: we can't use EB_EasyBuild as easyblock name, as that would require an easyblock named 'easybuild.py',
44 #       which would screw up namespacing and create all kinds of problems (e.g. easyblocks not being found anymore)
45 class EB_EasyBuildMeta(PythonPackage):
46     """Support for install EasyBuild."""
47 
48     def __init__(self, *args, **kwargs):
49         """Initialize custom class variables."""
50         super(EB_EasyBuildMeta, self).__init__(*args, **kwargs)
51         self.real_initial_environ = None
52 
53         self.easybuild_pkgs = ['easybuild-framework', 'easybuild-easyblocks', 'easybuild-easyconfigs']
54         if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) <= LooseVersion('3.999'):
55             # deliberately include vsc-install & vsc-base twice;
56             # first time to ensure the specified vsc-install/vsc-base package is available when framework gets installed
57             self.easybuild_pkgs.insert(0, 'vsc-base')
58             self.easybuild_pkgs.insert(0, 'vsc-install')
59             # second time as last package to be installed, to ensure that the vsc-base version listed
60             # in easy-install.pth is the one specified;
61             # when installing the easybuild-* packages, the vsc-base version in easy-install.pth may be 'bumped'
62             # if a newer vsc-base version is found somewhere (e.g. provided by the OS)
63             self.easybuild_pkgs.extend(['vsc-base', 'vsc-install'])
64             # consider setuptools first, in case it is listed as a sources
65             self.easybuild_pkgs.insert(0, 'setuptools')
66 
67     def check_readiness_step(self):
68         """Make sure EasyBuild can be installed with a loaded EasyBuild module."""
69         env_var_name = get_software_root_env_var_name(self.name)
70         if env_var_name in os.environ:
71             os.environ.pop(env_var_name)
72             self.log.debug("$%s is unset so EasyBuild can be installed with a loaded EasyBuild module" % env_var_name)
73         else:
74             self.log.debug("Not unsetting $%s since it's not set" % env_var_name)
75 
76         super(EB_EasyBuildMeta, self).check_readiness_step()
77 
78     def build_step(self):
79         """No building for EasyBuild packages."""
80         pass
81 
82     def install_step(self):
83         """Install EasyBuild packages one by one."""
84         try:
85             subdirs = os.listdir(self.builddir)
86             for pkg in self.easybuild_pkgs:
87                 seldirs = [x for x in subdirs if x.startswith(pkg)]
88                 if len(seldirs) != 1:
89                     # setuptools is optional since it may be available in the OS;
90                     # vsc-install and vsc-base sources are optional,
91                     # they can be pulled in from PyPi when installing easybuild-framework too
92                     if pkg not in ['setuptools', 'vsc-base', 'vsc-install']:
93                         raise EasyBuildError("Failed to find required EasyBuild package %s (subdirs: %s, seldirs: %s)",
94                                              pkg, subdirs, seldirs)
95 
96                 else:
97                     self.log.info("Installing package %s", pkg)
98                     os.chdir(os.path.join(self.builddir, seldirs[0]))
99                     super(EB_EasyBuildMeta, self).install_step()
100 
101         except OSError as err:
102             raise EasyBuildError("Failed to install EasyBuild packages: %s", err)
103 
104     def post_install_step(self):
105         """Remove setuptools.pth file that hard includes a system-wide (site-packages) path, if it is there."""
106 
107         setuptools_pth = os.path.join(self.installdir, self.pylibdir, 'setuptools.pth')
108         if os.path.exists(setuptools_pth):
109             setuptools_pth_txt = read_file(setuptools_pth)
110             # any line that starts with '/' is a sign of trouble
111             sys_path_regex = re.compile('^/', re.M)
112             if sys_path_regex.search(setuptools_pth_txt):
113                 self.log.warning("Found %s, and includes one or more absolute system paths. Removing it.",
114                                  setuptools_pth)
115                 try:
116                     os.remove(setuptools_pth)
117                 except OSError as err:
118                     raise EasyBuildError("Failed to remove %s: %s", setuptools_pth, err)
119 
120     def sanity_check_step(self):
121         """Custom sanity check for EasyBuild."""
122 
123         # check whether easy-install.pth contains correct entries
124         easy_install_pth = os.path.join(self.installdir, self.pylibdir, 'easy-install.pth')
125         if os.path.exists(easy_install_pth):
126             easy_install_pth_txt = read_file(easy_install_pth)
127 
128             ignore_pkgs = ['setuptools', 'vsc-install']
129             if LooseVersion(self.version) > LooseVersion('3.999'):
130                 ignore_pkgs.append('vsc-base')
131 
132             for pkg in [p for p in self.easybuild_pkgs if p not in ignore_pkgs]:
133                 if pkg == 'vsc-base':
134                     # don't include strict version check for vsc-base
135                     pkg_regex = re.compile(r"^\./%s" % pkg.replace('-', '_'), re.M)
136                 else:
137                     major_minor_version = '.'.join(self.version.split('.')[:2])
138                     pkg_regex = re.compile(r"^\./%s-%s" % (pkg.replace('-', '_'), major_minor_version), re.M)
139 
140                 if not pkg_regex.search(easy_install_pth_txt):
141                     raise EasyBuildError("Failed to find pattern '%s' in %s: %s",
142                                          pkg_regex.pattern, easy_install_pth, easy_install_pth_txt)
143 
144         # list of dirs to check, by package
145         # boolean indicates whether dir is expected to reside in Python lib/pythonX/site-packages dir
146         subdirs_by_pkg = {
147             'easybuild-framework': [('easybuild/framework', True), ('easybuild/tools', True)],
148             'easybuild-easyblocks': [('easybuild/easyblocks', True)],
149             'easybuild-easyconfigs': [('easybuild/easyconfigs', False)],
150         }
151         if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) < LooseVersion('3.999'):
152             subdirs_by_pkg.update({
153                 'vsc-base': [('vsc/utils', True)],
154             })
155 
156         # final list of directories to check, by setup tool
157         # order matters, e.g. setuptools before distutils
158         eb_dirs = OrderedDict()
159         eb_dirs['setuptools'] = []
160         eb_dirs['distutils.core'] = flatten([x for x in subdirs_by_pkg.values()])
161 
162         # determine setup tool (setuptools or distutils)
163         setup_tool = None
164         for tool in eb_dirs.keys():
165             self.log.debug("Trying %s.." % tool)
166             try:
167                 exec("from %s import setup" % tool)
168                 setup_tool = tool
169                 break
170             except ImportError:
171                 pass
172         self.log.debug('setup_tool: %s' % setup_tool)
173 
174         # for a setuptools installation, we need to figure out the egg dirs,
175         # since we don't know the individual package versions
176         if setup_tool == 'setuptools':
177             try:
178                 installed_dirs = os.listdir(os.path.join(self.installdir, self.pylibdir))
179                 for (pkg, subdirs) in subdirs_by_pkg.items():
180                     sel_dirs = [x for x in installed_dirs if x.startswith(pkg.replace('-', '_'))]
181                     if not len(sel_dirs) == 1:
182                         raise EasyBuildError("Failed to isolate installed egg dir for %s", pkg)
183 
184                     for (subdir, _) in subdirs:
185                         # eggs always go in Python lib/pythonX/site-packages dir with setuptools
186                         eb_dirs['setuptools'].append((os.path.join(sel_dirs[0], subdir), True))
187             except OSError as err:
188                 raise EasyBuildError("Failed to determine sanity check dir paths: %s", err)
189 
190         # set of sanity check paths to check for EasyBuild
191         custom_paths = {
192             'files': ['bin/eb'],
193             'dirs': [self.pylibdir] + [[x, os.path.join(self.pylibdir, x)][y] for (x, y) in eb_dirs[setup_tool]],
194         }
195 
196         # make sure we don't trip over deprecated behavior in old EasyBuild versions
197         eb_cmd = 'eb'
198         if LooseVersion(self.version) <= LooseVersion('1.16.0'):
199             eb_cmd = 'EASYBUILD_DEPRECATED=1.0 eb'
200 
201         # set of sanity check commands to run for EasyBuild
202         custom_commands = [
203             # this may spit out a wrong version, but that should be safe to ignore
204             # occurs when the EasyBuild being used is newer than the EasyBuild being installed
205             (eb_cmd, '--version'),
206             (eb_cmd, '-a'),
207             (eb_cmd, '-e ConfigureMake -a'),
208         ]
209 
210         # (temporary) cleanse copy of initial environment to avoid conflict with (potentially) loaded EasyBuild module
211         self.real_initial_environ = copy.deepcopy(self.initial_environ)
212         for env_var in ['_LMFILES_', 'LOADEDMODULES']:
213             if env_var in self.initial_environ:
214                 self.initial_environ.pop(env_var)
215                 os.environ.pop(env_var)
216                 self.log.debug("Unset $%s in current env and copy of original env to make sanity check work" % env_var)
217 
218         super(EB_EasyBuildMeta, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)
219 
220     def make_module_extra(self):
221         """
222         Set $EB_PYTHON to ensure that this EasyBuild installation uses the same Python executable it was installed with.
223         """
224         txt = super(EB_EasyBuildMeta, self).make_module_extra()
225         txt += self.module_generator.set_environment('EB_PYTHON', self.python_cmd)
226         return txt
227 
228     def make_module_step(self, fake=False):
229         """Create module file, before copy of original environment that was tampered with is restored."""
230         modpath = super(EB_EasyBuildMeta, self).make_module_step(fake=fake)
231 
232         if not fake:
233             # restore copy of original environment
234             self.initial_environ = copy.deepcopy(self.real_initial_environ)
235             self.log.debug("Restored copy of original environment")
236 
237         return modpath
238
```
--- 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/easyblocks/e/easybuildmeta.py b/easybuild/easyblocks/e/easybuildmeta.py
--- a/easybuild/easyblocks/e/easybuildmeta.py
+++ b/easybuild/easyblocks/e/easybuildmeta.py
@@ -219,10 +219,11 @@
 
     def make_module_extra(self):
         """
-        Set $EB_PYTHON to ensure that this EasyBuild installation uses the same Python executable it was installed with.
+        Set $EB_INSTALLPYTHON to ensure that this EasyBuild installation uses the same Python executable it was
+        installed with (which can still be overridden by the user with $EB_PYTHON).
         """
         txt = super(EB_EasyBuildMeta, self).make_module_extra()
-        txt += self.module_generator.set_environment('EB_PYTHON', self.python_cmd)
+        txt += self.module_generator.set_environment('EB_INSTALLPYTHON', self.python_cmd)
         return txt
 
     def make_module_step(self, fake=False):

{"golden_diff": "diff --git a/easybuild/easyblocks/e/easybuildmeta.py b/easybuild/easyblocks/e/easybuildmeta.py\n--- a/easybuild/easyblocks/e/easybuildmeta.py\n+++ b/easybuild/easyblocks/e/easybuildmeta.py\n@@ -219,10 +219,11 @@\n \n     def make_module_extra(self):\n         \"\"\"\n-        Set $EB_PYTHON to ensure that this EasyBuild installation uses the same Python executable it was installed with.\n+        Set $EB_INSTALLPYTHON to ensure that this EasyBuild installation uses the same Python executable it was\n+        installed with (which can still be overridden by the user with $EB_PYTHON).\n         \"\"\"\n         txt = super(EB_EasyBuildMeta, self).make_module_extra()\n-        txt += self.module_generator.set_environment('EB_PYTHON', self.python_cmd)\n+        txt += self.module_generator.set_environment('EB_INSTALLPYTHON', self.python_cmd)\n         return txt\n \n     def make_module_step(self, fake=False):\n", "issue": "EB_PYTHON startup behaviour\nThe documentation at https://easybuild.readthedocs.io/en/latest/Python-2-3-compatibility.html?#controlling-which-python-command-easybuild-will-use-via-eb-python suggests that one can control which version of Python EasyBuild will use by setting EB_PYTHON.\r\n\r\nSince https://github.com/easybuilders/easybuild-easyblocks/commit/40b76bef5a1f4f149e0c13cce913c051b54da5a3 running `module load EasyBuild` will now overwrite any existing EB_PYTHON environment variable.\r\n\r\nWhile it is still possible to configure EB_PYTHON after running `module load EasyBuild`, it is no longer possible to configure EB_PYTHON first (e.g. in one's shell startup), since it is overwritten when EasyBuild loads.\r\n\r\nIf this is the desired behaviour then it should be documented. If this is not the desired behaviour, then it is a bug.\n", "before_files": [{"content": "# #\n# Copyright 2013-2020 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\"\"\"\nEasyBuild support for installing EasyBuild, implemented as an easyblock\n\n@author: Kenneth Hoste (UGent)\n\"\"\"\nimport copy\nimport os\nimport re\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.pythonpackage import PythonPackage\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import read_file\nfrom easybuild.tools.modules import get_software_root_env_var_name\nfrom easybuild.tools.py2vs3 import OrderedDict\nfrom easybuild.tools.utilities import flatten\n\n\n# note: we can't use EB_EasyBuild as easyblock name, as that would require an easyblock named 'easybuild.py',\n#       which would screw up namespacing and create all kinds of problems (e.g. easyblocks not being found anymore)\nclass EB_EasyBuildMeta(PythonPackage):\n    \"\"\"Support for install EasyBuild.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initialize custom class variables.\"\"\"\n        super(EB_EasyBuildMeta, self).__init__(*args, **kwargs)\n        self.real_initial_environ = None\n\n        self.easybuild_pkgs = ['easybuild-framework', 'easybuild-easyblocks', 'easybuild-easyconfigs']\n        if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) <= LooseVersion('3.999'):\n            # deliberately include vsc-install & vsc-base twice;\n            # first time to ensure the specified vsc-install/vsc-base package is available when framework gets installed\n            self.easybuild_pkgs.insert(0, 'vsc-base')\n            self.easybuild_pkgs.insert(0, 'vsc-install')\n            # second time as last package to be installed, to ensure that the vsc-base version listed\n            # in easy-install.pth is the one specified;\n            # when installing the easybuild-* packages, the vsc-base version in easy-install.pth may be 'bumped'\n            # if a newer vsc-base version is found somewhere (e.g. provided by the OS)\n            self.easybuild_pkgs.extend(['vsc-base', 'vsc-install'])\n            # consider setuptools first, in case it is listed as a sources\n            self.easybuild_pkgs.insert(0, 'setuptools')\n\n    def check_readiness_step(self):\n        \"\"\"Make sure EasyBuild can be installed with a loaded EasyBuild module.\"\"\"\n        env_var_name = get_software_root_env_var_name(self.name)\n        if env_var_name in os.environ:\n            os.environ.pop(env_var_name)\n            self.log.debug(\"$%s is unset so EasyBuild can be installed with a loaded EasyBuild module\" % env_var_name)\n        else:\n            self.log.debug(\"Not unsetting $%s since it's not set\" % env_var_name)\n\n        super(EB_EasyBuildMeta, self).check_readiness_step()\n\n    def build_step(self):\n        \"\"\"No building for EasyBuild packages.\"\"\"\n        pass\n\n    def install_step(self):\n        \"\"\"Install EasyBuild packages one by one.\"\"\"\n        try:\n            subdirs = os.listdir(self.builddir)\n            for pkg in self.easybuild_pkgs:\n                seldirs = [x for x in subdirs if x.startswith(pkg)]\n                if len(seldirs) != 1:\n                    # setuptools is optional since it may be available in the OS;\n                    # vsc-install and vsc-base sources are optional,\n                    # they can be pulled in from PyPi when installing easybuild-framework too\n                    if pkg not in ['setuptools', 'vsc-base', 'vsc-install']:\n                        raise EasyBuildError(\"Failed to find required EasyBuild package %s (subdirs: %s, seldirs: %s)\",\n                                             pkg, subdirs, seldirs)\n\n                else:\n                    self.log.info(\"Installing package %s\", pkg)\n                    os.chdir(os.path.join(self.builddir, seldirs[0]))\n                    super(EB_EasyBuildMeta, self).install_step()\n\n        except OSError as err:\n            raise EasyBuildError(\"Failed to install EasyBuild packages: %s\", err)\n\n    def post_install_step(self):\n        \"\"\"Remove setuptools.pth file that hard includes a system-wide (site-packages) path, if it is there.\"\"\"\n\n        setuptools_pth = os.path.join(self.installdir, self.pylibdir, 'setuptools.pth')\n        if os.path.exists(setuptools_pth):\n            setuptools_pth_txt = read_file(setuptools_pth)\n            # any line that starts with '/' is a sign of trouble\n            sys_path_regex = re.compile('^/', re.M)\n            if sys_path_regex.search(setuptools_pth_txt):\n                self.log.warning(\"Found %s, and includes one or more absolute system paths. Removing it.\",\n                                 setuptools_pth)\n                try:\n                    os.remove(setuptools_pth)\n                except OSError as err:\n                    raise EasyBuildError(\"Failed to remove %s: %s\", setuptools_pth, err)\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for EasyBuild.\"\"\"\n\n        # check whether easy-install.pth contains correct entries\n        easy_install_pth = os.path.join(self.installdir, self.pylibdir, 'easy-install.pth')\n        if os.path.exists(easy_install_pth):\n            easy_install_pth_txt = read_file(easy_install_pth)\n\n            ignore_pkgs = ['setuptools', 'vsc-install']\n            if LooseVersion(self.version) > LooseVersion('3.999'):\n                ignore_pkgs.append('vsc-base')\n\n            for pkg in [p for p in self.easybuild_pkgs if p not in ignore_pkgs]:\n                if pkg == 'vsc-base':\n                    # don't include strict version check for vsc-base\n                    pkg_regex = re.compile(r\"^\\./%s\" % pkg.replace('-', '_'), re.M)\n                else:\n                    major_minor_version = '.'.join(self.version.split('.')[:2])\n                    pkg_regex = re.compile(r\"^\\./%s-%s\" % (pkg.replace('-', '_'), major_minor_version), re.M)\n\n                if not pkg_regex.search(easy_install_pth_txt):\n                    raise EasyBuildError(\"Failed to find pattern '%s' in %s: %s\",\n                                         pkg_regex.pattern, easy_install_pth, easy_install_pth_txt)\n\n        # list of dirs to check, by package\n        # boolean indicates whether dir is expected to reside in Python lib/pythonX/site-packages dir\n        subdirs_by_pkg = {\n            'easybuild-framework': [('easybuild/framework', True), ('easybuild/tools', True)],\n            'easybuild-easyblocks': [('easybuild/easyblocks', True)],\n            'easybuild-easyconfigs': [('easybuild/easyconfigs', False)],\n        }\n        if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) < LooseVersion('3.999'):\n            subdirs_by_pkg.update({\n                'vsc-base': [('vsc/utils', True)],\n            })\n\n        # final list of directories to check, by setup tool\n        # order matters, e.g. setuptools before distutils\n        eb_dirs = OrderedDict()\n        eb_dirs['setuptools'] = []\n        eb_dirs['distutils.core'] = flatten([x for x in subdirs_by_pkg.values()])\n\n        # determine setup tool (setuptools or distutils)\n        setup_tool = None\n        for tool in eb_dirs.keys():\n            self.log.debug(\"Trying %s..\" % tool)\n            try:\n                exec(\"from %s import setup\" % tool)\n                setup_tool = tool\n                break\n            except ImportError:\n                pass\n        self.log.debug('setup_tool: %s' % setup_tool)\n\n        # for a setuptools installation, we need to figure out the egg dirs,\n        # since we don't know the individual package versions\n        if setup_tool == 'setuptools':\n            try:\n                installed_dirs = os.listdir(os.path.join(self.installdir, self.pylibdir))\n                for (pkg, subdirs) in subdirs_by_pkg.items():\n                    sel_dirs = [x for x in installed_dirs if x.startswith(pkg.replace('-', '_'))]\n                    if not len(sel_dirs) == 1:\n                        raise EasyBuildError(\"Failed to isolate installed egg dir for %s\", pkg)\n\n                    for (subdir, _) in subdirs:\n                        # eggs always go in Python lib/pythonX/site-packages dir with setuptools\n                        eb_dirs['setuptools'].append((os.path.join(sel_dirs[0], subdir), True))\n            except OSError as err:\n                raise EasyBuildError(\"Failed to determine sanity check dir paths: %s\", err)\n\n        # set of sanity check paths to check for EasyBuild\n        custom_paths = {\n            'files': ['bin/eb'],\n            'dirs': [self.pylibdir] + [[x, os.path.join(self.pylibdir, x)][y] for (x, y) in eb_dirs[setup_tool]],\n        }\n\n        # make sure we don't trip over deprecated behavior in old EasyBuild versions\n        eb_cmd = 'eb'\n        if LooseVersion(self.version) <= LooseVersion('1.16.0'):\n            eb_cmd = 'EASYBUILD_DEPRECATED=1.0 eb'\n\n        # set of sanity check commands to run for EasyBuild\n        custom_commands = [\n            # this may spit out a wrong version, but that should be safe to ignore\n            # occurs when the EasyBuild being used is newer than the EasyBuild being installed\n            (eb_cmd, '--version'),\n            (eb_cmd, '-a'),\n            (eb_cmd, '-e ConfigureMake -a'),\n        ]\n\n        # (temporary) cleanse copy of initial environment to avoid conflict with (potentially) loaded EasyBuild module\n        self.real_initial_environ = copy.deepcopy(self.initial_environ)\n        for env_var in ['_LMFILES_', 'LOADEDMODULES']:\n            if env_var in self.initial_environ:\n                self.initial_environ.pop(env_var)\n                os.environ.pop(env_var)\n                self.log.debug(\"Unset $%s in current env and copy of original env to make sanity check work\" % env_var)\n\n        super(EB_EasyBuildMeta, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)\n\n    def make_module_extra(self):\n        \"\"\"\n        Set $EB_PYTHON to ensure that this EasyBuild installation uses the same Python executable it was installed with.\n        \"\"\"\n        txt = super(EB_EasyBuildMeta, self).make_module_extra()\n        txt += self.module_generator.set_environment('EB_PYTHON', self.python_cmd)\n        return txt\n\n    def make_module_step(self, fake=False):\n        \"\"\"Create module file, before copy of original environment that was tampered with is restored.\"\"\"\n        modpath = super(EB_EasyBuildMeta, self).make_module_step(fake=fake)\n\n        if not fake:\n            # restore copy of original environment\n            self.initial_environ = copy.deepcopy(self.real_initial_environ)\n            self.log.debug(\"Restored copy of original environment\")\n\n        return modpath\n", "path": "easybuild/easyblocks/e/easybuildmeta.py"}], "after_files": [{"content": "# #\n# Copyright 2013-2020 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\"\"\"\nEasyBuild support for installing EasyBuild, implemented as an easyblock\n\n@author: Kenneth Hoste (UGent)\n\"\"\"\nimport copy\nimport os\nimport re\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.pythonpackage import PythonPackage\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import read_file\nfrom easybuild.tools.modules import get_software_root_env_var_name\nfrom easybuild.tools.py2vs3 import OrderedDict\nfrom easybuild.tools.utilities import flatten\n\n\n# note: we can't use EB_EasyBuild as easyblock name, as that would require an easyblock named 'easybuild.py',\n#       which would screw up namespacing and create all kinds of problems (e.g. easyblocks not being found anymore)\nclass EB_EasyBuildMeta(PythonPackage):\n    \"\"\"Support for install EasyBuild.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initialize custom class variables.\"\"\"\n        super(EB_EasyBuildMeta, self).__init__(*args, **kwargs)\n        self.real_initial_environ = None\n\n        self.easybuild_pkgs = ['easybuild-framework', 'easybuild-easyblocks', 'easybuild-easyconfigs']\n        if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) <= LooseVersion('3.999'):\n            # deliberately include vsc-install & vsc-base twice;\n            # first time to ensure the specified vsc-install/vsc-base package is available when framework gets installed\n            self.easybuild_pkgs.insert(0, 'vsc-base')\n            self.easybuild_pkgs.insert(0, 'vsc-install')\n            # second time as last package to be installed, to ensure that the vsc-base version listed\n            # in easy-install.pth is the one specified;\n            # when installing the easybuild-* packages, the vsc-base version in easy-install.pth may be 'bumped'\n            # if a newer vsc-base version is found somewhere (e.g. provided by the OS)\n            self.easybuild_pkgs.extend(['vsc-base', 'vsc-install'])\n            # consider setuptools first, in case it is listed as a sources\n            self.easybuild_pkgs.insert(0, 'setuptools')\n\n    def check_readiness_step(self):\n        \"\"\"Make sure EasyBuild can be installed with a loaded EasyBuild module.\"\"\"\n        env_var_name = get_software_root_env_var_name(self.name)\n        if env_var_name in os.environ:\n            os.environ.pop(env_var_name)\n            self.log.debug(\"$%s is unset so EasyBuild can be installed with a loaded EasyBuild module\" % env_var_name)\n        else:\n            self.log.debug(\"Not unsetting $%s since it's not set\" % env_var_name)\n\n        super(EB_EasyBuildMeta, self).check_readiness_step()\n\n    def build_step(self):\n        \"\"\"No building for EasyBuild packages.\"\"\"\n        pass\n\n    def install_step(self):\n        \"\"\"Install EasyBuild packages one by one.\"\"\"\n        try:\n            subdirs = os.listdir(self.builddir)\n            for pkg in self.easybuild_pkgs:\n                seldirs = [x for x in subdirs if x.startswith(pkg)]\n                if len(seldirs) != 1:\n                    # setuptools is optional since it may be available in the OS;\n                    # vsc-install and vsc-base sources are optional,\n                    # they can be pulled in from PyPi when installing easybuild-framework too\n                    if pkg not in ['setuptools', 'vsc-base', 'vsc-install']:\n                        raise EasyBuildError(\"Failed to find required EasyBuild package %s (subdirs: %s, seldirs: %s)\",\n                                             pkg, subdirs, seldirs)\n\n                else:\n                    self.log.info(\"Installing package %s\", pkg)\n                    os.chdir(os.path.join(self.builddir, seldirs[0]))\n                    super(EB_EasyBuildMeta, self).install_step()\n\n        except OSError as err:\n            raise EasyBuildError(\"Failed to install EasyBuild packages: %s\", err)\n\n    def post_install_step(self):\n        \"\"\"Remove setuptools.pth file that hard includes a system-wide (site-packages) path, if it is there.\"\"\"\n\n        setuptools_pth = os.path.join(self.installdir, self.pylibdir, 'setuptools.pth')\n        if os.path.exists(setuptools_pth):\n            setuptools_pth_txt = read_file(setuptools_pth)\n            # any line that starts with '/' is a sign of trouble\n            sys_path_regex = re.compile('^/', re.M)\n            if sys_path_regex.search(setuptools_pth_txt):\n                self.log.warning(\"Found %s, and includes one or more absolute system paths. Removing it.\",\n                                 setuptools_pth)\n                try:\n                    os.remove(setuptools_pth)\n                except OSError as err:\n                    raise EasyBuildError(\"Failed to remove %s: %s\", setuptools_pth, err)\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for EasyBuild.\"\"\"\n\n        # check whether easy-install.pth contains correct entries\n        easy_install_pth = os.path.join(self.installdir, self.pylibdir, 'easy-install.pth')\n        if os.path.exists(easy_install_pth):\n            easy_install_pth_txt = read_file(easy_install_pth)\n\n            ignore_pkgs = ['setuptools', 'vsc-install']\n            if LooseVersion(self.version) > LooseVersion('3.999'):\n                ignore_pkgs.append('vsc-base')\n\n            for pkg in [p for p in self.easybuild_pkgs if p not in ignore_pkgs]:\n                if pkg == 'vsc-base':\n                    # don't include strict version check for vsc-base\n                    pkg_regex = re.compile(r\"^\\./%s\" % pkg.replace('-', '_'), re.M)\n                else:\n                    major_minor_version = '.'.join(self.version.split('.')[:2])\n                    pkg_regex = re.compile(r\"^\\./%s-%s\" % (pkg.replace('-', '_'), major_minor_version), re.M)\n\n                if not pkg_regex.search(easy_install_pth_txt):\n                    raise EasyBuildError(\"Failed to find pattern '%s' in %s: %s\",\n                                         pkg_regex.pattern, easy_install_pth, easy_install_pth_txt)\n\n        # list of dirs to check, by package\n        # boolean indicates whether dir is expected to reside in Python lib/pythonX/site-packages dir\n        subdirs_by_pkg = {\n            'easybuild-framework': [('easybuild/framework', True), ('easybuild/tools', True)],\n            'easybuild-easyblocks': [('easybuild/easyblocks', True)],\n            'easybuild-easyconfigs': [('easybuild/easyconfigs', False)],\n        }\n        if LooseVersion(self.version) >= LooseVersion('2.0') and LooseVersion(self.version) < LooseVersion('3.999'):\n            subdirs_by_pkg.update({\n                'vsc-base': [('vsc/utils', True)],\n            })\n\n        # final list of directories to check, by setup tool\n        # order matters, e.g. setuptools before distutils\n        eb_dirs = OrderedDict()\n        eb_dirs['setuptools'] = []\n        eb_dirs['distutils.core'] = flatten([x for x in subdirs_by_pkg.values()])\n\n        # determine setup tool (setuptools or distutils)\n        setup_tool = None\n        for tool in eb_dirs.keys():\n            self.log.debug(\"Trying %s..\" % tool)\n            try:\n                exec(\"from %s import setup\" % tool)\n                setup_tool = tool\n                break\n            except ImportError:\n                pass\n        self.log.debug('setup_tool: %s' % setup_tool)\n\n        # for a setuptools installation, we need to figure out the egg dirs,\n        # since we don't know the individual package versions\n        if setup_tool == 'setuptools':\n            try:\n                installed_dirs = os.listdir(os.path.join(self.installdir, self.pylibdir))\n                for (pkg, subdirs) in subdirs_by_pkg.items():\n                    sel_dirs = [x for x in installed_dirs if x.startswith(pkg.replace('-', '_'))]\n                    if not len(sel_dirs) == 1:\n                        raise EasyBuildError(\"Failed to isolate installed egg dir for %s\", pkg)\n\n                    for (subdir, _) in subdirs:\n                        # eggs always go in Python lib/pythonX/site-packages dir with setuptools\n                        eb_dirs['setuptools'].append((os.path.join(sel_dirs[0], subdir), True))\n            except OSError as err:\n                raise EasyBuildError(\"Failed to determine sanity check dir paths: %s\", err)\n\n        # set of sanity check paths to check for EasyBuild\n        custom_paths = {\n            'files': ['bin/eb'],\n            'dirs': [self.pylibdir] + [[x, os.path.join(self.pylibdir, x)][y] for (x, y) in eb_dirs[setup_tool]],\n        }\n\n        # make sure we don't trip over deprecated behavior in old EasyBuild versions\n        eb_cmd = 'eb'\n        if LooseVersion(self.version) <= LooseVersion('1.16.0'):\n            eb_cmd = 'EASYBUILD_DEPRECATED=1.0 eb'\n\n        # set of sanity check commands to run for EasyBuild\n        custom_commands = [\n            # this may spit out a wrong version, but that should be safe to ignore\n            # occurs when the EasyBuild being used is newer than the EasyBuild being installed\n            (eb_cmd, '--version'),\n            (eb_cmd, '-a'),\n            (eb_cmd, '-e ConfigureMake -a'),\n        ]\n\n        # (temporary) cleanse copy of initial environment to avoid conflict with (potentially) loaded EasyBuild module\n        self.real_initial_environ = copy.deepcopy(self.initial_environ)\n        for env_var in ['_LMFILES_', 'LOADEDMODULES']:\n            if env_var in self.initial_environ:\n                self.initial_environ.pop(env_var)\n                os.environ.pop(env_var)\n                self.log.debug(\"Unset $%s in current env and copy of original env to make sanity check work\" % env_var)\n\n        super(EB_EasyBuildMeta, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)\n\n    def make_module_extra(self):\n        \"\"\"\n        Set $EB_INSTALLPYTHON to ensure that this EasyBuild installation uses the same Python executable it was\n        installed with (which can still be overridden by the user with $EB_PYTHON).\n        \"\"\"\n        txt = super(EB_EasyBuildMeta, self).make_module_extra()\n        txt += self.module_generator.set_environment('EB_INSTALLPYTHON', self.python_cmd)\n        return txt\n\n    def make_module_step(self, fake=False):\n        \"\"\"Create module file, before copy of original environment that was tampered with is restored.\"\"\"\n        modpath = super(EB_EasyBuildMeta, self).make_module_step(fake=fake)\n\n        if not fake:\n            # restore copy of original environment\n            self.initial_environ = copy.deepcopy(self.real_initial_environ)\n            self.log.debug(\"Restored copy of original environment\")\n\n        return modpath\n", "path": "easybuild/easyblocks/e/easybuildmeta.py"}]}