class_docstr: 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
  
      foo()
  
  would have been transformed to
  
      get_ipython().run_cell_magic('time', '', 'foo()\n')
  
  and we look for instances of the latter.
class_docstr_tok: ["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","foo","(",")","would","have","been","transformed","to","get_ipython","(",")",".run_cell_magic","(","'time","'",",","``",",","'foo","(",")","\\n","'",")","and","we","look","for","instances","of","the","latter","."]
docstr: Find cell magic, extract header and body.
docstr_tok: ["Find","cell","magic",",","extract","header","and","body","."]
code: def visit_Expr(self, node: ast.Expr) -> None:
      """Find cell magic, extract header and body."""
      if (
          isinstance(node.value, ast.Call)
          and _is_ipython_magic(node.value.func)
          and node.value.func.attr == "run_cell_magic"
      ):
          args = _get_str_args(node.value.args)
          self.cell_magic = CellMagic(
              name=args[0], params=args[1], body=args[2]
          )
      self.generic_visit(node)
  
imports: import ast
  import collections
  import dataclasses
  import secrets
  import sys
  from functools import lru_cache
  from importlib.util import find_spec
  from typing import Dict, List, Optional, Tuple
  from black.output import out
  from black.report import NothingChanged
label_desc: Use image node_id 2 for calling the CellMagicFinder obj's underlying member method code with example usage: obj.visit_Expr(node) without return types