From 4a61cf138cd11f32979ae2c4765d2c748d6ef539 Mon Sep 17 00:00:00 2001 From: stonebig Date: Sun, 28 Apr 2024 16:31:03 +0200 Subject: [PATCH] get rid of pip inspect rely on importlib.metadata --- winpython/piptree.py | 83 ++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 61 deletions(-) diff --git a/winpython/piptree.py b/winpython/piptree.py index 5a6a711a..e424df81 100644 --- a/winpython/piptree.py +++ b/winpython/piptree.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- import json, sys, re, platform, os, sysconfig import re -from winpython import utils from collections import OrderedDict from pip._vendor.packaging.markers import Marker - +from importlib.metadata import Distribution , distributions +from pathlib import Path def normalize(this): """apply https://peps.python.org/pep-0503/#normalized-names""" @@ -25,6 +25,7 @@ def __init__(self, Target=None): # req_version = version needed # req_marker = marker of the requirement (if any) # on current Python, use from importlib.metadata + Distribution.Discover() for 2x speed-up + # on other Python, use importlib.metadata + distributions(path=[str(Path(Target).parent /'lib'/'site-packages'),]) self.distro = {} self.raw = {} replacements = str.maketrans({" ": "", "[": "", "]": "", "'": "", '"': ""}) @@ -45,20 +46,25 @@ def __init__(self, Target=None): } # get pip_inpsect raw data in json form - if Target == None or sys.executable==Target: - # self-Distro inspection case - # faster then pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & python -X utf8=1 -m pip inspect', sys.prefix) - from importlib.metadata import Distribution + if Target == None: + Target = sys.executable + + # faster then pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & python -X utf8=1 -m pip inspect', sys.prefix) + if sys.executable==Target: + # self-Distro inspection case (use all packages reachable per sys.path I presume ) pip_json_installed=Distribution.discover() - for p in pip_json_installed: - meta = p.metadata - name = p.name - version = p.version - key = normalize(name) - requires = [] - self.raw[key] = meta - if p.requires: - for i in p.requires: + else: + # not self-Distro inspection case , look at site-packages only) + pip_json_installed=distributions(path=[str(Path(Target).parent /'lib'/'site-packages'),]) + for p in pip_json_installed: + meta = p.metadata + name = p.name + version = p.version + key = normalize(name) + requires = [] + self.raw[key] = meta + if p.requires: + for i in p.requires: det = (i + ";").split(";") # req_nameextra is "python-jose[cryptography]" @@ -81,7 +87,7 @@ def __init__(self, Target=None): if not req_marker == "": req_add["req_marker"] = req_marker requires += [req_add] - self.distro[key] = { + self.distro[key] = { "name": name, "version": p.version, "summary": meta["Summary"] if "Summary" in meta else "", @@ -89,52 +95,7 @@ def __init__(self, Target=None): "wanted_per": [], "description": meta["Description"] if "Description" in meta else "", } - else: - # General Any Distro inspection case - # unreliable to utf-8: pip_inspect = utils.exec_run_cmd([Target , "-X" ,"utf8=1", "-m", "pip", "inspect"]) - # os.environ["pythonutf8"] = "1" causes issues in movable function, so limit to this moment - pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & "{Target}" -X utf8=1 -m pip inspect', sys.prefix) - pip_json = json.loads(pip_inspect) - - - for p in pip_json["installed"]: - meta = p["metadata"] - name = meta["name"] - key = normalize(name) - requires = [] - self.raw[key] = meta - if "requires_dist" in meta: - for i in meta["requires_dist"]: - det = (i + ";").split(";") - - # req_nameextra is "python-jose[cryptography]" - # from fastapi "python-jose[cryptography]<4.0.0,>=3.3.0 - # req_nameextra is "google-cloud-storage" - # from "google-cloud-storage (<2.0.0,>=1.26.0) - req_nameextra = re.split(" |;|==|!|>|<", det[0] + ";")[0] - req_nameextra = normalize(req_nameextra) - req_key = normalize((req_nameextra + "[").split("[")[0]) - req_key_extra = req_nameextra[len(req_key) + 1 :].split("]")[0] - req_version = det[0][len(req_nameextra) :].translate(replacements) - req_marker = det[1] - req_add = { - "req_key": req_key, - "req_version": req_version, - "req_extra": req_key_extra, - } - # add the marker of the requirement, if not nothing: - if not req_marker == "": - req_add["req_marker"] = req_marker - requires += [req_add] - self.distro[key] = { - "name": name, - "version": meta["version"], - "summary": meta["summary"] if "summary" in meta else "", - "requires_dist": requires, - "wanted_per": [], - "description": meta["description"] if "description" in meta else "", - } # On a second pass, complement distro in reverse mode with 'wanted-per': # - get all downward links in 'requires_dist' of each package # - feed the required packages 'wanted_per' as a reverse dict of dict