11# -*- coding: utf-8 -*-
22import json , sys , re , platform , os , sysconfig
33import re
4- from winpython import utils
54from collections import OrderedDict
65from pip ._vendor .packaging .markers import Marker
7-
6+ from importlib .metadata import Distribution , distributions
7+ from pathlib import Path
88
99def normalize (this ):
1010 """apply https://peps.python.org/pep-0503/#normalized-names"""
@@ -25,6 +25,7 @@ def __init__(self, Target=None):
2525 # req_version = version needed
2626 # req_marker = marker of the requirement (if any)
2727 # on current Python, use from importlib.metadata + Distribution.Discover() for 2x speed-up
28+ # on other Python, use importlib.metadata + distributions(path=[str(Path(Target).parent /'lib'/'site-packages'),])
2829 self .distro = {}
2930 self .raw = {}
3031 replacements = str .maketrans ({" " : "" , "[" : "" , "]" : "" , "'" : "" , '"' : "" })
@@ -45,20 +46,25 @@ def __init__(self, Target=None):
4546 }
4647
4748 # get pip_inpsect raw data in json form
48- if Target == None or sys .executable == Target :
49- # self-Distro inspection case
50- # faster then pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & python -X utf8=1 -m pip inspect', sys.prefix)
51- from importlib .metadata import Distribution
49+ if Target == None :
50+ Target = sys .executable
51+
52+ # faster then pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & python -X utf8=1 -m pip inspect', sys.prefix)
53+ if sys .executable == Target :
54+ # self-Distro inspection case (use all packages reachable per sys.path I presume )
5255 pip_json_installed = Distribution .discover ()
53- for p in pip_json_installed :
54- meta = p .metadata
55- name = p .name
56- version = p .version
57- key = normalize (name )
58- requires = []
59- self .raw [key ] = meta
60- if p .requires :
61- for i in p .requires :
56+ else :
57+ # not self-Distro inspection case , look at site-packages only)
58+ pip_json_installed = distributions (path = [str (Path (Target ).parent / 'lib' / 'site-packages' ),])
59+ for p in pip_json_installed :
60+ meta = p .metadata
61+ name = p .name
62+ version = p .version
63+ key = normalize (name )
64+ requires = []
65+ self .raw [key ] = meta
66+ if p .requires :
67+ for i in p .requires :
6268 det = (i + ";" ).split (";" )
6369
6470 # req_nameextra is "python-jose[cryptography]"
@@ -81,60 +87,15 @@ def __init__(self, Target=None):
8187 if not req_marker == "" :
8288 req_add ["req_marker" ] = req_marker
8389 requires += [req_add ]
84- self .distro [key ] = {
90+ self .distro [key ] = {
8591 "name" : name ,
8692 "version" : p .version ,
8793 "summary" : meta ["Summary" ] if "Summary" in meta else "" ,
8894 "requires_dist" : requires ,
8995 "wanted_per" : [],
9096 "description" : meta ["Description" ] if "Description" in meta else "" ,
9197 }
92- else :
93- # General Any Distro inspection case
94- # unreliable to utf-8: pip_inspect = utils.exec_run_cmd([Target , "-X" ,"utf8=1", "-m", "pip", "inspect"])
95- # os.environ["pythonutf8"] = "1" causes issues in movable function, so limit to this moment
96- pip_inspect = utils .exec_shell_cmd (f'set pythonutf8=1 & "{ Target } " -X utf8=1 -m pip inspect' , sys .prefix )
97- pip_json = json .loads (pip_inspect )
98-
99-
100- for p in pip_json ["installed" ]:
101- meta = p ["metadata" ]
102- name = meta ["name" ]
103- key = normalize (name )
104- requires = []
105- self .raw [key ] = meta
106- if "requires_dist" in meta :
107- for i in meta ["requires_dist" ]:
108- det = (i + ";" ).split (";" )
109-
110- # req_nameextra is "python-jose[cryptography]"
111- # from fastapi "python-jose[cryptography]<4.0.0,>=3.3.0
112- # req_nameextra is "google-cloud-storage"
113- # from "google-cloud-storage (<2.0.0,>=1.26.0)
114- req_nameextra = re .split (" |;|==|!|>|<" , det [0 ] + ";" )[0 ]
115- req_nameextra = normalize (req_nameextra )
116- req_key = normalize ((req_nameextra + "[" ).split ("[" )[0 ])
117- req_key_extra = req_nameextra [len (req_key ) + 1 :].split ("]" )[0 ]
118- req_version = det [0 ][len (req_nameextra ) :].translate (replacements )
119- req_marker = det [1 ]
12098
121- req_add = {
122- "req_key" : req_key ,
123- "req_version" : req_version ,
124- "req_extra" : req_key_extra ,
125- }
126- # add the marker of the requirement, if not nothing:
127- if not req_marker == "" :
128- req_add ["req_marker" ] = req_marker
129- requires += [req_add ]
130- self .distro [key ] = {
131- "name" : name ,
132- "version" : meta ["version" ],
133- "summary" : meta ["summary" ] if "summary" in meta else "" ,
134- "requires_dist" : requires ,
135- "wanted_per" : [],
136- "description" : meta ["description" ] if "description" in meta else "" ,
137- }
13899 # On a second pass, complement distro in reverse mode with 'wanted-per':
139100 # - get all downward links in 'requires_dist' of each package
140101 # - feed the required packages 'wanted_per' as a reverse dict of dict
0 commit comments