From 8c8b21dc5438591bbb19882864342d58ae96590c Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Mon, 1 Sep 2025 15:13:35 +0200 Subject: [PATCH 1/2] Allow packages through from which we can't get the metadata Example: openpyxl/0.0rc0 (or openpyxl-1.1.0-py2.6.egg) --- simple_repository_browser/fetch_description.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/simple_repository_browser/fetch_description.py b/simple_repository_browser/fetch_description.py index 15e984d..061c8d7 100644 --- a/simple_repository_browser/fetch_description.py +++ b/simple_repository_browser/fetch_description.py @@ -160,10 +160,20 @@ async def _fetch_metadata_resource( tmp_file_path: str, ) -> tuple[model.File, pkginfo.Distribution]: """Fetch metadata resource and return updated file and package info.""" - if file.dist_info_metadata: - resource_name = file.filename + ".metadata" - else: - raise ValueError(f"Metadata not available for {file}") + if not file.dist_info_metadata: + # No metadata available for this file type (e.g., .egg files) + # Return a minimal distribution object with basic info + class MinimalDistribution(pkginfo.Distribution): + def __init__(self, name: str, filename: str): + super().__init__() # Get all the default None values + self.name = name + ext = filename.split(".")[-1] if "." in filename else "unknown" + self.summary = f"Legacy package format ({ext}) - metadata not available" + + minimal_dist = MinimalDistribution(project_name, file.filename) + return file, minimal_dist + + resource_name = file.filename + ".metadata" logging.debug(f"Downloading metadata for {file.filename} from {resource_name}") From 65a9b8c93cf2b0c1e2ba1660be9771a1f5c6942f Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Mon, 1 Sep 2025 16:01:26 +0200 Subject: [PATCH 2/2] Allow packages through which cause metadata injector to raise (e.g. /browse/project/distance/0.1.3/files) --- .../fetch_description.py | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/simple_repository_browser/fetch_description.py b/simple_repository_browser/fetch_description.py index 061c8d7..cd82def 100644 --- a/simple_repository_browser/fetch_description.py +++ b/simple_repository_browser/fetch_description.py @@ -15,7 +15,9 @@ import readme_renderer.markdown import readme_renderer.rst import readme_renderer.txt +import simple_repository from simple_repository import SimpleRepository, model +import simple_repository.errors @dataclasses.dataclass @@ -153,6 +155,13 @@ def _create_files_info_mapping( return files_info +class MinimalDistribution(pkginfo.Distribution): + def __init__(self, name: str, summary: str): + super().__init__() # Get all the default None values + self.name = name + self.summary = summary + + async def _fetch_metadata_resource( repository: SimpleRepository, project_name: str, @@ -163,21 +172,22 @@ async def _fetch_metadata_resource( if not file.dist_info_metadata: # No metadata available for this file type (e.g., .egg files) # Return a minimal distribution object with basic info - class MinimalDistribution(pkginfo.Distribution): - def __init__(self, name: str, filename: str): - super().__init__() # Get all the default None values - self.name = name - ext = filename.split(".")[-1] if "." in filename else "unknown" - self.summary = f"Legacy package format ({ext}) - metadata not available" - - minimal_dist = MinimalDistribution(project_name, file.filename) + ext = file.filename.rsplit(".", 1)[-1] + reason = f"Legacy package format ({ext}) - metadata not available" + minimal_dist = MinimalDistribution(project_name, summary=reason) return file, minimal_dist resource_name = file.filename + ".metadata" logging.debug(f"Downloading metadata for {file.filename} from {resource_name}") - resource = await repository.get_resource(project_name, resource_name) + try: + resource = await repository.get_resource(project_name, resource_name) + except simple_repository.errors.ResourceUnavailable as err: + reason = f"Unable to retrieve metadata for {file.filename} ({err})" + minimal_dist = MinimalDistribution(project_name, summary=reason) + logging.exception(reason) + return file, minimal_dist if isinstance(resource, model.TextResource): with open(tmp_file_path, "wb") as tmp: