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 theglobals.templates
dictionary. The keys are the base names of the files (i.e.foo.ul4
will beglobals.templates.foo
; stdin will beglobals.templates.stdin
).
- --oracle <flag>
Provide the method
Globals.oracle()
(asglobals.oracle
) to the template? If switched offglobals.oracle
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --sqlite <flag>
Provide the method
Globals.sqlite()
(asglobals.sqlite
) to the template? If switched offglobals.sqlite
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --mysql <flag>
Provide the method
Globals.mysql()
(asglobals.mysql
) to the template? If switched offglobals.mysql
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --redis <flag>
Provide the method
Globals.redis()
(asglobals.redis
) to the template? If switched offglobals.redis
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --system <flag>
Provide the method
Globals.system()
(asglobals.system
) to the template? If switched offglobals.system
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --load <flag>
Provide the method
Globals.load()
(asglobals.load
) to the template? If switched offglobals.load
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --save <flag>
Provide the method
Globals.save()
(asglobals.save
) to the template? If switched offglobals.save
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- --compile <flag>
Provide the method
Globals.compile()
(asglobals.compile
) to the template? If switched offglobals.compile
will beNone
.(Allowed values are
false
,no
,0
,true
,yes
or1
; the default istrue
)
- -w <value>, --whitespace <value>
Specifies how to handle whitespace in the template (Allowed values are
keep
,strip
, orsmart
). 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
foo
will be available asglobals.vars.foo
).-D
can be specified multiple times. The following formats are supported:var
Defines
var
as an empty string;var=value
Defines
var
as the stringvalue
;var:type
Defines
var
as an empty variable of the typetype
;var:type=value
Defines
var
as a variable of the typetype
with the valuevalue
.
type
can be any of the following:int
value
is an integer value.float
value
is a float value.bool
value
is a boolean value.0
,no
,false
,False
or the empty string will be recognized as false and1
,yes
,true
orTrue
will be recognized as true.str
value
is a string.oracle
value
will be a connection to an Oracle database, e.g.:-Ddb:oracle=user/password@database
sqlite
value
is a connection to an SQLite database.mysql
value
is a connection to a MySQL database.redis
value
will be a connection to an Redis database, e.g.:-Ddb:redis=192.168.123.1:6379/42
The port (i.e. the
6379
in the above value) is optional and defaults to 6379. The database number (i.e. the42
in 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
Connection
object provides a database connection to an UL4 template.To execute SQL the two methods
query()
andexecute()
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()
anddate()
. The resulting value of the out parameter is available from thevalue
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/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
Connection
object can be created with the methodsGlobals.mysql()
orGlobals.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
None
if the query didn’t output any record).queryparts
is handled the same way asquery()
does.
- execute(*queryparts)[source]
Similar to
query()
andqueryone()
, 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
OracleConnection
is a subclass ofConnection
that implements functionality that is specific to Oracle databases (e.g. support for variables). The inferface is the same asConnection
s.An
OracleConnection
object can be created with the methodGlobals.oracle()
.
- class ll.scripts.rul4.RedisConnection[source]
Bases:
object
A connection to a Redis database. A
RedisConnection
object provides the methodsget()
to read data from the database andset()
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
key
orNone
if the key doesn’t exist.
- set(key, data, timeout=None)[source]
Store the string value
data
under the keykey
.If
timeout
isNone
the value will be stored indefinitely. Otherwise it specifies when the value will expire.timeout
can be an integer (the number of seconds) or atimedelta
object.
- class ll.scripts.rul4.Globals[source]
Bases:
object
An instance of the
Globals
class will be passed to the main template as theglobals
variable. The following attributes will be accessible to UL4 templates:templates
dictionaryA dictionary containing the templates specified on the command line. This will include the main template.
vars
dictionaryA dictionary containing the variables that have been specified via the
-D
/--define
option.encoding
stringThe encoding that will be used for output (this is the same as
sys.stdout.encoding
, so it can be set with the environment variablePYTHONIOENCODING
).env
dictionaryA reference to
os.environ
.
Furthermore the following methods can be called from UL4 templates:
error()
,log()
,oracle()
,mysql()
,sqlite()
,redis()
,system()
,load()
,save()
andcompile()
.- from_args(args)[source]
Sets the attributes of
self
from the objectargs
(which must be an instance ofargparse.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)
message
is the error message andast
can 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
args
tosys.stderr
.The parameters
sep
,end
andflush
have the same meaning as forprint()
.
- oracle(connectstring)[source]
Return an
OracleConnection
object 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
Connection
object 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
Connection
object to an SQLite database for the connectstring passed in. The connectstring will be passed directly tosqlite3.connect()
.
- redis(connectstring)[source]
Return a
RedisConnection
object, which provides a connection to a Redis database. The connectstring has the format:host:port/db
port
is optional and defaults to 6379.db
is optional too and defaults to 0.
- system(cmd)[source]
Execute the system command
cmd
and 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.
filename
is the filename andencoding
is 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
data
to a file on disk.filename
is the filename andencoding
is 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")?>