Skip to content

Write a report plugin (Python)

An Interactive Report (IReport) plugin generates formatted content — paragraphs, headings, trees, tables, images, and links — that Understand displays and can sync to other views. They power everything from documentation and engineering reports to Mermaid exports and script-writing aids. A report plugin is one of Understand's five plugin types; this page covers the report-specific contract.

Python recommended

New report plugins are best written as Python scripts (.upy), which is what this page covers. You emit content through the Understand report API in a generate function. Legacy Perl (.upl) report plugins that subclass Understand::IReport are also supported, and several ship with the product.

The plugin contract

Understand classifies a .upy file as a report plugin because it defines a top-level generate function. Define at least one test_ function so the report is offered for the right targets.

Function Required Purpose
name() yes The report's name, shown in the menu.
generate(report, target, pageId) yes Emits the report's content. pageId is empty on the first page.
description() no HTML shown in the Plugin Manager.
tags() no List of tags shown in the Plugin Manager.
init(report, target) no Called once on creation — define options here.
test_entity(ent) no Return True to offer the report for that entity.
test_architecture(arch) no Return True to offer the report for an architecture.
test_global(db) no Return True to list the report as a project-level report.
pages(report, target) no Return the page IDs of a multi-page report.
support_abort() no Return True if the report honors report.is_aborted().

The target passed to init/generate is an understand.Ent, understand.Arch, or understand.Db, depending on which test_ function matched — branch on it with isinstance if your report supports more than one.

Writing report output

Inside init and generate, the report object (a ReportContext) is your output stream. For the full class reference and the API's own plugin-writing narrative, see the Python API reports guide:

Call Does
report.print(text) Write text into the report.
report.heading(...) Emit a heading.
bold/nobold, italic, underline Toggle inline text styles around later print() calls.
fontcolor(...) / bgcolor(...) Set text and background color.
report.tree(...) Structure output as a collapsible tree.
report.table(...) / tablecell() Build a table and advance cells.
report.draw(...) Embed a graph.
report.entity(ent) / syncfile(...) / compare(...) Insert links that sync an entity, a file location, or a comparison diff view.
report.options() Define (in init) and read (.lookup(...)) user options.

For long or multi-page reports, see is_aborted() and progress(...), and the pagelink(...) / breadcrumbs(...) methods that work with pages().

Example: print the target's name

import understand

def name():
    return "Print Name"

def test_entity(ent):
    return True

def init(report, target):
    # Options appear in the report's sidebar; read them in generate().
    report.options().checkbox("test", "This is a test", True)

def generate(report, target, pageId):
    report.bold()
    report.print(target.name())          # Ent, Arch, and Db all have name()
    report.nobold()
    report.print(f"\noption: {report.options().lookup('test')}\n")

The shipped plugins/IReport/sample.upy is a fuller version of this template (with description, tags, and all three test_ functions).

Start from a template

The shipped plugins/IReport/ library is the easiest starting point, and it doubles as a tour of what reports can do — API Info, parameter and reference tables, and more (plus solution reports like duplicate-line detection under plugins/Solutions/). In the Plugin Manager, filter by the Sample Template tag, pick one, and Customize it to drop an editable copy into your plugin folder.

Install & run

Install a report plugin like any other — drag the .upy onto the main window, or add it from the Plugin Manager. Understand recognizes it as a report (it defines generate) and files it under your per-user IReport plugin folder.

Once enabled, a report is offered for its valid targets — from the Interactive Reports menu, or an entity's or architecture's report menu. See What is a report & how do I run one? for the GUI workflow, and Write a plugin for the plugin model and common gotchas (broken plugins, reloading, the per-interpreter GIL).

You can also generate a report headlessly — to PDF, HTML, text, CSV, or PNG — from the Python API with ent.report("*[name]*", ...), arch.report, or db.report, or from the command line with und reportund report "<name>" <output>, with -ent/-arch to target an entity or architecture. See the API tutorial interactive reports for a full worked plugin.