Skip to content

fw.render_plaintext

Use fw.render_plaintext for notebooks, terminal inspection, and text reports where you need control over width and length. It formats already-computed evidence and makes omissions visible.

The analysis budget and the text budget are independent: shortening a report never changes the saved result.

Jump to the worked example or the argument reference.

fw.render_plaintext(
result,
*,
width=100,
max_lines=200,
max_nodes=1000,
detail='full',
missing_label='<NA>',
unicode_mode='display',
)

This page describes Fieldwork 0.3.2. Import the package with import fieldwork as fw. View the documented source.

Argument Type / default Effect
result Result or mapping; required A fw.Result or its to_dict() export. Rendering uses saved evidence and never reruns analysis or accesses the original dataframe.
width positive int; 100 Maximum rendered line width. Long lines are clipped with an omission marker. Display mode uses terminal display widths; safe mode counts escaped ASCII characters.
max_lines positive int; 200 Maximum output lines. When content remains, the final line is replaced with a truncation notice.
max_nodes nonnegative int; 1000 Maximum items shown per list: findings, candidate summaries, completed dependency tests, and census nodes (breadth first, so every top-level group appears before any subdivision). Saved evidence is unchanged.
detail “full” or “topology”; 'full' "full" includes quantitative evidence. "topology" suppresses quantitative support and selectors in the presentation, while keeping structural labels. It is not anonymization: labels can still identify people or records.
missing_label str; '<NA>' Text shown for a missing value wherever the report displays one, such as a level, census node or context value. It does not rewrite other text.
unicode_mode “safe” or “display”; 'display' "display" preserves displayable Unicode while escaping control characters. Widths use wcwidth when the optional fieldwork[unicode] extra is installed, otherwise Unicode width rules. "safe" escapes all non-ASCII text.

Returns a string; it does not print or write a file. Use print(text) or Path("report.txt").write_text(text, encoding="utf-8"). Every result kind is supported, including overviews, profiles and schema proposals, and every report starts with a Fieldwork · <kind> header. Plaintext has no section argument: pass result.section("dependencies") (or a saved section mapping) to render one part of an overview or profile.

Full dependency presentations include candidate summaries and every completed per-target test within display limits, including tests below the finding threshold. They distinguish observed target coverage from consistency on evaluated rows and repeat-only consistency. Missing-category tests are labeled. Candidate and test lists have separate display bounds; SVG shows at most five candidate summaries. The overview summary stays compact; render its dependencies section for detail. These numerical qualifications are absent from topology.

A clipped report is a view of saved evidence, not the evidence archive. Save result.to_dict() as well if you will need the full analytical record. detail="topology" suppresses counts in the presentation, not in the original result.

Invalid widths, limits, detail, or Unicode modes raise ValueError. Display mode works without the optional wcwidth dependency; it only measures some characters less precisely.

Discovery text includes search coverage and saved/total example-position counts. Positions are zero-based offsets in the original ordered source, not index labels; the first saved examples do not represent the entire matching population.

Walkthrough: a festival report that fits the handoff

Section titled “Walkthrough: a festival report that fits the handoff”

A festival coordinator wants a short report for the colleague assigning screening rooms. There are eight submissions, each already assigned a venue, language, and category. The immediate question is how many submissions each venue has; the language and category breakdown will matter later.

fw.render_plaintext turns saved evidence into a string. We will choose a display budget that answers the immediate question without mistaking a short report for a smaller population. Download the runnable example.

Each row below is a separate submission. The two identical Rialto rows represent two films with the same classification. The newline in the Annex name is deliberately untidy imported text.

import pandas as pd
import fieldwork as fw
films = pd.DataFrame(
[
("Rialto", "English", "Short"),
("Rialto", "English", "Short"),
("Rialto", "English", "Feature"),
("Rialto", "French", "Short"),
("Café", "French", "Short"),
("Café", "French", "Feature"),
("Café", "English", "Short"),
("Annex\nStudio", "English", "Short"),
],
columns=["venue", "language", "category"],
)
evidence = fw.census(films, ["venue", "language", "category"])

