Skip to content

Commit

Permalink
Differenctiate ValueErrors
Browse files Browse the repository at this point in the history
ValueErrors are a bit too generic, and by raising/catching them we loose
a potential useful information; For example an invalid content type for
the index, is dealt as the same way than a missing wheel.

This introduces new exceptions for various cases, ant stop catching the
now UnsupportedContentTypeError, as I believe it should be a hard error as
we are likely having either an error with the index software, or a user
configuraition error.

See also beginning of discussion in #142
  • Loading branch information
Carreau committed Oct 18, 2024
1 parent 4044983 commit 86f40d6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
21 changes: 14 additions & 7 deletions micropip/package_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ def _contain_placeholder(url: str, placeholder: str = "package_name") -> bool:
return placeholder in fields


class UnsupportedContentTypeError(Exception):
pass


def _select_parser(content_type: str, pkgname: str) -> Callable[[str], ProjectInfo]:
"""
Select the function to parse the response based on the content type.
Expand All @@ -234,7 +238,13 @@ def _select_parser(content_type: str, pkgname: str) -> Callable[[str], ProjectIn
):
return partial(ProjectInfo.from_simple_html_api, pkgname=pkgname)
case _:
raise ValueError(f"Unsupported content type: {content_type}")
raise UnsupportedContentTypeError(
f"Unsupported content type: {content_type}"
)


class NoValidIndexForPackageError(Exception):
pass


async def query_package(
Expand Down Expand Up @@ -296,14 +306,11 @@ async def query_package(
raise

content_type = headers.get("content-type", "").lower()
try:
parser = _select_parser(content_type, name)
except ValueError as e:
raise ValueError(f"Error trying to decode url: {url}") from e
parser = _select_parser(content_type, name)
return parser(metadata)
else:
raise ValueError(
f"Can't fetch metadata for '{name}'. "
raise NoValidIndexForPackageError(
f"Can't fetch metadata for {name!r}. "
"Please make sure you have entered a correct package name "
"and correctly specified index_urls (if you changed them)."
)
29 changes: 22 additions & 7 deletions micropip/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ._utils import best_compatible_tag_index, check_compatible
from .constants import FAQ_URLS
from .package import PackageMetadata
from .package_index import ProjectInfo
from .package_index import NoValidIndexForPackageError, ProjectInfo
from .wheelinfo import WheelInfo

logger = logging.getLogger("micropip")
Expand Down Expand Up @@ -153,12 +153,23 @@ def eval_marker(e: dict[str, str]) -> bool:
else:
try:
await self._add_requirement_from_package_index(req)
except ValueError:
logger.debug(
"Transaction: package %r not found in index, will search lock file",
except NoValidIndexForPackageError:
logger.warning(
"Transaction: package %r was not found in any index, "
"falling back to pyodide lock file",
req,
)
# This is most likely an error, and it's likely we should
# hard fail here, but the legacy behavior was to ignore
# errors.
if not self._add_requirement_from_pyodide_lock(req):
raise
except NoCompatibleWheelError:
logger.warning(
"Transaction: no compatible wheels for package %r was "
"found falling back to pyodide lock file",
req,
)

# If the requirement is not found in package index,
# we still have a chance to find it from pyodide lockfile.
if not self._add_requirement_from_pyodide_lock(req):
Expand All @@ -167,7 +178,7 @@ def eval_marker(e: dict[str, str]) -> bool:
)

raise
except ValueError:
except (NoCompatibleWheelError, NoValidIndexForPackageError):
self.failed.append(req)
if not self.keep_going:
raise
Expand Down Expand Up @@ -252,6 +263,10 @@ async def add_wheel(
self.wheels.append(wheel)


class NoCompatibleWheelError(Exception):
pass


def find_wheel(metadata: ProjectInfo, req: Requirement) -> WheelInfo:
"""Parse metadata to find the latest version of pure python wheel.
Parameters
Expand Down Expand Up @@ -292,7 +307,7 @@ def find_wheel(metadata: ProjectInfo, req: Requirement) -> WheelInfo:
if best_wheel is not None:
return wheel

raise ValueError(
raise NoCompatibleWheelError(
f"Can't find a pure Python 3 wheel for '{req}'.\n"
f"See: {FAQ_URLS['cant_find_wheel']}\n"
"You can use `await micropip.install(..., keep_going=True)` "
Expand Down

0 comments on commit 86f40d6

Please sign in to comment.