{
  "__type": "IngestedDoc",
  "__tag": 4010,
  "_content": {
    "Notes": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Warns": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Raises": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Yields": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Methods": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Returns": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Summary": {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "No Docstrings"
            }
          ]
        }
      ],
      "title": [],
      "level": 0,
      "target": null
    },
    "Receives": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Warnings": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Attributes": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Parameters": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Extended Summary": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    },
    "Other Parameters": {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [],
      "level": 0,
      "target": null
    }
  },
  "_ordered_sections": [
    "Summary",
    "Extended Summary",
    "Parameters",
    "Attributes",
    "Methods",
    "Returns",
    "Yields",
    "Receives",
    "Other Parameters",
    "Raises",
    "Warns",
    "Warnings",
    "Notes"
  ],
  "item_file": "/IPython/core/magics/ast_mod.py",
  "item_line": 0,
  "item_type": "module",
  "aliases": [
    "IPython.core.magics.ast_mod"
  ],
  "example_section_data": {
    "__type": "Section",
    "__tag": 4015,
    "children": [],
    "title": [],
    "level": 0,
    "target": null
  },
  "see_also": [],
  "signature": null,
  "references": null,
  "qa": "IPython.core.magics.ast_mod",
  "arbitrary": [
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This module contains utility function and classes to inject simple ast transformations based on code strings into IPython. While it is already possible with ast-transformers it is not easy to directly manipulate ast."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "IPython has pre-code and post-code hooks, but are ran from within the IPython machinery so may be inappropriate, for example for performance measurement."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This module give you tools to simplify this, and expose 2 classes:"
            }
          ]
        },
        {
          "__type": "BulletList",
          "__tag": 4053,
          "ordered": false,
          "start": 1,
          "children": [
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "CrossRef",
                      "__tag": 4002,
                      "value": "ReplaceCodeTransformer",
                      "reference": {
                        "__type": "LocalRef",
                        "__tag": 4022,
                        "kind": "module",
                        "path": "IPython.core.magics.ast_mod:ReplaceCodeTransformer"
                      },
                      "kind": "module"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": " which is a simple ast transformer based on code   template,"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "and for advance case:"
            }
          ]
        },
        {
          "__type": "BulletList",
          "__tag": 4053,
          "ordered": false,
          "start": 1,
          "children": [
            {
              "__type": "ListItem",
              "__tag": 4054,
              "children": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "CrossRef",
                      "__tag": 4002,
                      "value": "Mangler",
                      "reference": {
                        "__type": "LocalRef",
                        "__tag": 4022,
                        "kind": "module",
                        "path": "IPython.core.magics.ast_mod:Mangler"
                      },
                      "kind": "module"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": " which is a simple ast transformer that mangle names in the ast."
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Example, let's try to make a simple version of the "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "timeit"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " magic, that run a code snippet 10 times and print the average time taken."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Basically we want to run :"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "from time import perf_counter\nnow = perf_counter()\nfor i in range(10):\n    __code__ # our code\nprint(f\"Time taken: {(perf_counter() - now)/10}\")\n__ret__ # the result of the last statement",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Where "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "__code__"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is the code snippet we want to run, and "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "__ret__"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is the result, so that if we for example run "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "dataframe.head()",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " IPython still display the head of dataframe instead of nothing."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Here is a complete example of a file "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "timit2.py",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " that define such a magic:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "from IPython.core.magic import (\n    Magics,\n    magics_class,\n    line_cell_magic,\n)\nfrom IPython.core.magics.ast_mod import ReplaceCodeTransformer\nfrom textwrap import dedent\nimport ast\n\ntemplate = template = dedent('''\n    from time import perf_counter\n    now = perf_counter()\n    for i in range(10):\n        __code__\n    print(f\"Time taken: {(perf_counter() - now)/10}\")\n    __ret__\n'''\n)\n\n\n@magics_class\nclass AstM(Magics):\n    @line_cell_magic\n    def t2(self, line, cell):\n        transformer = ReplaceCodeTransformer.from_string(template)\n        transformer.debug = True\n        transformer.mangler.debug = True\n        new_code = transformer.visit(ast.parse(cell))\n        return exec(compile(new_code, \"<ast>\", \"exec\"))\n\n\ndef load_ipython_extension(ip):\n    ip.register_magics(AstM)",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "In [1]: %load_ext timit2\n\nIn [2]: %%t2\n   ...: import time\n   ...: time.sleep(0.05)\n   ...:\n   ...:\nTime taken: 0.05435649999999441",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "If you wish to ran all the code enter in IPython in an ast transformer, you can do so as well:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer\n   ...:\n   ...: template = '''\n   ...: from time import perf_counter\n   ...: now = perf_counter()\n   ...: __code__\n   ...: print(f\"Code ran in {perf_counter()-now}\")\n   ...: __ret__'''\n   ...:\n   ...: get_ipython().ast_transformers.append(ReplaceCodeTransformer.from_string(template))\n\nIn [2]: 1+1\nCode ran in 3.40410006174352e-05\nOut[2]: 2",
          "execution_status": null,
          "out": ""
        }
      ],
      "title": [],
      "level": 0,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The ast transformer above is not hygienic, it may not work if the user code use the same variable names as the ones used in the template. For example."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To help with this by default the "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "ReplaceCodeTransformer",
              "reference": {
                "__type": "LocalRef",
                "__tag": 4022,
                "kind": "module",
                "path": "IPython.core.magics.ast_mod:ReplaceCodeTransformer"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " will mangle all names staring with 3 underscores. This is a simple heuristic that should work in most case, but can be cumbersome in some case. We provide a "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "Mangler",
              "reference": {
                "__type": "LocalRef",
                "__tag": 4022,
                "kind": "module",
                "path": "IPython.core.magics.ast_mod:Mangler"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " class that can be overridden to change the mangling heuristic, or simply use the "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "mangle_all",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " utility function. It will _try_ to mangle all names (except "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "__ret__",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "__code__",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "), but this include builtins ("
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "print"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "range"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "type"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ") and replace those by invalid identifiers py prepending "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "mangle-"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ": "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "mangle-print"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "mangle-range"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "mangle-type"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " etc. This is not a problem as currently Python AST support invalid identifiers, but it may not be the case in the future."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "You can set "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "ReplaceCodeTransformer.debug=True",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "ReplaceCodeTransformer.mangler.debug=True",
              "domain": null,
              "role": null,
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " to see the code after mangling and transforming:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer, mangle_all\n   ...:\n   ...: template = '''\n   ...: from builtins import type, print\n   ...: from time import perf_counter\n   ...: now = perf_counter()\n   ...: __code__\n   ...: print(f\"Code ran in {perf_counter()-now}\")\n   ...: __ret__'''\n   ...:\n   ...: transformer = ReplaceCodeTransformer.from_string(template, mangling_predicate=mangle_all)\n\n\nIn [2]: transformer.debug = True\n   ...: transformer.mangler.debug = True\n   ...: get_ipython().ast_transformers.append(transformer)\n\nIn [3]: 1+1\nMangling Alias mangle-type\nMangling Alias mangle-print\nMangling Alias mangle-perf_counter\nMangling now\nMangling perf_counter\nNot mangling __code__\nMangling print\nMangling perf_counter\nMangling now\nNot mangling __ret__\n---- Transformed code ----\nfrom builtins import type as mangle-type, print as mangle-print\nfrom time import perf_counter as mangle-perf_counter\nmangle-now = mangle-perf_counter()\nret-tmp = 1 + 1\nmangle-print(f'Code ran in {mangle-perf_counter() - mangle-now}')\nret-tmp\n---- ---------------- ----\nCode ran in 0.00013654199938173406\nOut[3]: 2",
          "execution_status": null,
          "out": ""
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Hygiene and Mangling"
        }
      ],
      "level": 0,
      "target": null
    }
  ],
  "local_refs": []
}