The census counts all eight submissions, then groups them by venue, language, and category. We will shorten that report while keeping all eight submissions in its counts.

An eight-line message sounds sufficient. Try it before deciding what to send:

line_limited = fw.render_plaintext(evidence, width=90, max_lines=8)
print(line_limited)
Fieldwork · census
Census (computed)
Input population · 8 evaluated / 8 input rows · 0 missing, 0 restricted exclusions
path: venue > language > category
total: 8 rows
venue=Rialto: 4 rows
language=English: 3 rows
... more output not rendered (max_lines)

The final marker occupies one of the eight lines. The report starts down Rialto’s subtree and never reaches Café or Annex. Their absence is a display omission, not evidence that they have no submissions. The header names the kind of result being shown.

Limiting the number of nodes instead of lines is a way to keep only the venues. Check what three nodes show:

three_nodes = fw.render_plaintext(evidence, width=90, max_nodes=3)
print(three_nodes)
Fieldwork · census
Census (computed)
Input population · 8 evaluated / 8 input rows · 0 missing, 0 restricted exclusions
path: venue > language > category
total: 8 rows
venue=Rialto: 4 rows
venue=Café: 3 rows
venue=Annex\u000aStudio: 1 row
... 12 nodes not rendered (renderer max_nodes)

The renderer spends its node budget breadth first, so three nodes are exactly the three venues. The 12 omitted nodes are languages and categories, not 12 omitted submissions. The report still names the deeper path and announces the hidden nodes: a display budget hides stored nodes, but it does not change what the census counted.

For a handoff that is only about venue totals, count venues alone. The census covers the same eight submissions, without the deeper path or an omission notice:

venues = fw.census(films, ["venue"])
venue_report = fw.render_plaintext(venues, width=90)
print(venue_report)
Fieldwork · census
Census (computed)
Input population · 8 evaluated / 8 input rows · 0 missing, 0 restricted exclusions
path: venue
total: 8 rows
venue=Rialto: 4 rows
venue=Café: 3 rows
venue=Annex\u000aStudio: 1 row

This report answers the colleague’s question: Rialto has four of eight submissions, Café three, and Annex one. The newline in the Annex name is shown escaped as \u000a, so it cannot split the line or be mistaken for a separate venue. Rendering never changes the saved evidence; to see deeper groups later, render evidence with a larger budget.

A narrow report clips individual lines instead of wrapping them:

narrow = fw.render_plaintext(venues, width=36)
print(narrow)
Fieldwork · census
Census (computed)
Input population · 8 evaluated ...
path: venue
total: 8 rows
venue=Rialto: 4 rows
venue=Café: 3 rows
venue=Annex\u000aStudio: 1 row

The venue counts survive, but the exclusion details are no longer visible. Use a width that preserves the context the reader needs, as well as a sufficient line budget.

For a colleague checking labels rather than workload, suppress the quantities explicitly:

topology = fw.render_plaintext(venues, width=90, detail="topology")
print(topology)
Fieldwork · census
Topology only · quantitative evidence suppressed
Census (computed)
path: venue
venue=Annex\u000aStudio
venue=Café
venue=Rialto

Topology orders these venue names by value rather than by frequency. Annex appearing first here says nothing about workload. Send the full-detail venue report for room allocation, and use this version to check the structure and spelling of labels.

The default unicode_mode="display" shows Café as written. When a log, terminal or file only accepts ASCII, use safe mode instead:

ascii_only = fw.render_plaintext(venues, width=90, unicode_mode="safe")
print(ascii_only)
Fieldwork \xb7 census
Census (computed)
Input population \xb7 8 evaluated / 8 input rows \xb7 0 missing, 0 restricted exclusions
path: venue
total: 8 rows
venue=Rialto: 4 rows
venue=Caf\xe9: 3 rows
venue=Annex\u000aStudio: 1 row

Safe mode escapes the accent as \xe9 and the separator dot as \xb7. In both modes the newline embedded in the Annex name stays escaped.

To explore the language breakdown next, render evidence with a larger max_nodes.

fw.render_svg, fw.render_html, fw.visualization_data. See results and configuration for serialization and result-method contracts.