Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 956f892

Browse files
committed
simplify piptree with gemini flash help
still it did propose bad simplifications or unwanted code removal
1 parent 89a4c9d commit 956f892

File tree

1 file changed

+101
-113
lines changed

1 file changed

+101
-113
lines changed

winpython/piptree.py

+101-113
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
# require python 3.8+ because of importlib.metadata
3+
# revamped via github/gpt-4o free then gemini flash 2 free
34
import json
45
import sys
56
import re
@@ -43,20 +44,21 @@ def __init__(self, target=None):
4344
self.raw = {}
4445
self.environment = self._get_environment()
4546

46-
target = target or sys.executable
47+
search_path = target or sys.executable
4748

48-
if sys.executable==target:
49+
if sys.executable==search_path:
4950
# self-Distro inspection case (use all packages reachable per sys.path I presume )
5051
packages=Distribution.discover()
5152
else:
5253
# not self-Distro inspection case , look at site-packages only)
53-
packages=distributions(path=[str(Path(target).parent /'lib'/'site-packages'),])
54+
packages=distributions(path=[str(Path(search_path).parent /'lib'/'site-packages'),])
55+
5456

5557
for package in packages:
5658
self._process_package(package)
5759

5860
# On a second pass, complement dependancies in reverse mode with 'wanted-per':
59-
self._populate_wanted_per()
61+
self._populate_reverse_dependencies()
6062

6163
def _get_environment(self):
6264
"""Get the current environment details."""
@@ -141,7 +143,7 @@ def _get_provides(self, package):
141143
provides[req_marker.split('extra == ')[1].translate(remove_list)] = None
142144
return provides
143145

144-
def _populate_wanted_per(self):
146+
def _populate_reverse_dependencies(self):
145147
"""Populate the wanted_per field for each package."""
146148
# - get all downward links in 'requires_dist' of each package
147149
# - feed the required packages 'wanted_per' as a reverse dict of dict
@@ -171,125 +173,111 @@ def _populate_wanted_per(self):
171173
self.distro[r["req_key"]]["provided"][r["req_marker"].split('extra == ')[1].translate(remove_list)] = None
172174
self.distro[r["req_key"]]["wanted_per"].append(want_add)
173175

176+
def _get_dependency_tree(self, package_name, extra="", version_req="", depth=20, path=None, verbose=False, upward=False):
177+
"""Recursive function to build dependency tree."""
178+
path = path or []
179+
extras = extra.split(",")
180+
package_key = normalize(package_name)
181+
ret_all = []
182+
#pe = normalize(f'{package_key}[{extras}]')
183+
if package_key + "[" + extra + "]" in path:
184+
print("cycle!", "->".join(path + [package_key + "[" + extra + "]"]))
185+
return [] # Return empty list to avoid further recursion
174186

187+
package_data = self.distro.get(package_key)
188+
if package_data and len(path) <= depth:
189+
for extra in extras:
190+
environment = {"extra": extra, **self.environment}
191+
summary = f' {package_data["summary"]}' if verbose else ''
192+
base_name = f'{package_name}[{extra}]' if extra else package_name
193+
ret = [f'{base_name}=={package_data["version"]} {version_req}{summary}']
175194

176-
def _downraw(self, pp, extra="", version_req="", depth=20, path=[], verbose=False):
177-
"""build a nested list of needed packages with given extra and depth"""
178-
envi = {"extra": extra, **self.environment}
179-
p = normalize(pp)
180-
extras = extra.split(",") # to handle several extras, example: dask[array,diagnostics]
181-
ret_all = []
182-
if p + "[" + extra + "]" in path: # for dask[complete]->dask[array,test,..]
183-
print("cycle!", "->".join(path + [p + "[" + extra + "]"]))
184-
elif p in self.distro and len(path) <= depth:
185-
for extra in extras: # several extras request management
186-
envi = {"extra": extra, **self.environment}
187-
summary = f' {self.distro[p]["summary"]}' if verbose else ''
188-
if extra == "":
189-
ret = [f'{p}=={self.distro[p]["version"]} {version_req}{summary}']
190-
else:
191-
ret = [f'{p}[{extra}]=={self.distro[p]["version"]} {version_req}{summary}']
192-
for r in self.distro[p]["requires_dist"]:
193-
if r["req_key"] in self.distro:
194-
if "req_marker" not in r or Marker(r["req_marker"]).evaluate(environment=envi):
195-
ret += self._downraw(
196-
r["req_key"],
197-
r["req_extra"],
198-
r["req_version"],
199-
depth,
200-
path + [p + "[" +extra + "]"],
201-
verbose=verbose,
202-
)
203-
ret_all.append(ret)
204-
return ret_all
195+
dependencies = package_data["requires_dist"] if not upward else package_data["wanted_per"]
205196

