Skip to main content

Programmable infographic generation powered by sympy and svg.py

Project description

Infogroove

Infogroove converts declarative template definitions into SVG infographics using sympy for formula evaluation and svg.py for SVG generation.

Quick Start

Create the virtual environment and install dependencies with uv:

uv sync

Render any of the bundled examples (each lives in its own subdirectory):

uv run infogroove -f examples/horizontal-bars/def.json -i examples/horizontal-bars/data.json -o examples/horizontal-bars/horizontal-bars.svg
uv run infogroove -f examples/stat-cards/def.json -i examples/stat-cards/data.json -o examples/stat-cards/stat-cards.svg
uv run infogroove -f examples/blue-parallelograms/def.json -i examples/blue-parallelograms/data.json -o examples/blue-parallelograms/blue-parallelograms.svg
uv run infogroove -f examples/arc-circles/def.json -i examples/arc-circles/data.json -o examples/arc-circles/arc-circles.svg
uv run infogroove -f examples/staggered-keywords/def.json -i examples/staggered-keywords/data.json -o examples/staggered-keywords/staggered-keywords.svg

Running Tests

Install development dependencies and execute the test suite with pytest:

uv sync --extra dev
uv run --extra dev pytest

To measure coverage locally you can add the --cov flag:

uv run --extra dev pytest --cov=infogroove --cov=tests

Example Gallery

Template Preview
Horizontal Bars Horizontal bars preview
Stat Cards Stat cards preview
Blue Parallelogram Bands Blue parallelograms preview
Arc Circles Arc circles preview
Staggered Keywords Staggered keywords preview
Key Messages Key messages preview

Template Overview

A template definition is a JSON document with these top-level keys. The design aims to keep templates declarative and predictable:

  • Explicit scopes. Global properties establish shared context, while element-level let blocks create isolated overlays that run after any repeat bindings. Values never bleed across scope boundaries unless you intentionally rebind them.

  • Deterministic evaluation. Element let bindings resolve lazily the first time they are referenced. Cycles are detected and reported early, preventing runaway recursion and making intent obvious.

  • Composable building blocks. Elements remain small, nested structures. Complex layouts emerge from combining scoped bindings and child trees rather than inventing a verbose DSL.

  • properties: Global assignments evaluated before rendering begins. Provide the canvas size here (width, height) along with reusable constants such as palette, margin, or font_family. Values are injected into the rendering context as-is, so strings like "Inter, Arial, sans-serif" remain literal.

  • template: A list of element descriptors. Each descriptor has a type, optional attribute map, optional text, optional let, and optional children. Elements render once unless a repeat block is present.

  • numElementsRange (optional): Expected minimum and maximum number of input records for validation.

Each element may declare its own let block. These bindings evaluate against the current context (including repeat helpers) and the results become available to the element's attributes and its children.

The repeat block explicitly controls iteration:

{
  "type": "text",
  "repeat": {
    "items": "items",
    "as": "row"
  },
  "let": {
    "label": "row.label",
    "x": "__index__ * 24"
  },
  "attributes": {"x": "{x}", "y": "40"},
  "text": "{label}"
}
  • items references the collection to iterate (any dotted path resolved via the current context).
  • as names the current element. Use the reserved helpers (e.g. __index__, __count__) inside expressions when you need positional data; when the iterated item is a mapping, those helpers are also exposed on the alias (for example, row.__index__).
  • Element let injects per-iteration bindings scoped to that element. Expressions can reference the current item, previously declared loop bindings, and globals.

During iteration, Infogroove also injects reserved helpers such as __index__, __first__, __last__, __count__, and __total__ for convenience.

Placeholder syntax supports both {path.to.value} lookups and inline Python expressions such as {__index__ * 10} or {canvas.width / 2}. Expressions are evaluated inside the same safe context as loop bindings (global properties, data fields, derived metrics, and loop-scoped bindings).

Mixed casing identifiers (e.g. {items[0].myValue}) are resolved by normalising to snake/camel case automatically, but adopting snake_case within your own datasets keeps templates more predictable.

CLI Options

uv run infogroove --help

Key flags:

  • -f, --template: Path to the template definition JSON file (e.g. def.json).
  • -i, --input: JSON file containing an array of data objects.
  • -o, --output: Destination SVG path or - for stdout.

Programmatic Usage

Infogroove exposes a loader for integrating templates directly into Python applications:

from infogroove.loader import load

with open("examples/arc-circles/def.json", encoding="utf-8") as fh:
    infographic = load(fh)

data = [{"label": "Alpha", "value": 3}]
svg_markup = infographic.render(data)

Prefer infogroove.loader.load for file objects and infogroove.loader.loads when the template definition is already in memory as a string. Both helpers return an InfogrooveRenderer, exposing the parsed template via the template property for metadata inspection.

When you already have the JSON structure as a Python mapping, instantiate an infographic directly with the Infogroove factory:

from infogroove import Infogroove

infographic = Infogroove({
    "properties": {
        "canvas": {"width": 200, "height": 40},
        "gap": 10,
    },
    "template": [
        {
            "type": "circle",
            "attributes": {"cx": "{__index__ * gap}", "cy": "20", "r": "5"},
            "repeat": {"items": "data", "as": "item"}
        }
    ],
})

svg_inline = infographic.render([{}] * 10)

Developing Templates

  • Keep shared constants (including canvas dimensions) under the top-level properties block.
  • Use repeat to make iteration explicit; push derived per-loop values into an element's let block so they stay scoped to that element.
  • Inline expressions handle quick maths ({__index__ * 10}) while element let bindings are ideal for shared or multi-step calculations.
  • Let bindings resolve lazily, so the order you declare keys does not matter. However, circular definitions (e.g. total: "max", max: "total") will be rejected with a clear error. Break cycles by lifting shared calculations into a new binding or restructuring the dependency chain.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infogroove-0.3.1.tar.gz (42.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infogroove-0.3.1-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file infogroove-0.3.1.tar.gz.

File metadata

  • Download URL: infogroove-0.3.1.tar.gz
  • Upload date:
  • Size: 42.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.7

File hashes

Hashes for infogroove-0.3.1.tar.gz
Algorithm Hash digest
SHA256 3b40cc3990a8727e599321222f1a5c2f2b145095636967ac6f9bdbdc2c923db8
MD5 f076f0ff98eabedd7f3d06d9821d75db
BLAKE2b-256 6b6a7d5d77a37c0ecd6ffc4a1a2327ce828ed6113a3bd4470a62fc4b6b27e6a3

See more details on using hashes here.

File details

Details for the file infogroove-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: infogroove-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 18.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.7

File hashes

Hashes for infogroove-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 75aff4d1efa65d89952229fe320b34f028a79de62e1d4c20a654df9cb21e9a93
MD5 0db0069173850f696590fc71b7e74205
BLAKE2b-256 99a56680efaa852473af79f7bce2170a03f1e745c0b42ff5d7bcde627e7668fa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page