AppyPrinciplesGetting started
appy.pod Writing ODT templates The « with » statement

Already introduced in the main section about statements, the with statement deserves more attention.

Recall that its general syntax is the following.

do <document_part> with <variable_name> = <python_expression>

Scopes and variable hiding

Introduced in the previous section about the for statement, the principle of scopes and variable hiding also holds for with statements. If, when defining some <variable_name> via a with statement, this name already denotes a variable in the context, this latter will be hidden in the scope defined by the part of the ODT template being the target of the statement. Once going out of this scope, the global variable will be reified and available again.

Semicolon-separated statements

The statement's syntax as presented at the start of this page is too restrictive: other forms exist. Several statements can be defined on a single line, separated by semi-colons, like in this example.

do section- with var1=computeVar1();var2=computeVar2()

Any number of variables may be defined that way, provided they are all written down in a single line within the LibreOffice comment.

Unwrapping several variables at once

Like iterator variables in for statements, it is possible to unwrap several variables at once in a with statement. Suppose you have this highly interesting function available in the POD context:

def fun(): return (1, 'two', {'three': 3})

You can unwrap, in 3 variables, the 3 elements extracted from the function's result, via this statement:

do table with one, two, three = fun()

The following variables will be added in the POD context.

Variable name Variable value
one 1
two 'two'
three {'three': 3}

Unwrapping a dynamic number of variables (Python 3 only)

Yet another form of with statement is available (but not in Appy for Python 2), allowing to unwrap a dynamic number of variables. It works by unwrapping a Python dict with a star-based notation. Suppose you have this function available in the POD context:

def moreFun(count):
    r = {}
    for i in range(count):
        r['var%d' % (i+1)] = i
    return r

If you use the following with statement:

do row with *=moreFun(2)

You will define, in the table row where this statement is defined, the following variables.

Variable name Variable value
var1 0
var2 1

Calling moreFun with count=5 wil produce these variables.

Variable name Variable value
var1 0
var2 1
var3 2
var4 3
var5 4

The interest of using this form of statement is not necessarily the fact that a dynamic number of variables can de defined. Handling the possible existence or inexistence of some variables in the context would lead to fuzzy POD statements or expressions. Using such statements has sense when used with functions that produce a dict being a kind of mini-POD context, that you may then reuse to inject a set of variables, at various specified places, in one or several POD templates.

Referencing existing variables via the @ prefix

As previously stated, a with statement defines a new variable, potentially hiding a variable having the same name and already being in the current context.

It is also possible to define a with statement that will reference and update an existing variable, instead of defining a new one.

Example

Suppose you have a section containing a table and, possibly, a paragraph below it. The objective is to fill the table with events from a database. Every event has (or should have) a date. Consequently, the table has 2 columns: one for the event name, one for the event date. In the pod template, the table contains a template row having a for statement, that will produce as many rows as there are events to dump. The purpose of the paragraph below the table is to give a word of explanation if at least one date, for one event, is missing.

What you can do, in order to achieve this result, is to define, at the section level, a variable named missingDate:

do section- with missingDate=False

Then, each time an event is walked in the loop, you may update the value of variable missingDate, as shown in the statement below, tied to the template row.

do row for event in events
with @missingDate = missingDate or event.date is None

The with statement hereabove tells pod to update the existing variable named missingDate instead of defining a new one.

At the end of the loop, this variable is True if at least one undated event has been dumped.

Then, the last paragraph may have this statement:

do text if missingDate

Lasting variables: the « with+ » statement

As previously mentioned, the scope of variable·s defined via a with statement is the part of the ODT template being the target of the statement. That being said, an alternate behaviour exists. By using the variant statement named with+, defined variables become lasting: their scope is expanded until the end of the POD template.

If such a statement is defined at the very beginning of a POD template, it is close to defining what could be called global variables.

Note that lasting variables violates the principle of variable hiding: once a variable is hidden by an homonym lasting variable, it will never be available again.

Combine all these forms at will

All the presented forms of with statements can be combined, but not that way:

do text with a, b, * = silly()

Keep in mind to write POD templates being as simple as readable as possible.