Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > a6d417e36f6bb1154f4c003e6717e298 > files > 142

a-a-p-1.090-2mdv2009.0.noarch.rpm

<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:&gt; <strong class="userinput"><code>aap</code></strong><br>
    INCLUDE is "-Ic:/vc/include"<br>
    C:&gt;<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>