@@ -135,7 +135,18 @@ def get_full_basenames(node: astroid.nodes.ClassDef) -> Iterable[str]:
135135 yield _resolve_annotation (base )
136136
137137
138- def _get_const_value (node : astroid .nodes .NodeNG ) -> str | None :
138+ def get_const_value (node : astroid .nodes .NodeNG ) -> str | None :
139+ """Get the string representation of the value represented by a node.
140+
141+ The value must be a constant or container of constants.
142+
143+ Args:
144+ node: The node to get the representation of.
145+
146+ Returns:
147+ The string representation of the value represented by the node
148+ (if it can be converted).
149+ """
139150 if isinstance (node , astroid .nodes .Const ):
140151 if isinstance (node .value , str ) and "\n " in node .value :
141152 return f'"""{ node .value } """'
@@ -168,19 +179,18 @@ def _inner(node: astroid.nodes.NodeNG) -> Any:
168179 return repr (result )
169180
170181
171- def get_assign_value (
182+ def _get_assign_target_node (
172183 node : astroid .nodes .Assign | astroid .nodes .AnnAssign ,
173- ) -> tuple [ str , str | None ] | None :
174- """Get the name and value of the assignment of the given node.
184+ ) -> astroid . nodes . NodeNG | None :
185+ """Get the target of the given assignment node.
175186
176- Assignments to multiple names are ignored, as per PEP 257.
187+ Assignments to multiple names are ignored, as per :pep:` 257` .
177188
178189 Args:
179190 node: The node to get the assignment value from.
180191
181192 Returns:
182- The name that is assigned to, and the string representation of
183- the value assigned to the name (if it can be converted).
193+ The node representing the name that is assigned to.
184194 """
185195 try :
186196 targets = node .targets
@@ -189,17 +199,42 @@ def get_assign_value(
189199
190200 if len (targets ) == 1 :
191201 target = targets [0 ]
192- if isinstance (target , astroid .nodes .AssignName ):
193- name = target .name
194- elif isinstance (target , astroid .nodes .AssignAttr ):
195- name = target .attrname
196- else :
197- return None
198- return (name , _get_const_value (node .value ))
202+ if isinstance (target , (astroid .nodes .AssignName , astroid .nodes .AssignAttr )):
203+ return target
199204
200205 return None
201206
202207
208+ def get_assign_value (
209+ node : astroid .nodes .Assign | astroid .nodes .AnnAssign ,
210+ ) -> tuple [str , str | None ] | None :
211+ """Get the name and value of the assignment of the given node.
212+
213+ Assignments to multiple names are ignored, as per :pep:`257`.
214+
215+ Args:
216+ node: The node to get the assignment value from.
217+
218+ Returns:
219+ The name that is assigned to, and the string representation of
220+ the value assigned to the name (if it can be converted).
221+ """
222+ target = _get_assign_target_node (node )
223+
224+ if isinstance (target , astroid .nodes .AssignName ):
225+ name = target .name
226+ elif isinstance (target , astroid .nodes .AssignAttr ):
227+ name = target .attrname
228+ else :
229+ return None
230+
231+ value = next (target .infer ())
232+ if value is astroid .util .Uninferable :
233+ value = None
234+
235+ return (name , value )
236+
237+
203238def get_assign_annotation (
204239 node : astroid .nodes .Assign | astroid .nodes .AnnAssign ,
205240) -> str | None :
@@ -680,3 +715,18 @@ def is_abstract_class(node: astroid.nodes.ClassDef) -> bool:
680715 return True
681716
682717 return False
718+
719+
720+ def is_functional_namedtuple (node : astroid .nodes .NodeNG ) -> bool :
721+ if not isinstance (node , astroid .nodes .Call ):
722+ return False
723+
724+ func = node .func
725+ if isinstance (func , astroid .nodes .Attribute ):
726+ name = func .attrname
727+ elif isinstance (func , astroid .nodes .Name ):
728+ name = func .name
729+ else :
730+ return False
731+
732+ return name in ("namedtuple" , "NamedTuple" )
0 commit comments