Chapter 19. Using Python

Python commands can be used where A-A-P commands are not sufficient. This includes conditionally executing of commands, repeating commands for a list of items and much more.

PYTHON EXPRESSION:

Python expressions can be embedded in many places.  They are specified in
backticks.

The result should be a string or a list of strings.  A list is automatically
converted to a white-separated string of all list items.

A Python expression cannot be used for the variable name in an assignment.
This doesn't work:

	`varname` = value

Use this instead:

	@eval(varname + ' = "value"')

When using a function from a module, it must be imported first.  Example:

	@from glob import glob
	SOURCE = `glob('*.c')`

However, for your convenience these things are imported for you already:
	from glob import glob

A backtick in the Python expression has to be doubled to avoid it being
recognized as the end of the expression:

	CMD = `my_func("``grep -l foo *.c``")`

contains the Python expression:

	my_func("`grep -l foo *.c`")

Note that a following attribute is only attached to the last item resulting
from the Python expression.

	SOURCE = `glob('*.c')` {check = md5}

Can be equivalent to:

	SOURCE = foo.c bar.c {check = md5}

To apply it to all items, use parenthesis

	SOURCE = (`glob('*.c')`) {check = md5}

Can be equivalent to:

	SOURCE = (foo.c bar.c) {check = md5}
or:
	SOURCE = foo.c {check = md5} bar.c {check = md5}


Backtick expressions and $VAR can be used inside a string:

	DIR = /home/foo /home/bar
	:print "`DIR + "/fi le"`"
results in:
	"/home/foo /home/bar/fi le"

Compare this to:
	:print "$*DIR/fi le"
which results in:

In the result of the Python expression a $ is changed to $$, so that it's not
used for a variable name.  The $$ is reduced to $ again when evaluating the
whole expression.


USEFUL PYTHON ITEMS:

	VAR = `os.environ.get('VAR', 'default')`

Obtain environment variable $VAR.  If it is not set use "default".

	@os.environ["PATH"] = mypath

Set an environment variable.

	files = `glob("*.ext")`

Obtain a list of files matching "*.ext".  A-A-P will take care of turning the
list that glob() returns into a string, using quotes where needed.

	choice = `raw_input("Enter the value: ")`

Prompt the user to enter a value.

	tempfile = `tempfname()`

Get a file name to use for temporary files.  The file will not exist.  If you
create it you need to make sure it is deleted afterwards.


AAP PYTHON FUNCTIONS:

These functions can be used in Python code:

aap_sufreplace(from, to, expr)
			Returns "expr" with all occurences of the suffix
			"from" changed to "to".
			When "from" is empty any suffix is changed to "to".
			"expr" can be a list of file names.
			Example:
				OBJECT = `aap_sufreplace("", OBJSUF, SOURCE)`

aap_abspath(expr)	Returns "expr" with all file names turned into
			absolute paths.  Prepends the current directory to
			each item in "expr" which isn't an absolute path name.
			Example:
				:print `aap_abspath("foo bar")`
			results in:
				/home/mool/test/foo /home/mool/test/bar

string = src2obj(source)
			Transform a string, which is a list of source files,
			into the corresponding list of object files.  Each
			item in "source" is change by prepending $BDIR and
			changing or appending the suffix to $OBJSUF.

get_attr(name)		Returns a dictionary with the attributes of "name".
			If "name" is unknown or has no attributes, an empty
			dictionary is returned.  Example:
			      :attr {logical = yes} foobar
			      @print "foobar attributes: ", get_attr("foobar")

program_path(name)
			Returns the path for program "name".  This uses the
			$PATH environment variable or os.defpath if it isn't
			set.
			On MS-Windows and OS/2 also checks with these
			extensions added: ".exe", ".com", ".bat", ".cmd".
			When "name" includes a suffix (a dot in the last
			component) adding extensions is not done.
			Returns the first program found.
			Returns None when "name" could not be found.
			Optional arguments:
			path		search path to use instead of $PATH;
					when a string items are separated with
					os.pathsep
			pathext		extensions to try; when a string
					items are separated with os.pathsep
			skip		name of directory to skip searching
			Example, search for program "foo.py" and "foo.sh":

		p = `program_path("foo", pathext = [ '.py', '.sh' ])`

redir_system(cmd [, use_tee])
			Execute shell commands "cmd" and return two items: a
			number indicating success and the stdout.
			By default "tee" is used to display the
			output as well as redirecting it.  When no output is
			desired set "use_tee" to zero.  Example:

			  ok, text = redir_system("ls", 0)
			  if ok:
			       print "ls output: %s" % text
			  else:
			       print "ls failed"

list = sort_list(list)
			sorts a list and returns the list.  Example:

				INP = `sort_list(glob("*.inp"))`

list = var2list(var)	Turns a variable with a string value into a list of
			items.  Attributes are ignored.  Example:

				source = file1 file2 file3
				@for fname in var2list(source):
					:sys prog $fname

list = var2dictlist(var)
			Turns a variable with a string value into a list of
			dictionaries.  Each dictionary has a "name" entry for
			item itself and other entries are attributes.
			Example:

				source = file1 {force} file2 file3
				@for item in var2dictlist(source):
				@    if item.get("force"):
					:print forced item: `item["name"]`

string = file2string(fname [, dict])
			Reads the file "fname" and concatenates the lines into
			one string.  Lines starting with a '#' are ignored.
			One space is inserted in between joined lines, other
			white space at the start and end of a line is removed.
			When "fname" doesn't exist or can't be read an error
			message is given and an empty string is returned.
			"dict" is used to obtain the value for $MESSAGE.
			The default is None.

has_target(target)
			Returns:
				0	no dependency for "target"
				1	dependency for "target" exists
				2	dependency for "target" exists and has
					build commands
			Example:
				@if not has_target("fetch"):

tempfname()		Returns the name of a file which does not exist and
			can be used temporarily.


PYTHON BLOCK:

A block of Python commands is started with a ":python" command.  Optionally
a terminator string may be specified.  This cannot contain white space.  A
comment may follow.  If no terminator string is specified the python code ends
where the indent is equal to or less than the ":python" command.  Otherwise
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.
 
	SOURCE = foo.c bar.c
	:python
	    for i in items:
		SOURCE = SOURCE + " " + i
	...
	:python EOF
    INCLUDE = glob("include/*.c")
    		EOF