Purpose
rul4 is a script that can be used for rendering UL4 templates. Templates
have access to Oracle, MySQL, SQLite and Redis databases and can execute system
commands.
Options
rul4 supports the following options:
templatesOne 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 thetemplatesdictionary. The keys are the base names of the files (i.e.foo.ul4will betemplates.foo; stdin will betemplates.stdin).--oracle(false,no,0,true,yesor1)Provide the object
oracleto the template or not (see below)?--sqlite(false,no,0,true,yesor1)Provide the object
sqliteto the template or not (see below)?--mysql(false,no,0,true,yesor1)Provide the object
mysqlto the template or not (see below)?--redis(false,no,0,true,yesor1)Provide the object
redisto the template or not (see below)?--system(false,no,0,true,yesor1)Provide the object
systemto the template or not (see below)?--load(false,no,0,true,yesor1)Provide the function
loadto the template or not (see below)?--compile(false,no,0,true,yesor1)Provide the function
compileto the template or not (see below)?-e,--encodingThe encoding of the templates files (default
utf-8)-w,--whitespace(keep,strip, orsmart)Specifies how to handle whitespace in the template
-D,--defineDefines an additional value that will be available inside the template.
-Dcan be specified multiple times. The following formats are supported:varDefines
varas an empty string;var=valueDefines
varas the stringvalue;var:typeDefines
varas an empty variable of the typetype;var:type=valueDefines
varas a variable of the typetypewith the valuevalue.
typecan be any of the following:intvalueis an integer value.floatvalueis a float value.boolvalueis a boolean value.0,no,false,Falseor the empty string will be recognized as false and1,yes,trueorTruewill be recognized as true.strvalueis a string.oraclevaluewill be a connection to an Oracle database, e.g.:-Ddb:oracle=user/pwd@database
sqlitevalueis a connection to an SQLite database.mysqlvalueis a connection to a MySQL database.redisvaluewill 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. the42in the above value) is also optional and defaults to 0.
Template variables
Inside the template the following variables are available (if enabled via the matching options):
templatesA dictionary containing all the templates specified on the command line.
encodingThe output encoding.
systemAn object with an
executemethod that executes system commands and returns their output, e.g. the template:<?print system.execute("whoami")?>will output the user name.
oracleAn object with a
connectmethod that returns a connection to an oracle database.mysqlAn object with a
connectmethod that return a MySQL connection for the MySQL connect strings passed in. A MySQL connect string is a string of the formuser/pwd@host/db.sqliteAn object with a
connectmethod that return a SQLite connection for the connect strings passed in. The connect string will be passed directly tosqlite3.connect.redisAn object with a
connectmethod that return a Redis connection for the connect strings passed in. The connectstring is of the formhostname:port/db.portanddbare optional.loadloadis a function that reads a file from disk and returns the content. Its first parameter is the filename and its second parameter is the encoding of the file. The encoding parameter is optional and defaults to"utf-8":<?code data = load("/home/user/data.txt", "iso-8859-1")?>compilecompileis a function that compiles a string into an UL4 template. The signature is:compile(source, name=None, whitespace="keep", signature=None, startdelim="<?", enddelim="?>")errorerroris a function that can be called to output an error message and abort template execution. The signature is:error(message, ast=None)
messageis the error message andastcan be an AST node from an UL4 template syntax tree to print an error message that originates from that node.
All variables defined via the -D/--define option will also
be available. (Note that you can't overwrite any of the predefined variables).
Database connections
All connection objects (except redis) have a query method that executes
the query passed in and returns an iterator over the resulting records. This
query method requires at least one positional argument. Arguments alternate
between fragments of the SQL query and parameters that will be embedded in the
query. For example:
<?code db = oracle.connect("user/pwd@db")?>
<?code name = "Bob"?>
<?for p in db.query("select * from person where firstname=", name, " or lastname=", name)?>
...The records returned from query are dict-like objects mapping field names to
field values.
Connection objects also have an execute method that supports the same
parameters as query but doesn't return an iterable result. This can be used
to call functions or procedures.
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 value attribute 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/pwd@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')?>Redis connections have a get and a put method:
<?code db = redis.connect("192.168.123.42/1")?>
<?code value = db.get("key")?>
<?if isnone(value)?>
<?code value = "foobar"?>
<?code db.put("key", value, timedelta(seconds=10*60))?>
<?end if?>The timeout value in the put method is optional. Without it the value will
be stored indefinitely.
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 = oracle.connect("user/pwd@database')?>
<persons>
<?for p in db.query("select id, firstname, lastname from person order by 2, 1")?>
<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/pwd@database --oracle=0 --sqlite=0 --mysql=0 --redis=0 --system=0 >person.xml
Then the template could use the Oracle connection object db directly.