Skip to content

Commit

Permalink
Abort other fetches when resolution fails
Browse files Browse the repository at this point in the history
  • Loading branch information
CNSeniorious000 committed May 26, 2024
1 parent 7ad2963 commit e01491f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
25 changes: 22 additions & 3 deletions micropip/_compat_in_pyodide.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from asyncio import CancelledError
from pathlib import Path
from urllib.parse import urlparse

Expand All @@ -7,7 +8,7 @@

try:
import pyodide_js
from js import Object
from js import AbortController, Object
from pyodide_js import loadedPackages, loadPackage
from pyodide_js._api import ( # type: ignore[import]
loadBinaryFile,
Expand All @@ -21,6 +22,24 @@
raise
# Otherwise, this is pytest test collection so let it go.

if IN_BROWSER:

async def _pyfetch(url: str, **kwargs):
if "signal" in kwargs:
return await pyfetch(url, **kwargs)

controller = AbortController.new()
kwargs["signal"] = controller.signal

try:
return await pyfetch(url, **kwargs)
except CancelledError:
controller.abort()
raise

else:
_pyfetch = pyfetch


async def fetch_bytes(url: str, kwargs: dict[str, str]) -> bytes:
parsed_url = urlparse(url)
Expand All @@ -29,13 +48,13 @@ async def fetch_bytes(url: str, kwargs: dict[str, str]) -> bytes:
if parsed_url.scheme == "file":
return (await loadBinaryFile(parsed_url.path)).to_bytes()

return await (await pyfetch(url, **kwargs)).bytes()
return await (await _pyfetch(url, **kwargs)).bytes()


async def fetch_string_and_headers(
url: str, kwargs: dict[str, str]
) -> tuple[str, dict[str, str]]:
response = await pyfetch(url, **kwargs)
response = await _pyfetch(url, **kwargs)

content = await response.string()
# TODO: replace with response.headers when pyodide>= 0.24 is released
Expand Down
12 changes: 11 additions & 1 deletion micropip/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ async def gather_requirements(
for requirement in requirements:
requirement_promises.append(self.add_requirement(requirement))

await asyncio.gather(*requirement_promises)
futures: list[asyncio.Future] = []
try:
for coro in requirement_promises:
futures.append(asyncio.ensure_future(coro))
await asyncio.gather(*futures)
except ValueError:
if not self.keep_going:
for future in futures:
if not future.done():
future.cancel()
raise

async def add_requirement(self, req: str | Requirement) -> None:
if isinstance(req, Requirement):
Expand Down

0 comments on commit e01491f

Please sign in to comment.