Properties¶
A model can be extended with a table of properties to document additional details:
from c4 import (
Container,
ContainerBoundary,
ContainerDb,
ContainerDiagram,
Person,
Rel,
SystemBoundary,
)
from c4.contrib.plantuml import RelLeft
with ContainerDiagram(title="Properties") as diagram:
user = Person("User", "Interacts with the system")
user.add_property("Channel", "Web")
user.add_property("Region", "EU")
with SystemBoundary("Demo System", "Example system"):
app = Container("App Service", "Handles business logic")
app.add_property("Runtime", "Python 3.11")
app.add_property("Team", "Backend Team")
db = ContainerDb("App Database", "Stores application data")
db.add_property("Version", "PostgreSQL 15")
db.add_property("Backup", "Daily")
with ContainerBoundary("Async Processing", "Background jobs"):
queue = Container("Worker", "Processes async tasks")
queue.add_property("Concurrency", "4 workers")
queue.add_property("RetryPolicy", "3 attempts")
user_app_rel = user >> Rel("Uses") >> app
app_queue_rel = app >> RelLeft("Sends jobs") >> queue
app_queue_rel.set_property_header("Key", "Value", "Notes")
app_queue_rel.add_property("Mode", "Async", "Fire-and-forget")
app_queue_rel.add_property("Retry", "Enabled", "Max 3 attempts")
app_db_rel: Rel = app >> Rel("Reads/Writes") >> db
app_db_rel.add_property("AccessPattern", "Transactional")
app_db_rel.without_property_header()
This produces the following diagram:
API¶
-
add_property(*args: str)Adds a row to the property table. The number of values must match the number of columns in the header. This is the step-by-step alternative when properties are added conditionally or built one row at a time:
app = Container("App Service", "Handles business logic") app.add_property("Runtime", "Python 3.12") app.add_property("Team", "Platform") -
with_properties(*properties, header=None, show_header=True)Adds one or more rows to the property table and returns the element. This is available as
BaseDiagramElement.with_properties. For one row, pass values directly; for multiple rows, pass row sequences. Use this form when the element is already being created in-place and you want to keep its properties next to the constructor:app = Container("App Service", "Handles business logic").with_properties( ("Runtime", "Python 3.12"), ("Team", "Platform"), )The top-level
with_propertiesfunction can add the same rows to an existing element:from c4 import Container, with_properties app = with_properties( Container("App Service", "Handles business logic"), ("Runtime", "Python 3.12"), ("Team", "Platform"), )It can also wrap a reusable element factory. Every element created by the wrapped factory receives the same property rows:
from functools import partial from c4 import Container, with_properties PlatformContainer = with_properties( partial(Container, description="Owned by the platform team."), ("Team", "Platform"), ("Support", "24/7"), ) app = PlatformContainer(label="App Service") worker = PlatformContainer(label="Worker Service") -
set_property_header(*args: str)Sets the column headers for the property table. This must be called before adding any property rows, unless the new header has the same number of columns as the existing rows. The default header is
("Property", "Value"). -
without_property_headerDisables rendering of the header row for the property table.
Supported elements¶
Properties can be added to diagram elements and relationships supported by C4-PlantUML. They are emitted as C4-PlantUML property macros before the target element or relationship.