rul4 – Rendering UL4 templates
Purpose
rul4 is a script that can be used to render an UL4 template.
The globals object
Inside the template the object globals (an instance of the class
Globals) will be available to make database connections, load and save
files, compile templates, access environment variables and parameters etc.
However access to those features can be switched off via command line
options.
Options
rul4 supports the following options:
- templates
- One or more template files. A file named - -will be treated as standard input. The first file in the list is the main template, i.e. the one that gets rendered. All templates will be available in the main template as the- globals.templatesdictionary. The keys are the base names of the files (i.e.- foo.ul4will be- globals.templates.foo; stdin will be- globals.templates.stdin).
- --oracle <flag>
- Provide the method - Globals.oracle()(as- globals.oracle) to the template? If switched off- globals.oraclewill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --oracle_thick <flag>
- If true, use - oracledbs thick mode. (Valid flag values are- false,- no,- 0,- true,- yesor- 1)
- --oracle_config_dir <directory>
- In - oracledbs thin mode, specify the directory that contains the- tnsnames.orafile. This can be used if “Connect Descriptor Strings” from- tnsnames.oramust be used but- tnsnames.oracan’t be found in its default location.
- --sqlite <flag>
- Provide the method - Globals.sqlite()(as- globals.sqlite) to the template? If switched off- globals.sqlitewill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --mysql <flag>
- Provide the method - Globals.mysql()(as- globals.mysql) to the template? If switched off- globals.mysqlwill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --redis <flag>
- Provide the method - Globals.redis()(as- globals.redis) to the template? If switched off- globals.rediswill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --system <flag>
- Provide the method - Globals.system()(as- globals.system) to the template? If switched off- globals.systemwill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --load <flag>
- Provide the method - Globals.load()(as- globals.load) to the template? If switched off- globals.loadwill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --save <flag>
- Provide the method - Globals.save()(as- globals.save) to the template? If switched off- globals.savewill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- --compile <flag>
- Provide the method - Globals.compile()(as- globals.compile) to the template? If switched off- globals.compilewill be- None.- (Allowed values are - false,- no,- 0,- true,- yesor- 1; the default is- true)
- -w <value>, --whitespace <value>
- Specifies how to handle whitespace in the template (Allowed values are - keep,- strip, or- smart). This can of course be overwritten with the template tag- <?whitespace ...?>in the template files.
- -D, --define
- Defines an additional variable that will be available inside the template (e.g. the variable - foowill be available as- globals.vars.foo).- -Dcan be specified multiple times. The following formats are supported:- var
- Defines - varas an empty string;
- var=value
- Defines - varas the string- value;
- var:type
- Defines - varas an empty variable of the type- type;
- var:type=value
- Defines - varas a variable of the type- typewith the value- value.
 - typecan be any of the following:- int
- valueis an integer value.
- float
- valueis a float value.
- bool
- valueis a boolean value.- 0,- no,- false,- Falseor the empty string will be recognized as false and- 1,- yes,- trueor- Truewill be recognized as true.
- str
- valueis a string.
- oracle
- valuewill be a connection to an Oracle database, e.g.:- -Ddb:oracle=user/password@database 
- sqlite
- valueis a connection to an SQLite database.
- mysql
- valueis a connection to a MySQL database.
- redis
- valuewill be a connection to an Redis database, e.g.:- -Ddb:redis=192.168.123.1:6379/42 - The port (i.e. the - 6379in the above value) is optional and defaults to 6379. The database number (i.e. the- 42in the above value) is also optional and defaults to 0.
 
Example
This example shows how to connect to an Oracle database and output the content
of a person table into an XML file.
Suppose we have a database table that looks like this:
create table person
(
        id integer not null,
        firstname varchar2(200),
        lastname varchar2(200)
);
Then we can use the following template to output the table into an XML file:
<?xml version='1.0' encoding='utf-8'?>
<?code db = globals.oracle("user/password@database")?>
<persons>
        <?for p in db.query("select id, firstname, lastname from person order by 3, 2")?>
                <person id="<?printx p.id?>">
                        <firstname><?printx p.firstname?></firstname>
                        <lastname><?printx p.lastname?></lastname>
                </person>
        <?end for?>
</persons>
If we put the template into the file person.ul4 we can call
rul4 like this:
$ rul4 person.ul4 >person.xml
We could also pass the connection to our database via the -D option
and disallow the script to make any database connections itself or execute any
system commands:
$ rul4 person.ul4 -Ddb:oracle=user/password@database --oracle=0 --sqlite=0 --mysql=0 --redis=0 --system=0 >person.xml
Then the template can use the Oracle connection object db directly.
API
- class ll.scripts.rul4.Connection[source]
- Bases: - object- A - Connectionobject provides a database connection to an UL4 template.- To execute SQL the two methods - query()and- execute()are provided.- Calling functions or procedures with out parameters can be done with variable objects that can be created with the methods - int(),- number(),- str(),- clob()and- date(). The resulting value of the out parameter is available from the- valueattribute of the variable object. The following example creates a function, calls it to get at the result and drops it again:- <?code db = oracle.connect('user/password@database')?> <?code db.execute(''' create or replace function ul4test(p_arg integer) return integer as begin return 2*p_arg; end; ''')?> <?code vout = db.int()?> <?code db.execute('begin ', vout, ' := ul4test(42); end;')?> <?print vout.value?> <?code db.execute('drop function ul4test')?> - A - Connectionobject can be created with the methods- Globals.mysql()or- Globals.sqlite().- query(*queryparts)[source]
- Execute the query passed in and return an iterator over the resulting records. - At least one positional argument is required. Arguments alternate between fragments of the SQL query and parameters that will be embedded in the query. For example: - <?code db = globals.oracle("user/pwd@db")?> <?code name = "Bob"?> <ul> <?for p in db.query( "select * from person where firstname=", name, " or lastname=", name )?> <li><?print p.firstname?> <?print p.lastname?></li> <?end for?> </ul> - The records returned from - query()are dict-like objects mapping field names to field values.
 - queryone(*queryparts)[source]
