@@ -47,9 +47,70 @@ def infer_parents_subscript(
4747 raise UseInferenceDefault
4848
4949
50+ def _looks_like_parents_name (node : nodes .Name ) -> bool :
51+ """Check if a Name node was assigned from a Path.parents attribute."""
52+ # Look for the assignment in the current scope
53+ try :
54+ frame , stmts = node .lookup (node .name )
55+ if not stmts :
56+ return False
57+
58+ # Check each assignment statement
59+ for stmt in stmts :
60+ if isinstance (stmt , nodes .AssignName ):
61+ # Get the parent Assign node
62+ assign_node = stmt .parent
63+ if isinstance (assign_node , nodes .Assign ):
64+ # Check if the value is an Attribute access to .parents
65+ if (isinstance (assign_node .value , nodes .Attribute )
66+ and assign_node .value .attrname == "parents" ):
67+ try :
68+ # Check if the attribute is from a Path object
69+ value = next (assign_node .value .expr .infer ())
70+ if (isinstance (value , bases .Instance )
71+ and isinstance (value ._proxied , nodes .ClassDef )
72+ and value .qname () in ("pathlib.Path" , "pathlib._local.Path" )):
73+ return True
74+ except (InferenceError , StopIteration ):
75+ pass
76+ except (InferenceError , StopIteration ):
77+ pass
78+ return False
79+
80+
81+ def infer_parents_name (
82+ name_node : nodes .Name , ctx : context .InferenceContext | None = None
83+ ) -> Iterator [bases .Instance ]:
84+ """Infer a Name node that was assigned from Path.parents."""
85+ if PY313 :
86+ # For Python 3.13+, parents is a tuple
87+ from astroid import nodes
88+ # Create a tuple that behaves like Path.parents
89+ parents_tuple = nodes .Tuple ()
90+ # Add some mock Path elements to make indexing work
91+ path_cls = next (_extract_single_node (PATH_TEMPLATE ).infer ())
92+ parents_tuple .elts = [path_cls .instantiate_class () for _ in range (3 )] # Mock some parents
93+ return iter ([parents_tuple ])
94+ else :
95+ # For older versions, it's a _PathParents object
96+ # We need to create a mock _PathParents instance that behaves correctly
97+ parents_cls = _extract_single_node ("""
98+ class _PathParents:
99+ def __getitem__(self, key):
100+ from pathlib import Path
101+ return Path()
102+ """ )
103+ return iter ([parents_cls .instantiate_class ()])
104+
105+
50106def register (manager : AstroidManager ) -> None :
51107 manager .register_transform (
52108 nodes .Subscript ,
53109 inference_tip (infer_parents_subscript ),
54110 _looks_like_parents_subscript ,
55111 )
112+ manager .register_transform (
113+ nodes .Name ,
114+ inference_tip (infer_parents_name ),
115+ _looks_like_parents_name ,
116+ )
0 commit comments