Skip to content

Charts (scriptt-charts)

A separate package: uv add --editable ./worldapi/packages/scriptt-charts. It needs scriptt, for the text of numbers and dates.

Charts for World API results, in a separate package. A chart answers 1 question and shows its evidence. It shows the count behind each value (n) and where each value came from (trace). It shows what the data covers and leaves out (Scope), a rule that marks some items (Flag) and notes. A reader can change an assumption on the chart (Choice).

The forms for values are:

  • ranked (items with their share of a total)
  • ranges (low to high with a middle and a point)
  • over_time (values over dates)
  • views (2 or 3 named views of the same items)
  • members (items against groups)
  • flows (moves between categories)
  • side_by_side (2 charts of the same items)

The forms for the shape of the data are:

  • tree (things under things, with totals)
  • graph (things and typed links)
  • timeline (versions of things as lanes, with the time each became known)

Each form gives a Chart. A Chart renders to Vega-Lite (chart.json()), to Altair (chart.altair() with the extra scriptt-charts[altair]), to HTML (chart.html()) or to a plain table (chart.table()).

Numbers and dates are written as the World API writes them. A trace may give a World API Origin or Entry. The chart reads their source and known.

Chart dataclass

Chart(
    title: str,
    view: dict[str, Any],
    scope: Scope,
    rows: tuple[dict[str, Any], ...] = (),
    columns: tuple[str, ...] = (),
    summary: str | Mapping[Any, str] = "",
    marked: str = "",
    choice: Choice | None = None,
    width: int = 560,
)

1 chart. It has a title and a Vega-Lite view. It also has a scope and the rows that it draws. Make it with a form such as ranked or flows. Do not build it by hand.

Attributes:

Name Type Description
title str

The question the chart answers.

view dict[str, Any]

The Vega-Lite view. It has no title, config or parameters.

scope Scope

What the chart covers and leaves out.

rows tuple[dict[str, Any], ...]

The rows the chart draws (for the table view). Each row is a dict of plain values.

columns tuple[str, ...]

The columns of the table view in order.

summary str | Mapping[Any, str]

A sentence shown above the chart, or 1 sentence for each value of the choice.

marked str

The line that explains the flag mark, or "".

choice Choice | None

The assumption the reader can change, or None.

title instance-attribute

title: str

view instance-attribute

view: dict[str, Any]

scope instance-attribute

scope: Scope

rows class-attribute instance-attribute

rows: tuple[dict[str, Any], ...] = ()

columns class-attribute instance-attribute

columns: tuple[str, ...] = ()

summary class-attribute instance-attribute

summary: str | Mapping[Any, str] = ''

marked class-attribute instance-attribute

marked: str = ''

choice class-attribute instance-attribute

choice: Choice | None = None

width class-attribute instance-attribute

width: int = 560

vega_lite

vega_lite() -> dict[str, Any]

The full Vega-Lite spec. It has a schema and a theme. It also has the title with the scope, the control of the choice and the view.

resized

resized(
    width: int | None = None, height: int | None = None
) -> Chart

A copy of the chart with a new width or height in pixels (the plot area without the labels).

Parameters:

Name Type Description Default
width int | None

The new width. None keeps the width. For side_by_side this is the width of each chart.

None
height int | None

The new height. None keeps the height.

None

Returns:

Type Description
Chart

The new chart. The chart itself does not change.

json

json() -> str

The Vega-Lite spec as JSON text for a page or a file.

altair

altair() -> Any

An Altair chart of the same spec (needs scriptt-charts[altair]).

html

html() -> str

A standalone HTML page that draws the chart with vega-embed from a CDN.

table

table() -> str

The chart as plain text for a reader who cannot see it. The text gives the title and the summary. It gives the scope and the flag rule with its count. It gives the target with its status and the assumption. The rows follow. ⚑ in the first column marks a flagged row. With a choice, the rows are those of its default value.

Choice dataclass

Choice(
    name: str,
    values: tuple[V, ...],
    default: V,
    label: str,
)

An assumption that the reader can change on the chart, such as a fee or a pace. The chart is made for each value. A control picks the value to show. The control is labelled as an assumption.

Attributes:

Name Type Description
name str

A short name with no spaces for use inside the chart. For example "hours".