206-
def _upraw(self, pp, extra="", version_req="", depth=20, path=[], verbose=False):
207-
"""build a nested list of user packages with given extra and depth
208-
from direct dependancies like dask-image <--dask['array']
209-
or indirect like Pytest['test'] <-- pandas['test']"""
197+
for dependency in dependencies:
198+
if dependency["req_key"] in self.distro:
199+
if not dependency.get("req_marker") or Marker(dependency["req_marker"]).evaluate(environment=environment):
200+
next_path = path + [base_name]
201+
if upward:
202+
up_req = (dependency.get("req_marker", "").split('extra == ')+[""])[1].strip("'\"")
203+
# 2024-06-30 example of langchain <- numpy. pip.distro['numpy']['wanted_per'] has:
204+
# {'req_key': 'langchain', 'req_version': '(>=1,<2)', 'req_extra': '', 'req_marker': ' python_version < "3.12"'},
205+
# {'req_key': 'langchain', 'req_version': '(>=1.26.0,<2.0.0)', 'req_extra': '', 'req_marker': ' python_version >= "3.12"'}
206+
# must be no extra dependancy, optionnal extra in the package, or provided extra per upper packages
207+
if dependency["req_key"] in self.distro and dependency["req_key"]+"["+up_req+"]" not in path: # avoids circular links on dask[array]
208+
if (not dependency.get("req_marker") and extra =="") or (extra !="" and extra==up_req and dependency["req_key"]!=package_key) or (extra !="" and "req_marker" in dependency and extra+',' in dependency["req_extra"]+',' #bingo1346 contourpy[test-no-images]
209+
or "req_marker" in dependency and extra+',' in dependency["req_extra"]+',' and Marker(dependency["req_marker"]).evaluate(environment=environment)
210+
):
211+
ret += self._get_dependency_tree(
212+
dependency["req_key"],
213+
up_req, # pydask[array] going upwards will look for pydask[dataframe]
214+
f"[requires: {package_name}"
215+
+ (
216+
"[" + dependency["req_extra"] + "]"
217+
if dependency["req_extra"] != ""
218+
else ""
219+
)
220+
+ f'{dependency["req_version"]}]',
221+
depth,
222+
next_path,
223+
verbose=verbose,
224+
upward=upward,
225+
)
226+
else:
227+
ret += self._get_dependency_tree(
228+
dependency["req_key"],
229+
dependency["req_extra"],
230+
dependency["req_version"],
231+
depth,
232+
next_path,
233+
verbose=verbose,
234+
upward=upward,
235+
)
210236

211-
remove_list = {ord("'"):None, ord('"'):None} # to clean-up req_extra
212-
envi = {"extra": extra, **self.environment}
213-
p = normalize(pp)
214-
pe = normalize(f'{pp}[{extra}]')
215-
ret_all = []
216-
if pe in path:
217-
print("cycle!", "->".join(path + [pe]))
218-
elif p in self.distro and len(path) <= depth:
219-
summary = f' {self.distro[p]["summary"]}' if verbose else ''
220-
if extra == "":
221-
ret_all = [f'{p}=={self.distro[p]["version"]} {version_req}{summary}']
222-
elif extra in set(self.distro[p]["provided"]).union(set(self.distro[p]["provides"])): # so that -r pytest[test] gives
223-
ret_all = [f'{p}[{extra}]=={self.distro[p]["version"]} {version_req}{summary}']
224-
else:
225-
return []
226-
ret = []
227-
for r in self.distro[p]["wanted_per"]:
228-
up_req = (r.get("req_marker", "").split('extra == ')+[""])[1].translate(remove_list)
229-
if r["req_key"] in self.distro and r["req_key"]+"["+up_req+"]" not in path: # avoids circular links on dask[array]
230-
# 2024-06-30 example of langchain <- numpy. pip.distro['numpy']['wanted_per'] has:
231-
# {'req_key': 'langchain', 'req_version': '(>=1,<2)', 'req_extra': '', 'req_marker': ' python_version < "3.12"'},
232-
# {'req_key': 'langchain', 'req_version': '(>=1.26.0,<2.0.0)', 'req_extra': '', 'req_marker': ' python_version >= "3.12"'}
233-
# must be no extra dependancy, optionnal extra in the package, or provided extra per upper packages
234-
if ("req_marker" not in r and extra =="") or (extra !="" and extra==up_req and r["req_key"]!=p) or (extra !="" and "req_marker" in r and extra+',' in r["req_extra"]+',' #bingo1346 contourpy[test-no-images]
235-
or "req_marker" in r and extra+',' in r["req_extra"]+',' and Marker(r["req_marker"]).evaluate(environment=envi)
236-
):
237-
ret += self._upraw(
238-
r["req_key"],
239-
up_req, # pydask[array] going upwards will look for pydask[dataframe]
240-
f"[requires: {p}"
241-
+ (
242-
"[" + r["req_extra"] + "]"
243-
if r["req_extra"] != ""
244-
else ""
245-
)
246-
+ f'{r["req_version"]}]',
247-
depth,
248-
path + [pe],
249-
verbose=verbose,
250-
)
251-
if not ret == []:
252237
ret_all.append(ret)
253238
return ret_all
254239