- Execute the query passed in and return the first result record (or - Noneif the query didn’t output any record).- querypartsis handled the same way as- query()does.
 - execute(*queryparts)[source]
- Similar to - query()and- queryone(), but doesn’t doesn’t return a result. This can be used to call functions or procedures.
 - str(value=None)[source]
- Create a variable that can be used for OUT parameters of type - varchar.
 - clob(value=None)[source]
- Create a variable that can be used for OUT parameters of type - clob.
 - int(value=None)[source]
- Create a variable that can be used for OUT parameters of type - integer.
 - number(value=None)[source]
- Create a variable that can be used for OUT parameters of type - number.
 - date(value=None)[source]
- Create a variable that can be used for OUT parameters of type - date.
 
- class ll.scripts.rul4.OracleConnection[source]
- Bases: - Connection- OracleConnectionis a subclass of- Connectionthat implements functionality that is specific to Oracle databases (e.g. support for variables). The inferface is the same as- Connections.- An - OracleConnectionobject can be created with the method- Globals.oracle().
- class ll.scripts.rul4.RedisConnection[source]
- Bases: - object- A connection to a Redis database. A - RedisConnectionobject provides the methods- get()to read data from the database and- set()to write data to the database.- Example: - <?code db = redis.connect("192.168.123.42/1")?> <?code value = db.get("key")?> <?if value is None?> <?code value = "foobar"?> <?code db.put("key", value, timedelta(seconds=10*60))?> <?end if?> - get(key)[source]
- Return the value for the key - keyor- Noneif the key doesn’t exist.
 - set(key, data, timeout=None)[source]
- Store the string value - dataunder the key- key.- If - timeoutis- Nonethe value will be stored indefinitely. Otherwise it specifies when the value will expire.- timeoutcan be an integer (the number of seconds) or a- timedeltaobject.
 
- class ll.scripts.rul4.Globals[source]
- Bases: - object- An instance of the - Globalsclass will be passed to the main template as the- globalsvariable. The following attributes will be accessible to UL4 templates:- templatesdictionary
- A dictionary containing the templates specified on the command line. This will include the main template. 
- varsdictionary
- A dictionary containing the variables that have been specified via the - -D/- --defineoption.
- encodingstring
- The encoding that will be used for output (this is the same as - sys.stdout.encoding, so it can be set with the environment variable- PYTHONIOENCODING).
- envdictionary
- A reference to - os.environ.
 - Furthermore the following methods can be called from UL4 templates: - error(),- log(),- oracle(),- mysql(),- sqlite(),- redis(),- system(),- load(),- save()and- compile().- from_args(args)[source]
- Sets the attributes of - selffrom the object- args(which must be an instance of- argparse.Namespace).- Returns the main template. 
 - error(message, ast=None)[source]
- Can be called to output an error message and abort template execution. The signature is: - globals.error(message, ast=None) - messageis the error message and- astcan be an AST node from an UL4 template syntax tree to print an error message that originates from that node.
 - log(*args, sep=' ', end='\n', flush=False)[source]
- Logs - argsto- sys.stderr.- The parameters - sep,- endand- flushhave the same meaning as for- print().
 - oracle(connectstring)[source]
- Return an - OracleConnectionobject for the Oracle connect string passed in:- <?code db = globals.oracle("user/password@database")?> <?for row in db.query("select sysdate as sd from dual")?> <?print row.sd?> <?end for?> 
 - mysql(connectstring)[source]
- Return a - Connectionobject to a MySQL database for the connectstring passed in. The format of the connect string is:- user/password@host/database 
 - sqlite(connectstring)[source]
- Return a - Connectionobject to an SQLite database for the connectstring passed in. The connectstring will be passed directly to- sqlite3.connect().
 - redis(connectstring)[source]
- Return a - RedisConnectionobject, which provides a connection to a Redis database. The connectstring has the format:- host:port/db - portis optional and defaults to 6379.- dbis optional too and defaults to 0.
 - system(cmd)[source]
- Execute the system command - cmdand returns its output, e.g. the template:- <?print globals.system("whoami")?> - will output the user name. 
 - load(filename, encoding='utf-8')[source]
- Read a file from disk and returns the content. - filenameis the filename and- encodingis the encoding of the file. The encoding parameter is optional and defaults to- "utf-8":- <?code data = globals.load("/home/user/data.txt", "iso-8859-1")?> 
 - save(filename, data, encoding='utf-8')[source]
- Save the string - datato a file on disk.- filenameis the filename and- encodingis the encoding of the file. The encoding parameter is optional and defaults to- "utf-8":- <?code globals.save("/home/user/data.txt", "foo\nbar\n", "iso-8859-1")?>