11# -*- coding: utf-8 -*-
22"""
3- This script provides functionality to inspect and display package dependencies
3+ This script provides functionality to inspect and display package dependencies
44in a Python environment, including both downward and upward dependencies.
55Requires Python 3.8+ due to importlib.metadata.
66"""
1111import platform
1212import os
1313from collections import OrderedDict
14+ from typing import Dict , List , Optional , Tuple , Union
1415from pip ._vendor .packaging .markers import Marker , InvalidMarker
1516from importlib .metadata import Distribution , distributions
1617from pathlib import Path
1718
18-
19- def normalize (name ):
19+ def normalize (name : str ) -> str :
2020 """Normalize package name according to PEP 503."""
2121 return re .sub (r"[-_.]+" , "-" , name ).lower ()
2222
23-
24- def sum_up (text , max_length = 144 , stop_at = ". " ):
23+ def sum_up (text : str , max_length : int = 144 , stop_at : str = ". " ) -> str :
2524 """
2625 Summarize text to fit within max_length characters, ending at the last complete sentence if possible.
27-
26+
2827 :param text: The text to summarize
2928 :param max_length: Maximum length for summary
3029 :param stop_at: String to stop summarization at
@@ -37,14 +36,14 @@ def sum_up(text, max_length=144, stop_at=". "):
3736 summary = summary [:max_length ]
3837 return summary
3938
40- class pipdata :
39+ class PipData :
4140 """
4241 Wrapper around Distribution.discover() or Distribution.distributions() to manage package metadata.
4342 """
4443
45- def __init__ (self , target = None ):
46- self .distro = {}
47- self .raw = {}
44+ def __init__ (self , target : Optional [ str ] = None ):
45+ self .distro : Dict [ str , Dict ] = {}
46+ self .raw : Dict [ str , Dict ] = {}
4847 self .environment = self ._get_environment ()
4948
5049 search_path = target or sys .executable
@@ -57,18 +56,18 @@ def __init__(self, target=None):
5756 for package in packages :
5857 self ._process_package (package )
5958
60- # On a second pass, complement dependancies in reverse mode with 'wanted-per':
59+ # On a second pass, complement dependencies in reverse mode with 'wanted-per':
6160 self ._populate_reverse_dependencies ()
6261
63- def _get_environment (self ):
62+ def _get_environment (self ) -> Dict [ str , str ] :
6463 """
6564 Collect environment details for dependency evaluation.
66-
65+
6766 :return: Dictionary containing system and Python environment information
6867 """
6968 return {
7069 "implementation_name" : sys .implementation .name ,
71- "implementation_version" : "{0. major}.{0.minor}.{0.micro}" . format ( sys .implementation .version ) ,
70+ "implementation_version" : f" { sys . implementation . version . major } .{ sys . implementation . version . minor } . { sys .implementation .version . micro } " ,
7271 "os_name" : os .name ,
7372 "platform_machine" : platform .machine (),
7473 "platform_release" : platform .release (),
@@ -80,7 +79,7 @@ def _get_environment(self):
8079 "sys_platform" : sys .platform ,
8180 }
8281
83- def _process_package (self , package ) :
82+ def _process_package (self , package : Distribution ) -> None :
8483 """Process package metadata and store it in the distro dictionary."""
8584 meta = package .metadata
8685 name = meta ['Name' ]
@@ -99,7 +98,7 @@ def _process_package(self, package):
9998 "provided" : {'' : None } # Placeholder for extras provided by this package
10099 }
101100
102- def _get_requires (self , package ) :
101+ def _get_requires (self , package : Distribution ) -> List [ Dict [ str , str ]] :
103102 """Extract and normalize requirements for a package."""
104103 # requires = list of dict with 1 level need downward
105104 # req_key = package_key requires
@@ -136,7 +135,7 @@ def _get_requires(self, package):
136135 requires .append (req_add )
137136 return requires
138137
139- def _get_provides (self , package ) :
138+ def _get_provides (self , package : Distribution ) -> Dict [ str , None ] :
140139 """Get the list of extras provided by this package."""
141140 provides = {'' : None }
142141 if package .requires :
@@ -147,7 +146,7 @@ def _get_provides(self, package):
147146 provides [req_marker .split ('extra == ' )[1 ].translate (remove_list )] = None
148147 return provides
149148
150- def _populate_reverse_dependencies (self ):
149+ def _populate_reverse_dependencies (self ) -> None :
151150 """Add reverse dependencies to each package."""
152151 # - get all downward links in 'requires_dist' of each package
153152 # - feed the required packages 'reverse_dependencies' as a reverse dict of dict
@@ -167,11 +166,11 @@ def _populate_reverse_dependencies(self):
167166 if "req_marker" in requirement :
168167 want_add ["req_marker" ] = requirement ["req_marker" ]
169168 if 'extra == ' in requirement ["req_marker" ]:
170- remove_list = {ord ("'" ):None , ord ('"' ):None }
169+ remove_list = {ord ("'" ): None , ord ('"' ): None }
171170 self .distro [requirement ["req_key" ]]["provided" ][requirement ["req_marker" ].split ('extra == ' )[1 ].translate (remove_list )] = None
172171 self .distro [requirement ["req_key" ]]["reverse_dependencies" ].append (want_add )
173172
174- def _get_dependency_tree (self , package_name , extra = "" , version_req = "" , depth = 20 , path = None , verbose = False , upward = False ):
173+ def _get_dependency_tree (self , package_name : str , extra : str = "" , version_req : str = "" , depth : int = 20 , path : Optional [ List [ str ]] = None , verbose : bool = False , upward : bool = False ) -> List [ List [ str ]] :
175174 """Recursive function to build dependency tree."""
176175 path = path or []
177176 extras = extra .split ("," )
@@ -235,7 +234,7 @@ def _get_dependency_tree(self, package_name, extra="", version_req="", depth=20,
235234 ret_all .append (ret )
236235 return ret_all
237236
238- def down (self , pp = "" , extra = "" , depth = 20 , indent = 5 , version_req = "" , verbose = False ):
237+ def down (self , pp : str = "" , extra : str = "" , depth : int = 20 , indent : int = 5 , version_req : str = "" , verbose : bool = False ) -> str :
239238 """Print the downward requirements for the package or all packages."""
240239 if pp == "." :
241240 results = [self .down (one_pp , extra , depth , indent , version_req , verbose = verbose ) for one_pp in sorted (self .distro )]
@@ -255,9 +254,8 @@ def down(self, pp="", extra="", depth=20, indent=5, version_req="", verbose=Fals
255254 lines = [l for l in rawtext .split ("\n " ) if len (l .strip ()) > 2 ]
256255 return "\n " .join (lines ).replace ('"' , "" )
257256
258- def up (self , pp , extra = "" , depth = 20 , indent = 5 , version_req = "" , verbose = False ):
257+ def up (self , pp : str , extra : str = "" , depth : int = 20 , indent : int = 5 , version_req : str = "" , verbose : bool = False ) -> str :
259258 """Print the upward needs for the package."""
260-
261259 if pp == "." :
262260 results = [self .up (one_pp , extra , depth , indent , version_req , verbose ) for one_pp in sorted (self .distro )]
263261 return '\n ' .join (filter (None , results ))
@@ -274,22 +272,22 @@ def up(self, pp, extra="", depth=20, indent=5, version_req="", verbose=False):
274272
275273 rawtext = json .dumps (self ._get_dependency_tree (pp , extra , version_req , depth , verbose = verbose , upward = True ), indent = indent )
276274 lines = [l for l in rawtext .split ("\n " ) if len (l .strip ()) > 2 ]
277- return ' \n ' .join (filter (None , lines )).replace ('"' , "" )
275+ return " \n " .join (filter (None , lines )).replace ('"' , "" )
278276
279- def description (self , pp ) :
277+ def description (self , pp : str ) -> None :
280278 """Return description of the package."""
281279 if pp in self .distro :
282280 return print ("\n " .join (self .distro [pp ]["description" ].split (r"\n" )))
283281
284282 def summary (self , pp ):
285283 """Return summary of the package."""
286284 if pp in self .distro :
287- return self .distro [pp ]["summary" ]
285+ return self .distro [pp ]["summary" ]
286+ return ""
288287
289- def pip_list (self , full = False , max_length = 144 ):
288+ def pip_list (self , full : bool = False , max_length : int = 144 ) -> List [ Tuple [ str , Union [ str , Tuple [ str , str ]]]] :
290289 """List installed packages similar to pip list."""
291290 if full :
292- return [(p , self .distro [p ]["version" ], sum_up (self .distro [p ]["summary" ]) , max_length ) for p in sorted (self .distro )]
291+ return [(p , self .distro [p ]["version" ], sum_up (self .distro [p ]["summary" ], max_length ) ) for p in sorted (self .distro )]
293292 else :
294293 return [(p , sum_up (self .distro [p ]["version" ], max_length )) for p in sorted (self .distro )]
295-
0 commit comments