r"""Find cell magics. Note that the source of the abstract syntax tree will already have been processed by IPython's TransformerManager().transform_cell. For example, %%time\n foo() would have been transformed to get_ipython().run_cell_magic('time', '
| 377 | |
| 378 | # ast.NodeVisitor + dataclass = breakage under mypyc. |
| 379 | class CellMagicFinder(ast.NodeVisitor): |
| 380 | r"""Find cell magics. |
| 381 | |
| 382 | Note that the source of the abstract syntax tree |
| 383 | will already have been processed by IPython's |
| 384 | TransformerManager().transform_cell. |
| 385 | |
| 386 | For example, |
| 387 | |
| 388 | %%time\n |
| 389 | foo() |
| 390 | |
| 391 | would have been transformed to |
| 392 | |
| 393 | get_ipython().run_cell_magic('time', '', 'foo()\n') |
| 394 | |
| 395 | and we look for instances of the latter. |
| 396 | """ |
| 397 | |
| 398 | def __init__(self, cell_magic: CellMagic | None = None) -> None: |
| 399 | self.cell_magic = cell_magic |
| 400 | |
| 401 | def visit_Expr(self, node: ast.Expr) -> None: |
| 402 | """Find cell magic, extract header and body.""" |
| 403 | if ( |
| 404 | isinstance(node.value, ast.Call) |
| 405 | and _is_ipython_magic(node.value.func) |
| 406 | and node.value.func.attr == "run_cell_magic" |
| 407 | ): |
| 408 | args = _get_str_args(node.value.args) |
| 409 | self.cell_magic = CellMagic(name=args[0], params=args[1], body=args[2]) |
| 410 | self.generic_visit(node) |
| 411 | |
| 412 | |
| 413 | @dataclasses.dataclass(frozen=True) |
no outgoing calls
no test coverage detected