@@ -135,7 +135,18 @@ def get_full_basenames(node: astroid.nodes.ClassDef) -> Iterable[str]:
135
135
yield _resolve_annotation (base )
136
136
137
137
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
+ """
139
150
if isinstance (node , astroid .nodes .Const ):
140
151
if isinstance (node .value , str ) and "\n " in node .value :
141
152
return f'"""{ node .value } """'
@@ -168,19 +179,18 @@ def _inner(node: astroid.nodes.NodeNG) -> Any:
168
179
return repr (result )
169
180
170
181
171
- def get_assign_value (
182
+ def _get_assign_target_node (
172
183
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.
175
186
176
- Assignments to multiple names are ignored, as per PEP 257.
187
+ Assignments to multiple names are ignored, as per :pep:` 257` .
177
188
178
189
Args:
179
190
node: The node to get the assignment value from.
180
191
181
192
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.
184
194
"""
185
195
try :
186
196
targets = node .targets
@@ -189,17 +199,42 @@ def get_assign_value(
189
199
190
200
if len (targets ) == 1 :
191
201
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
199
204
200
205
return None
201
206
202
207
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
+
203
238
def get_assign_annotation (
204
239
node : astroid .nodes .Assign | astroid .nodes .AnnAssign ,
205
240
) -> str | None :
@@ -680,3 +715,18 @@ def is_abstract_class(node: astroid.nodes.ClassDef) -> bool:
680
715
return True
681
716
682
717
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