We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
meson/ninja scipy install not producing egg / dist info 
And that means it does not appear in the result of `pip list` and causes anything requiring `scipy` to fail the sanity check.

--- 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/s/scipy.py`
Content:
```
1 ##
2 # Copyright 2009-2023 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 building and installing scipy, implemented as an easyblock
27 
28 @author: Stijn De Weirdt (Ghent University)
29 @author: Dries Verdegem (Ghent University)
30 @author: Kenneth Hoste (Ghent University)
31 @author: Pieter De Baets (Ghent University)
32 @author: Jens Timmerman (Ghent University)
33 @author: Jasper Grimm (University of York)
34 """
35 import os
36 import tempfile
37 from distutils.version import LooseVersion
38 
39 import easybuild.tools.environment as env
40 import easybuild.tools.toolchain as toolchain
41 from easybuild.easyblocks.generic.fortranpythonpackage import FortranPythonPackage
42 from easybuild.easyblocks.generic.mesonninja import MesonNinja
43 from easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir
44 from easybuild.framework.easyconfig import CUSTOM
45 from easybuild.tools.build_log import EasyBuildError
46 from easybuild.tools.filetools import change_dir, copy_dir
47 
48 
49 class EB_scipy(FortranPythonPackage, PythonPackage, MesonNinja):
50     """Support for installing the scipy Python package as part of a Python installation."""
51 
52     @staticmethod
53     def extra_options():
54         """Easyconfig parameters specific to scipy."""
55         extra_vars = ({
56             'enable_slow_tests': [False, "Run scipy test suite, including tests marked as slow", CUSTOM],
57             'ignore_test_result': [None, "Run scipy test suite, but ignore test failures (True/False/None). Default "
58                                          "(None) implies True for scipy < 1.9, and False for scipy >= 1.9", CUSTOM],
59         })
60 
61         return PythonPackage.extra_options(extra_vars=extra_vars)
62 
63     def __init__(self, *args, **kwargs):
64         """Set scipy-specific test command."""
65         # calling PythonPackage __init__ also lets MesonNinja work in an extension
66         PythonPackage.__init__(self, *args, **kwargs)
67         self.testinstall = True
68 
69         if LooseVersion(self.version) >= LooseVersion('1.9'):
70             self.use_meson = True
71 
72             # enforce scipy test suite results if not explicitly disabled for scipy >= 1.9
73             # strip inherited PythonPackage installopts
74             installopts = self.cfg['installopts']
75             pythonpackage_installopts = ['--no-deps', '--ignore-installed', '--no-index', '--egg',
76                                          '--zip-ok', '--no-index']
77             self.log.info("Stripping inherited PythonPackage installopts %s from installopts %s",
78                           pythonpackage_installopts, installopts)
79             for i in pythonpackage_installopts:
80                 installopts = installopts.replace(i, '')
81             self.cfg['installopts'] = installopts
82 
83         else:
84             self.use_meson = False
85 
86         if self.cfg['ignore_test_result'] is None:
87             # automatically ignore scipy test suite results for scipy < 1.9, as we did in older easyconfigs
88             self.cfg['ignore_test_result'] = LooseVersion(self.version) < '1.9'
89             self.log.info("ignore_test_result not specified, so automatically set to %s for scipy %s",
90                           self.cfg['ignore_test_result'], self.version)
91 
92         if self.cfg['ignore_test_result']:
93             # used to maintain compatibility with easyconfigs predating scipy 1.9;
94             # runs tests (serially) in a way that exits with code 0 regardless of test results,
95             # see https://github.com/easybuilders/easybuild-easyblocks/issues/2237
96             self.testcmd = "cd .. && %(python)s -c 'import numpy; import scipy; scipy.test(verbose=2)'"
97         else:
98             self.testcmd = " && ".join([
99                 "cd ..",
100                 "touch %(srcdir)s/.coveragerc",
101                 "%(python)s %(srcdir)s/runtests.py -v --no-build --parallel %(parallel)s",
102             ])
103             if self.cfg['enable_slow_tests']:
104                 self.testcmd += " -m full "
105 
106     def configure_step(self):
107         """Custom configure step for scipy: set extra installation options when needed."""
108 
109         # scipy >= 1.9.0 uses Meson/Ninja
110         if self.use_meson:
111             # configure BLAS/LAPACK library to use with Meson for scipy >= 1.9.0
112             lapack_lib = self.toolchain.lapack_family()
113             if lapack_lib == toolchain.FLEXIBLAS:
114                 blas_lapack = 'flexiblas'
115             elif lapack_lib == toolchain.INTELMKL:
116                 blas_lapack = 'mkl'
117             elif lapack_lib == toolchain.OPENBLAS:
118                 blas_lapack = 'openblas'
119             else:
120                 raise EasyBuildError("Unknown BLAS/LAPACK library used: %s", lapack_lib)
121 
122             for opt in ('blas', 'lapack'):
123                 self.cfg.update('configopts', '-D%(opt)s=%(blas_lapack)s' % {'opt': opt, 'blas_lapack': blas_lapack})
124 
125             # need to have already installed extensions in PATH, PYTHONPATH for configure/build/install steps
126             pythonpath = os.getenv('PYTHONPATH')
127             pylibdir = det_pylibdir()
128             env.setvar('PYTHONPATH', os.pathsep.join([os.path.join(self.installdir, pylibdir), pythonpath]))
129 
130             path = os.getenv('PATH')
131             env.setvar('PATH', os.pathsep.join([os.path.join(self.installdir, 'bin'), path]))
132 
133             MesonNinja.configure_step(self)
134 
135         else:
136             # scipy < 1.9.0 uses install procedure using setup.py
137             FortranPythonPackage.configure_step(self)
138 
139         if LooseVersion(self.version) >= LooseVersion('0.13'):
140             # in recent scipy versions, additional compilation is done in the install step,
141             # which requires unsetting $LDFLAGS
142             if self.toolchain.comp_family() in [toolchain.GCC, toolchain.CLANGGCC]:  # @UndefinedVariable
143                 self.cfg.update('preinstallopts', "unset LDFLAGS && ")
144 
145     def build_step(self):
146         """Custom build step for scipy: use ninja for scipy >= 1.9.0"""
147         if self.use_meson:
148             MesonNinja.build_step(self)
149         else:
150             FortranPythonPackage.build_step(self)
151 
152     def test_step(self):
153         """Run available scipy unit tests. Adapted from numpy easyblock"""
154 
155         if self.use_meson:
156             # temporarily install scipy so we can run the test suite
157             tmpdir = tempfile.mkdtemp()
158             cwd = os.getcwd()
159 
160             tmp_builddir = os.path.join(tmpdir, 'build')
161             tmp_installdir = os.path.join(tmpdir, 'install')
162 
163             # create a copy of the builddir
164             copy_dir(cwd, tmp_builddir)
165             change_dir(tmp_builddir)
166 
167             # reconfigure (to update prefix), and install to tmpdir
168             MesonNinja.configure_step(self, cmd_prefix=tmp_installdir)
169             MesonNinja.install_step(self)
170 
171             tmp_pylibdir = [os.path.join(tmp_installdir, det_pylibdir())]
172             self.prepare_python()
173 
174             self.cfg['pretestopts'] = " && ".join([
175                 # LDFLAGS should not be set when testing numpy/scipy, because it overwrites whatever numpy/scipy sets
176                 # see http://projects.scipy.org/numpy/ticket/182
177                 "unset LDFLAGS",
178                 "export PYTHONPATH=%s:$PYTHONPATH" % tmp_pylibdir,
179                 "",
180             ])
181             self.cfg['runtest'] = self.testcmd % {
182                 'python': self.python_cmd,
183                 'srcdir': self.cfg['start_dir'],
184                 'parallel': self.cfg['parallel'],
185             }
186 
187             MesonNinja.test_step(self)
188 
189         else:
190             self.testcmd = self.testcmd % {
191                 'python': '%(python)s',
192                 'srcdir': self.cfg['start_dir'],
193                 'parallel': self.cfg['parallel'],
194             }
195             FortranPythonPackage.test_step(self)
196 
197     def install_step(self):
198         """Custom install step for scipy: use ninja for scipy >= 1.9.0"""
199         if self.use_meson:
200             MesonNinja.install_step(self)
201         else:
202             FortranPythonPackage.install_step(self)
203 
204     def sanity_check_step(self, *args, **kwargs):
205         """Custom sanity check for scipy."""
206 
207         # can't use self.pylibdir here, need to determine path on the fly using currently active 'python' command;
208         # this is important for numpy installations for multiple Python version (via multi_deps)
209         custom_paths = {
210             'files': [],
211             'dirs': [det_pylibdir()],
212         }
213 
214         return PythonPackage.sanity_check_step(self, custom_paths=custom_paths)
215
```
--- 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/s/scipy.py b/easybuild/easyblocks/s/scipy.py
--- a/easybuild/easyblocks/s/scipy.py
+++ b/easybuild/easyblocks/s/scipy.py
@@ -42,8 +42,8 @@
 from easybuild.easyblocks.generic.mesonninja import MesonNinja
 from easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir
 from easybuild.framework.easyconfig import CUSTOM
-from easybuild.tools.build_log import EasyBuildError
-from easybuild.tools.filetools import change_dir, copy_dir
+from easybuild.tools.build_log import EasyBuildError, print_warning
+from easybuild.tools.filetools import change_dir, copy_dir, copy_file
 
 
 class EB_scipy(FortranPythonPackage, PythonPackage, MesonNinja):
@@ -198,6 +198,18 @@
         """Custom install step for scipy: use ninja for scipy >= 1.9.0"""
         if self.use_meson:
             MesonNinja.install_step(self)
+
+            # copy PKG-INFO file included in scipy source tarball to scipy-<version>.egg-info in installation,
+            # so pip is aware of the scipy installation (required for 'pip list', 'pip check', etc.);
+            # see also https://github.com/easybuilders/easybuild-easyblocks/issues/2901
+            pkg_info = os.path.join(self.cfg['start_dir'], 'PKG-INFO')
+            target_egg_info = os.path.join(self.installdir, self.pylibdir, 'scipy-%s.egg-info' % self.version)
+            if os.path.isfile(pkg_info):
+                copy_file(pkg_info, target_egg_info)
+            else:
+                cwd = os.getcwd()
+                print_warning("%s not found in %s, so can't use it to create %s!", pkg_info, cwd, target_egg_info,
+                              log=self.log)
         else:
             FortranPythonPackage.install_step(self)
 
@@ -211,4 +223,9 @@
             'dirs': [det_pylibdir()],
         }
 
-        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths)
+        # make sure that scipy is included in output of 'pip list',
+        # so that 'pip check' passes if scipy is a required dependency for another Python package;
+        # use case-insensitive match, since name is sometimes reported as 'SciPy'
+        custom_commands = [r"pip list | grep -iE '^scipy\s+%s\s*$'" % self.version.replace('.', r'\.')]
+
+        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths, custom_commands=custom_commands)

{"golden_diff": "diff --git a/easybuild/easyblocks/s/scipy.py b/easybuild/easyblocks/s/scipy.py\n--- a/easybuild/easyblocks/s/scipy.py\n+++ b/easybuild/easyblocks/s/scipy.py\n@@ -42,8 +42,8 @@\n from easybuild.easyblocks.generic.mesonninja import MesonNinja\n from easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir\n from easybuild.framework.easyconfig import CUSTOM\n-from easybuild.tools.build_log import EasyBuildError\n-from easybuild.tools.filetools import change_dir, copy_dir\n+from easybuild.tools.build_log import EasyBuildError, print_warning\n+from easybuild.tools.filetools import change_dir, copy_dir, copy_file\n \n \n class EB_scipy(FortranPythonPackage, PythonPackage, MesonNinja):\n@@ -198,6 +198,18 @@\n         \"\"\"Custom install step for scipy: use ninja for scipy >= 1.9.0\"\"\"\n         if self.use_meson:\n             MesonNinja.install_step(self)\n+\n+            # copy PKG-INFO file included in scipy source tarball to scipy-<version>.egg-info in installation,\n+            # so pip is aware of the scipy installation (required for 'pip list', 'pip check', etc.);\n+            # see also https://github.com/easybuilders/easybuild-easyblocks/issues/2901\n+            pkg_info = os.path.join(self.cfg['start_dir'], 'PKG-INFO')\n+            target_egg_info = os.path.join(self.installdir, self.pylibdir, 'scipy-%s.egg-info' % self.version)\n+            if os.path.isfile(pkg_info):\n+                copy_file(pkg_info, target_egg_info)\n+            else:\n+                cwd = os.getcwd()\n+                print_warning(\"%s not found in %s, so can't use it to create %s!\", pkg_info, cwd, target_egg_info,\n+                              log=self.log)\n         else:\n             FortranPythonPackage.install_step(self)\n \n@@ -211,4 +223,9 @@\n             'dirs': [det_pylibdir()],\n         }\n \n-        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths)\n+        # make sure that scipy is included in output of 'pip list',\n+        # so that 'pip check' passes if scipy is a required dependency for another Python package;\n+        # use case-insensitive match, since name is sometimes reported as 'SciPy'\n+        custom_commands = [r\"pip list | grep -iE '^scipy\\s+%s\\s*$'\" % self.version.replace('.', r'\\.')]\n+\n+        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths, custom_commands=custom_commands)\n", "issue": "meson/ninja scipy install not producing egg / dist info \nAnd that means it does not appear in the result of `pip list` and causes anything requiring `scipy` to fail the sanity check.\n", "before_files": [{"content": "##\n# Copyright 2009-2023 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 building and installing scipy, implemented as an easyblock\n\n@author: Stijn De Weirdt (Ghent University)\n@author: Dries Verdegem (Ghent University)\n@author: Kenneth Hoste (Ghent University)\n@author: Pieter De Baets (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Jasper Grimm (University of York)\n\"\"\"\nimport os\nimport tempfile\nfrom distutils.version import LooseVersion\n\nimport easybuild.tools.environment as env\nimport easybuild.tools.toolchain as toolchain\nfrom easybuild.easyblocks.generic.fortranpythonpackage import FortranPythonPackage\nfrom easybuild.easyblocks.generic.mesonninja import MesonNinja\nfrom easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import change_dir, copy_dir\n\n\nclass EB_scipy(FortranPythonPackage, PythonPackage, MesonNinja):\n    \"\"\"Support for installing the scipy Python package as part of a Python installation.\"\"\"\n\n    @staticmethod\n    def extra_options():\n        \"\"\"Easyconfig parameters specific to scipy.\"\"\"\n        extra_vars = ({\n            'enable_slow_tests': [False, \"Run scipy test suite, including tests marked as slow\", CUSTOM],\n            'ignore_test_result': [None, \"Run scipy test suite, but ignore test failures (True/False/None). Default \"\n                                         \"(None) implies True for scipy < 1.9, and False for scipy >= 1.9\", CUSTOM],\n        })\n\n        return PythonPackage.extra_options(extra_vars=extra_vars)\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Set scipy-specific test command.\"\"\"\n        # calling PythonPackage __init__ also lets MesonNinja work in an extension\n        PythonPackage.__init__(self, *args, **kwargs)\n        self.testinstall = True\n\n        if LooseVersion(self.version) >= LooseVersion('1.9'):\n            self.use_meson = True\n\n            # enforce scipy test suite results if not explicitly disabled for scipy >= 1.9\n            # strip inherited PythonPackage installopts\n            installopts = self.cfg['installopts']\n            pythonpackage_installopts = ['--no-deps', '--ignore-installed', '--no-index', '--egg',\n                                         '--zip-ok', '--no-index']\n            self.log.info(\"Stripping inherited PythonPackage installopts %s from installopts %s\",\n                          pythonpackage_installopts, installopts)\n            for i in pythonpackage_installopts:\n                installopts = installopts.replace(i, '')\n            self.cfg['installopts'] = installopts\n\n        else:\n            self.use_meson = False\n\n        if self.cfg['ignore_test_result'] is None:\n            # automatically ignore scipy test suite results for scipy < 1.9, as we did in older easyconfigs\n            self.cfg['ignore_test_result'] = LooseVersion(self.version) < '1.9'\n            self.log.info(\"ignore_test_result not specified, so automatically set to %s for scipy %s\",\n                          self.cfg['ignore_test_result'], self.version)\n\n        if self.cfg['ignore_test_result']:\n            # used to maintain compatibility with easyconfigs predating scipy 1.9;\n            # runs tests (serially) in a way that exits with code 0 regardless of test results,\n            # see https://github.com/easybuilders/easybuild-easyblocks/issues/2237\n            self.testcmd = \"cd .. && %(python)s -c 'import numpy; import scipy; scipy.test(verbose=2)'\"\n        else:\n            self.testcmd = \" && \".join([\n                \"cd ..\",\n                \"touch %(srcdir)s/.coveragerc\",\n                \"%(python)s %(srcdir)s/runtests.py -v --no-build --parallel %(parallel)s\",\n            ])\n            if self.cfg['enable_slow_tests']:\n                self.testcmd += \" -m full \"\n\n    def configure_step(self):\n        \"\"\"Custom configure step for scipy: set extra installation options when needed.\"\"\"\n\n        # scipy >= 1.9.0 uses Meson/Ninja\n        if self.use_meson:\n            # configure BLAS/LAPACK library to use with Meson for scipy >= 1.9.0\n            lapack_lib = self.toolchain.lapack_family()\n            if lapack_lib == toolchain.FLEXIBLAS:\n                blas_lapack = 'flexiblas'\n            elif lapack_lib == toolchain.INTELMKL:\n                blas_lapack = 'mkl'\n            elif lapack_lib == toolchain.OPENBLAS:\n                blas_lapack = 'openblas'\n            else:\n                raise EasyBuildError(\"Unknown BLAS/LAPACK library used: %s\", lapack_lib)\n\n            for opt in ('blas', 'lapack'):\n                self.cfg.update('configopts', '-D%(opt)s=%(blas_lapack)s' % {'opt': opt, 'blas_lapack': blas_lapack})\n\n            # need to have already installed extensions in PATH, PYTHONPATH for configure/build/install steps\n            pythonpath = os.getenv('PYTHONPATH')\n            pylibdir = det_pylibdir()\n            env.setvar('PYTHONPATH', os.pathsep.join([os.path.join(self.installdir, pylibdir), pythonpath]))\n\n            path = os.getenv('PATH')\n            env.setvar('PATH', os.pathsep.join([os.path.join(self.installdir, 'bin'), path]))\n\n            MesonNinja.configure_step(self)\n\n        else:\n            # scipy < 1.9.0 uses install procedure using setup.py\n            FortranPythonPackage.configure_step(self)\n\n        if LooseVersion(self.version) >= LooseVersion('0.13'):\n            # in recent scipy versions, additional compilation is done in the install step,\n            # which requires unsetting $LDFLAGS\n            if self.toolchain.comp_family() in [toolchain.GCC, toolchain.CLANGGCC]:  # @UndefinedVariable\n                self.cfg.update('preinstallopts', \"unset LDFLAGS && \")\n\n    def build_step(self):\n        \"\"\"Custom build step for scipy: use ninja for scipy >= 1.9.0\"\"\"\n        if self.use_meson:\n            MesonNinja.build_step(self)\n        else:\n            FortranPythonPackage.build_step(self)\n\n    def test_step(self):\n        \"\"\"Run available scipy unit tests. Adapted from numpy easyblock\"\"\"\n\n        if self.use_meson:\n            # temporarily install scipy so we can run the test suite\n            tmpdir = tempfile.mkdtemp()\n            cwd = os.getcwd()\n\n            tmp_builddir = os.path.join(tmpdir, 'build')\n            tmp_installdir = os.path.join(tmpdir, 'install')\n\n            # create a copy of the builddir\n            copy_dir(cwd, tmp_builddir)\n            change_dir(tmp_builddir)\n\n            # reconfigure (to update prefix), and install to tmpdir\n            MesonNinja.configure_step(self, cmd_prefix=tmp_installdir)\n            MesonNinja.install_step(self)\n\n            tmp_pylibdir = [os.path.join(tmp_installdir, det_pylibdir())]\n            self.prepare_python()\n\n            self.cfg['pretestopts'] = \" && \".join([\n                # LDFLAGS should not be set when testing numpy/scipy, because it overwrites whatever numpy/scipy sets\n                # see http://projects.scipy.org/numpy/ticket/182\n                \"unset LDFLAGS\",\n                \"export PYTHONPATH=%s:$PYTHONPATH\" % tmp_pylibdir,\n                \"\",\n            ])\n            self.cfg['runtest'] = self.testcmd % {\n                'python': self.python_cmd,\n                'srcdir': self.cfg['start_dir'],\n                'parallel': self.cfg['parallel'],\n            }\n\n            MesonNinja.test_step(self)\n\n        else:\n            self.testcmd = self.testcmd % {\n                'python': '%(python)s',\n                'srcdir': self.cfg['start_dir'],\n                'parallel': self.cfg['parallel'],\n            }\n            FortranPythonPackage.test_step(self)\n\n    def install_step(self):\n        \"\"\"Custom install step for scipy: use ninja for scipy >= 1.9.0\"\"\"\n        if self.use_meson:\n            MesonNinja.install_step(self)\n        else:\n            FortranPythonPackage.install_step(self)\n\n    def sanity_check_step(self, *args, **kwargs):\n        \"\"\"Custom sanity check for scipy.\"\"\"\n\n        # can't use self.pylibdir here, need to determine path on the fly using currently active 'python' command;\n        # this is important for numpy installations for multiple Python version (via multi_deps)\n        custom_paths = {\n            'files': [],\n            'dirs': [det_pylibdir()],\n        }\n\n        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths)\n", "path": "easybuild/easyblocks/s/scipy.py"}], "after_files": [{"content": "##\n# Copyright 2009-2023 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 building and installing scipy, implemented as an easyblock\n\n@author: Stijn De Weirdt (Ghent University)\n@author: Dries Verdegem (Ghent University)\n@author: Kenneth Hoste (Ghent University)\n@author: Pieter De Baets (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Jasper Grimm (University of York)\n\"\"\"\nimport os\nimport tempfile\nfrom distutils.version import LooseVersion\n\nimport easybuild.tools.environment as env\nimport easybuild.tools.toolchain as toolchain\nfrom easybuild.easyblocks.generic.fortranpythonpackage import FortranPythonPackage\nfrom easybuild.easyblocks.generic.mesonninja import MesonNinja\nfrom easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError, print_warning\nfrom easybuild.tools.filetools import change_dir, copy_dir, copy_file\n\n\nclass EB_scipy(FortranPythonPackage, PythonPackage, MesonNinja):\n    \"\"\"Support for installing the scipy Python package as part of a Python installation.\"\"\"\n\n    @staticmethod\n    def extra_options():\n        \"\"\"Easyconfig parameters specific to scipy.\"\"\"\n        extra_vars = ({\n            'enable_slow_tests': [False, \"Run scipy test suite, including tests marked as slow\", CUSTOM],\n            'ignore_test_result': [None, \"Run scipy test suite, but ignore test failures (True/False/None). Default \"\n                                         \"(None) implies True for scipy < 1.9, and False for scipy >= 1.9\", CUSTOM],\n        })\n\n        return PythonPackage.extra_options(extra_vars=extra_vars)\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Set scipy-specific test command.\"\"\"\n        # calling PythonPackage __init__ also lets MesonNinja work in an extension\n        PythonPackage.__init__(self, *args, **kwargs)\n        self.testinstall = True\n\n        if LooseVersion(self.version) >= LooseVersion('1.9'):\n            self.use_meson = True\n\n            # enforce scipy test suite results if not explicitly disabled for scipy >= 1.9\n            # strip inherited PythonPackage installopts\n            installopts = self.cfg['installopts']\n            pythonpackage_installopts = ['--no-deps', '--ignore-installed', '--no-index', '--egg',\n                                         '--zip-ok', '--no-index']\n            self.log.info(\"Stripping inherited PythonPackage installopts %s from installopts %s\",\n                          pythonpackage_installopts, installopts)\n            for i in pythonpackage_installopts:\n                installopts = installopts.replace(i, '')\n            self.cfg['installopts'] = installopts\n\n        else:\n            self.use_meson = False\n\n        if self.cfg['ignore_test_result'] is None:\n            # automatically ignore scipy test suite results for scipy < 1.9, as we did in older easyconfigs\n            self.cfg['ignore_test_result'] = LooseVersion(self.version) < '1.9'\n            self.log.info(\"ignore_test_result not specified, so automatically set to %s for scipy %s\",\n                          self.cfg['ignore_test_result'], self.version)\n\n        if self.cfg['ignore_test_result']:\n            # used to maintain compatibility with easyconfigs predating scipy 1.9;\n            # runs tests (serially) in a way that exits with code 0 regardless of test results,\n            # see https://github.com/easybuilders/easybuild-easyblocks/issues/2237\n            self.testcmd = \"cd .. && %(python)s -c 'import numpy; import scipy; scipy.test(verbose=2)'\"\n        else:\n            self.testcmd = \" && \".join([\n                \"cd ..\",\n                \"touch %(srcdir)s/.coveragerc\",\n                \"%(python)s %(srcdir)s/runtests.py -v --no-build --parallel %(parallel)s\",\n            ])\n            if self.cfg['enable_slow_tests']:\n                self.testcmd += \" -m full \"\n\n    def configure_step(self):\n        \"\"\"Custom configure step for scipy: set extra installation options when needed.\"\"\"\n\n        # scipy >= 1.9.0 uses Meson/Ninja\n        if self.use_meson:\n            # configure BLAS/LAPACK library to use with Meson for scipy >= 1.9.0\n            lapack_lib = self.toolchain.lapack_family()\n            if lapack_lib == toolchain.FLEXIBLAS:\n                blas_lapack = 'flexiblas'\n            elif lapack_lib == toolchain.INTELMKL:\n                blas_lapack = 'mkl'\n            elif lapack_lib == toolchain.OPENBLAS:\n                blas_lapack = 'openblas'\n            else:\n                raise EasyBuildError(\"Unknown BLAS/LAPACK library used: %s\", lapack_lib)\n\n            for opt in ('blas', 'lapack'):\n                self.cfg.update('configopts', '-D%(opt)s=%(blas_lapack)s' % {'opt': opt, 'blas_lapack': blas_lapack})\n\n            # need to have already installed extensions in PATH, PYTHONPATH for configure/build/install steps\n            pythonpath = os.getenv('PYTHONPATH')\n            pylibdir = det_pylibdir()\n            env.setvar('PYTHONPATH', os.pathsep.join([os.path.join(self.installdir, pylibdir), pythonpath]))\n\n            path = os.getenv('PATH')\n            env.setvar('PATH', os.pathsep.join([os.path.join(self.installdir, 'bin'), path]))\n\n            MesonNinja.configure_step(self)\n\n        else:\n            # scipy < 1.9.0 uses install procedure using setup.py\n            FortranPythonPackage.configure_step(self)\n\n        if LooseVersion(self.version) >= LooseVersion('0.13'):\n            # in recent scipy versions, additional compilation is done in the install step,\n            # which requires unsetting $LDFLAGS\n            if self.toolchain.comp_family() in [toolchain.GCC, toolchain.CLANGGCC]:  # @UndefinedVariable\n                self.cfg.update('preinstallopts', \"unset LDFLAGS && \")\n\n    def build_step(self):\n        \"\"\"Custom build step for scipy: use ninja for scipy >= 1.9.0\"\"\"\n        if self.use_meson:\n            MesonNinja.build_step(self)\n        else:\n            FortranPythonPackage.build_step(self)\n\n    def test_step(self):\n        \"\"\"Run available scipy unit tests. Adapted from numpy easyblock\"\"\"\n\n        if self.use_meson:\n            # temporarily install scipy so we can run the test suite\n            tmpdir = tempfile.mkdtemp()\n            cwd = os.getcwd()\n\n            tmp_builddir = os.path.join(tmpdir, 'build')\n            tmp_installdir = os.path.join(tmpdir, 'install')\n\n            # create a copy of the builddir\n            copy_dir(cwd, tmp_builddir)\n            change_dir(tmp_builddir)\n\n            # reconfigure (to update prefix), and install to tmpdir\n            MesonNinja.configure_step(self, cmd_prefix=tmp_installdir)\n            MesonNinja.install_step(self)\n\n            tmp_pylibdir = [os.path.join(tmp_installdir, det_pylibdir())]\n            self.prepare_python()\n\n            self.cfg['pretestopts'] = \" && \".join([\n                # LDFLAGS should not be set when testing numpy/scipy, because it overwrites whatever numpy/scipy sets\n                # see http://projects.scipy.org/numpy/ticket/182\n                \"unset LDFLAGS\",\n                \"export PYTHONPATH=%s:$PYTHONPATH\" % tmp_pylibdir,\n                \"\",\n            ])\n            self.cfg['runtest'] = self.testcmd % {\n                'python': self.python_cmd,\n                'srcdir': self.cfg['start_dir'],\n                'parallel': self.cfg['parallel'],\n            }\n\n            MesonNinja.test_step(self)\n\n        else:\n            self.testcmd = self.testcmd % {\n                'python': '%(python)s',\n                'srcdir': self.cfg['start_dir'],\n                'parallel': self.cfg['parallel'],\n            }\n            FortranPythonPackage.test_step(self)\n\n    def install_step(self):\n        \"\"\"Custom install step for scipy: use ninja for scipy >= 1.9.0\"\"\"\n        if self.use_meson:\n            MesonNinja.install_step(self)\n\n            # copy PKG-INFO file included in scipy source tarball to scipy-<version>.egg-info in installation,\n            # so pip is aware of the scipy installation (required for 'pip list', 'pip check', etc.);\n            # see also https://github.com/easybuilders/easybuild-easyblocks/issues/2901\n            pkg_info = os.path.join(self.cfg['start_dir'], 'PKG-INFO')\n            target_egg_info = os.path.join(self.installdir, self.pylibdir, 'scipy-%s.egg-info' % self.version)\n            if os.path.isfile(pkg_info):\n                copy_file(pkg_info, target_egg_info)\n            else:\n                cwd = os.getcwd()\n                print_warning(\"%s not found in %s, so can't use it to create %s!\", pkg_info, cwd, target_egg_info,\n                              log=self.log)\n        else:\n            FortranPythonPackage.install_step(self)\n\n    def sanity_check_step(self, *args, **kwargs):\n        \"\"\"Custom sanity check for scipy.\"\"\"\n\n        # can't use self.pylibdir here, need to determine path on the fly using currently active 'python' command;\n        # this is important for numpy installations for multiple Python version (via multi_deps)\n        custom_paths = {\n            'files': [],\n            'dirs': [det_pylibdir()],\n        }\n\n        # make sure that scipy is included in output of 'pip list',\n        # so that 'pip check' passes if scipy is a required dependency for another Python package;\n        # use case-insensitive match, since name is sometimes reported as 'SciPy'\n        custom_commands = [r\"pip list | grep -iE '^scipy\\s+%s\\s*$'\" % self.version.replace('.', r'\\.')]\n\n        return PythonPackage.sanity_check_step(self, custom_paths=custom_paths, custom_commands=custom_commands)\n", "path": "easybuild/easyblocks/s/scipy.py"}]}