From 114081f8adafa16283df30c456716a1bef4758d0 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 2 Mar 2020 03:14:06 +0000 Subject: bpo-39199: Add descriptions of non-deprecated nodes to the AST module documentation (GH-17812) Adapted from https://greentreesnakes.readthedocs.io Co-authored-by: Karthikeyan Singaravelan Co-authored-by: Carol Willing --- Doc/library/ast.rst | 1503 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1497 insertions(+), 6 deletions(-) diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index bfd571d..ea30578 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -7,6 +7,10 @@ .. sectionauthor:: Martin v. Löwis .. sectionauthor:: Georg Brandl +.. testsetup:: + + import ast + **Source code:** :source:`Lib/ast.py` -------------- @@ -23,6 +27,17 @@ classes all inherit from :class:`ast.AST`. An abstract syntax tree can be compiled into a Python code object using the built-in :func:`compile` function. +.. _abstract-grammar: + +Abstract Grammar +---------------- + +The abstract grammar is currently defined as follows: + +.. literalinclude:: ../../Parser/Python.asdl + :language: none + + Node classes ------------ @@ -112,16 +127,1492 @@ Node classes but they will be removed in future Python releases. In the meanwhile, instantiating them will return an instance of a different class. +Literals +^^^^^^^^ + +.. class:: Constant(value) + + A constant value. The ``value`` attribute of the ``Constant`` literal contains the + Python object it represents. The values represented can be simple types + such as a number, string or ``None``, but also immutable container types + (tuples and frozensets) if all of their elements are constant. + + .. doctest:: + + >>> print(ast.dump(ast.parse("123"), indent=4)) + Module( + body=[ + Expr( + value=Constant(value=123, kind=None))], + type_ignores=[]) + + +.. class:: FormattedValue(value, conversion, format_spec) + + Node representing a single formatting field in an f-string. If the string + contains a single formatting field and nothing else the node can be + isolated otherwise it appears in :class:`JoinedStr`. + + * ``value`` is any expression node (such as a literal, a variable, or a + function call). + * ``conversion`` is an integer: + + * -1: no formatting + * 115: ``!s`` string formatting + * 114: ``!r`` repr formatting + * 97: ``!a`` ascii formatting + + * ``format_spec`` is a :class:`JoinedStr` node representing the formatting + of the value, or ``None`` if no format was specified. Both + ``conversion`` and ``format_spec`` can be set at the same time. + + +.. class:: JoinedStr(values) + + An f-string, comprising a series of :class:`FormattedValue` and :class:`Constant` + nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"'), indent=4)) + Module( + body=[ + Expr( + value=JoinedStr( + values=[ + Constant(value='sin(', kind=None), + FormattedValue( + value=Name(id='a', ctx=Load()), + conversion=-1, + format_spec=None), + Constant(value=') is ', kind=None), + FormattedValue( + value=Call( + func=Name(id='sin', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]), + conversion=-1, + format_spec=JoinedStr( + values=[ + Constant(value='.3', kind=None)]))]))], + type_ignores=[]) + + +.. class:: List(elts, ctx) + Tuple(elts, ctx) + + A list or tuple. ``elts`` holds a list of nodes representing the elements. + ``ctx`` is :class:`Store` if the container is an assignment target (i.e. + ``(x,y)=something``), and :class:`Load` otherwise. + + .. doctest:: + + >>> print(ast.dump(ast.parse("[1, 2, 3]"), indent=4)) + Module( + body=[ + Expr( + value=List( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load()))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("(1, 2, 3)"), indent=4)) + Module( + body=[ + Expr( + value=Tuple( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load()))], + type_ignores=[]) + + +.. class:: Set(elts) + + A set. ``elts`` holds a list of nodes representing the set's elements. + + .. doctest:: + + >>> print(ast.dump(ast.parse("{1, 2, 3}"), indent=4)) + Module( + body=[ + Expr( + value=Set( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)]))], + type_ignores=[]) + + +.. class:: Dict(keys, values) + + A dictionary. ``keys`` and ``values`` hold lists of nodes representing the + keys and the values respectively, in matching order (what would be returned + when calling :code:`dictionary.keys()` and :code:`dictionary.values()`). + + When doing dictionary unpacking using dictionary literals the expression to be + expanded goes in the ``values`` list, with a ``None`` at the corresponding + position in ``keys``. + + .. doctest:: + + >>> print(ast.dump(ast.parse("{'a':1, **d}"), indent=4)) + Module( + body=[ + Expr( + value=Dict( + keys=[ + Constant(value='a', kind=None), + None], + values=[ + Constant(value=1, kind=None), + Name(id='d', ctx=Load())]))], + type_ignores=[]) + + +Variables +^^^^^^^^^ + +.. class:: Name(id, ctx) + + A variable name. ``id`` holds the name as a string, and ``ctx`` is one of + the following types. + + +.. class:: Load() + Store() + Del() + + Variable references can be used to load the value of a variable, to assign + a new value to it, or to delete it. Variable references are given a context + to distinguish these cases. + + .. doctest:: + + >>> print(ast.dump(ast.parse('a'), indent=4)) + Module( + body=[ + Expr( + value=Name(id='a', ctx=Load()))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse('a = 1'), indent=4)) + Module( + body=[ + Assign( + targets=[ + Name(id='a', ctx=Store())], + value=Constant(value=1, kind=None), + type_comment=None)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse('del a'), indent=4)) + Module( + body=[ + Delete( + targets=[ + Name(id='a', ctx=Del())])], + type_ignores=[]) + + +.. class:: Starred(value, ctx) + + A ``*var`` variable reference. ``value`` holds the variable, typically a + :class:`Name` node. This type must be used when building a :class:`Call` + node with ``*args``. + + .. doctest:: -.. _abstract-grammar: + >>> print(ast.dump(ast.parse('a, *b = it'), indent=4)) + Module( + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='a', ctx=Store()), + Starred( + value=Name(id='b', ctx=Store()), + ctx=Store())], + ctx=Store())], + value=Name(id='it', ctx=Load()), + type_comment=None)], + type_ignores=[]) -Abstract Grammar ----------------- -The abstract grammar is currently defined as follows: +Expressions +^^^^^^^^^^^ -.. literalinclude:: ../../Parser/Python.asdl - :language: none +.. class:: Expr(value) + + When an expression, such as a function call, appears as a statement by itself + with its return value not used or stored, it is wrapped in this container. + ``value`` holds one of the other nodes in this section, a :class:`Constant`, a + :class:`Name`, a :class:`Lambda`, a :class:`Yield` or :class:`YieldFrom` node. + + .. doctest:: + + >>> print(ast.dump(ast.parse('-a'), indent=4)) + Module( + body=[ + Expr( + value=UnaryOp( + op=USub(), + operand=Name(id='a', ctx=Load())))], + type_ignores=[]) + + +.. class:: UnaryOp(op, operand) + + A unary operation. ``op`` is the operator, and ``operand`` any expression + node. + + +.. class:: UAdd + USub + Not + Invert + + Unary operator tokens. :class:`Not` is the ``not`` keyword, :class:`Invert` + is the ``~`` operator. + + .. doctest:: + + >>> print(ast.dump(ast.parse("not x"), indent=4)) + Module( + body=[ + Expr( + value=UnaryOp( + op=Not(), + operand=Name(id='x', ctx=Load())))], + type_ignores=[]) + + +.. class:: BinOp(left, op, right) + + A binary operation (like addition or division). ``op`` is the operator, and + ``left`` and ``right`` are any expression nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x + y"), indent=4)) + Module( + body=[ + Expr( + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())))], + type_ignores=[]) + + +.. class:: Add + Sub + Mult + Div + FloorDiv + Mod + Pow + LShift + RShift + BitOr + BitXor + BitAnd + MatMult + + Binary operator tokens. + + +.. class:: BoolOp(op, values) + + A boolean operation, 'or' or 'and'. ``op`` is :class:`Or` or :class:`And`. + ``values`` are the values involved. Consecutive operations with the same + operator, such as ``a or b or c``, are collapsed into one node with several + values. + + This doesn't include ``not``, which is a :class:`UnaryOp`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x or y"), indent=4)) + Module( + body=[ + Expr( + value=BoolOp( + op=Or(), + values=[ + Name(id='x', ctx=Load()), + Name(id='y', ctx=Load())]))], + type_ignores=[]) + + +.. class:: And + Or + + Boolean operator tokens. + + +.. class:: Compare(left, ops, comparators) + + A comparison of two or more values. ``left`` is the first value in the + comparison, ``ops`` the list of operators, and ``comparators`` the list + of values after the first element in the comparison. + + .. doctest:: + + >>> print(ast.dump(ast.parse("1 < a < 10"), indent=4)) + Module( + body=[ + Expr( + value=Compare( + left=Constant(value=1, kind=None), + ops=[ + Lt(), + Lt()], + comparators=[ + Name(id='a', ctx=Load()), + Constant(value=10, kind=None)]))], + type_ignores=[]) + + +.. class:: Eq + NotEq + Lt + LtE + Gt + GtE + Is + IsNot + In + NotIn + + Comparison operator tokens. + + +.. class:: Call(func, args, keywords, starargs, kwargs) + + A function call. ``func`` is the function, which will often be a + :class:`Name` or :class:`Attribute` object. Of the arguments: + + * ``args`` holds a list of the arguments passed by position. + * ``keywords`` holds a list of :class:`keyword` objects representing + arguments passed by keyword. + + When creating a ``Call`` node, ``args`` and ``keywords`` are required, but + they can be empty lists. ``starargs`` and ``kwargs`` are optional. + + .. doctest:: + + >>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)'), indent=4)) + Module( + body=[ + Expr( + value=Call( + func=Name(id='func', ctx=Load()), + args=[ + Name(id='a', ctx=Load()), + Starred( + value=Name(id='d', ctx=Load()), + ctx=Load())], + keywords=[ + keyword( + arg='b', + value=Name(id='c', ctx=Load())), + keyword( + arg=None, + value=Name(id='e', ctx=Load()))]))], + type_ignores=[]) + + +.. class:: keyword(arg, value) + + A keyword argument to a function call or class definition. ``arg`` is a raw + string of the parameter name, ``value`` is a node to pass in. + + +.. class:: IfExp(test, body, orelse) + + An expression such as ``a if b else c``. Each field holds a single node, so + in the following example, all three are :class:`Name` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("a if b else c"), indent=4)) + Module( + body=[ + Expr( + value=IfExp( + test=Name(id='b', ctx=Load()), + body=Name(id='a', ctx=Load()), + orelse=Name(id='c', ctx=Load())))], + type_ignores=[]) + + +.. class:: Attribute(value, attr, ctx) + + Attribute access, e.g. ``d.keys``. ``value`` is a node, typically a + :class:`Name`. ``attr`` is a bare string giving the name of the attribute, + and ``ctx`` is :class:`Load`, :class:`Store` or :class:`Del` according to how + the attribute is acted on. + + .. doctest:: + + >>> print(ast.dump(ast.parse('snake.colour'), indent=4)) + Module( + body=[ + Expr( + value=Attribute( + value=Name(id='snake', ctx=Load()), + attr='colour', + ctx=Load()))], + type_ignores=[]) + + +.. class:: NamedExpr(target, value) + + A named expression. This AST node is produced by the assignment expressions + operator (also known as the walrus operator). As opposed to the :class:`Assign` + node in which the first argument can be multiple nodes, in this case both + ``target`` and ``value`` must be single nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("(x := 4)"), indent=4)) + Module( + body=[ + Expr( + value=NamedExpr( + target=Name(id='x', ctx=Store()), + value=Constant(value=4, kind=None)))], + type_ignores=[]) + + +Subscripting +~~~~~~~~~~~~ + +.. class:: Subscript(value, slice, ctx) + + A subscript, such as ``l[1]``. ``value`` is the object, often a + :class:`Name`. ``slice`` is one of :class:`Index`, :class:`Slice` or + :class:`ExtSlice`. ``ctx`` is :class:`Load`, :class:`Store` or :class:`Del` + according to the action performed with the subscript. + + +.. class:: Index(value) + + Simple subscripting with a single value + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=Index( + value=Constant(value=1, kind=None)), + ctx=Load()))], + type_ignores=[]) + + +.. class:: Slice(lower, upper, step) + + Regular slicing (on the form x:y). + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1:2]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + ctx=Load()))], + type_ignores=[]) + + +.. class:: ExtSlice(dims) + + Advanced slicing. ``dims`` holds a list of :class:`Slice` and + :class:`Index` nodes + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1:2, 3]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=ExtSlice( + dims=[ + Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + Index( + value=Constant(value=3, kind=None))]), + ctx=Load()))], + type_ignores=[]) + + +Comprehensions +~~~~~~~~~~~~~~ + +.. class:: ListComp(elt, generators) + SetComp(elt, generators) + GeneratorExp(elt, generators) + DictComp(key, value, generators) + + List and set comprehensions, generator expressions, and dictionary + comprehensions. ``elt`` (or ``key`` and ``value``) is a single node + representing the part that will be evaluated for each item. + + ``generators`` is a list of :class:`comprehension` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("[x for x in numbers]"), indent=4)) + Module( + body=[ + Expr( + value=ListComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("{x: x**2 for x in numbers}"), indent=4)) + Module( + body=[ + Expr( + value=DictComp( + key=Name(id='x', ctx=Load()), + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Pow(), + right=Constant(value=2, kind=None)), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("{x for x in numbers}"), indent=4)) + Module( + body=[ + Expr( + value=SetComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + +.. class:: comprehension(target, iter, ifs, is_async) + + One ``for`` clause in a comprehension. ``target`` is the reference to use for + each element - typically a :class:`Name` or :class:`Tuple` node. ``iter`` + is the object to iterate over. ``ifs`` is a list of test expressions: each + ``for`` clause can have multiple ``ifs``. + + ``is_async`` indicates a comprehension is asynchronous (using an + ``async for`` instead of ``for``). The value is an integer (0 or 1). + + .. doctest:: + + >>> print(ast.dump(ast.parse("[ord(c) for line in file for c in line]", mode='eval'), + ... indent=4)) # Multiple comprehensions in one. + Expression( + body=ListComp( + elt=Call( + func=Name(id='ord', ctx=Load()), + args=[ + Name(id='c', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='line', ctx=Store()), + iter=Name(id='file', ctx=Load()), + ifs=[], + is_async=0), + comprehension( + target=Name(id='c', ctx=Store()), + iter=Name(id='line', ctx=Load()), + ifs=[], + is_async=0)])) + + >>> print(ast.dump(ast.parse("(n**2 for n in it if n>5 if n<10)", mode='eval'), + ... indent=4)) # generator comprehension + Expression( + body=GeneratorExp( + elt=BinOp( + left=Name(id='n', ctx=Load()), + op=Pow(), + right=Constant(value=2, kind=None)), + generators=[ + comprehension( + target=Name(id='n', ctx=Store()), + iter=Name(id='it', ctx=Load()), + ifs=[ + Compare( + left=Name(id='n', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=5, kind=None)]), + Compare( + left=Name(id='n', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=10, kind=None)])], + is_async=0)])) + + >>> print(ast.dump(ast.parse("async def f():" + ... " return [i async for i in soc]"), + ... indent=4)) # Async comprehension + Module( + body=[ + AsyncFunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=[ + Return( + value=ListComp( + elt=Name(id='i', ctx=Load()), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Name(id='soc', ctx=Load()), + ifs=[], + is_async=1)]))], + decorator_list=[], + returns=None, + type_comment=None)], + type_ignores=[]) + +Statements +^^^^^^^^^^ + +.. class:: Assign(targets, value, type_comment) + + An assignment. ``targets`` is a list of nodes, and ``value`` is a single node. + + Multiple nodes in ``targets`` represents assigning the same value to each. + Unpacking is represented by putting a :class:`Tuple` or :class:`List` + within ``targets``. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + .. doctest:: + + >>> print(ast.dump(ast.parse("a = b = 1"), indent=4)) # Multiple assignment + Module( + body=[ + Assign( + targets=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + value=Constant(value=1, kind=None), + type_comment=None)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a,b = c"), indent=4)) # Unpacking + Module( + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + ctx=Store())], + value=Name(id='c', ctx=Load()), + type_comment=None)], + type_ignores=[]) + + +.. class:: AnnAssign(target, annotation, value, simple) + + An assignment with a type annotation. ``target`` is a single node and can + be a :class:`Name`, a :class:`Attribute` or a :class:`Subscript`. + ``annotation`` is the annotation, such as a :class:`Constant` or :class:`Name` + node. ``value`` is a single optional node. ``simple`` is a boolean integer + set to True for a :class:`Name` node in ``target`` that do not appear in + between parenthesis and are hence pure names and not expressions. + + .. doctest:: + + >>> print(ast.dump(ast.parse("c: int"), indent=4)) + Module( + body=[ + AnnAssign( + target=Name(id='c', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=1)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("(a): int = 1"), indent=4)) # Annotation with parenthesis + Module( + body=[ + AnnAssign( + target=Name(id='a', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=Constant(value=1, kind=None), + simple=0)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a.b: int"), indent=4)) # Attribute annotation + Module( + body=[ + AnnAssign( + target=Attribute( + value=Name(id='a', ctx=Load()), + attr='b', + ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=0)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a[1]: int"), indent=4)) # Subscript annotation + Module( + body=[ + AnnAssign( + target=Subscript( + value=Name(id='a', ctx=Load()), + slice=Index( + value=Constant(value=1, kind=None)), + ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=0)], + type_ignores=[]) + + +.. class:: AugAssign(target, op, value) + + Augmented assignment, such as ``a += 1``. In the following example, + ``target`` is a :class:`Name` node for ``x`` (with the :class:`Store` + context), ``op`` is :class:`Add`, and ``value`` is a :class:`Constant` with + value for 1. + + The ``target`` attribute connot be of class :class:`Tuple` or :class:`List`, + unlike the targets of :class:`Assign`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x += 2"), indent=4)) + Module( + body=[ + AugAssign( + target=Name(id='x', ctx=Store()), + op=Add(), + value=Constant(value=2, kind=None))], + type_ignores=[]) + + +.. class:: Raise(exc, cause) + + A ``raise`` statement. ``exc`` is the exception object to be raised, normally a + :class:`Call` or :class:`Name`, or ``None`` for a standalone ``raise``. + ``cause`` is the optional part for ``y`` in ``raise x from y``. + + .. doctest:: + + >>> print(ast.dump(ast.parse("raise x from y"), indent=4)) + Module( + body=[ + Raise( + exc=Name(id='x', ctx=Load()), + cause=Name(id='y', ctx=Load()))], + type_ignores=[]) + + +.. class:: Assert(test, msg) + + An assertion. ``test`` holds the condition, such as a :class:`Compare` node. + ``msg`` holds the failure message. + + .. doctest:: + + >>> print(ast.dump(ast.parse("assert x,y"), indent=4)) + Module( + body=[ + Assert( + test=Name(id='x', ctx=Load()), + msg=Name(id='y', ctx=Load()))], + type_ignores=[]) + + +.. class:: Delete(targets) + + Represents a ``del`` statement. ``targets`` is a list of nodes, such as + :class:`Name`, :class:`Attribute` or :class:`Subscript` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("del x,y,z"), indent=4)) + Module( + body=[ + Delete( + targets=[ + Name(id='x', ctx=Del()), + Name(id='y', ctx=Del()), + Name(id='z', ctx=Del())])], + type_ignores=[]) + + +.. class:: Pass() + + A ``pass`` statement. + + .. doctest:: + + >>> print(ast.dump(ast.parse("pass"), indent=4)) + Module( + body=[ + Pass()], + type_ignores=[]) + + +Other statements which are only applicable inside functions or loops are +described in other sections. + +Imports +~~~~~~~ + +.. class:: Import(names) + + An import statement. ``names`` is a list of :class:`alias` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("import x,y,z"), indent=4)) + Module( + body=[ + Import( + names=[ + alias(name='x', asname=None), + alias(name='y', asname=None), + alias(name='z', asname=None)])], + type_ignores=[]) + + +.. class:: ImportFrom(module, names, level) + + Represents ``from x import y``. ``module`` is a raw string of the 'from' name, + without any leading dots, or ``None`` for statements such as ``from . import foo``. + ``level`` is an integer holding the level of the relative import (0 means + absolute import). + + .. doctest:: + + >>> print(ast.dump(ast.parse("from y import x,y,z"), indent=4)) + Module( + body=[ + ImportFrom( + module='y', + names=[ + alias(name='x', asname=None), + alias(name='y', asname=None), + alias(name='z', asname=None)], + level=0)], + type_ignores=[]) + + +.. class:: alias(name, asname) + + Both parameters are raw strings of the names. ``asname`` can be ``None`` if + the regular name is to be used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("from ..foo.bar import a as b, c"), indent=4)) + Module( + body=[ + ImportFrom( + module='foo.bar', + names=[ + alias(name='a', asname='b'), + alias(name='c', asname=None)], + level=2)], + type_ignores=[]) + +Control flow +^^^^^^^^^^^^ + +.. note:: + Optional clauses such as ``else`` are stored as an empty list if they're + not present. + +.. class:: If(test, body, orelse) + + An ``if`` statement. ``test`` holds a single node, such as a :class:`Compare` + node. ``body`` and ``orelse`` each hold a list of nodes. + + ``elif`` clauses don't have a special representation in the AST, but rather + appear as extra :class:`If` nodes within the ``orelse`` section of the + previous one. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... if x: + ... ... + ... elif y: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + If( + test=Name(id='x', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + If( + test=Name(id='y', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])])], + type_ignores=[]) + + +.. class:: For(target, iter, body, orelse, type_comment) + + A ``for`` loop. ``target`` holds the variable(s) the loop assigns to, as a + single :class:`Name`, :class:`Tuple` or :class:`List` node. ``iter`` holds + the item to be looped over, again as a single node. ``body`` and ``orelse`` + contain lists of nodes to execute. Those in ``orelse`` are executed if the + loop finishes normally, rather than via a ``break`` statement. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... for x in y: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + For( + target=Name(id='x', ctx=Store()), + iter=Name(id='y', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + type_comment=None)], + type_ignores=[]) + + +.. class:: While(test, body, orelse) + + A ``while`` loop. ``test`` holds the condition, such as a :class:`Compare` + node. + + .. doctest:: + + >> print(ast.dump(ast.parse(""" + ... while x: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + While( + test=Name(id='x', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + type_ignores=[]) + + +.. class:: Break + Continue + + The ``break`` and ``continue`` statements. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... for a in b: + ... if a > 5: + ... break + ... else: + ... continue + ... + ... """), indent=4)) + Module( + body=[ + For( + target=Name(id='a', ctx=Store()), + iter=Name(id='b', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='a', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=5, kind=None)]), + body=[ + Break()], + orelse=[ + Continue()])], + orelse=[], + type_comment=None)], + type_ignores=[]) + + +.. class:: Try(body, handlers, orelse, finalbody) + + ``try`` blocks. All attributes are list of nodes to execute, except for + ``handlers``, which is a list of :class:`ExceptHandler` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... try: + ... ... + ... except Exception: + ... ... + ... except OtherException as e: + ... ... + ... else: + ... ... + ... finally: + ... ... + ... """), indent=4)) + Module( + body=[ + Try( + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name=None, + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))]), + ExceptHandler( + type=Name(id='OtherException', ctx=Load()), + name='e', + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + finalbody=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + type_ignores=[]) + + +.. class:: ExceptHandler(type, name, body) + + A single ``except`` clause. ``type`` is the exception type it will match, + typically a :class:`Name` node (or ``None`` for a catch-all ``except:`` clause). + ``name`` is a raw string for the name to hold the exception, or ``None`` if + the clause doesn't have ``as foo``. ``body`` is a list of nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... try: + ... a + 1 + ... except TypeError: + ... pass + ... """), indent=4)) + Module( + body=[ + Try( + body=[ + Expr( + value=BinOp( + left=Name(id='a', ctx=Load()), + op=Add(), + right=Constant(value=1, kind=None)))], + handlers=[ + ExceptHandler( + type=Name(id='TypeError', ctx=Load()), + name=None, + body=[ + Pass()])], + orelse=[], + finalbody=[])], + type_ignores=[]) + + +.. class:: With(items, body, type_comment) + + A ``with`` block. ``items`` is a list of :class:`withitem` nodes representing + the context managers, and ``body`` is the indented block inside the context. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + +.. class:: withitem(context_expr, optional_vars) + + A single context manager in a ``with`` block. ``context_expr`` is the context + manager, often a :class:`Call` node. ``optional_vars`` is a :class:`Name`, + :class:`Tuple` or :class:`List` for the ``as foo`` part, or ``None`` if that + isn't used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... with a as b, c as d: + ... something(b, d) + ... """), indent=4)) + Module( + body=[ + With( + items=[ + withitem( + context_expr=Name(id='a', ctx=Load()), + optional_vars=Name(id='b', ctx=Store())), + withitem( + context_expr=Name(id='c', ctx=Load()), + optional_vars=Name(id='d', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Name(id='something', ctx=Load()), + args=[ + Name(id='b', ctx=Load()), + Name(id='d', ctx=Load())], + keywords=[]))], + type_comment=None)], + type_ignores=[]) + + +Function and class definitions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. class:: FunctionDef(name, args, body, decorator_list, returns, type_comment) + + A function definition. + + * ``name`` is a raw string of the function name. + * ``args`` is a :class:`arguments` node. + * ``body`` is the list of nodes inside the function. + * ``decorator_list`` is the list of decorators to be applied, stored outermost + first (i.e. the first in the list will be applied last). + * ``returns`` is the return annotation. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + +.. class:: Lambda(args, body) + + ``lambda`` is a minimal function definition that can be used inside an + expression. Unlike :class:`FunctionDef`, ``body`` holds a single node. + + .. doctest:: + + >>> print(ast.dump(ast.parse("lambda x,y: ..."), indent=4)) + Module( + body=[ + Expr( + value=Lambda( + args=arguments( + posonlyargs=[], + args=[ + arg(arg='x', annotation=None, type_comment=None), + arg(arg='y', annotation=None, type_comment=None)], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=Constant(value=Ellipsis, kind=None)))], + type_ignores=[]) + + +.. class:: arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults) + + The arguments for a function. + + * ``posonlyargs``, ``args`` and ``kwonlyargs`` are lists of :class:`arg` nodes. + * ``vararg`` and ``kwarg`` are single :class:`arg` nodes, referring to the + ``*args, **kwargs`` parameters. + * ``kw_defaults`` is a list of default values for keyword-only arguments. If + one is ``None``, the corresponding argument is required. + * ``defaults`` is a list of default values for arguments that can be passed + positionally. If there are fewer defaults, they correspond to the last n + arguments. + + +.. class:: arg(arg, annotation, type_comment) + + A single argument in a list. ``arg`` is a raw string of the argument + name, ``annotation`` is its annotation, such as a :class:`Str` or + :class:`Name` node. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... @decorator1 + ... @decorator2 + ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': + ... pass + ... """), indent=4)) + Module( + body=[ + FunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Constant(value='annotation', kind=None), + type_comment=None), + arg(arg='b', annotation=None, type_comment=None), + arg(arg='c', annotation=None, type_comment=None)], + vararg=arg(arg='d', annotation=None, type_comment=None), + kwonlyargs=[ + arg(arg='e', annotation=None, type_comment=None), + arg(arg='f', annotation=None, type_comment=None)], + kw_defaults=[ + None, + Constant(value=3, kind=None)], + kwarg=arg(arg='g', annotation=None, type_comment=None), + defaults=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None)]), + body=[ + Pass()], + decorator_list=[ + Name(id='decorator1', ctx=Load()), + Name(id='decorator2', ctx=Load())], + returns=Constant(value='return annotation', kind=None), + type_comment=None)], + type_ignores=[]) + + +.. class:: Return(value) + + A ``return`` statement. + + .. doctest:: + + >>> print(ast.dump(ast.parse("return 4"), indent=4)) + Module( + body=[ + Return( + value=Constant(value=4, kind=None))], + type_ignores=[]) + + +.. class:: Yield(value) + YieldFrom(value) + + A ``yield`` or ``yield from`` expression. Because these are expressions, they + must be wrapped in a :class:`Expr` node if the value sent back is not used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("yield x"), indent=4)) + Module( + body=[ + Expr( + value=Yield( + value=Name(id='x', ctx=Load())))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("yield from x"), indent=4)) + Module( + body=[ + Expr( + value=YieldFrom( + value=Name(id='x', ctx=Load())))], + type_ignores=[]) + + +.. class:: Global(names) + Nonlocal(names) + + ``global`` and ``nonlocal`` statements. ``names`` is a list of raw strings. + + .. doctest:: + + >>> print(ast.dump(ast.parse("global x,y,z"), indent=4)) + Module( + body=[ + Global( + names=[ + 'x', + 'y', + 'z'])], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("nonlocal x,y,z"), indent=4)) + Module( + body=[ + Nonlocal( + names=[ + 'x', + 'y', + 'z'])], + type_ignores=[]) + + +.. class:: ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list) + + A class definition. + + * ``name`` is a raw string for the class name + * ``bases`` is a list of nodes for explicitly specified base classes. + * ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'. + Other keywords will be passed to the metaclass, as per `PEP-3115 + `_. + * ``starargs`` and ``kwargs`` are each a single node, as in a function call. + starargs will be expanded to join the list of base classes, and kwargs will + be passed to the metaclass. + * ``body`` is a list of nodes representing the code within the class + definition. + * ``decorator_list`` is a list of nodes, as in :class:`FunctionDef`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... @decorator1 + ... @decorator2 + ... class Foo(base1, base2, metaclass=meta): + ... pass + ... """), indent=4)) + Module( + body=[ + ClassDef( + name='Foo', + bases=[ + Name(id='base1', ctx=Load()), + Name(id='base2', ctx=Load())], + keywords=[ + keyword( + arg='metaclass', + value=Name(id='meta', ctx=Load()))], + body=[ + Pass()], + decorator_list=[ + Name(id='decorator1', ctx=Load()), + Name(id='decorator2', ctx=Load())])], + type_ignores=[]) + +Async and await +^^^^^^^^^^^^^^^ + +.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment) + + An ``async def`` function definition. Has the same fields as + :class:`FunctionDef`. + + +.. class:: Await(value) + + An ``await`` expression. ``value`` is what it waits for. + Only valid in the body of an :class:`AsyncFunctionDef`. + +.. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... async def f(): + ... await other_func() + ... """), indent=4)) + Module( + body=[ + AsyncFunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=[ + Expr( + value=Await( + value=Call( + func=Name(id='other_func', ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=None, + type_comment=None)], + type_ignores=[]) + + +.. class:: AsyncFor(target, iter, body, orelse, type_comment) + AsyncWith(items, body, type_comment) + + ``async for`` loops and ``async with`` context managers. They have the same + fields as :class:`For` and :class:`With`, respectively. Only valid in the + body of an :class:`AsyncFunctionDef`. :mod:`ast` Helpers -- cgit v0.12