values tuple[V, ...]

The values the reader can pick. Rising numbers that are evenly spaced give a slider. Other values give buttons.

default V

The value shown first. It must be in values.

label str

The assumption in words. For example "hours of work per day".

Example
from scriptt.charts import Choice

Choice(
    "hours",
    values=(2, 3, 4, 5, 6, 8),
    default=4,
    label="hours of work per day",
)

name instance-attribute

name: str

values instance-attribute

values: tuple[V, ...]

default instance-attribute

default: V

label instance-attribute

label: str

control

control() -> dict[str, Any]

The Vega-Lite parameter with its control. The control is a slider for evenly spaced numbers and radio buttons for other values.

Flag dataclass

Flag(
    rule: str,
    test: Callable[[T], bool],
    per: Callable[[T], object] | None = None,
)

A rule that marks some items. The chart shows the rule in words and the count of marked items.

Attributes:

Name Type Description
rule str

The rule in words. For example "fewer than 5 sales".

test Callable[[T], bool]

A function that is true for an item the rule marks.

per Callable[[T], object] | None

What the count counts when several items show 1 thing. For example per=lambda v: v.task counts tasks and not versions. None counts items.

Example
from types import SimpleNamespace as Task
from scriptt.charts import Flag

Flag[Task]("under 30 minutes", lambda t: t.minutes < 30)

rule instance-attribute

rule: str

test instance-attribute

test: Callable[[T], bool]

per class-attribute instance-attribute

per: Callable[[T], object] | None = None

Scope dataclass

Scope(covers: str, left_out: Mapping[str, int] = dict())

What the chart covers and what it leaves out and why. Every chart needs one. A chart without its scope can be read as more than the data shows.

Attributes:

Name Type Description
covers str

The data in words. This is the date window and the sample. For example "the to-do list of 4 Nov 2026, 5 of the 6 tasks".

left_out Mapping[str, int]

The number of items left out for each reason. For example {"no due date": 1}.

Example
from scriptt.charts import Scope

Scope(
    "the to-do list of 4 Nov 2026",
    left_out={"tasks with no due date": 1},
)

covers instance-attribute

covers: str

left_out class-attribute instance-attribute

left_out: Mapping[str, int] = field(default_factory=dict)

text

text() -> str

The scope as 1 line. It gives what the scope covers and then each reason with its count.

Target dataclass

Target(
    value: float | date, label: str, met: bool | None = None
)

A target value drawn as a line. It has a label and a status.

Attributes:

Name Type Description
value float | date

The target on the value axis (a number or a date).

label str

The target in words. For example "10 tasks done".

met bool | None

True if met. False if not met. None if the status depends on a choice.

Example
from scriptt.charts import Target

Target(10, "10 tasks done", met=False)

value instance-attribute

value: float | date

label instance-attribute

label: str

met class-attribute instance-attribute

met: bool | None = None

text

text() -> str

The label with its status. For example "10 tasks done: not met".

Trace dataclass

Trace(source: str, known: datetime | None = None)

Where a shown value came from. It has its source and the time that the value was known.

Attributes:

Name Type Description
source str

The name of the source. For example "my to-do list".

known datetime | None

The time the value was known. None means that the value is not known.

Example
import datetime as dt
from scriptt.charts import Trace

Trace("my to-do list", dt.datetime(2026, 11, 2, 9, 0))

source instance-attribute

source: str

known class-attribute instance-attribute

known: datetime | None = None

of classmethod

of(value: Any) -> Trace | None

A trace from a Trace, a World API Origin (it has .entry), a World API Entry (it has .source and .known) or None. It reads these attributes. Any object that has them works.

Parameters:

Name Type Description Default
value Any

The object to read.

required

Returns:

Type Description
Trace | None

The trace. It is None if value is None.

Raises:

Type Description
TypeError

If value has neither .entry nor .source.

side_by_side

side_by_side(
    title: str, *charts: Chart, summary: str = ""
) -> Chart

2 or more charts of the same items next to each other. Each chart has its own value axis. Use it for 2 measures of different units (pay and people). Never use 2 scales on 1 axis.

Parameters:

Name Type Description Default
title str

The question the charts answer together.

required
*charts Chart

