plantuml-compose
A Python library that makes creating PlantUML diagrams intuitive and type-safe.
https://github.com/jealouscloud/plantuml-compose
Why plantuml-compose?
PlantUML is powerful but its text syntax can be cryptic. What does A -[#red,dashed]-> B mean? What options are available for a state transition?
plantuml-compose solves this by providing:
- Discoverable APIs: Use your IDE's autocomplete to explore options
- Type safety: Catch errors before rendering, not after
- Pure factory functions: Compose diagrams declaratively with nesting
- Full PlantUML coverage: Every diagram type, every feature
Quick Start
from plantuml_compose import sequence_diagram, render
d = sequence_diagram(title="API Call")
p = d.participants
e = d.events
client = p.actor("Client")
server = p.participant("Server")
d.add(client, server)
d.phase("Request", [
e.message(client, server, "GET /users"),
e.reply(server, client, "200 OK"),
])
print(render(d))
The Pattern
Every diagram follows the same shape:
# 1. Create diagram — get namespace(s)
d = state_diagram(title="Lifecycle")
el = d.elements
t = d.transitions
# 2. Create elements via namespace factories
idle = el.state("Idle")
active = el.state("Active")
# 3. Register elements
d.add(idle, active)
# 4. Create and register connections
d.connect(
t.transitions(
(el.initial(), idle, "start"),
(idle, active, "go"),
(active, el.final(), "done"),
)
)
# 5. Render
print(render(d))
Namespaces organize the API — type d.elements. or d.transitions. and your IDE shows every available factory method.
Bulk helpers reduce repetition:
# Instead of individual calls:
t.transition(a, b, label="x"),
t.transition(b, c, label="y"),
t.transition(c, d, label="z"),
# Use the plural form:
t.transitions(
(a, b, "x"),
(b, c, "y"),
(c, d, "z"),
)
# Or fan-out from one source:
r.arrows_from(api,
(db, "queries"),
(cache, "reads"),
(queue, "publishes"),
)
Styling
Two levels of styling are available on every diagram type.
Inline styles on individual elements and connections:
# Element styling
el.state("Error", style={"background": "#FFCDD2", "line_color": "red"})
# Connection styling — string shorthand or dict
t.transition(a, b, style="dashed")
t.transition(a, b, style={"color": "red", "pattern": "dotted"})
# Arrow length (layout hint)
r.arrow(a, b, length=1) # short: ->
r.arrow(a, b, length=3) # long: --->
# Custom arrow heads
r.arrow(a, b, left_head="o", right_head=">>") # o-->>
Diagram-wide styling via diagram_style=:
d = class_diagram(
title="Model",
diagram_style={
"class_": {"background": "#E3F2FD", "round_corner": 10},
"arrow": {"line_color": "gray", "font_size": 10},
"note": {"background": "#FFF9C4"},
"stereotypes": {
"important": {"background": "pink", "font_style": "bold"},
},
},
)
Every element property is documented in ElementStyleDict — hover over it in your IDE to see all available keys (background, line_color, font_color, font_name, font_size, padding, margin, round_corner, shadowing, max_width, and more).
Supported Diagram Types
Behavioral
| Type | Use When | Guide |
|---|---|---|
| Sequence | Message flows between participants | API calls, protocols |
| State | Entity lifecycle tracking | Order status, workflows |
| Activity | Process flow with decisions and parallelism | Business processes, algorithms |
| Use Case | System boundaries and actor goals | Requirements, features |
| Timing | State changes over time | Hardware signals, protocol timing |
Structural
| Type | Use When | Guide |
|---|---|---|
| Class | Types, attributes, and relationships | Domain models, API types |
| Object | Specific instances and values | Test scenarios, snapshots |
| Component | System architecture | Services, modules, dependencies |
| Deployment | Software on infrastructure | Servers, containers, cloud |
| Network | Network topology | IP addressing, segments |
Hierarchical
| Type | Use When | Guide |
|---|---|---|
| Mind Map | Brainstorming and organizing ideas | Feature planning, concepts |
| WBS | Breaking down work | Project planning, tasks |
| Gantt | Scheduling with dependencies | Timelines, sprint planning |
Data & UI
| Type | Use When | Guide |
|---|---|---|
| JSON | Visualizing JSON data | API responses, config |
| YAML | Visualizing YAML data | Config files, specs |
| Salt | UI wireframes | Forms, layouts, menus |
Composition
| Feature | Guide |
|---|---|
| Sub-diagrams | Embed diagrams inside notes and messages |
Server URLs
from plantuml_compose import render, render_url
render_url(render(d)) # https://www.plantuml.com/plantuml/svg/...
render_url(render(d), format="png") # PNG format
render_url(render(d), server="http://my-server") # custom server
CLI: Markdown Processing
puml-md (also available as plantuml-compose md) processes markdown files, executing Python code blocks that import plantuml_compose and inserting rendered diagram images.
Given a markdown file containing:
```python
from plantuml_compose import state_diagram, render
d = state_diagram(title="Example")
d.add(d.elements.state("Active"))
print(render(d))
```
Running puml-md doc.md produces the same file with a diagram image appended after the code block:
```python
from plantuml_compose import state_diagram, render
d = state_diagram(title="Example")
d.add(d.elements.state("Active"))
print(render(d))
```

Re-running replaces existing diagram URLs rather than duplicating them.
puml-md doc.md # file → stdout
puml-md -i doc.md # in-place update
puml-md -id doc.md # in-place + wrap code in <details>
puml-md --validate doc.md # check diagrams against the server
cat doc.md | puml-md # stdin → stdout
| Flag | Description |
|---|---|
-i, --in-place |
Modify file in place |
-d, --details |
Wrap code blocks in collapsible <details><summary> |
--validate |
Check generated diagrams against the PlantUML server; exits non-zero on errors |
--server URL |
Custom PlantUML server (default: public server) |
--format FMT |
Output format: svg, png, txt (default: svg) |
Installation
pip install plantuml-compose
Requires Python 3.13+.
Development
# Install dependencies
uv sync
# Run tests
uv run pytest
# Validate output against PlantUML
plantuml --check-syntax output.puml
License
MIT
Release files for plantuml-compose 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| plantuml_compose-1.0.2.tar.gz | 142.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plantuml_compose-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 327.3 kB
Release files / plantuml_compose-1.0.2.tar.gz
| Download URL | plantuml_compose-1.0.2.tar.gz |
|---|---|
| Size | 142.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
89d50d67394121b077a5dc60f25afa534d0708b88983b58c668d2bf08794841c
|
|
BLAKE2b-256 checksum How to use checksums |
c38a9af1392ad8e9087ee66e83b8ae23ffe72f664b5bd4a1510ba3d79d2643ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"25.11","id":"xantusia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / plantuml_compose-1.0.2-py3-none-any.whl
| Download URL | plantuml_compose-1.0.2-py3-none-any.whl |
|---|---|
| Size | 184.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a6fc6578b81ffe10c6cab5acc2327b0d428e05090171ed3ec38b46123c4d1c46
|
|
BLAKE2b-256 checksum How to use checksums |
876ec1466667ba3ef97b9b8961d4cda533c5a2491a852d1ef315baaf03e3228d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"25.11","id":"xantusia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|