Visit cell to look for get_ipython calls. Note that the source of the abstract syntax tree will already have been processed by IPython's TransformerManager().transform_cell. For example, %matplotlib inline would have been transformed to get_ipython().run_line
| 419 | # Unsurprisingly, subclassing ast.NodeVisitor means we can't use dataclasses here |
| 420 | # as mypyc will generate broken code. |
| 421 | class MagicFinder(ast.NodeVisitor): |
| 422 | """Visit cell to look for get_ipython calls. |
| 423 | |
| 424 | Note that the source of the abstract syntax tree |
| 425 | will already have been processed by IPython's |
| 426 | TransformerManager().transform_cell. |
| 427 | |
| 428 | For example, |
| 429 | |
| 430 | %matplotlib inline |
| 431 | |
| 432 | would have been transformed to |
| 433 | |
| 434 | get_ipython().run_line_magic('matplotlib', 'inline') |
| 435 | |
| 436 | and we look for instances of the latter (and likewise for other |
| 437 | types of magics). |
| 438 | """ |
| 439 | |
| 440 | def __init__(self) -> None: |
| 441 | self.magics: dict[int, list[OffsetAndMagic]] = collections.defaultdict(list) |
| 442 | |
| 443 | def visit_Assign(self, node: ast.Assign) -> None: |
| 444 | """Look for system assign magics. |
| 445 | |
| 446 | For example, |
| 447 | |
| 448 | black_version = !black --version |
| 449 | env = %env var |
| 450 | |
| 451 | would have been (respectively) transformed to |
| 452 | |
| 453 | black_version = get_ipython().getoutput('black --version') |
| 454 | env = get_ipython().run_line_magic('env', 'var') |
| 455 | |
| 456 | and we look for instances of any of the latter. |
| 457 | """ |
| 458 | if isinstance(node.value, ast.Call) and _is_ipython_magic(node.value.func): |
| 459 | args = _get_str_args(node.value.args) |
| 460 | if node.value.func.attr == "getoutput": |
| 461 | src = f"!{args[0]}" |
| 462 | elif node.value.func.attr == "run_line_magic": |
| 463 | src = f"%{args[0]}" |
| 464 | if args[1]: |
| 465 | src += f" {args[1]}" |
| 466 | else: |
| 467 | raise AssertionError( |
| 468 | f"Unexpected IPython magic {node.value.func.attr!r} found. " |
| 469 | "Please report a bug on https://github.com/psf/black/issues." |
| 470 | ) from None |
| 471 | self.magics[node.value.lineno].append( |
| 472 | OffsetAndMagic(node.value.col_offset, src) |
| 473 | ) |
| 474 | self.generic_visit(node) |
| 475 | |
| 476 | def visit_Expr(self, node: ast.Expr) -> None: |
| 477 | """Look for magics in body of cell. |
| 478 |
no outgoing calls
no test coverage detected
searching dependent graphs…