The charts. The scope of the first chart is the scope of all charts. The charts may share 1 assumption (Choice). 2 different assumptions are an error.

()
summary str

A sentence shown above the charts.

''

Returns:

Type Description
Chart

1 chart that contains the others.

flows

flows(
    items: Iterable[T],
    *,
    title: str,
    scope: Scope,
    source: Callable[[T], object],
    target: Callable[[T], object],
    n: Callable[[T], int] = lambda item: 1,
    least: int = 2,
    singles: str | None = None,
    unit: str = "count",
    summary: str = "",
) -> Chart

How many items moved from 1 category to another. Flows below least are put together in 1 row. A single move is then counted but not drawn as a finding.

Parameters:

Name Type Description Default
items Iterable[T]

The moves.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
source Callable[[T], object]

The category a move starts in.

required
target Callable[[T], object]

The category a move ends in.

required
n Callable[[T], int]

The count of 1 move (default 1).

lambda item: 1
least int

The smallest flow drawn on its own row.

2
singles str | None

The name of the row that contains the smaller flows. The default says the size. For example "flows of 1" or "flows under 3".

None
unit str

The title of the value axis.

'count'
summary str

A sentence above the chart.

''

Returns:

Type Description
Chart

A ranked chart of the flows. The counts add up to the number of moves.

Example
from types import SimpleNamespace as Move
from scriptt.charts import Scope, flows

moves = [
    Move(before="home", after="work"),
    Move(before="work", after="home"),
]
flows(
    moves,
    title="Where do tasks move?",
    scope=Scope("2 to 4 Nov 2026"),
    source=lambda m: m.before,
    target=lambda m: m.after,
)

members

