Skip to content

Commit 88ceb63

Browse files
committed
stronger fix of wheelhouse report
1 parent 2e7f790 commit 88ceb63

File tree

3 files changed

+60
-14
lines changed

3 files changed

+60
-14
lines changed

winpython/piptree.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from pip._vendor.packaging.markers import Marker
1818
from importlib.metadata import Distribution, distributions
1919
from pathlib import Path
20+
from winpython import utils
2021

2122
logging.basicConfig(level=logging.INFO)
2223
logger = logging.getLogger(__name__)
@@ -25,15 +26,6 @@ class PipDataError(Exception):
2526
"""Custom exception for PipData related errors."""
2627
pass
2728

28-
def sum_up(text: str, max_length: int = 144, stop_at: str = ". ") -> str:
29-
"""Summarize text to fit within max_length, ending at last complete sentence."""
30-
summary = (text + os.linesep).splitlines()[0]
31-
if len(summary) <= max_length:
32-
return summary
33-
if stop_at and stop_at in summary[:max_length]:
34-
return summary[:summary.rfind(stop_at, 0, max_length)] + stop_at.rstrip()
35-
return summary[:max_length].rstrip()
36-
3729
class PipData:
3830
"""Manages package metadata and dependency relationships in a Python environment."""
3931

@@ -287,5 +279,5 @@ def pip_list(self, full: bool = False, max_length: int = 144) -> List[Tuple[str,
287279
"""
288280
pkgs = sorted(self.distro.items())
289281
if full:
290-
return [(p, d["version"], sum_up(d["summary"], max_length)) for p, d in pkgs]
282+
return [(p, d["version"], utils.sum_up(d["summary"], max_length)) for p, d in pkgs]
291283
return [(p, d["version"]) for p, d in pkgs]

winpython/wheelhouse.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22
"""
33
WheelHouse.py - manage WinPython local WheelHouse.
44
"""
5-
5+
import os
6+
import re
7+
import tarfile
8+
import zipfile
69
import sys
710
from pathlib import Path
811
from collections import defaultdict
912
import shutil
1013
import subprocess
1114
from typing import Dict, List, Optional, Tuple
15+
from email import message_from_bytes
16+
from . import utils
17+
18+
from packaging.utils import canonicalize_name
1219

1320
# Use tomllib if available (Python 3.11+), otherwise fall back to tomli
1421
try:
@@ -183,6 +190,53 @@ def get_pylock_wheels(wheelhouse: Path, lockfile: Path, wheelorigin: Optional[Pa
183190
else:
184191
print(f"\n\n*** We can't install {filename} ! ***\n\n")
185192

193+
def extract_metadata_from_wheel(filepath: Path) -> Optional[Tuple[str, str, str]]:
194+
"get metadata from a wheel package"
195+
with zipfile.ZipFile(filepath, 'r') as z:
196+
# Locate *.dist-info/METADATA file inside but not in a vendored directory (flit-core)
197+
for name in z.namelist():
198+
if name.endswith(r'.dist-info/METADATA') and name.split("/")[1] == "METADATA":
199+
with z.open(name) as meta_file:
200+
metadata = message_from_bytes(meta_file.read())
201+
name = canonicalize_name(str(metadata.get('Name', 'unknown'))) # Avoid Head type
202+
version = str(metadata.get('Version', 'unknown'))
203+
summary = utils.sum_up(str(metadata.get('Summary', '')))
204+
return name, version, summary
205+
return None
206+
207+
def extract_metadata_from_sdist(filepath: Path) -> Optional[Tuple[str, str, str]]:
208+
"get metadata from a tar.gz or .zip package"
209+
open_func = tarfile.open if filepath.suffixes[-2:] == ['.tar', '.gz'] else zipfile.ZipFile
210+
with open_func(filepath, 'r') as archive:
211+
namelist = archive.getnames() if isinstance(archive, tarfile.TarFile) else archive.namelist()
212+
for name in namelist:
213+
if name.endswith('PKG-INFO'):
214+
content = archive.extractfile(name).read() if isinstance(archive, tarfile.TarFile) else archive.open(name).read()
215+
metadata = message_from_bytes(content)
216+
name = canonicalize_name(str(metadata.get('Name', 'unknown'))) # Avoid Head type
217+
version = str(metadata.get('Version', 'unknown'))
218+
summary = utils.sum_up(str(metadata.get('Summary', '')))
219+
return name, version, summary
220+
return None
221+
222+
def list_packages_with_metadata(directory: str) -> List[Tuple[str, str, str]]:
223+
"get metadata from a Wheelhouse directory"
224+
results = []
225+
for file in os.listdir(directory):
226+
path = Path(directory) / file
227+
try:
228+
if path.suffix == '.whl':
229+
meta = extract_metadata_from_wheel(path)
230+
elif path.suffix == '.zip' or path.name.endswith('.tar.gz'):
231+
meta = extract_metadata_from_sdist(path)
232+
else:
233+
continue
234+
if meta:
235+
results.append(meta)
236+
except OSError: #Exception as e: # need to see it
237+
print(f"Skipping {file}: {e}")
238+
return results
239+
186240
def main() -> None:
187241
"""Main entry point for the script."""
188242
if len(sys.argv) != 2:

winpython/wppm.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
from argparse import ArgumentParser, RawTextHelpFormatter
1717
from winpython import utils, piptree, associate
1818
from winpython import wheelhouse as wh
19+
from operator import itemgetter
1920
# Workaround for installing PyVISA on Windows from source:
2021
os.environ["HOME"] = os.environ["USERPROFILE"]
2122

2223
class Package:
2324
"""Standardize a Package from filename or pip list."""
2425
def __init__(self, fname: str, suggested_summary: str = None):
2526
self.fname = fname
26-
self.description = piptree.sum_up(suggested_summary) if suggested_summary else ""
27+
self.description = (utils.sum_up(suggested_summary) if suggested_summary else "").strip()
2728
self.name, self.version = fname, '?.?.?'
2829
if fname.lower().endswith((".zip", ".tar.gz", ".whl")):
2930
bname = Path(self.fname).name # e.g., "sqlite_bro-1.0.0..."
@@ -81,8 +82,7 @@ def get_wheelhouse_packages_markdown(self) -> str:
8182
if wheeldir.is_dir():
8283
package_lines = [
8384
f"[{name}](https://pypi.org/project/{name}) | {version} | {summary}"
84-
for name, version, summary in wh.list_packages_with_metadata(str(wheeldir))
85-
#for pkg in sorted(wh.list_packages_with_metadata(str(wheeldir)), key=lambda p: p.name.lower())
85+
for name, version, summary in sorted(wh.list_packages_with_metadata(str(wheeldir)), key=itemgetter(0 , 1)) # lambda p: p[0].lower())
8686
]
8787
return "\n".join(package_lines)
8888
return ""

0 commit comments

Comments
 (0)