<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter 21. Using Python</title><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><link rel="start" href="index.html" title="A-A-P Recipe Executive"><link rel="up" href="user.html" title="Part II. User Manual"><link rel="prev" href="user-issue.html" title="Chapter 20. Issue Tracking"><link rel="next" href="user-porting.html" title="Chapter 22. Porting an Application"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table width="100%" id="navtable"><tbody><tr><td align="left" class="left" width="33%"><b><a href="http://www.a-a-p.org">A-A-P home page</a></b></td><td align="center" class="center" width="34%"><b><a href="index.html">A-A-P Recipe Executive</a></b></td><td align="right" class="right" width="33%"></td></tr><tr><td align="left" class="left"><a accesskey="p" href="user-issue.html">Prev</a></td><td align="center" class="center">User Manual</td><td align="right" class="right"><a accesskey="n" href="user-porting.html">Next</a></td></tr></tbody></table><hr><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="user-python"></a>Chapter 21. Using Python</h2></div></div></div><p> Python commands can be used where <span class="application">Aap</span> commands are not sufficient. This includes flow control, selecting the commands to be executed and repeating commands. </p><h2><a name="id2649018"></a>Using Python Lines</h2><p> Single lines of Python code can be included in the recipe by prepending "@". This is most often used for flow control: </p><pre class="programlisting"> @if os.path.isdir("/usr/local/bin"): :copy $File /usr/local/bin </pre><p> You can write multiple Python commands, just prefix a "@" to every line. Do remember that the amount of indent is used to form command blocks. The indent that is used excludes the "@" character. When there is a non-white character after the "@", the "@" is removed. When there is white space after the "@" it is replaced with a space. Generally you don't need to worry about this, if the indenting looks right it probably is. </p><p> The main advantage of using single Python lines is that they can be mixed freely with <span class="application">Aap</span> recipe command lines. You can use Python lines both at the recipe level and in build commands. Again, just make sure the indent indicates command blocks. </p><p> To learn using Python start at the Python web site: <a href="http://www.python.org/doc/" target="_top">http://www.python.org/doc/</a> </p><h2><a name="id2649735"></a>Using Aap variables in Python</h2><p> You can use all the Aap variables in Python code. You don't use the "$", Python syntax does not use a dollar for variables. </p><p> When using a scope name, as in "_recipe.var", the variable otherwise looks the same as in Aap commands. But when omitting a scope name it works differently. While "$var" in Aap searches for "var" in the "_no" scope, this does not happen for Python. Python only looks in the current scope. Thus you must explicitly specify "_no.var" in Python code to get the same effect as "$var" in an Aap command. </p><p> In the following example a local variable "system" is used: </p><pre class="programlisting"> CFLAGS = -DFOO all: system = $OSTYPE @if system == "posix": @ flags = _recipe.CFLAGS </pre><p> The same thing could be done by accessing $OSTYPE directly from Python: </p><pre class="programlisting"> CFLAGS = -DFOO all: @if _no.OSTYPE == "posix": @ flags = _recipe.CFLAGS </pre><h2><a name="python-expression"></a>Using Python Expressions</h2><p> In an assignment, command arguments and most other places a Python expression can be used in backticks. Expanding this is done before expanding $VAR items, because this allows the possibility to use the Python expression to result in the name of a variable. Example: </p><pre class="programlisting"> foovaridx = 5 Foo = $Src`foovaridx` </pre><p> Is equivalent to: </p><pre class="programlisting"> Foo = $Src5 </pre><p> The result of the Python expression in backticks should be a string or a list of strings. A list is automatically converted to a white-separated string of all list items. </p><p> A Python expression cannot be used for the variable name in an assignment. This doesn't work: </p><pre class="programlisting"> `varname` = this does not work </pre><p> If you really need this, use a Python command instead: </p><pre class="programlisting"> @eval(varname + ' = "value"') </pre><p> When using a function from a module, it must be imported first. Example: </p><pre class="programlisting"> @from httplib import HTTP Connection = `HTTP('www.microsoft.com')` </pre><p> For your convenience these things are imported for you already: </p><pre class="programlisting"> from glob import glob from RecPython import * </pre><p> The RecPython module defines the Python functions listed in <a href="ref-python.html" title="Chapter 41. A-A-P Python functions">Chapter 41, <i>A-A-P Python functions</i></a>. </p><p> A backtick in the Python expression has to be escaped to avoid it being recognized as the end of the expression: </p><pre class="programlisting"> CMD = `my_func("$(`)grep -l foo *.c$(`)")` </pre><p> contains the Python expression: </p><pre class="programlisting"> my_func("`grep -l foo *.c`") </pre><p> In the result of the Python expression $ characters are doubled, to avoid them being interpreted as the start of a variable reference. Otherwise Python expressions with arbitrary results would always have to be filtered explicitly. When the resulting string is used the $$ will be reduced to a single $ again. </p><p> The result of the expression is used as a string in place of the expression and the backticks. Example: </p><pre class="programlisting"> Foo = foo/`glob("*.tmp")` </pre><p> Would be equivalent to: </p><pre class="programlisting"> Foo = foo/one.tmp two.tmp </pre><p> Note that "foo/" is only prepended to the whole result, not each white-separated item. If you do want rc-style expansion, use two commands: </p><pre class="programlisting"> TT = `glob("*.tmp")` Foo = foo/$*TT </pre><p> Equivalent to: </p><pre class="programlisting"> Foo = foo/one.tmp foo/two.tmp </pre><p> Note that a following attribute is only attached to the last item resulting from the Python expression. </p><pre class="programlisting"> Source = `glob('*.c')` {check = md5} </pre><p> Can be equivalent to: </p><pre class="programlisting"> Source = foo.c bar.c {check = md5} </pre><p> To apply it to all items, use the <a href="ref-commands.html#cmd-attr">:attr</a> command: </p><pre class="programlisting"> Source = `glob('*.c')` :attr {check = md5} $Source </pre><p> Watch out for unexpected results when rc-style expansion is done for $*VAR. Example: </p><pre class="programlisting"> VAR = one two Foo = $*VAR/`glob("*.tmp")` </pre><p> Would result in: </p><pre class="programlisting"> Foo = one/one.tmp two/one.tmp two.tmp </pre><p> because the `` part is expanded first, thus the assignment is executed like: </p><pre class="programlisting"> Foo = $*VAR/one.tmp two.tmp </pre><p> The backticks for a Python expression are also recognized inside quotes. Thus you need to escape the special meaning there: </p><pre class="programlisting"> Foo = "this$(`)file" that$(`)file </pre><p> Backtick expressions can be used inside a string if you really need this: </p><pre class="programlisting"> DIR = /home/foo /home/bar :print "`DIR + "/fi le"`" </pre><p> results in: </p><div class="literallayout"><p> "/home/foo /home/bar/fi le"<br> </p></div><p> Compare this to: </p><pre class="programlisting"> :print "$*DIR/fi le" </pre><p> which results in: </p><div class="literallayout"><p> "/home/foo/fi le" "/home/bar/fi le"<br> </p></div><h2><a name="id2650899"></a>Python Block</h2><p> A block of Python commands is started with a <a href="ref-commands.html#cmd-python">:python</a> command. If no terminator string is specified the python code ends where the indent is equal to or less than the <a href="ref-commands.html#cmd-python">:python</a> command: </p><pre class="programlisting"> Source = foo.c bar.c :python for i in items: Source = Source + " " + i Target = foo </pre><p> Optionally a terminator string may be specified. The indent of the Python code may then drop below the indent of the <a href="ref-commands.html#cmd-python">:python</a> command. </p><p> The terminator cannot contain white space. A comment may follow. The Python block continues until the terminator string is found in a line by itself. It may be preceded and followed by white space and a comment may follow. Example: </p><pre class="programlisting"> @if ok: :print finding include files :python EOF # start of the Python block include = glob("include/*.c") EOF # end of the Python block </pre><h2><a name="id2650939"></a>Useful Python Items</h2><p> A list of Python functions defined by <span class="application">Aap</span> can be found in the reference manual, <a href="ref-python.html" title="Chapter 41. A-A-P Python functions">Chapter 41, <i>A-A-P Python functions</i></a>. </p><pre class="programlisting"> VAR = `os.environ.get('VAR', 'default')` </pre><p> Obtain environment variable $VAR. If it is not set use "default". </p><pre class="programlisting"> @os.environ["PATH"] = mypath </pre><p> Set an environment variable. </p><pre class="programlisting"> files = `glob("*.ext")` </pre><p> Obtain a list of files matching "*.ext". Aap will take care of turning the list that glob() returns into a string, using quotes where needed. </p><p> The difference with using "*.ext" directly is that the expansion is done right here, not later when $files is used. The catch with using glob() here is that when a file name contains a wildcard character it may be expanded again. So long as that expansion fails or matches the same file name it is still OK, but it becomes rather unpredictable. Use <a href="ref-python.html#python-wildescape">wildescape()</a> when needed. </p><pre class="programlisting"> choice = `raw_input("Enter the value: ")` </pre><p> Prompt the user to enter a value. </p><pre class="programlisting"> tempfile = `tempfname()` </pre><p> Get a file name to use for temporary files. The file will not exist. See <a href="ref-python.html#python-tempfname">tempfname()</a>. </p><p> If you create it you need to make sure it is deleted afterwards. Example: </p><pre class="programlisting"> tempfile = `tempfname()` @try: :print >$tempfile start of file :print >>$tempfile $this variable may not exist and cause an error :cat $tempfile @finally: # this is executed whether there is an error or not :del $tempfile </pre><p> Exception handling can be useful to handle situations where you know something might fail. Example: </p><pre class="programlisting"> @try: :sys links -dump exec.html >exec.txt @except: :sys lynx -dump -nolist exec.html >exec.txt </pre><p> This will execute the "links" command. If this fails for some reason (e.g., because a new version of "links" does not support the "-dump" argument) then the "lynx" command will be used. </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="user-issue.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="user.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="user-porting.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 20. Issue Tracking </td><td width="20%" align="center"><a accesskey="h" href="index.html"> Contents</a></td><td width="40%" align="right" valign="top"> Chapter 22. Porting an Application</td></tr></table></div></body></html>