255-
def down(self, pp="", extra="", depth=99, indent=5, version_req="", verbose=False):
256-
"""print the downward requirements for the package or all packages"""
257-
if pp != ".":
258-
if extra != ".":
259-
if pp in self.distro:
260-
extras = [s for s in extra.split(',') if s in sorted(self.distro[pp]["provides"])]
261-
if extras == []: return ''
262-
rawtext = json.dumps(self._downraw(pp, extra, version_req, depth, verbose=verbose), indent=indent)
263-
lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2]
264-
return ("\n".join(lines).replace('"', ""))
265-
else:
266-
if pp in self.distro:
267-
results = [self.down(pp, one_extra, depth, indent, version_req, verbose=verbose)
268-
for one_extra in sorted(self.distro[pp]["provides"])]
269-
return '\n'.join(filter(None, results))
270-
else:
271-
results = [self.down(one_pp, extra, depth, indent, version_req, verbose=verbose)
272-
for one_pp in sorted(self.distro)]
240+
def down(self, pp="", extra="", depth=20, indent=5, version_req="", verbose=False):
241+
"""Print the downward requirements for the package or all packages."""
242+
if pp == ".":
243+
results = [self.down(one_pp, extra, depth, indent, version_req, verbose=verbose) for one_pp in sorted(self.distro)]
273244
return '\n'.join(filter(None, results))
274-
275-
def up(self, pp, extra="", depth=99, indent=5, version_req="", verbose=False):
245+
246+
if extra == ".":
247+
if pp in self.distro:
248+
results = [self.down(pp, one_extra, depth, indent, version_req, verbose=verbose)
249+
for one_extra in sorted(self.distro[pp]["provides"])]
250+
return '\n'.join(filter(None, results))
251+
return "" # Handle cases where extra is "." and package_name is not found.
252+
253+
if pp not in self.distro:
254+
return "" # Handle cases where package_name is not found.
255+
256+
rawtext = json.dumps(self._get_dependency_tree(pp, extra, version_req, depth, verbose=verbose), indent=indent)
257+
lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2]
258+
return "\n".join(lines).replace('"', "")
259+
260+
def up(self, pp, extra="", depth=20, indent=5, version_req="", verbose=False):
276261
"""Print the upward needs for the package."""
277-
r = []
278-
if pp != ".":
279-
if extra != ".":
280-
rawtext = json.dumps(self._upraw(pp, extra, version_req, depth, verbose=verbose), indent=indent)
281-
lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2]
282-
return ('\n'.join(filter(None, lines)).replace('"', "") )
283-
else:
284-
if pp in self.distro:
285-
# get 'extra' tags from direct and from upward packages
286-
results = [self.up(pp, one_extra, depth, indent, version_req, verbose=verbose)
287-
for one_extra in sorted(set(self.distro[pp]["provided"]).union(set(self.distro[pp]["provides"])))]
288-
return '\n'.join(filter(None, results))
289-
else:
290-
results = [self.up(one_pp, extra, depth, indent, version_req, verbose=verbose) for one_pp in sorted(self.distro)]
262+
263+
if pp == ".":
264+
results = [self.up(one_pp, extra, depth, indent, version_req, verbose) for one_pp in sorted(self.distro)]
291265
return '\n'.join(filter(None, results))
292266

267+
if extra == ".":
268+
if pp in self.distro:
269+
extras = set(self.distro[pp]["provided"]).union(set(self.distro[pp]["provides"]))
270+
results = [self.up(pp, one_extra, depth, indent, version_req, verbose=verbose) for one_extra in sorted(extras)]
271+
return '\n'.join(filter(None, results))
272+
return ""
273+
274+
if pp not in self.distro:
275+
return ""
276+
277+
rawtext = json.dumps(self._get_dependency_tree(pp, extra, version_req, depth, verbose=verbose, upward=True), indent=indent)
278+
lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2]
279+
return '\n'.join(filter(None, lines)).replace('"', "")
280+
293281
def description(self, pp):
294282
"""Return description of the package."""
295283
if pp in self.distro:

0 commit comments

Comments
 (0)