We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`pyodide build -h` should print help text
## 🐛 Bug

`pyodide build -h` treats `-h` as a package name rather than as a request for help text.

--- 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/cli/build.py`
Content:
```
1 import re
2 import shutil
3 import sys
4 import tempfile
5 from pathlib import Path
6 from typing import Optional, cast, get_args
7 from urllib.parse import urlparse
8 
9 import requests
10 import typer
11 from build import ConfigSettingsType
12 
13 from ..build_env import check_emscripten_version, get_pyodide_root, init_environment
14 from ..io import _BuildSpecExports, _ExportTypes
15 from ..logger import logger
16 from ..out_of_tree import build
17 from ..out_of_tree.pypi import (
18     build_dependencies_for_wheel,
19     build_wheels_from_pypi_requirements,
20     fetch_pypi_package,
21 )
22 from ..pypabuild import parse_backend_flags
23 
24 
25 def convert_exports(exports: str) -> _BuildSpecExports:
26     if "," in exports:
27         return [x.strip() for x in exports.split(",") if x.strip()]
28     possible_exports = get_args(_ExportTypes)
29     if exports in possible_exports:
30         return cast(_ExportTypes, exports)
31     logger.stderr(
32         f"Expected exports to be one of "
33         '"pyinit", "requested", "whole_archive", '
34         "or a comma separated list of symbols to export. "
35         f'Got "{exports}".'
36     )
37     sys.exit(1)
38 
39 
40 def pypi(
41     package: str,
42     output_directory: Path,
43     exports: str,
44     config_settings: ConfigSettingsType,
45 ) -> Path:
46     """Fetch a wheel from pypi, or build from source if none available."""
47     with tempfile.TemporaryDirectory() as tmpdir:
48         srcdir = Path(tmpdir)
49 
50         # get package from pypi
51         package_path = fetch_pypi_package(package, srcdir)
52         if not package_path.is_dir():
53             # a pure-python wheel has been downloaded - just copy to dist folder
54             dest_file = output_directory / package_path.name
55             shutil.copyfile(str(package_path), output_directory / package_path.name)
56             print(f"Successfully fetched: {package_path.name}")
57             return dest_file
58 
59         built_wheel = build.run(
60             srcdir,
61             output_directory,
62             convert_exports(exports),
63             config_settings,
64         )
65         return built_wheel
66 
67 
68 def download_url(url: str, output_directory: Path) -> str:
69     with requests.get(url, stream=True) as response:
70         urlpath = Path(urlparse(response.url).path)
71         if urlpath.suffix == ".gz":
72             urlpath = urlpath.with_suffix("")
73         file_name = urlpath.name
74         with open(output_directory / file_name, "wb") as f:
75             for chunk in response.iter_content(chunk_size=1 << 20):
76                 f.write(chunk)
77         return file_name
78 
79 
80 def url(
81     package_url: str,
82     output_directory: Path,
83     exports: str,
84     config_settings: ConfigSettingsType,
85 ) -> Path:
86     """Fetch a wheel or build sdist from url."""
87     with tempfile.TemporaryDirectory() as tmpdir:
88         tmppath = Path(tmpdir)
89         filename = download_url(package_url, tmppath)
90         if Path(filename).suffix == ".whl":
91             shutil.move(tmppath / filename, output_directory / filename)
92             return output_directory / filename
93 
94         builddir = tmppath / "build"
95         shutil.unpack_archive(tmppath / filename, builddir)
96         files = list(builddir.iterdir())
97         if len(files) == 1 and files[0].is_dir():
98             # unzipped into subfolder
99             builddir = files[0]
100         wheel_path = build.run(
101             builddir, output_directory, convert_exports(exports), config_settings
102         )
103         return wheel_path
104 
105 
106 def source(
107     source_location: Path,
108     output_directory: Path,
109     exports: str,
110     config_settings: ConfigSettingsType,
111 ) -> Path:
112     """Use pypa/build to build a Python package from source"""
113     built_wheel = build.run(
114         source_location, output_directory, convert_exports(exports), config_settings
115     )
116     return built_wheel
117 
118 
119 # simple 'pyodide build' command
120 def main(
121     source_location: Optional[str] = typer.Argument(  # noqa: UP007 typer does not accept list[str] | None yet.
122         "",
123         help="Build source, can be source folder, pypi version specification, "
124         "or url to a source dist archive or wheel file. If this is blank, it "
125         "will build the current directory.",
126     ),
127     output_directory: str = typer.Option(
128         "",
129         "--outdir",
130         "-o",
131         help="which directory should the output be placed into?",
132     ),
133     requirements_txt: str = typer.Option(
134         "",
135         "--requirements",
136         "-r",
137         help="Build a list of package requirements from a requirements.txt file",
138     ),
139     exports: str = typer.Option(
140         "requested",
141         envvar="PYODIDE_BUILD_EXPORTS",
142         help="Which symbols should be exported when linking .so files?",
143     ),
144     build_dependencies: bool = typer.Option(
145         False, help="Fetch dependencies from pypi and build them too."
146     ),
147     output_lockfile: str = typer.Option(
148         "",
149         help="Output list of resolved dependencies to a file in requirements.txt format",
150     ),
151     skip_dependency: list[str] = typer.Option(
152         [],
153         help="Skip building or resolving a single dependency, or a pyodide-lock.json file. "
154         "Use multiple times or provide a comma separated list to skip multiple dependencies.",
155     ),
156     skip_built_in_packages: bool = typer.Option(
157         True,
158         help="Don't build dependencies that are built into the pyodide distribution.",
159     ),
160     compression_level: int = typer.Option(
161         6, help="Compression level to use for the created zip file"
162     ),
163     config_setting: Optional[list[str]] = typer.Option(  # noqa: UP007 typer does not accept list[str] | None yet.
164         None,
165         "--config-setting",
166         "-C",
167         help=(
168             "Settings to pass to the backend. "
169             "Works same as the --config-setting option of pypa/build."
170         ),
171         metavar="KEY[=VALUE]",
172     ),
173     ctx: typer.Context = typer.Context,  # type: ignore[assignment]
174 ) -> None:
175     """Use pypa/build to build a Python package from source, pypi or url."""
176     init_environment()
177     try:
178         check_emscripten_version()
179     except RuntimeError as e:
180         print(e.args[0], file=sys.stderr)
181         sys.exit(1)
182 
183     output_directory = output_directory or "./dist"
184 
185     outpath = Path(output_directory).resolve()
186     outpath.mkdir(exist_ok=True)
187     extras: list[str] = []
188 
189     # For backward compatibility, in addition to the `--config-setting` arguments, we also support
190     # passing config settings as positional arguments.
191     config_settings = parse_backend_flags((config_setting or []) + ctx.args)
192 
193     if skip_built_in_packages:
194         package_lock_json = get_pyodide_root() / "dist" / "pyodide-lock.json"
195         skip_dependency.append(str(package_lock_json.absolute()))
196 
197     if len(requirements_txt) > 0:
198         # a requirements.txt - build it (and optionally deps)
199         if not Path(requirements_txt).exists():
200             raise RuntimeError(
201                 f"Couldn't find requirements text file {requirements_txt}"
202             )
203         reqs = []
204         with open(requirements_txt) as f:
205             raw_reqs = [x.strip() for x in f.readlines()]
206         for x in raw_reqs:
207             # remove comments
208             comment_pos = x.find("#")
209             if comment_pos != -1:
210                 x = x[:comment_pos].strip()
211             if len(x) > 0:
212                 if x[0] == "-":
213                     raise RuntimeError(
214                         f"pyodide build only supports name-based PEP508 requirements. [{x}] will not work."
215                     )
216                 if x.find("@") != -1:
217                     raise RuntimeError(
218                         f"pyodide build does not support URL based requirements. [{x}] will not work"
219                     )
220                 reqs.append(x)
221         try:
222             build_wheels_from_pypi_requirements(
223                 reqs,
224                 outpath,
225                 build_dependencies,
226                 skip_dependency,
227                 # TODO: should we really use same "exports" value for all of our
228                 # dependencies? Not sure this makes sense...
229                 convert_exports(exports),
230                 config_settings,
231                 output_lockfile=output_lockfile,
232             )
233         except BaseException as e:
234             import traceback
235 
236             print("Failed building multiple wheels:", traceback.format_exc())
237             raise e
238         return
239 
240     if source_location is not None:
241         extras = re.findall(r"\[(\w+)\]", source_location)
242         if len(extras) != 0:
243             source_location = source_location[0 : source_location.find("[")]
244     if not source_location:
245         # build the current folder
246         wheel = source(Path.cwd(), outpath, exports, config_settings)
247     elif source_location.find("://") != -1:
248         wheel = url(source_location, outpath, exports, config_settings)
249     elif Path(source_location).is_dir():
250         # a folder, build it
251         wheel = source(
252             Path(source_location).resolve(), outpath, exports, config_settings
253         )
254     elif source_location.find("/") == -1:
255         # try fetch or build from pypi
256         wheel = pypi(source_location, outpath, exports, config_settings)
257     else:
258         raise RuntimeError(f"Couldn't determine source type for {source_location}")
259     # now build deps for wheel
260     if build_dependencies:
261         try:
262             build_dependencies_for_wheel(
263                 wheel,
264                 extras,
265                 skip_dependency,
266                 # TODO: should we really use same "exports" value for all of our
267                 # dependencies? Not sure this makes sense...
268                 convert_exports(exports),
269                 config_settings,
270                 output_lockfile=output_lockfile,
271                 compression_level=compression_level,
272             )
273         except BaseException as e:
274             import traceback
275 
276             print("Failed building dependencies for wheel:", traceback.format_exc())
277             wheel.unlink()
278             raise e
279 
280 
281 main.typer_kwargs = {  # type: ignore[attr-defined]
282     "context_settings": {
283         "ignore_unknown_options": True,
284         "allow_extra_args": True,
285     },
286 }
287
```
--- 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/cli/build.py b/pyodide-build/pyodide_build/cli/build.py
--- a/pyodide-build/pyodide_build/cli/build.py
+++ b/pyodide-build/pyodide_build/cli/build.py
@@ -282,5 +282,6 @@
     "context_settings": {
         "ignore_unknown_options": True,
         "allow_extra_args": True,
+        "help_option_names": ["-h", "--help"],
     },
 }

{"golden_diff": "diff --git a/pyodide-build/pyodide_build/cli/build.py b/pyodide-build/pyodide_build/cli/build.py\n--- a/pyodide-build/pyodide_build/cli/build.py\n+++ b/pyodide-build/pyodide_build/cli/build.py\n@@ -282,5 +282,6 @@\n     \"context_settings\": {\n         \"ignore_unknown_options\": True,\n         \"allow_extra_args\": True,\n+        \"help_option_names\": [\"-h\", \"--help\"],\n     },\n }\n", "issue": "`pyodide build -h` should print help text\n## \ud83d\udc1b Bug\r\n\r\n`pyodide build -h` treats `-h` as a package name rather than as a request for help text.\n", "before_files": [{"content": "import re\nimport shutil\nimport sys\nimport tempfile\nfrom pathlib import Path\nfrom typing import Optional, cast, get_args\nfrom urllib.parse import urlparse\n\nimport requests\nimport typer\nfrom build import ConfigSettingsType\n\nfrom ..build_env import check_emscripten_version, get_pyodide_root, init_environment\nfrom ..io import _BuildSpecExports, _ExportTypes\nfrom ..logger import logger\nfrom ..out_of_tree import build\nfrom ..out_of_tree.pypi import (\n    build_dependencies_for_wheel,\n    build_wheels_from_pypi_requirements,\n    fetch_pypi_package,\n)\nfrom ..pypabuild import parse_backend_flags\n\n\ndef convert_exports(exports: str) -> _BuildSpecExports:\n    if \",\" in exports:\n        return [x.strip() for x in exports.split(\",\") if x.strip()]\n    possible_exports = get_args(_ExportTypes)\n    if exports in possible_exports:\n        return cast(_ExportTypes, exports)\n    logger.stderr(\n        f\"Expected exports to be one of \"\n        '\"pyinit\", \"requested\", \"whole_archive\", '\n        \"or a comma separated list of symbols to export. \"\n        f'Got \"{exports}\".'\n    )\n    sys.exit(1)\n\n\ndef pypi(\n    package: str,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Fetch a wheel from pypi, or build from source if none available.\"\"\"\n    with tempfile.TemporaryDirectory() as tmpdir:\n        srcdir = Path(tmpdir)\n\n        # get package from pypi\n        package_path = fetch_pypi_package(package, srcdir)\n        if not package_path.is_dir():\n            # a pure-python wheel has been downloaded - just copy to dist folder\n            dest_file = output_directory / package_path.name\n            shutil.copyfile(str(package_path), output_directory / package_path.name)\n            print(f\"Successfully fetched: {package_path.name}\")\n            return dest_file\n\n        built_wheel = build.run(\n            srcdir,\n            output_directory,\n            convert_exports(exports),\n            config_settings,\n        )\n        return built_wheel\n\n\ndef download_url(url: str, output_directory: Path) -> str:\n    with requests.get(url, stream=True) as response:\n        urlpath = Path(urlparse(response.url).path)\n        if urlpath.suffix == \".gz\":\n            urlpath = urlpath.with_suffix(\"\")\n        file_name = urlpath.name\n        with open(output_directory / file_name, \"wb\") as f:\n            for chunk in response.iter_content(chunk_size=1 << 20):\n                f.write(chunk)\n        return file_name\n\n\ndef url(\n    package_url: str,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Fetch a wheel or build sdist from url.\"\"\"\n    with tempfile.TemporaryDirectory() as tmpdir:\n        tmppath = Path(tmpdir)\n        filename = download_url(package_url, tmppath)\n        if Path(filename).suffix == \".whl\":\n            shutil.move(tmppath / filename, output_directory / filename)\n            return output_directory / filename\n\n        builddir = tmppath / \"build\"\n        shutil.unpack_archive(tmppath / filename, builddir)\n        files = list(builddir.iterdir())\n        if len(files) == 1 and files[0].is_dir():\n            # unzipped into subfolder\n            builddir = files[0]\n        wheel_path = build.run(\n            builddir, output_directory, convert_exports(exports), config_settings\n        )\n        return wheel_path\n\n\ndef source(\n    source_location: Path,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Use pypa/build to build a Python package from source\"\"\"\n    built_wheel = build.run(\n        source_location, output_directory, convert_exports(exports), config_settings\n    )\n    return built_wheel\n\n\n# simple 'pyodide build' command\ndef main(\n    source_location: Optional[str] = typer.Argument(  # noqa: UP007 typer does not accept list[str] | None yet.\n        \"\",\n        help=\"Build source, can be source folder, pypi version specification, \"\n        \"or url to a source dist archive or wheel file. If this is blank, it \"\n        \"will build the current directory.\",\n    ),\n    output_directory: str = typer.Option(\n        \"\",\n        \"--outdir\",\n        \"-o\",\n        help=\"which directory should the output be placed into?\",\n    ),\n    requirements_txt: str = typer.Option(\n        \"\",\n        \"--requirements\",\n        \"-r\",\n        help=\"Build a list of package requirements from a requirements.txt file\",\n    ),\n    exports: str = typer.Option(\n        \"requested\",\n        envvar=\"PYODIDE_BUILD_EXPORTS\",\n        help=\"Which symbols should be exported when linking .so files?\",\n    ),\n    build_dependencies: bool = typer.Option(\n        False, help=\"Fetch dependencies from pypi and build them too.\"\n    ),\n    output_lockfile: str = typer.Option(\n        \"\",\n        help=\"Output list of resolved dependencies to a file in requirements.txt format\",\n    ),\n    skip_dependency: list[str] = typer.Option(\n        [],\n        help=\"Skip building or resolving a single dependency, or a pyodide-lock.json file. \"\n        \"Use multiple times or provide a comma separated list to skip multiple dependencies.\",\n    ),\n    skip_built_in_packages: bool = typer.Option(\n        True,\n        help=\"Don't build dependencies that are built into the pyodide distribution.\",\n    ),\n    compression_level: int = typer.Option(\n        6, help=\"Compression level to use for the created zip file\"\n    ),\n    config_setting: Optional[list[str]] = typer.Option(  # noqa: UP007 typer does not accept list[str] | None yet.\n        None,\n        \"--config-setting\",\n        \"-C\",\n        help=(\n            \"Settings to pass to the backend. \"\n            \"Works same as the --config-setting option of pypa/build.\"\n        ),\n        metavar=\"KEY[=VALUE]\",\n    ),\n    ctx: typer.Context = typer.Context,  # type: ignore[assignment]\n) -> None:\n    \"\"\"Use pypa/build to build a Python package from source, pypi or url.\"\"\"\n    init_environment()\n    try:\n        check_emscripten_version()\n    except RuntimeError as e:\n        print(e.args[0], file=sys.stderr)\n        sys.exit(1)\n\n    output_directory = output_directory or \"./dist\"\n\n    outpath = Path(output_directory).resolve()\n    outpath.mkdir(exist_ok=True)\n    extras: list[str] = []\n\n    # For backward compatibility, in addition to the `--config-setting` arguments, we also support\n    # passing config settings as positional arguments.\n    config_settings = parse_backend_flags((config_setting or []) + ctx.args)\n\n    if skip_built_in_packages:\n        package_lock_json = get_pyodide_root() / \"dist\" / \"pyodide-lock.json\"\n        skip_dependency.append(str(package_lock_json.absolute()))\n\n    if len(requirements_txt) > 0:\n        # a requirements.txt - build it (and optionally deps)\n        if not Path(requirements_txt).exists():\n            raise RuntimeError(\n                f\"Couldn't find requirements text file {requirements_txt}\"\n            )\n        reqs = []\n        with open(requirements_txt) as f:\n            raw_reqs = [x.strip() for x in f.readlines()]\n        for x in raw_reqs:\n            # remove comments\n            comment_pos = x.find(\"#\")\n            if comment_pos != -1:\n                x = x[:comment_pos].strip()\n            if len(x) > 0:\n                if x[0] == \"-\":\n                    raise RuntimeError(\n                        f\"pyodide build only supports name-based PEP508 requirements. [{x}] will not work.\"\n                    )\n                if x.find(\"@\") != -1:\n                    raise RuntimeError(\n                        f\"pyodide build does not support URL based requirements. [{x}] will not work\"\n                    )\n                reqs.append(x)\n        try:\n            build_wheels_from_pypi_requirements(\n                reqs,\n                outpath,\n                build_dependencies,\n                skip_dependency,\n                # TODO: should we really use same \"exports\" value for all of our\n                # dependencies? Not sure this makes sense...\n                convert_exports(exports),\n                config_settings,\n                output_lockfile=output_lockfile,\n            )\n        except BaseException as e:\n            import traceback\n\n            print(\"Failed building multiple wheels:\", traceback.format_exc())\n            raise e\n        return\n\n    if source_location is not None:\n        extras = re.findall(r\"\\[(\\w+)\\]\", source_location)\n        if len(extras) != 0:\n            source_location = source_location[0 : source_location.find(\"[\")]\n    if not source_location:\n        # build the current folder\n        wheel = source(Path.cwd(), outpath, exports, config_settings)\n    elif source_location.find(\"://\") != -1:\n        wheel = url(source_location, outpath, exports, config_settings)\n    elif Path(source_location).is_dir():\n        # a folder, build it\n        wheel = source(\n            Path(source_location).resolve(), outpath, exports, config_settings\n        )\n    elif source_location.find(\"/\") == -1:\n        # try fetch or build from pypi\n        wheel = pypi(source_location, outpath, exports, config_settings)\n    else:\n        raise RuntimeError(f\"Couldn't determine source type for {source_location}\")\n    # now build deps for wheel\n    if build_dependencies:\n        try:\n            build_dependencies_for_wheel(\n                wheel,\n                extras,\n                skip_dependency,\n                # TODO: should we really use same \"exports\" value for all of our\n                # dependencies? Not sure this makes sense...\n                convert_exports(exports),\n                config_settings,\n                output_lockfile=output_lockfile,\n                compression_level=compression_level,\n            )\n        except BaseException as e:\n            import traceback\n\n            print(\"Failed building dependencies for wheel:\", traceback.format_exc())\n            wheel.unlink()\n            raise e\n\n\nmain.typer_kwargs = {  # type: ignore[attr-defined]\n    \"context_settings\": {\n        \"ignore_unknown_options\": True,\n        \"allow_extra_args\": True,\n    },\n}\n", "path": "pyodide-build/pyodide_build/cli/build.py"}], "after_files": [{"content": "import re\nimport shutil\nimport sys\nimport tempfile\nfrom pathlib import Path\nfrom typing import Optional, cast, get_args\nfrom urllib.parse import urlparse\n\nimport requests\nimport typer\nfrom build import ConfigSettingsType\n\nfrom ..build_env import check_emscripten_version, get_pyodide_root, init_environment\nfrom ..io import _BuildSpecExports, _ExportTypes\nfrom ..logger import logger\nfrom ..out_of_tree import build\nfrom ..out_of_tree.pypi import (\n    build_dependencies_for_wheel,\n    build_wheels_from_pypi_requirements,\n    fetch_pypi_package,\n)\nfrom ..pypabuild import parse_backend_flags\n\n\ndef convert_exports(exports: str) -> _BuildSpecExports:\n    if \",\" in exports:\n        return [x.strip() for x in exports.split(\",\") if x.strip()]\n    possible_exports = get_args(_ExportTypes)\n    if exports in possible_exports:\n        return cast(_ExportTypes, exports)\n    logger.stderr(\n        f\"Expected exports to be one of \"\n        '\"pyinit\", \"requested\", \"whole_archive\", '\n        \"or a comma separated list of symbols to export. \"\n        f'Got \"{exports}\".'\n    )\n    sys.exit(1)\n\n\ndef pypi(\n    package: str,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Fetch a wheel from pypi, or build from source if none available.\"\"\"\n    with tempfile.TemporaryDirectory() as tmpdir:\n        srcdir = Path(tmpdir)\n\n        # get package from pypi\n        package_path = fetch_pypi_package(package, srcdir)\n        if not package_path.is_dir():\n            # a pure-python wheel has been downloaded - just copy to dist folder\n            dest_file = output_directory / package_path.name\n            shutil.copyfile(str(package_path), output_directory / package_path.name)\n            print(f\"Successfully fetched: {package_path.name}\")\n            return dest_file\n\n        built_wheel = build.run(\n            srcdir,\n            output_directory,\n            convert_exports(exports),\n            config_settings,\n        )\n        return built_wheel\n\n\ndef download_url(url: str, output_directory: Path) -> str:\n    with requests.get(url, stream=True) as response:\n        urlpath = Path(urlparse(response.url).path)\n        if urlpath.suffix == \".gz\":\n            urlpath = urlpath.with_suffix(\"\")\n        file_name = urlpath.name\n        with open(output_directory / file_name, \"wb\") as f:\n            for chunk in response.iter_content(chunk_size=1 << 20):\n                f.write(chunk)\n        return file_name\n\n\ndef url(\n    package_url: str,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Fetch a wheel or build sdist from url.\"\"\"\n    with tempfile.TemporaryDirectory() as tmpdir:\n        tmppath = Path(tmpdir)\n        filename = download_url(package_url, tmppath)\n        if Path(filename).suffix == \".whl\":\n            shutil.move(tmppath / filename, output_directory / filename)\n            return output_directory / filename\n\n        builddir = tmppath / \"build\"\n        shutil.unpack_archive(tmppath / filename, builddir)\n        files = list(builddir.iterdir())\n        if len(files) == 1 and files[0].is_dir():\n            # unzipped into subfolder\n            builddir = files[0]\n        wheel_path = build.run(\n            builddir, output_directory, convert_exports(exports), config_settings\n        )\n        return wheel_path\n\n\ndef source(\n    source_location: Path,\n    output_directory: Path,\n    exports: str,\n    config_settings: ConfigSettingsType,\n) -> Path:\n    \"\"\"Use pypa/build to build a Python package from source\"\"\"\n    built_wheel = build.run(\n        source_location, output_directory, convert_exports(exports), config_settings\n    )\n    return built_wheel\n\n\n# simple 'pyodide build' command\ndef main(\n    source_location: Optional[str] = typer.Argument(  # noqa: UP007 typer does not accept list[str] | None yet.\n        \"\",\n        help=\"Build source, can be source folder, pypi version specification, \"\n        \"or url to a source dist archive or wheel file. If this is blank, it \"\n        \"will build the current directory.\",\n    ),\n    output_directory: str = typer.Option(\n        \"\",\n        \"--outdir\",\n        \"-o\",\n        help=\"which directory should the output be placed into?\",\n    ),\n    requirements_txt: str = typer.Option(\n        \"\",\n        \"--requirements\",\n        \"-r\",\n        help=\"Build a list of package requirements from a requirements.txt file\",\n    ),\n    exports: str = typer.Option(\n        \"requested\",\n        envvar=\"PYODIDE_BUILD_EXPORTS\",\n        help=\"Which symbols should be exported when linking .so files?\",\n    ),\n    build_dependencies: bool = typer.Option(\n        False, help=\"Fetch dependencies from pypi and build them too.\"\n    ),\n    output_lockfile: str = typer.Option(\n        \"\",\n        help=\"Output list of resolved dependencies to a file in requirements.txt format\",\n    ),\n    skip_dependency: list[str] = typer.Option(\n        [],\n        help=\"Skip building or resolving a single dependency, or a pyodide-lock.json file. \"\n        \"Use multiple times or provide a comma separated list to skip multiple dependencies.\",\n    ),\n    skip_built_in_packages: bool = typer.Option(\n        True,\n        help=\"Don't build dependencies that are built into the pyodide distribution.\",\n    ),\n    compression_level: int = typer.Option(\n        6, help=\"Compression level to use for the created zip file\"\n    ),\n    config_setting: Optional[list[str]] = typer.Option(  # noqa: UP007 typer does not accept list[str] | None yet.\n        None,\n        \"--config-setting\",\n        \"-C\",\n        help=(\n            \"Settings to pass to the backend. \"\n            \"Works same as the --config-setting option of pypa/build.\"\n        ),\n        metavar=\"KEY[=VALUE]\",\n    ),\n    ctx: typer.Context = typer.Context,  # type: ignore[assignment]\n) -> None:\n    \"\"\"Use pypa/build to build a Python package from source, pypi or url.\"\"\"\n    init_environment()\n    try:\n        check_emscripten_version()\n    except RuntimeError as e:\n        print(e.args[0], file=sys.stderr)\n        sys.exit(1)\n\n    output_directory = output_directory or \"./dist\"\n\n    outpath = Path(output_directory).resolve()\n    outpath.mkdir(exist_ok=True)\n    extras: list[str] = []\n\n    # For backward compatibility, in addition to the `--config-setting` arguments, we also support\n    # passing config settings as positional arguments.\n    config_settings = parse_backend_flags((config_setting or []) + ctx.args)\n\n    if skip_built_in_packages:\n        package_lock_json = get_pyodide_root() / \"dist\" / \"pyodide-lock.json\"\n        skip_dependency.append(str(package_lock_json.absolute()))\n\n    if len(requirements_txt) > 0:\n        # a requirements.txt - build it (and optionally deps)\n        if not Path(requirements_txt).exists():\n            raise RuntimeError(\n                f\"Couldn't find requirements text file {requirements_txt}\"\n            )\n        reqs = []\n        with open(requirements_txt) as f:\n            raw_reqs = [x.strip() for x in f.readlines()]\n        for x in raw_reqs:\n            # remove comments\n            comment_pos = x.find(\"#\")\n            if comment_pos != -1:\n                x = x[:comment_pos].strip()\n            if len(x) > 0:\n                if x[0] == \"-\":\n                    raise RuntimeError(\n                        f\"pyodide build only supports name-based PEP508 requirements. [{x}] will not work.\"\n                    )\n                if x.find(\"@\") != -1:\n                    raise RuntimeError(\n                        f\"pyodide build does not support URL based requirements. [{x}] will not work\"\n                    )\n                reqs.append(x)\n        try:\n            build_wheels_from_pypi_requirements(\n                reqs,\n                outpath,\n                build_dependencies,\n                skip_dependency,\n                # TODO: should we really use same \"exports\" value for all of our\n                # dependencies? Not sure this makes sense...\n                convert_exports(exports),\n                config_settings,\n                output_lockfile=output_lockfile,\n            )\n        except BaseException as e:\n            import traceback\n\n            print(\"Failed building multiple wheels:\", traceback.format_exc())\n            raise e\n        return\n\n    if source_location is not None:\n        extras = re.findall(r\"\\[(\\w+)\\]\", source_location)\n        if len(extras) != 0:\n            source_location = source_location[0 : source_location.find(\"[\")]\n    if not source_location:\n        # build the current folder\n        wheel = source(Path.cwd(), outpath, exports, config_settings)\n    elif source_location.find(\"://\") != -1:\n        wheel = url(source_location, outpath, exports, config_settings)\n    elif Path(source_location).is_dir():\n        # a folder, build it\n        wheel = source(\n            Path(source_location).resolve(), outpath, exports, config_settings\n        )\n    elif source_location.find(\"/\") == -1:\n        # try fetch or build from pypi\n        wheel = pypi(source_location, outpath, exports, config_settings)\n    else:\n        raise RuntimeError(f\"Couldn't determine source type for {source_location}\")\n    # now build deps for wheel\n    if build_dependencies:\n        try:\n            build_dependencies_for_wheel(\n                wheel,\n                extras,\n                skip_dependency,\n                # TODO: should we really use same \"exports\" value for all of our\n                # dependencies? Not sure this makes sense...\n                convert_exports(exports),\n                config_settings,\n                output_lockfile=output_lockfile,\n                compression_level=compression_level,\n            )\n        except BaseException as e:\n            import traceback\n\n            print(\"Failed building dependencies for wheel:\", traceback.format_exc())\n            wheel.unlink()\n            raise e\n\n\nmain.typer_kwargs = {  # type: ignore[attr-defined]\n    \"context_settings\": {\n        \"ignore_unknown_options\": True,\n        \"allow_extra_args\": True,\n        \"help_option_names\": [\"-h\", \"--help\"],\n    },\n}\n", "path": "pyodide-build/pyodide_build/cli/build.py"}]}