members(
    items: Items[T],
    *,
    title: str,
    scope: Scope,
    label: Callable[[T], object],
    groups: Mapping[str, Callable[[T], Any]],
    missing_text: str = "missing",
    target: Target | None = None,
    column_width: int = 130,
    summary: str | Mapping[Any, str] = "",
    choice: Choice | None = None,
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

A grid of items against groups. A cell shows the item's value in that group or "missing". Use it to see which items are in which groups and where a part is missing.

Parameters:

Name Type Description Default
items Items[T]

The items. A function of the choice value that gives the items also works.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
label Callable[[T], object]

The name of an item.

required
groups Mapping[str, Callable[[T], Any]]

For each group name, the item's value in that group. A value is missing if it is None, False, "" or an empty list. A value of 0 is shown as 0.

required
missing_text str

The text of a missing cell.

'missing'
target Target | None

A goal for the grid with its status, such as "every task has a note". The chart shows it under the title.

None
column_width int

The width of each column in pixels. Widen it for long cell text.

130
summary str | Mapping[Any, str]

A sentence shown above the chart. A dict with 1 sentence for each choice value also works.

''
choice Choice | None

An assumption the reader can change. Then items is a function of its value.

None
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
note Callable[[T], str | None] | None

A short note shown next to an item.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view. For example {"sales": lambda p: p.sales}.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values by name. Each gives " source" and " known".

None

Returns:

Type Description
Chart

The chart. A subtitle line counts the items in each group.

Example
from types import SimpleNamespace as Task
from scriptt.charts import Scope, members

tasks = [Task(id="t1", notes=1), Task(id="t3", notes=0)]
count_notes = lambda t: t.notes
members(
    tasks,
    title="Does every task have a note?",
    scope=Scope("6 tasks"),
    label=lambda t: t.id,
    groups={"notes": lambda t: count_notes(t) or None},
)

money

money(value: float | None) -> str

A dollar amount for a label. An amount below $10,000 has cents. For example money(14.0) -> "$14.00" and money(12500.0) -> "$12,500".

over_time

over_time(
    items: Items[T],
    *,
    title: str,
    scope: Scope,
    x: Callable[[T], date | datetime],
    series: Mapping[str, Callable[[T], float | None]],
    unit: str = "",
    steps: bool = False,
    partial_from: date | datetime | None = None,
    dates: Mapping[str, date | datetime | None]
    | None = None,
    target: Target | None = None,
    date_format: str = "%-d %b",
    notes_on: str | None = None,
    summary: str | Mapping[Any, str] = "",
    choice: Choice | None = None,
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
    counts: Mapping[str, Callable[[T], int | None]]
    | None = None,
) -> Chart

1 or more values over dates. Each series is named at its last point.

Parameters:

Name Type Description Default
items Items[T]

1 item for each date. A function of the choice value that gives them also works.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
x Callable[[T], date | datetime]

The date or time of an item.

required
series Mapping[str, Callable[[T], float | None]]

For each series name, its value for an item. None means no point on that date.

required
unit str

The title of the value axis.

''
steps bool

True if a value stays the same until the next date (a step line). False for a straight line between points.

False
partial_from date | datetime | None

Dates from here on are a partial period (the month is not over). The chart shades and labels them.

None
dates Mapping[str, date | datetime | None] | None

Named dates drawn as vertical lines. For example {"deadline": dt.date(2026, 12, 8)}. A date that is None is not drawn.

None
target Target | None

A target line on the value axis.

None
date_format str

The format of the date labels on the axis.

'%-d %b'
counts Mapping[str, Callable[[T], int | None]] | None

The count behind each series' value by series name. For example {"with a pay range": lambda m: m.paid}. A series with no entry uses n.

None
notes_on str | None

The series whose points carry the notes and the ⚑ marks. By default the chart draws an item's note once on the first series that has a value for it.

None
summary str | Mapping[Any, str]

A sentence shown above the chart. A dict with 1 sentence for each choice value also works.

''
choice Choice | None

An assumption the reader can change. Then items is a function of its value.

None
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view. For example {"sales": lambda p: p.sales}.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values by name. Each gives " source" and " known".

None
note Callable[[T], str | None] | None

A short note. The chart draws it at its point.

None

Returns:

Type Description
Chart

The chart.

Example
import datetime as dt
from types import SimpleNamespace as Month
from scriptt.charts import Scope, over_time

months = [
    Month(month=dt.date(2026, 9, 1), added=60),
    Month(month=dt.date(2026, 10, 1), added=70),
]
over_time(
    months,
    title="Do I add more tasks each month?",
    scope=Scope("the to-do list, 2 months"),
    x=lambda m: m.month,
    series={"added": lambda m: m.added},
    partial_from=dt.date(2026, 10, 1),
)

ranges

ranges(
    items: Items[T],
    *,
    title: str,
    scope: Scope,
    label: Callable[[T], object],
    low: Callable[[T], float | date | None],
    high: Callable[[T], float | date | None],
    mid: Callable[[T], float | date | None] | None = None,
    point: Callable[[T], float | date | None]
    | None = None,
    range_name: str = "low to high",
    mid_name: str = "middle",
    point_name: str = "value",
    unit: str = "",
    order: Callable[[T], Any] | None = None,
    summary: str | Mapping[Any, str] = "",
    choice: Choice | None = None,
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

For each item, a range from low to high. Each range has a middle and a point. The values may be numbers or dates. With dates the range is 2 dates of 1 item, such as true from and known. Its label gives the gap in days.

An item with no low or high has no range. The chart still draws its middle and point.

Parameters:

Name Type Description Default
items Items[T]

The items. A function of the choice value that gives the items also works.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
label Callable[[T], object]

The name of an item.

required
low Callable[[T], float | date | None]

The low end of the range (a number or a date).

required
high Callable[[T], float | date | None]

The high end of the range.

required
mid Callable[[T], float | date | None] | None

A middle value. The chart draws it as a tick.

None
point Callable[[T], float | date | None] | None

A second measure of the same unit. The chart draws it as a diamond (an ask against a sold range).

None
range_name str

The name of the range in the legend.

'low to high'
mid_name str

The name of the middle tick in the legend.

'middle'
point_name str

The name of the point in the legend.

'value'
unit str

The title of the value axis.

''
order Callable[[T], Any] | None

The sort key of the items. The default is the order given.

None
summary str | Mapping[Any, str]

A sentence shown above the chart. A dict with 1 sentence for each choice value also works.

''
choice Choice | None

An assumption the reader can change. Then items is a function of its value.

None
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
note Callable[[T], str | None] | None

A short note shown next to an item.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view. For example {"sales": lambda p: p.sales}.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values by name. Each gives " source" and " known".

None

Returns:

Type Description
Chart

The chart.

Example
from types import SimpleNamespace as Guess
from scriptt.charts import Scope, ranges

guesses = [Guess(title="Send the report", low=30, high=90, best=45, runs=10)]
ranges(
    guesses,
    title="Which time guesses can I trust?",
    scope=Scope("62 finished tasks"),
    label=lambda g: g.title,
    low=lambda g: g.low,
    high=lambda g: g.high,
    mid=lambda g: g.best,
    n=lambda g: g.runs,
)

ranked

ranked(
    items: Items[T],
    *,
    title: str,
    scope: Scope,
    label: Callable[[T], object],
    value: Callable[[T], float | None],
    unit: str = "",
    show: Callable[[float], str] = figures,
    missing: Callable[[T], str | None] | None = None,
    target: Target | None = None,
    shares: bool = True,
    summary: str | Mapping[Any, str] = "",
    choice: Choice | None = None,
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

Items in order of a value. Each item has its share of the total and the cumulative share.

An item with no value is listed at the end as "no value" and with the reason that missing gives. The total does not count it and the chart does not draw it as 0.

Parameters:

Name Type Description Default
items Items[T]

The items. A function of the choice value that gives the items also works.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
label Callable[[T], object]

The name of an item.

required
value Callable[[T], float | None]

The value of an item, or None if it has none.

required
unit str

The title of the value axis. For example "dollars".

''
show Callable[[float], str]

How a value is written in its label (money for dollars).

figures
missing Callable[[T], str | None] | None

The reason an item has no value.

None
target Target | None

A target line on the value axis (with its status).

None
shares bool

False if the items are not parts of 1 whole (plans or scenarios). Then no share is shown.

True
summary str | Mapping[Any, str]

A sentence above the chart. 1 sentence for each choice value also works.

''
choice Choice | None

An assumption the reader can change.

None
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
note Callable[[T], str | None] | None

A short note shown next to an item.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view. For example {"sales": lambda p: p.sales}.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values by name. Each gives " source" and " known".

None

Returns:

Type Description
Chart

The chart. Its table view lists each item with its value, share and cumulative

Chart

share.

Example
from scriptt.charts import Scope, ranked
from types import SimpleNamespace as Task

items = [
    Task(title="Buy milk", minutes=15),
    Task(title="Send the report", minutes=45),
]
ranked(
    items,
    title="Which tasks take the most time?",
    scope=Scope("the to-do list of 4 Nov 2026"),
    label=lambda t: t.title,
    value=lambda t: t.minutes,
    unit="minutes",
)

views

views(
    items: Items[T],
    *,
    title: str,
    scope: Scope,
    label: Callable[[T], object],
    views: Mapping[str, Callable[[T], float | None]],
    unit: str = "",
    show: Callable[[float], str] = figures,
    domain: tuple[float, float] | None = None,
    order: Callable[[T], Any] | None = None,
    summary: str | Mapping[Any, str] = "",
    choice: Choice | None = None,
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

2 or 3 named views of the same items side by side. The chart draws a point for each view and joins the points by a line. Name each view with its date or its assumption. For example "as planned on 1 Nov 2026", "now (4 Nov 2026)" or "if I finish early".

Parameters:

Name Type Description Default
items Items[T]

The items. A function of the choice value that gives the items also works.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
label Callable[[T], object]

The name of an item.

required
views Mapping[str, Callable[[T], float | None]]

For each view name, the item's value in that view. None means not in that view.

required
unit str

The title of the value axis.

''
show Callable[[float], str]

How a value is written in the label at the right.

figures
domain tuple[float, float] | None

The value axis from low to high. For example (0, 1) for probabilities. The default starts at 0 and leaves room for the labels.

None
order Callable[[T], Any] | None

The sort key of the items. The default is the order given.

None
summary str | Mapping[Any, str]

A sentence shown above the chart. A dict with 1 sentence for each choice value also works.

''
choice Choice | None

An assumption the reader can change. Then items is a function of its value.

None
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
note Callable[[T], str | None] | None

A short note shown next to an item.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view. For example {"sales": lambda p: p.sales}.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values by name. Each gives " source" and " known".

None

Returns:

Type Description
Chart

The chart. The label at the right gives each view's value.

Example
from types import SimpleNamespace as Plan
from scriptt.charts import Scope, views

plans = [Plan(task="Book the room", planned=30, now=50)]
views(
    plans,
    title="Did any time guess change after the work?",
    scope=Scope("5 tasks"),
    label=lambda p: p.task,
    views={"as planned": lambda p: p.planned, "now": lambda p: p.now},
)

figures

figures(value: Any) -> str

A value as text for a label, written as world.describe writes it. A number has only its significant figures. A date reads "8 Oct 2026". A missing value is "no value".

graph

graph(
    edges: Iterable[T],
    *,
    title: str,
    scope: Scope,
    source: Callable[[T], object],
    target: Callable[[T], object],
    label: Callable[[T], str | None] | None = None,
    weight: Callable[[T], float | None] | None = None,
    sign: Callable[[T], int] | None = None,
    kind: Callable[[str], str] | None = None,
    summary: str = "",
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

Things and the typed links between them, as nodes and arrows. The layout reads left to right. A thing stands to the right of the things that link to it. A chain of steps then reads in order.

Parameters:

Name Type Description Default
edges Iterable[T]

The links. Each gives its 2 ends.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
source Callable[[T], object]

The thing a link starts at.

required
target Callable[[T], object]

The thing a link ends at.

required
label Callable[[T], str | None] | None

The kind of link, written at its middle. For example "raises", "triggers" or "scored with".

None
weight Callable[[T], float | None] | None

The strength of a link (a confidence or a count of people). The chart scales the line width to the strongest link.

None
sign Callable[[T], int] | None

+1 or -1 for a link that raises or lowers. The 2 signs get 2 colours and a legend.

None
kind Callable[[str], str] | None

The kind of a thing, from its name. For example "task" or "note". Each kind gets a colour and a legend.

None
summary str

A sentence shown above the chart.

''
n Callable[[T], int | None] | None

The count behind a link. It is shown in its tooltip.

None
trace Callable[[T], Any] | None

The source and known time of a link. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some links with ⚑ at their middle. The subtitle gives the rule and the count.

None
note Callable[[T], str | None] | None

A short note on a link, in its tooltip.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of a link's other values, by name.

None

Returns:

Type Description
Chart

The chart. Its table lists each link with the columns from, to, kind and weight.

Example
from types import SimpleNamespace as Link
from scriptt.charts import Scope, graph

links = [Link(before="Book the room", after="Send the report", sign=1, size=2)]
graph(
    links,
    title="Which task waits for which?",
    scope=Scope("6 tasks"),
    source=lambda k: k.before,
    target=lambda k: k.after,
    label=lambda k: "unlocks" if k.sign > 0 else "blocks",
    weight=lambda k: k.size,
    sign=lambda k: k.sign,
)

timeline

timeline(
    items: Iterable[T],
    *,
    title: str,
    scope: Scope,
    lane: Callable[[T], object],
    start: Callable[[T], date | None],
    end: Callable[[T], date | None],
    known: Callable[[T], date | datetime | None]
    | None = None,
    label: Callable[[T], object] | None = None,
    thing: Callable[[T], object] | None = None,
    until: date | None = None,
    summary: str = "",
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

When each version of a thing was true. The chart draws bars in 1 lane for each thing. A mark shows where each version became known. A version known after it started shows the gap. The mark sits to the right of the bar's start.

Parameters:

Name Type Description Default
items Iterable[T]

The versions. For a World API fact these are the entries of view.history(fact). An end entry stops the version before it and the chart does not draw it. A retract entry marks the thing's versions "retracted later".

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
lane Callable[[T], object]

The thing a version belongs to. Each thing has 1 lane.

required
start Callable[[T], date | None]

The first day the version is true. None means before the chart starts.

required
end Callable[[T], date | None]

The day it stops. None means it stops where the next version of the same thing starts, or it is still true and the bar runs to until.

required
thing Callable[[T], object] | None

What a version is a version of (a role and not the person who has it). The default is the entry's identity for World API entries. For other versions it is the lane. 2 things in 1 lane can both be true at once.

None
known Callable[[T], date | datetime | None] | None

The time the version became known (a diamond).

None
label Callable[[T], object] | None

The text on the bar (the value of the version).

None
until date | None

The last day on the chart. The default is the latest date in the data.

None
summary str

A sentence shown above the chart.

''
n Callable[[T], int | None] | None

The count behind a version. It is shown in its tooltip.

None
trace Callable[[T], Any] | None

The source and known time of a version. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some versions with ⚑. The subtitle gives the rule and the count.

None
note Callable[[T], str | None] | None

A short note on a version, after its label.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of a version's other values, by name.

None

Returns:

Type Description
Chart

The chart. Its table lists each version with the columns lane, start, end and

Chart

known.

Example
import datetime as dt
from types import SimpleNamespace as Entry
from scriptt.charts import Scope, timeline

t1 = [
    Entry(
        true_from=dt.date(2026, 11, 2),
        true_until=dt.date(2026, 11, 3),
        known=dt.date(2026, 11, 2),
        body={"status": "open"},
    )
]
timeline(
    t1,
    title="When was each status true?",
    scope=Scope("the history of task t1"),
    lane=lambda e: "t1",
    start=lambda e: e.true_from,
    end=lambda e: e.true_until,
    known=lambda e: e.known,
    label=lambda e: e.body["status"],
)

tree

tree(
    items: Iterable[T],
    *,
    title: str,
    scope: Scope,
    label: Callable[[T], object],
    parent: Callable[[T], object | None],
    value: Callable[[T], float | None] | None = None,
    root: str | None = None,
    rollup: bool = True,
    unit: str = "",
    show: Callable[[float], str] = figures,
    summary: str = "",
    n: Callable[[T], int | None] | None = None,
    trace: Callable[[T], Any] | None = None,
    flag: Flag[T] | None = None,
    note: Callable[[T], str | None] | None = None,
    detail: Mapping[str, Callable[[T], Any]]
    | None = None,
    traces: Mapping[str, Callable[[T], Any]]
    | None = None,
) -> Chart

Things under things, each with the total of everything under it. Read it from the top down. A child is indented under its parent. Its bar is its own value plus the values under it.

The chart adds a parent that is not one of the items (a list that contains tasks). That parent has no value of its own.

Parameters:

Name Type Description Default
items Iterable[T]

The things.

required
title str

The question the chart answers.

required
scope Scope

What the chart covers and leaves out.

required
label Callable[[T], object]

The name of a thing. Names must be unique. A name that repeats is an error. A loop is also an error.

required
parent Callable[[T], object | None]

The name of the thing directly above it, or None for a top thing.

required
value Callable[[T], float | None] | None

The value of a thing (minutes of work). The default counts each thing as 1. Then a bar is the count under it.

None
root str | None

The name of 1 top thing that contains every thing with no parent ("all tasks"). None draws no root.

None
rollup bool

True means a bar is the thing's value plus the values under it (minutes of a list). False means a bar is the thing's own value (the minutes of 1 task). Then only a root shows a total.

True
unit str

The title of the value axis.

''
show Callable[[float], str]

How a total is written in its label.

figures
summary str

A sentence shown above the chart.

''
n Callable[[T], int | None] | None

The count behind an item's value. It is shown next to the value.

None
trace Callable[[T], Any] | None

The source and known time of an item's value. It is a Trace, a World API Origin or a World API Entry.

None
flag Flag[T] | None

A rule that marks some items with ⚑. The subtitle gives the rule and the count it marks.

None
note Callable[[T], str | None] | None

A short note shown next to an item.

None
detail Mapping[str, Callable[[T], Any]] | None

More values for the tooltip and the table view.

None
traces Mapping[str, Callable[[T], Any]] | None

The traces of an item's other values, by name.

None

Returns:

Type Description
Chart

The chart. Its table lists each thing with its depth, own value and total.

Example
from types import SimpleNamespace as Task
from scriptt.charts import Scope, tree

items = [
    Task(title="Buy milk", list="home", minutes=15),
    Task(title="Send the report", list="work", minutes=45),
]
tree(
    items,
    title="Where does the time go?",
    scope=Scope("the to-do list of 4 Nov 2026"),
    label=lambda i: i.title,
    parent=lambda i: i.list,
    value=lambda i: i.minutes,
)