==========
Superseded
==========

PythonReports_ is superseded by s-reports_, a banded report formatter
with a template format that grew out of this one.
New reports should be written for s-reports.

Existing templates and printouts can be carried over with the
``pr2sr`` command; see `Migrating to s-reports`_ below.

============
Introduction
============

PythonReports_ is a toolkit aimed to build database reports
in |Python(r)| programs.  The toolkit includes the report builder
and printout_ renderer for PDF output.

Report builder applies a template_ to a sequence of uniform data
objects and produces a printout_ structure that can be saved in
a file and/or rendered to PDF.

It is possible to render printouts for other presentation formats
such as a specific printer language or a GUI toolkit display.
There used to be printing output for wxPython_ and screen
display for Tkinter and wxPython_, but they fell out of use
and their support is discontinued.

============
Requirements
============

Current version of PythonReports_ has only been tested with Python v3.12.
Earlier versions of Python3 may or may not work; Python2 is not supported
starting from PythonReports v1.0.0.

Report building and printout_ rendering require the ReportLab_ Toolkit.
Reports containing images additionally require
`Python Imaging Library`_: Pillow_ (preferred) or PIL_.

Templates in RSON format (introduced in v0.7.0) require rsonlite_.

`QR`_ barcodes (introduced in v0.8.0) require qrcode_.

===========
Quick Start
===========

A report is built from a list of data dictionaries or data objects
having uniform structure.  An example of such data is a list of rows
fetched from an SQL server.

Report layout is defined by a template_ file which can have
either XML format or a textual format based on rsonlite_.

Report builder applies loaded template to a list of data
objects and produces a printout_ structure.  Printout can
be saved in XML format.

PDF writer creates an output file from a printout structure.

There are example templates in the `test directory`_:
`sakila.prt` is in XML format, and `sakila.prtr` is the
same template in RSON format.  The data file for those
templates is distributed as `sakila.zip`_ with the project releases.

This is an example of building a PDF from that data::

    import pickle
    from PythonReports.api import Builder, parse_rson, write_pdf

    with open("sakila.dat", "rb") as data_file:
        data = pickle.load(data_file, encoding="latin1")[:200]
    template = parse_rson("sakila.prtr")
    build = Builder(template)
    printout = build.run(data)
    with open("sakila.prp", "wb") as printout_file:
        printout.write(printout_file)
    # It is necessary to call .validate() on built or loaded printout
    # before creating PDF output.
    printout.validate()
    write_pdf(printout, "sakila.pdf")

======================
Migrating to s-reports
======================

The ``pr2sr`` command converts PythonReports files to s-reports ones.
It is installed with PythonReports, and ``python -m
PythonReports.migrate`` runs it as well::

    pr2sr template sakila.prt                  # writes sakila.kdl
    pr2sr template sakila.prt --records payments.jsonl
    pr2sr printout sakila.prp                  # writes sakila.srp.jsonl
    pr2sr printout sakila.prp -o sakila.pdf    # rendered by s-reports

``pr2sr template`` reads a template in either format, XML or RSON,
and writes an s-reports template in KDL.  It needs nothing beyond
PythonReports, and rsonlite_ for RSON.  ``pr2sr printout`` reads
a printout and writes an s-reports printout, as NDJSON (``.srp.jsonl``),
CBOR (``.srp.cbor``), or PDF (``.pdf``), so that archived printouts
can be rendered by s-reports.  It needs s-reports itself::

    pip install PythonReports[sr]

Where s-reports is installed, ``pr2sr template`` also checks the converted
template with it, and exits with status 1 if s-reports does not accept it.

What the conversion could not carry over unchanged is listed on
standard error, and in the converted template as comments that begin
with ``migrate:``.  These are the things to look at most often:

* Record fields.  s-reports declares the fields of the data records
  and their types.  The converter declares every field the
  expressions read.  With ``--records``, a JSON array or NDJSON file
  of sample records, the types come from the data; without it, they
  are guessed from how the expressions use the fields.  A field that
  the expressions test for None or for truth is declared nullable.
* Data.  s-reports reads its records from JSON rather than from
  Python objects, so the program that built reports has to write
  its data as JSON instead.
* Expressions.  s-reports evaluates Starlark rather than Python.
  The converter rewrites what has a Starlark counterpart, and notes
  what has none, such as names from ``import`` elements.
* Deferred fields.  s-reports sizes a field or a bar code that has
  ``evaltime`` by a placeholder text.  Where the template gave none,
  the converter writes a guess.
* Values of None.  PythonReports prints nothing for them,
  and s-reports prints ``None``.  A field that shows a variable prints
  only when the value is not None.
* Inline subreports.  s-reports runs an inline subreport without a page
  header or footer of its own.

.. _External hyperlink targets:

.. _PythonReports: https://github.com/a1s/PythonReports
.. _s-reports: https://github.com/a1s/sr.py
.. _template: https://github.com/a1s/PythonReports/wiki/Report-Templates
.. _printout: https://github.com/a1s/PythonReports/wiki/Printout-Format
.. _Python: http://www.python.org/
.. _ReportLab: https://www.reportlab.com/software/opensource/rl-toolkit/
.. _PIL: http://www.pythonware.com/products/pil/
.. _Python Imaging Library:
.. _Pillow: https://pypi.python.org/pypi/Pillow
.. _qrcode: https://pypi.python.org/pypi/qrcode
.. _QR: https://en.wikipedia.org/wiki/QR_code
.. _rsonlite: https://pypi.python.org/pypi/rsonlite
.. _wxPython: http://www.wxpython.org/
.. _test directory: https://github.com/a1s/PythonReports/tree/main/test
.. _sakila.zip: https://github.com/a1s/PythonReports/releases/download/v1.0.0/sakila.zip

.. |Python(r)| unicode:: Python U+00AE

.. vim: set et ft=rst sts=2 sw=2 :
