@@ -163,24 +163,42 @@ def format_deps(
163163 find_dependent_tests_tree ,
164164 get_lib_paths ,
165165 get_test_paths ,
166+ resolve_hard_dep_parent ,
166167 )
167168
168169 if _visited is None :
169170 _visited = set ()
170171
171172 lines = []
172173
174+ # Resolve test_ prefix to module (e.g., test_pydoc -> pydoc)
175+ if name .startswith ("test_" ):
176+ module_name = name [5 :] # strip "test_"
177+ lines .append (f"(redirecting { name } -> { module_name } )" )
178+ name = module_name
179+
180+ # Resolve hard_dep to parent module (e.g., pydoc_data -> pydoc)
181+ parent = resolve_hard_dep_parent (name )
182+ if parent :
183+ lines .append (f"(redirecting { name } -> { parent } )" )
184+ name = parent
185+
173186 # lib paths (only show existing)
174187 lib_paths = get_lib_paths (name , cpython_prefix )
175- for p in lib_paths :
176- if p . exists () :
177- lines .append (f"[+] lib: { p } " )
188+ existing_lib_paths = [ p for p in lib_paths if p . exists ()]
189+ for p in existing_lib_paths :
190+ lines .append (f"[+] lib: { p } " )
178191
179192 # test paths (only show existing)
180193 test_paths = get_test_paths (name , cpython_prefix )
181- for p in test_paths :
182- if p .exists ():
183- lines .append (f"[+] test: { p } " )
194+ existing_test_paths = [p for p in test_paths if p .exists ()]
195+ for p in existing_test_paths :
196+ lines .append (f"[+] test: { p } " )
197+
198+ # If no lib or test paths exist, module doesn't exist
199+ if not existing_lib_paths and not existing_test_paths :
200+ lines .append (f"(module '{ name } ' not found)" )
201+ return lines
184202
185203 # hard_deps (from DEPENDENCIES table)
186204 dep_info = DEPENDENCIES .get (name , {})
@@ -258,6 +276,56 @@ def count_tests(t: dict) -> int:
258276 return lines
259277
260278
279+ def _resolve_module_name (
280+ name : str ,
281+ cpython_prefix : str ,
282+ lib_prefix : str ,
283+ ) -> list [str ]:
284+ """Resolve module name through redirects.
285+
286+ Returns a list of module names (usually 1, but test support files may expand to multiple).
287+ """
288+ import pathlib
289+
290+ from update_lib .deps import (
291+ _build_test_import_graph ,
292+ get_lib_paths ,
293+ get_test_paths ,
294+ resolve_hard_dep_parent ,
295+ )
296+
297+ # Resolve test_ prefix
298+ if name .startswith ("test_" ):
299+ name = name [5 :]
300+
301+ # Resolve hard_dep to parent
302+ parent = resolve_hard_dep_parent (name )
303+ if parent :
304+ return [parent ]
305+
306+ # Check if it's a valid module
307+ lib_paths = get_lib_paths (name , cpython_prefix )
308+ test_paths = get_test_paths (name , cpython_prefix )
309+ if any (p .exists () for p in lib_paths ) or any (p .exists () for p in test_paths ):
310+ return [name ]
311+
312+ # Check for test support files (e.g., string_tests -> bytes, str, userstring)
313+ test_support_path = pathlib .Path (cpython_prefix ) / "Lib" / "test" / f"{ name } .py"
314+ if test_support_path .exists ():
315+ test_dir = pathlib .Path (lib_prefix ) / "test"
316+ if test_dir .exists ():
317+ import_graph , _ = _build_test_import_graph (test_dir )
318+ importing_tests = []
319+ for file_key , imports in import_graph .items ():
320+ if name in imports and file_key .startswith ("test_" ):
321+ importing_tests .append (file_key )
322+ if importing_tests :
323+ # Resolve test names to module names (test_bytes -> bytes)
324+ return sorted (set (t [5 :] for t in importing_tests ))
325+
326+ return [name ]
327+
328+
261329def show_deps (
262330 names : list [str ],
263331 cpython_prefix : str = "cpython" ,
@@ -273,10 +341,19 @@ def show_deps(
273341 else :
274342 expanded_names .append (name )
275343
344+ # Resolve and deduplicate names (preserving order)
345+ seen : set [str ] = set ()
346+ resolved_names : list [str ] = []
347+ for name in expanded_names :
348+ for resolved in _resolve_module_name (name , cpython_prefix , lib_prefix ):
349+ if resolved not in seen :
350+ seen .add (resolved )
351+ resolved_names .append (resolved )
352+
276353 # Shared visited set across all modules
277354 visited : set [str ] = set ()
278355
279- for i , name in enumerate (expanded_names ):
356+ for i , name in enumerate (resolved_names ):
280357 if i > 0 :
281358 print () # blank line between modules
282359 for line in format_deps (name , cpython_prefix , lib_prefix , max_depth , visited ):
0 commit comments