<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter 6. 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="tutorial.html" title="Part I. Tutorial"><link rel="prev" href="tutor-variant.html" title="Chapter 5. Building Variants"><link rel="next" href="tutor-cvs.html" title="Chapter 7. Version Control with CVS"></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="tutor-variant.html">Prev</a></td><td align="center" class="center">Tutorial</td><td align="right" class="right"><a accesskey="n" href="tutor-cvs.html">Next</a></td></tr></tbody></table><hr><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tutor-python"></a>Chapter 6. Using Python</h2></div></div></div><p> In various places in the recipe Python commands and expressions can be used. Python is a powerful and portable scripting language. In most recipes you will only use a few Python items. But where needed you can do just about anything with it. </p><h2><a name="id2627492"></a>Expressions</h2><p> (Almost) anywhere you have a value, such as a text string, you can use a Python expression instead. For instance, you could use a Python expression to retrieve the value of an environment variable for use in a recipe, or use an expression to compute some strange value. </p><p> Expressions are written between backticks (` `) and must be valid Python expressions. Some examples: </p><pre class="programlisting"> 1 myhome = `os.environ.get("HOME")` 2 label = `"L"+str(17*22)` </pre><p> The first example line shows how to retrieve an environment variable by using Python's built-in <code class="literal">os.environ</code> module. The second shows how you can use Python to compute something within an <span class="application">Aap</span> recipe. It doesn't do anything useful, but it uses Python to compute the value <code class="literal">L374</code>, and then <span class="application">Aap</span> assigns that value to the variable <code class="literal">label</code>. </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"> Using environment variables is probably not portable. </td></tr></table></div><h2><a name="id2628773"></a>Conditionals</h2><p> When a recipe needs to work both on Unix and on MS-Windows you quickly run into the problem that the compiler does not use the same arguments. Here is an example how you can handle that. </p><pre class="programlisting"> 1 @if OSTYPE == "posix": 2 INCLUDE += -I/usr/local/include 3 @else: 4 INCLUDE += -Ic:/vc/include 5 6 all: 7 :print INCLUDE is "$INCLUDE" </pre><p> The first and third line start with the "@" character. This means a Python command follows. The other lines are normal recipe lines. You can see how these two kinds of lines can be mixed. </p><p> The first line is a simple "if" statement. The <code class="literal">OSTYPE</code> variable is compared with the string "posix". If they compare equal, the next line is executed. When the <code class="literal">OSTYPE</code> variable has a different value the line below <code class="computeroutput">@else:</code> is executed. Executing this recipe on Unix: </p><div class="literallayout"><p> % <strong class="userinput"><code>aap</code></strong><br> INCLUDE is "-I/usr/local/include"<br> %<br> </p></div><p> <code class="literal">OSTYPE</code> has the value "posix" only on Unix and Unix-like systems. Executing the recipe on MS-Windows, where <code class="literal">OSTYPE</code> has the value "mswin": </p><div class="literallayout"><p> C:> <strong class="userinput"><code>aap</code></strong><br> INCLUDE is "-Ic:/vc/include"<br> C:><br> </p></div><p> Note that the Python conditional commands end in a colon. Don't forget to add it, you will get an error message! The indent is used to form blocks, thus you must take care to align the "@if" and "@else" lines. </p><p> You can include more lines in a block, without the need for extra characters, such as { } in C: </p><pre class="programlisting"> @if OSTYPE == "posix": INCLUDE += -I/usr/local/include LDFLAGS += -L/usr/local @else: INCLUDE += -Ic:/vc/include LDFLAGS += -Lc:/vc/lib </pre><h2><a name="id2628864"></a>Scope</h2><p> In Aap commands a variable without a scope is searched for in other scopes. Unfortunately, this does not happen for variables used in Python. To search other scopes you need to prepend "_no." before the variable name. Changing the above example to print the result from Python: </p><pre class="programlisting"> @if OSTYPE == "posix": INCLUDE += -I/usr/local/include @else: INCLUDE += -Ic:/vc/include all: @print 'INCLUDE is "%s"' % _no.INCLUDE </pre><h2><a name="id2628875"></a>Loops</h2><p> Python has a "for" loop that is very flexible. In a recipe it is often used to go over a list of items. Example: </p><pre class="programlisting"> 1 @for name in [ "solaris", "hpux", "linux", "freebsd" ]: 2 fname = README_$name 3 @if os.path.exists(fname): 4 Files += $fname 5 all: 6 :print $?Files </pre><p> The first line contains a list of strings. A Python list uses square brackets. The lines 2 to 4 are executed with the <code class="literal">name</code> variable set to each value in the list, thus four times. The indent of line 5 is equal to the <code class="computeroutput">@for</code> line, this indicates the "for" loop has ended. </p><p> Note how the <code class="literal">name</code> and <code class="literal">fname</code> variables are used without a dollar in the Python code. You only put a dollar before a variable name in the argument of an Aap command. Not in Python code and not on the left hand side of an assignment. </p><p> In line 2 the <code class="literal">fname</code> variable is set to "README_" plus the value of <code class="literal">name</code>. The <code class="computeroutput">os.path.exists()</code> function in line 3 tests if a file exists. Assuming all four files exist, this is the result of executing this recipe: </p><div class="literallayout"><p> % <strong class="userinput"><code>aap</code></strong><br> README_solaris README_hpux README_linux README_freebsd<br> %<br> </p></div><h2><a name="id2628949"></a>Python Block</h2><p> When the number of Python lines gets longer, the "@" characters become annoying. It is easier to put the lines in a block. Example: </p><pre class="programlisting"> :python Files = '' for name in [ "solaris", "hpux", "linux", "freebsd" ]: fname = "README_" + name if os.path.exists(fname): if Files: Files = Files + ' ' Files = Files + fname all: :print $Files </pre><p> This does the same thing as the above recipe, but now using Python commands. As usual, the <code class="computeroutput">:python</code> block ends where the indent is equal to or less than that of the <code class="computeroutput">:python</code> line. </p><p> When using the <code class="computeroutput">:python</code> command, make sure you get the assignments right. Up to the "=" character the Python assignment is the same as the recipe assignment, but what comes after it is different. </p><h2><a name="id2628983"></a>Expressions for Files</h2><p> In many places a Python expression can be used. For example, the <code class="computeroutput">glob()</code> function can be used to expand wildcards: </p><pre class="programlisting"> Source = `glob("*.c")` </pre><p> Python users know that the <code class="computeroutput">glob()</code> function returns a list of items. <span class="application">Aap</span> automatically converts the list to a string, because all <span class="application">Aap</span> variables are strings. A space is inserted in between the items and quotes are added around items that contain a space. </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note: Using glob() is dangerous"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Using glob() is dangerous</th></tr><tr><td align="left" valign="top"><p> It is actually a bit dangerous to get the list of source files with the <code class="computeroutput">glob()</code> function, because a "test.c" file that you temporarily used will accidentally be included. It is often better to list the source files explicitly. </p></td></tr></table></div><p> Why use <code class="computeroutput">glob()</code> when you can use wildcards directly? The difference is that the expansion with <code class="computeroutput">glob()</code> takes place immediately, thus $Source will get the expanded value. When using wildcards directly the expansion is done when using the variable, but that depends on where it is used. For example, the <a href="ref-commands.html#cmd-print">:print</a> command does not do wildcard expansion: </p><pre class="programlisting"> pattern = *.c expanded = `glob(pattern)` all: :print pattern $pattern expands into $expanded </pre><p> When "foo.c" and "bar.c" exist, the output will be: </p><div class="literallayout"><p> % <strong class="userinput"><code>aap</code></strong><br> pattern *.c expands into foo.c bar.c<br> %<br> </p></div><p> The following example turns the list of source files into a list of header files: </p><pre class="programlisting"> Source = `glob("*.c")` Header = `sufreplace(".c", ".h", Source)` all: :print Source is "$Source" :print Header is "$Header" </pre><p> Running <span class="application">Aap</span> in a directory with "main.c" and "version.c"? </p><div class="literallayout"><p> % <strong class="userinput"><code>aap</code></strong><br> Source is "version.c main.c"<br> Header is "version.h main.h"<br> %<br> </p></div><p> The <a href="ref-python.html#python-sufreplace">sufreplace()</a> function takes three arguments. The first argument is the suffix which is to be replaced. The middle argument is the replacement suffix. The last argument is the name of a variable that is a list of names, or a Python expression. In this example each name in <code class="literal">Source</code> ending in ".c" will be changed to end in ".h". </p><h2><a name="id2629195"></a>Further Reading</h2><p> The User manual <a href="user-python.html" title="Chapter 21. Using Python">Chapter 21, <i>Using Python</i></a> has more information. Documentation about Python can be found on its web site: <a href="http://www.python.org/doc/" target="_top">http://www.python.org/doc/</a> </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tutor-variant.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="tutor-cvs.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 5. Building Variants </td><td width="20%" align="center"><a accesskey="h" href="index.html"> Contents</a></td><td width="40%" align="right" valign="top"> Chapter 7. Version Control with CVS</td></tr></table></div></body></html>