@@ -205,8 +205,7 @@ def why(
205205 if version :
206206 package_nodes = [node for node in package_nodes if node .version in version ]
207207 for node in package_nodes :
208- print (f"\n { node .key } " )
209- find_why (graph , node , depth , 1 , requirement_type )
208+ find_why (graph , node , depth , 0 , requirement_type )
210209
211210
212211def find_why (
@@ -215,22 +214,50 @@ def find_why(
215214 max_depth : int ,
216215 depth : int ,
217216 req_type : list [RequirementType ],
218- ):
217+ seen : set [str ] | None = None ,
218+ ) -> None :
219+ if seen is None :
220+ seen = set ()
221+
222+ if node .key in seen :
223+ print (f"{ ' ' * depth } * { node .key } has a cycle" )
224+ return
225+
226+ # Print the name of the package we are asking about. We do this here because
227+ # we might be invoked for multiple packages and we want the format to be
228+ # consistent.
229+ if depth == 0 :
230+ print (f"\n { node .key } " )
231+
232+ seen = set ([node .key ]).union (seen )
219233 all_skipped = True
220234 is_toplevel = False
221235 for parent in node .parents :
236+ # Show the toplevel dependencies regardless of the req_type because they
237+ # are the ones that are actually installed and may influence other
238+ # dependencies.
222239 if parent .destination_node .key == ROOT :
223240 is_toplevel = True
224- print (f" * { node .key } is a toplevel dependency" )
241+ print (
242+ f"{ ' ' * depth } * { node .key } is a toplevel dependency with req { parent .req } "
243+ )
225244 continue
245+ # Skip dependencies that don't match the req_type.
226246 if req_type and parent .req_type not in req_type :
227247 continue
228248 all_skipped = False
229249 print (
230- f"{ ' ' * depth } * is an { parent .req_type } dependency of { parent .destination_node .key } with req { parent .req } "
250+ f"{ ' ' * depth } * { node . key } is an { parent .req_type } dependency of { parent .destination_node .key } with req { parent .req } "
231251 )
232252 if max_depth and (max_depth == - 1 or depth <= max_depth ):
233- find_why (graph , parent .destination_node , max_depth , depth + 1 , [])
253+ find_why (
254+ graph = graph ,
255+ node = parent .destination_node ,
256+ max_depth = max_depth ,
257+ depth = depth + 1 ,
258+ req_type = req_type ,
259+ seen = seen ,
260+ )
234261
235262 if all_skipped and not is_toplevel :
236263 print (
0 commit comments