We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Scipy build failing with Cython error
## 🐛 Bug

Scipy build is failing in [main](https://app.circleci.com/pipelines/github/ryanking13/pyodide/705/workflows/f75c57c6-95c0-4437-85ca-47889051954d/jobs/11444?invite=true#step-105-1365). I guess it is related to the new Cython release.

```
_stats.pyx:173:0: Referring to a memoryview typed argument directly in a nested closure function is not supported in Cython 0.x. Either upgrade to Cython 3, or assign the argument to a local variable and use that in the nested function.
Traceback (most recent call last):
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 317, in <module>
    main()
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 313, in main
    find_process_files(root_dir)
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 302, in find_process_files
    for result in pool.imap_unordered(lambda args: process(*args), jobs):
  File "/usr/local/lib/python3.10/multiprocessing/pool.py", line 870, in next
    raise value
  File "/usr/local/lib/python3.10/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 302, in <lambda>
    for result in pool.imap_unordered(lambda args: process(*args), jobs):
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 236, in process
    processor_function(fromfile, tofile, cwd=path)
  File "/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py", line 102, in process_pyx
    raise Exception('Cython failed')
Exception: Cython failed
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyodide-build/pyodide_build/pypabuild.py`
Content:
```
1 import os
2 import shutil
3 import sys
4 import traceback
5 from collections.abc import Mapping
6 from itertools import chain
7 from pathlib import Path
8 
9 from build import BuildBackendException, ConfigSettingsType, ProjectBuilder
10 from build.__main__ import (
11     _STYLES,
12     _error,
13     _handle_build_error,
14     _IsolatedEnvBuilder,
15     _ProjectBuilder,
16 )
17 from build.env import IsolatedEnv
18 from packaging.requirements import Requirement
19 
20 from .common import (
21     get_hostsitepackages,
22     get_pyversion,
23     get_unisolated_packages,
24     replace_env,
25 )
26 
27 
28 def symlink_unisolated_packages(env: IsolatedEnv) -> None:
29     pyversion = get_pyversion()
30     site_packages_path = f"lib/{pyversion}/site-packages"
31     env_site_packages = Path(env.path) / site_packages_path  # type: ignore[attr-defined]
32     sysconfigdata_name = os.environ["SYSCONFIG_NAME"]
33     sysconfigdata_path = (
34         Path(os.environ["TARGETINSTALLDIR"]) / f"sysconfigdata/{sysconfigdata_name}.py"
35     )
36     shutil.copy(sysconfigdata_path, env_site_packages)
37     host_site_packages = Path(get_hostsitepackages())
38     for name in get_unisolated_packages():
39         for path in chain(
40             host_site_packages.glob(f"{name}*"), host_site_packages.glob(f"_{name}*")
41         ):
42             (env_site_packages / path.name).unlink(missing_ok=True)
43             (env_site_packages / path.name).symlink_to(path)
44 
45 
46 def remove_unisolated_requirements(requires: set[str]) -> set[str]:
47     for reqstr in list(requires):
48         req = Requirement(reqstr)
49         for avoid_name in get_unisolated_packages():
50             if avoid_name in req.name.lower():
51                 requires.remove(reqstr)
52     return requires
53 
54 
55 def install_reqs(env: IsolatedEnv, reqs: set[str]) -> None:
56     env.install(remove_unisolated_requirements(reqs))
57     # Some packages (numcodecs) don't declare cython as a build dependency and
58     # only recythonize if it is present. We need them to always recythonize so
59     # we always install cython. If the reqs included some cython version already
60     # then this won't do anything.
61     env.install(["cython", "pythran"])
62 
63 
64 def _build_in_isolated_env(
65     build_env: Mapping[str, str],
66     builder: ProjectBuilder,
67     outdir: str,
68     distribution: str,
69     config_settings: ConfigSettingsType,
70 ) -> str:
71     # For debugging: The following line disables removal of the isolated venv.
72     # It will be left in the /tmp folder and can be inspected or entered as
73     # needed.
74     # _IsolatedEnvBuilder.__exit__ = lambda *args: None
75     with _IsolatedEnvBuilder() as env:
76         builder.python_executable = env.executable
77         builder.scripts_dir = env.scripts_dir
78         # first install the build dependencies
79         symlink_unisolated_packages(env)
80         install_reqs(env, builder.build_system_requires)
81         installed_requires_for_build = False
82         try:
83             build_reqs = builder.get_requires_for_build(distribution, config_settings)
84         except BuildBackendException:
85             pass
86         else:
87             install_reqs(env, build_reqs)
88             installed_requires_for_build = True
89 
90         with replace_env(build_env):
91             if not installed_requires_for_build:
92                 install_reqs(
93                     env, builder.get_requires_for_build(distribution, config_settings)
94                 )
95             return builder.build(distribution, outdir, config_settings)
96 
97 
98 def parse_backend_flags(backend_flags: str) -> ConfigSettingsType:
99     config_settings: dict[str, str | list[str]] = {}
100     for arg in backend_flags.split():
101         setting, _, value = arg.partition("=")
102         if setting not in config_settings:
103             config_settings[setting] = value
104             continue
105 
106         cur_value = config_settings[setting]
107         if isinstance(cur_value, str):
108             config_settings[setting] = [cur_value, value]
109         else:
110             cur_value.append(value)
111     return config_settings
112 
113 
114 def build(build_env: Mapping[str, str], backend_flags: str) -> None:
115     srcdir = Path.cwd()
116     outdir = srcdir / "dist"
117     builder = _ProjectBuilder(str(srcdir))
118     distribution = "wheel"
119     config_settings = parse_backend_flags(backend_flags)
120     try:
121         with _handle_build_error():
122             built = _build_in_isolated_env(
123                 build_env, builder, str(outdir), distribution, config_settings
124             )
125             print("{bold}{green}Successfully built {}{reset}".format(built, **_STYLES))
126     except Exception as e:  # pragma: no cover
127         tb = traceback.format_exc().strip("\n")
128         print("\n{dim}{}{reset}\n".format(tb, **_STYLES))
129         _error(str(e))
130         sys.exit(1)
131
```
--- 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/pyodide-build/pyodide_build/pypabuild.py b/pyodide-build/pyodide_build/pypabuild.py
--- a/pyodide-build/pyodide_build/pypabuild.py
+++ b/pyodide-build/pyodide_build/pypabuild.py
@@ -58,7 +58,12 @@
     # only recythonize if it is present. We need them to always recythonize so
     # we always install cython. If the reqs included some cython version already
     # then this won't do anything.
-    env.install(["cython", "pythran"])
+    env.install(
+        [
+            "cython<0.29.31",  # cython 0.29.31 is incompatible with scipy 1.8.1. TODO: remove this after the scipy update.
+            "pythran",
+        ]
+    )
 
 
 def _build_in_isolated_env(

{"golden_diff": "diff --git a/pyodide-build/pyodide_build/pypabuild.py b/pyodide-build/pyodide_build/pypabuild.py\n--- a/pyodide-build/pyodide_build/pypabuild.py\n+++ b/pyodide-build/pyodide_build/pypabuild.py\n@@ -58,7 +58,12 @@\n     # only recythonize if it is present. We need them to always recythonize so\n     # we always install cython. If the reqs included some cython version already\n     # then this won't do anything.\n-    env.install([\"cython\", \"pythran\"])\n+    env.install(\n+        [\n+            \"cython<0.29.31\",  # cython 0.29.31 is incompatible with scipy 1.8.1. TODO: remove this after the scipy update.\n+            \"pythran\",\n+        ]\n+    )\n \n \n def _build_in_isolated_env(\n", "issue": "Scipy build failing with Cython error\n## \ud83d\udc1b Bug\r\n\r\nScipy build is failing in [main](https://app.circleci.com/pipelines/github/ryanking13/pyodide/705/workflows/f75c57c6-95c0-4437-85ca-47889051954d/jobs/11444?invite=true#step-105-1365). I guess it is related to the new Cython release.\r\n\r\n```\r\n_stats.pyx:173:0: Referring to a memoryview typed argument directly in a nested closure function is not supported in Cython 0.x. Either upgrade to Cython 3, or assign the argument to a local variable and use that in the nested function.\r\nTraceback (most recent call last):\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 317, in <module>\r\n    main()\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 313, in main\r\n    find_process_files(root_dir)\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 302, in find_process_files\r\n    for result in pool.imap_unordered(lambda args: process(*args), jobs):\r\n  File \"/usr/local/lib/python3.10/multiprocessing/pool.py\", line 870, in next\r\n    raise value\r\n  File \"/usr/local/lib/python3.10/multiprocessing/pool.py\", line 125, in worker\r\n    result = (True, func(*args, **kwds))\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 302, in <lambda>\r\n    for result in pool.imap_unordered(lambda args: process(*args), jobs):\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 236, in process\r\n    processor_function(fromfile, tofile, cwd=path)\r\n  File \"/root/repo/packages/scipy/build/scipy-1.8.1/tools/cythonize.py\", line 102, in process_pyx\r\n    raise Exception('Cython failed')\r\nException: Cython failed\r\n```\r\n\n", "before_files": [{"content": "import os\nimport shutil\nimport sys\nimport traceback\nfrom collections.abc import Mapping\nfrom itertools import chain\nfrom pathlib import Path\n\nfrom build import BuildBackendException, ConfigSettingsType, ProjectBuilder\nfrom build.__main__ import (\n    _STYLES,\n    _error,\n    _handle_build_error,\n    _IsolatedEnvBuilder,\n    _ProjectBuilder,\n)\nfrom build.env import IsolatedEnv\nfrom packaging.requirements import Requirement\n\nfrom .common import (\n    get_hostsitepackages,\n    get_pyversion,\n    get_unisolated_packages,\n    replace_env,\n)\n\n\ndef symlink_unisolated_packages(env: IsolatedEnv) -> None:\n    pyversion = get_pyversion()\n    site_packages_path = f\"lib/{pyversion}/site-packages\"\n    env_site_packages = Path(env.path) / site_packages_path  # type: ignore[attr-defined]\n    sysconfigdata_name = os.environ[\"SYSCONFIG_NAME\"]\n    sysconfigdata_path = (\n        Path(os.environ[\"TARGETINSTALLDIR\"]) / f\"sysconfigdata/{sysconfigdata_name}.py\"\n    )\n    shutil.copy(sysconfigdata_path, env_site_packages)\n    host_site_packages = Path(get_hostsitepackages())\n    for name in get_unisolated_packages():\n        for path in chain(\n            host_site_packages.glob(f\"{name}*\"), host_site_packages.glob(f\"_{name}*\")\n        ):\n            (env_site_packages / path.name).unlink(missing_ok=True)\n            (env_site_packages / path.name).symlink_to(path)\n\n\ndef remove_unisolated_requirements(requires: set[str]) -> set[str]:\n    for reqstr in list(requires):\n        req = Requirement(reqstr)\n        for avoid_name in get_unisolated_packages():\n            if avoid_name in req.name.lower():\n                requires.remove(reqstr)\n    return requires\n\n\ndef install_reqs(env: IsolatedEnv, reqs: set[str]) -> None:\n    env.install(remove_unisolated_requirements(reqs))\n    # Some packages (numcodecs) don't declare cython as a build dependency and\n    # only recythonize if it is present. We need them to always recythonize so\n    # we always install cython. If the reqs included some cython version already\n    # then this won't do anything.\n    env.install([\"cython\", \"pythran\"])\n\n\ndef _build_in_isolated_env(\n    build_env: Mapping[str, str],\n    builder: ProjectBuilder,\n    outdir: str,\n    distribution: str,\n    config_settings: ConfigSettingsType,\n) -> str:\n    # For debugging: The following line disables removal of the isolated venv.\n    # It will be left in the /tmp folder and can be inspected or entered as\n    # needed.\n    # _IsolatedEnvBuilder.__exit__ = lambda *args: None\n    with _IsolatedEnvBuilder() as env:\n        builder.python_executable = env.executable\n        builder.scripts_dir = env.scripts_dir\n        # first install the build dependencies\n        symlink_unisolated_packages(env)\n        install_reqs(env, builder.build_system_requires)\n        installed_requires_for_build = False\n        try:\n            build_reqs = builder.get_requires_for_build(distribution, config_settings)\n        except BuildBackendException:\n            pass\n        else:\n            install_reqs(env, build_reqs)\n            installed_requires_for_build = True\n\n        with replace_env(build_env):\n            if not installed_requires_for_build:\n                install_reqs(\n                    env, builder.get_requires_for_build(distribution, config_settings)\n                )\n            return builder.build(distribution, outdir, config_settings)\n\n\ndef parse_backend_flags(backend_flags: str) -> ConfigSettingsType:\n    config_settings: dict[str, str | list[str]] = {}\n    for arg in backend_flags.split():\n        setting, _, value = arg.partition(\"=\")\n        if setting not in config_settings:\n            config_settings[setting] = value\n            continue\n\n        cur_value = config_settings[setting]\n        if isinstance(cur_value, str):\n            config_settings[setting] = [cur_value, value]\n        else:\n            cur_value.append(value)\n    return config_settings\n\n\ndef build(build_env: Mapping[str, str], backend_flags: str) -> None:\n    srcdir = Path.cwd()\n    outdir = srcdir / \"dist\"\n    builder = _ProjectBuilder(str(srcdir))\n    distribution = \"wheel\"\n    config_settings = parse_backend_flags(backend_flags)\n    try:\n        with _handle_build_error():\n            built = _build_in_isolated_env(\n                build_env, builder, str(outdir), distribution, config_settings\n            )\n            print(\"{bold}{green}Successfully built {}{reset}\".format(built, **_STYLES))\n    except Exception as e:  # pragma: no cover\n        tb = traceback.format_exc().strip(\"\\n\")\n        print(\"\\n{dim}{}{reset}\\n\".format(tb, **_STYLES))\n        _error(str(e))\n        sys.exit(1)\n", "path": "pyodide-build/pyodide_build/pypabuild.py"}], "after_files": [{"content": "import os\nimport shutil\nimport sys\nimport traceback\nfrom collections.abc import Mapping\nfrom itertools import chain\nfrom pathlib import Path\n\nfrom build import BuildBackendException, ConfigSettingsType, ProjectBuilder\nfrom build.__main__ import (\n    _STYLES,\n    _error,\n    _handle_build_error,\n    _IsolatedEnvBuilder,\n    _ProjectBuilder,\n)\nfrom build.env import IsolatedEnv\nfrom packaging.requirements import Requirement\n\nfrom .common import (\n    get_hostsitepackages,\n    get_pyversion,\n    get_unisolated_packages,\n    replace_env,\n)\n\n\ndef symlink_unisolated_packages(env: IsolatedEnv) -> None:\n    pyversion = get_pyversion()\n    site_packages_path = f\"lib/{pyversion}/site-packages\"\n    env_site_packages = Path(env.path) / site_packages_path  # type: ignore[attr-defined]\n    sysconfigdata_name = os.environ[\"SYSCONFIG_NAME\"]\n    sysconfigdata_path = (\n        Path(os.environ[\"TARGETINSTALLDIR\"]) / f\"sysconfigdata/{sysconfigdata_name}.py\"\n    )\n    shutil.copy(sysconfigdata_path, env_site_packages)\n    host_site_packages = Path(get_hostsitepackages())\n    for name in get_unisolated_packages():\n        for path in chain(\n            host_site_packages.glob(f\"{name}*\"), host_site_packages.glob(f\"_{name}*\")\n        ):\n            (env_site_packages / path.name).unlink(missing_ok=True)\n            (env_site_packages / path.name).symlink_to(path)\n\n\ndef remove_unisolated_requirements(requires: set[str]) -> set[str]:\n    for reqstr in list(requires):\n        req = Requirement(reqstr)\n        for avoid_name in get_unisolated_packages():\n            if avoid_name in req.name.lower():\n                requires.remove(reqstr)\n    return requires\n\n\ndef install_reqs(env: IsolatedEnv, reqs: set[str]) -> None:\n    env.install(remove_unisolated_requirements(reqs))\n    # Some packages (numcodecs) don't declare cython as a build dependency and\n    # only recythonize if it is present. We need them to always recythonize so\n    # we always install cython. If the reqs included some cython version already\n    # then this won't do anything.\n    env.install(\n        [\n            \"cython<0.29.31\",  # cython 0.29.31 is incompatible with scipy 1.8.1. TODO: remove this after the scipy update.\n            \"pythran\",\n        ]\n    )\n\n\ndef _build_in_isolated_env(\n    build_env: Mapping[str, str],\n    builder: ProjectBuilder,\n    outdir: str,\n    distribution: str,\n    config_settings: ConfigSettingsType,\n) -> str:\n    # For debugging: The following line disables removal of the isolated venv.\n    # It will be left in the /tmp folder and can be inspected or entered as\n    # needed.\n    # _IsolatedEnvBuilder.__exit__ = lambda *args: None\n    with _IsolatedEnvBuilder() as env:\n        builder.python_executable = env.executable\n        builder.scripts_dir = env.scripts_dir\n        # first install the build dependencies\n        symlink_unisolated_packages(env)\n        install_reqs(env, builder.build_system_requires)\n        installed_requires_for_build = False\n        try:\n            build_reqs = builder.get_requires_for_build(distribution, config_settings)\n        except BuildBackendException:\n            pass\n        else:\n            install_reqs(env, build_reqs)\n            installed_requires_for_build = True\n\n        with replace_env(build_env):\n            if not installed_requires_for_build:\n                install_reqs(\n                    env, builder.get_requires_for_build(distribution, config_settings)\n                )\n            return builder.build(distribution, outdir, config_settings)\n\n\ndef parse_backend_flags(backend_flags: str) -> ConfigSettingsType:\n    config_settings: dict[str, str | list[str]] = {}\n    for arg in backend_flags.split():\n        setting, _, value = arg.partition(\"=\")\n        if setting not in config_settings:\n            config_settings[setting] = value\n            continue\n\n        cur_value = config_settings[setting]\n        if isinstance(cur_value, str):\n            config_settings[setting] = [cur_value, value]\n        else:\n            cur_value.append(value)\n    return config_settings\n\n\ndef build(build_env: Mapping[str, str], backend_flags: str) -> None:\n    srcdir = Path.cwd()\n    outdir = srcdir / \"dist\"\n    builder = _ProjectBuilder(str(srcdir))\n    distribution = \"wheel\"\n    config_settings = parse_backend_flags(backend_flags)\n    try:\n        with _handle_build_error():\n            built = _build_in_isolated_env(\n                build_env, builder, str(outdir), distribution, config_settings\n            )\n            print(\"{bold}{green}Successfully built {}{reset}\".format(built, **_STYLES))\n    except Exception as e:  # pragma: no cover\n        tb = traceback.format_exc().strip(\"\\n\")\n        print(\"\\n{dim}{}{reset}\\n\".format(tb, **_STYLES))\n        _error(str(e))\n        sys.exit(1)\n", "path": "pyodide-build/pyodide_build/pypabuild.py"}]}