======= 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: ``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 ``templates`` dictionary. The keys are the base names of the files (i.e. ``foo.ul4`` will be ``templates.foo``; stdin will be ``templates.stdin``). ``--oracle`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the object ``oracle`` to the template or not (see below)? ``--sqlite`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the object ``sqlite`` to the template or not (see below)? ``--mysql`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the object ``mysql`` to the template or not (see below)? ``--redis`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the object ``redis`` to the template or not (see below)? ``--system`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the object ``system`` to the template or not (see below)? ``--load`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the function ``load`` to the template or not (see below)? ``--compile`` (``false``, ``no``, ``0``, ``true``, ``yes`` or ``1``) Provide the function ``compile`` to the template or not (see below)? ``-e``, ``--encoding`` The encoding of the templates files (default ``utf-8``) ``-w``, ``--whitespace`` (``keep``, ``strip``, or ``smart``) Specifies how to handle whitespace in the template ``-D``, ``--define`` Defines an additional value that will be available inside the template. ``-D`` can be specified multiple times. The following formats are supported: ``var`` Defines ``var`` as an empty string; ``var=value`` Defines ``var`` as the string ``value``; ``var:type`` Defines ``var`` as an empty variable of the type ``type``; ``var:type=value`` Defines ``var`` as a variable of the type ``type`` with the value ``value``. ``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 and ``1``, ``yes``, ``true`` or ``True`` 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/pwd@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. the ``42`` in 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): ``templates`` A dictionary containing all the templates specified on the command line. ``encoding`` The output encoding. ``system`` An object with an ``execute`` method that executes system commands and returns their output, e.g. the template: will output the user name. ``oracle`` An object with a ``connect`` method that returns a connection to an oracle database. ``mysql`` An object with a ``connect`` method that return a MySQL connection for the MySQL connect strings passed in. A MySQL connect string is a string of the form ``user/pwd@host/db``. ``sqlite`` An object with a ``connect`` method that return a SQLite connection for the connect strings passed in. The connect string will be passed directly to ``sqlite3.connect``. ``redis`` An object with a ``connect`` method that return a Redis connection for the connect strings passed in. The connectstring is of the form ``hostname:port/db``. ``port`` and ``db`` are optional. ``load`` ``load`` is 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"``: ``compile`` ``compile`` is a function that compiles a string into an UL4 template. The signature is: compile(source, name=None, whitespace="keep", signature=None, startdelim="") ``error`` ``error`` is a function that can be called to output an error message and abort template execution. The signature is: error(message, ast=None) ``message`` is the error message and ``ast`` can 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: ... 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: Redis connections have a ``get`` and a ``put`` method: 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: 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. ============================== class ``System``​(``object``): ============================== def ``execute``​(``self``, ``cmd``): ------------------------------------ ====================================================== def ``load``​(``filename``, ``encoding``=``'utf-8'``): ====================================================== =================================================================================================================================================== def ``compile``​(``source``, ``name``=``None``, ``whitespace``=``'keep'``, ``signature``=``None``, ``startdelim``=``''``): =================================================================================================================================================== ============================================== def ``error``​(``message``, ``ast``=``None``): ============================================== =========================== class ``Var``​(``object``): =========================== def ``__init__``​(``self``, ``value``=``None``): ------------------------------------------------ def ``ul4setattr``​(``self``, ``name``, ``value``): --------------------------------------------------- def ``makevar``​(``self``, *``args``, **``kwargs``): ---------------------------------------------------- ================================== class ``Connection``​(``object``): ================================== def ``__init__``​(``self``, ``connection``): -------------------------------------------- def ``_execute``​(``self``, ``cursor``, ``queryparts``): -------------------------------------------------------- def ``query``​(``self``, *``queryparts``): ------------------------------------------ def ``execute``​(``self``, *``queryparts``): -------------------------------------------- def ``str``​(``self``, *``args``, **``kwargs``): ------------------------------------------------ def ``clob``​(``self``, *``args``, **``kwargs``): ------------------------------------------------- def ``int``​(``self``, *``args``, **``kwargs``): ------------------------------------------------ def ``number``​(``self``, *``args``, **``kwargs``): --------------------------------------------------- def ``date``​(``self``, *``args``, **``kwargs``): ------------------------------------------------- ============================================ class ``OracleConnection``​(``Connection``): ============================================ class ``IntVar``​(``Var``): --------------------------- def ``makevar``​(``self``, ``c``): """""""""""""""""""""""""""""""""" class ``NumberVar``​(``Var``): ------------------------------ def ``makevar``​(``self``, ``c``): """""""""""""""""""""""""""""""""" class ``StrVar``​(``Var``): --------------------------- def ``makevar``​(``self``, ``c``): """""""""""""""""""""""""""""""""" class ``CLOBVar``​(``Var``): ---------------------------- def ``makevar``​(``self``, ``c``): """""""""""""""""""""""""""""""""" class ``DateVar``​(``Var``): ---------------------------- def ``makevar``​(``self``, ``c``): """""""""""""""""""""""""""""""""" def ``__repr__``​(``self``): ---------------------------- def ``str``​(``self``, ``value``=``None``): ------------------------------------------- def ``clob``​(``self``, ``value``=``None``): -------------------------------------------- def ``int``​(``self``, ``value``=``None``): ------------------------------------------- def ``number``​(``self``, ``value``=``None``): ---------------------------------------------- def ``date``​(``self``, ``value``=``None``): -------------------------------------------- ============================== class ``Oracle``​(``object``): ============================== def ``connect``​(``self``, ``connectstring``): ---------------------------------------------- ============================== class ``SQLite``​(``object``): ============================== def ``connect``​(``self``, ``connectstring``): ---------------------------------------------- ============================= class ``MySQL``​(``object``): ============================= def ``connect``​(``self``, ``connectstring``): ---------------------------------------------- ======================================= class ``RedisConnection``​(``object``): ======================================= def ``__init__``​(``self``, ``host``, ``port``, ``db``): -------------------------------------------------------- def ``get``​(``self``, ``key``): -------------------------------- def ``set``​(``self``, ``key``, ``data``, ``timeout``=``None``): ---------------------------------------------------------------- ============================= class ``Redis``​(``object``): ============================= def ``connect``​(``self``, ``connectstring``): ---------------------------------------------- =========================== def ``fixname``​(``name``): =========================== ========================= def ``define``​(``arg``): ========================= ======================================== def ``print_exception_chain``​(``exc``): ======================================== ================================= def ``main``​(``args``=``None``): =================================