Custom Blocks

Custom blocks allow you to extend the standard catalog of seventy blocks with your own content bricks, written in Python. This extensibility is designed for teams with specific needs not covered by built-in blocks: recurring internal analyses, specific formatting requirements, or integration with an organization's external API. Custom blocks are saved at the workstation level and can be shared via the branding interface.

Accessing the Interface

The interface for creating custom blocks is located in the Customization tab of the Reports module, under the Blocks sub-tab. It lists previously created blocks and provides an editor to create new ones or modify existing ones.

Reports > Customization > Blocks > + New Block

Once created, custom blocks appear in the main editor's library alongside standard blocks and can be dragged onto the canvas in the same way.

Custom Block Metadata

A custom block carries the same metadata as a standard block, entered via a form. Consistency with the FAIH structure is maintained: every block must declare its nature.

Field Constraint Example
Unique Key Lowercase, underscores, 3 to 50 characters, must be unique audit_custom_labo
Display Name Free text, as it will appear in the PDF Internal Laboratory Audit
Short Description One line, displayed in the library Summary of internal controls
FAIH Nature F, A, I, or H A (Analytical)
Icon 2 uppercase letters, visual badge AC
The unique key cannot be modified once the block is created: it serves as the identifier in templates and already generated reports. Choose an explicit and stable name from the start.

Block Python Code

The heart of a custom block is a Python code snippet that describes what the block should produce in the PDF. The code runs in a restricted context with a set of variables and tools provided.

Variable or Tool Role
data Dictionary of project data (samples, geochemistry, isotopes, molecules, etc.)
lang Current report language, 'fr' or 'en'
story ReportLab list to which the elements produced by the block are appended
_table(headers, rows, col_widths, nature) Helper to produce a styled table consistent with the IsoFind identity
_kv_table(items) Helper to produce an aligned key-value list
colors, mm ReportLab constants for colors and unit conversion
Paragraph, Spacer Standard ReportLab classes for text and spacing
api_results Results of external API calls declared for this block

Custom Block Example

The following example, provided in the editor as a getting-started guide, produces a summary paragraph and a table of average concentrations per element.

samples = data.get('samples', [])
gc = _geochem_context(data)

story.append(Paragraph(
    f'{len(samples)} sample(s) analyzed',
    ParagraphStyle('Custom', fontSize=10, fontName='Helvetica-Bold')
))

if gc['has_geochem']:
    rows = [[el, f'{v:.4g}'] for el, v in gc['means'].items()]
    story.extend(_table(['Element', 'Concentration'], rows,
                        col_widths=[40*mm, 40*mm], nature='I'))

This code illustrates several common patterns: retrieving a section of the data dictionary, using a context helper, adding a styled paragraph, and then a table with an explicit declaration of its FAIH nature. The nature declared in the _table() call influences the visual formatting (border color, badge).

Using the _table() and _kv_table() helpers is not a restriction but a guarantee of graphical consistency. A custom block using them produces an output visually indistinguishable from a standard block.

External API Calls

A custom block can enrich its content with data from an external API (internal organization server, business database, third-party service). Calls are declared in the block form, executed by the IsoFind backend during generation, and their results are injected into api_results for use in the Python code.

API Call Parameter Role
Identifier Key under which the result will be accessible in api_results
URL Address of the external API; can contain project-related placeholders
Method GET, POST, PUT, etc.
Headers & Authentication Configurable for APIs requiring a token

In the block's Python code, the result of a call declared with the identifier stock_labo is accessible via api_results['stock_labo']. JSON responses are automatically deserialized; other types are returned as raw text.

API calls are executed for every PDF generation. A block making a slow call will proportionally slow down generation. For data that rarely changes, prefer an external API-side cache rather than a systematic call for every report.

Storage and Sharing

Custom blocks are stored locally on the workstation via the /api/reports/custom-blocks endpoint. They persist between sessions and are automatically loaded when the Reports module is opened.

To share a custom block with other users, two methods exist. The first is manual export of the Python code, which can be copied into another instance. The second, more integrated approach, uses the theme system, which can include custom blocks in a distributable package across the organization.

Python Code Security

Executing arbitrary Python code within an application context is an attack surface that must be handled with care. IsoFind applies several protections:

  • The execution context is restricted: only the variables and classes listed above are accessible. Arbitrary imports are blocked.
  • Access to the file system, network (excluding declared API calls), and other processes is impossible from the block code.
  • An execution timeout protects against infinite loops that would hang generation.
  • Execution errors are captured and displayed in the report as an error block, without interrupting the rest of the generation.
  • In controlled environments (enterprise deployments), administrators can totally disable custom block creation via configuration.

FAIH Nature for Custom Blocks

Choosing the block's nature is not cosmetic: it influences the overall register count in the report and the visual style applied. The choice must honestly reflect the produced content.

If the block... Recommended Nature
Displays raw values as they are F (Factual)
Calculates averages, ratios, or statistics A (Analytical)
Offers a reading, diagnosis, or recommendation I (Interpretative)
Clearly states the limits of the system and its interpretation H (Honest)
A single block can declare multiple natures for different tables it produces by passing the nature parameter to each _table() call. The nature declared in the block's metadata is the global dominant nature used for counting and the library.

Limits and Best Practices

  • A custom block should not exceed a few hundred lines of Python. Beyond that, it is better to offload the logic to an external API called by the block.
  • Custom blocks do not benefit from automatic engine updates. A major update to IsoFind may require a code review.
  • Documenting code with comments is highly recommended: a block created two years ago by a colleague who has since left will need review before being modified.
  • Systematically test the block on a small project before including it in a critical template.

Learn More