(node: ast.AST, parent_stack: list[ast.AST])
| 186 | |
| 187 | |
| 188 | def _stringify_ast(node: ast.AST, parent_stack: list[ast.AST]) -> Iterator[str]: |
| 189 | if ( |
| 190 | isinstance(node, ast.Constant) |
| 191 | and isinstance(node.value, str) |
| 192 | and node.kind == "u" |
| 193 | ): |
| 194 | # It's a quirk of history that we strip the u prefix over here. We used to |
| 195 | # rewrite the AST nodes for Python version compatibility and we never copied |
| 196 | # over the kind |
| 197 | node.kind = None |
| 198 | |
| 199 | yield f"{' ' * len(parent_stack)}{node.__class__.__name__}(" |
| 200 | |
| 201 | for field in sorted(node._fields): |
| 202 | # TypeIgnore has only one field 'lineno' which breaks this comparison |
| 203 | if isinstance(node, ast.TypeIgnore): |
| 204 | break |
| 205 | |
| 206 | try: |
| 207 | value: object = getattr(node, field) |
| 208 | except AttributeError: |
| 209 | continue |
| 210 | |
| 211 | yield f"{' ' * (len(parent_stack) + 1)}{field}=" |
| 212 | |
| 213 | if isinstance(value, list): |
| 214 | for item in value: |
| 215 | # Ignore nested tuples within del statements, because we may insert |
| 216 | # parentheses and they change the AST. |
| 217 | if ( |
| 218 | field == "targets" |
| 219 | and isinstance(node, ast.Delete) |
| 220 | and isinstance(item, ast.Tuple) |
| 221 | ): |
| 222 | for elt in _unwrap_tuples(item): |
| 223 | yield from _stringify_ast_with_new_parent( |
| 224 | elt, parent_stack, node |
| 225 | ) |
| 226 | |
| 227 | elif isinstance(item, ast.AST): |
| 228 | yield from _stringify_ast_with_new_parent(item, parent_stack, node) |
| 229 | |
| 230 | elif isinstance(value, ast.AST): |
| 231 | yield from _stringify_ast_with_new_parent(value, parent_stack, node) |
| 232 | |
| 233 | else: |
| 234 | normalized: object |
| 235 | if ( |
| 236 | isinstance(node, ast.Constant) |
| 237 | and field == "value" |
| 238 | and isinstance(value, str) |
| 239 | and len(parent_stack) >= 2 |
| 240 | # Any standalone string, ideally this would |
| 241 | # exactly match black.nodes.is_docstring |
| 242 | and isinstance(parent_stack[-1], ast.Expr) |
| 243 | ): |
| 244 | # Constant strings may be indented across newlines, if they are |
| 245 | # docstrings; fold spaces after newlines when comparing. Similarly, |
no test coverage detected