engrapha-diagrams 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. engrapha_diagrams-0.1.0/PKG-INFO +414 -0
  2. engrapha_diagrams-0.1.0/README.md +396 -0
  3. engrapha_diagrams-0.1.0/pyproject.toml +37 -0
  4. engrapha_diagrams-0.1.0/setup.cfg +4 -0
  5. engrapha_diagrams-0.1.0/src/engrapha_diagrams/__init__.py +43 -0
  6. engrapha_diagrams-0.1.0/src/engrapha_diagrams/architecture.py +707 -0
  7. engrapha_diagrams-0.1.0/src/engrapha_diagrams/base.py +244 -0
  8. engrapha_diagrams-0.1.0/src/engrapha_diagrams/c4.py +395 -0
  9. engrapha_diagrams-0.1.0/src/engrapha_diagrams/class_diagram.py +578 -0
  10. engrapha_diagrams-0.1.0/src/engrapha_diagrams/cloud.py +378 -0
  11. engrapha_diagrams-0.1.0/src/engrapha_diagrams/er_diagram.py +817 -0
  12. engrapha_diagrams-0.1.0/src/engrapha_diagrams/flowchart.py +650 -0
  13. engrapha_diagrams-0.1.0/src/engrapha_diagrams/git.py +250 -0
  14. engrapha_diagrams-0.1.0/src/engrapha_diagrams/layout.py +470 -0
  15. engrapha_diagrams-0.1.0/src/engrapha_diagrams/network.py +1088 -0
  16. engrapha_diagrams-0.1.0/src/engrapha_diagrams/py.typed +1 -0
  17. engrapha_diagrams-0.1.0/src/engrapha_diagrams/schema.py +459 -0
  18. engrapha_diagrams-0.1.0/src/engrapha_diagrams/sequence.py +456 -0
  19. engrapha_diagrams-0.1.0/src/engrapha_diagrams/shapes.py +1026 -0
  20. engrapha_diagrams-0.1.0/src/engrapha_diagrams/stack.py +221 -0
  21. engrapha_diagrams-0.1.0/src/engrapha_diagrams/state_machine.py +1073 -0
  22. engrapha_diagrams-0.1.0/src/engrapha_diagrams/theme.py +442 -0
  23. engrapha_diagrams-0.1.0/src/engrapha_diagrams/timing.py +289 -0
  24. engrapha_diagrams-0.1.0/src/engrapha_diagrams.egg-info/PKG-INFO +414 -0
  25. engrapha_diagrams-0.1.0/src/engrapha_diagrams.egg-info/SOURCES.txt +40 -0
  26. engrapha_diagrams-0.1.0/src/engrapha_diagrams.egg-info/dependency_links.txt +1 -0
  27. engrapha_diagrams-0.1.0/src/engrapha_diagrams.egg-info/requires.txt +8 -0
  28. engrapha_diagrams-0.1.0/src/engrapha_diagrams.egg-info/top_level.txt +1 -0
  29. engrapha_diagrams-0.1.0/tests/test_base.py +141 -0
  30. engrapha_diagrams-0.1.0/tests/test_class_diagram.py +139 -0
  31. engrapha_diagrams-0.1.0/tests/test_er_diagram.py +134 -0
  32. engrapha_diagrams-0.1.0/tests/test_flowchart.py +128 -0
  33. engrapha_diagrams-0.1.0/tests/test_integration.py +172 -0
  34. engrapha_diagrams-0.1.0/tests/test_layout.py +135 -0
  35. engrapha_diagrams-0.1.0/tests/test_network.py +186 -0
  36. engrapha_diagrams-0.1.0/tests/test_notes_upgrades.py +126 -0
  37. engrapha_diagrams-0.1.0/tests/test_sequence.py +127 -0
  38. engrapha_diagrams-0.1.0/tests/test_shapes.py +184 -0
  39. engrapha_diagrams-0.1.0/tests/test_stack.py +96 -0
  40. engrapha_diagrams-0.1.0/tests/test_state_machine.py +127 -0
  41. engrapha_diagrams-0.1.0/tests/test_theme.py +46 -0
  42. engrapha_diagrams-0.1.0/tests/test_timing.py +83 -0
@@ -0,0 +1,414 @@
1
+ Metadata-Version: 2.4
2
+ Name: engrapha-diagrams
3
+ Version: 0.1.0
4
+ Summary: Vector-native PDF diagram toolkit for ReportLab Platypus
5
+ Author: Bharat Dangi
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: reportlab>=4.5.1
12
+ Requires-Dist: pydantic>=2.13.4
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=9.0.3; extra == "dev"
15
+ Requires-Dist: pytest-cov>=6.0; extra == "dev"
16
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
17
+ Requires-Dist: mypy>=1.11.0; extra == "dev"
18
+
19
+
20
+ > **Transparency Notice:** Built to solve my own frustration with inconsistent AI-generated notes. Heavy AI assistance was used for code generation, but the architecture, testing, and curation are mine.
21
+
22
+ ![Engrapha](../assets/Engrapha_logo_black.svg)
23
+ # 📊 engrapha_diagrams
24
+
25
+ ### Project Status: Early alpha — feedback welcome!
26
+
27
+ [![Python Version](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)
28
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
29
+ [![Format](https://img.shields.io/badge/format-ReportLab%20Drawing-orange.svg)](#)
30
+
31
+ Vector-native PDF diagram toolkit for ReportLab Platypus. Draw complex diagrams natively inside your ReportLab documents with a clean, pythonic API.
32
+
33
+ No raster images, no external command-line tools, and no internet connection required. All diagram types compile directly to `reportlab.graphics.shapes.Drawing` objects that wrap seamlessly as Platypus Flowables.
34
+
35
+ ---
36
+
37
+ ## 🚀 Features
38
+
39
+ * **Flowchart**: ANSI/ISO flowchart symbols (terminals, processes, decisions, io, connectors).
40
+ * **SequenceDiagram**: UML sequence diagrams (actors, lifelines, activation bars, message arrows, dividers).
41
+ * **ClassDiagram**: UML class diagrams (class boxes, headers, attributes, methods, relations).
42
+ * **ERDiagram**: Entity-Relationship diagrams (entities, relations, primary key and multi-value attributes).
43
+ * **StateMachine**: DFA/NFA and process state diagrams (states, transitions, initial/accepting indicators).
44
+ * **NetworkDiagram**: Network topology (hosts, servers, databases, links).
45
+ * **ArchitectureDiagram**: System architecture topologies with clients, services, databases, queues, and auto-routed connections.
46
+ * **AWSDiagram**: Cloud infrastructure architecture with AWS icons (EC2, S3, RDS, Lambda, SQS).
47
+ * **GitDiagram**: Git branch timeline diagrams with commits, merges, and distinct branch lanes.
48
+ * **SchemaDiagram**: Database table schema definition diagrams with field types, primary keys, and foreign-key links.
49
+ * **C4ContainerDiagram**: C4 Model container diagrams with System Context, Container, Component layers, and descriptive relationships.
50
+ * **TimingDiagram**: Digital waveform timing diagrams.
51
+ * **LayeredStack**: OSI model, TCP/IP stack, memory hierarchy.
52
+ * **Standalone Export**: Save drawings directly to PDF, SVG, and PNG/JPG formats.
53
+
54
+ ---
55
+
56
+ ## 📦 Installation
57
+
58
+ Install the package locally from the monorepo root:
59
+
60
+ ```bash
61
+ pip install ./packages/engrapha_diagrams
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 🎨 Supported Diagram Types & Examples
67
+
68
+ ### 1. Flowchart
69
+ Draw processes, decisions, and connectors with auto-layout or manual coordinates.
70
+
71
+ ```python
72
+ import engrapha_diagrams as ed
73
+
74
+ # Create a horizontal flowchart with a custom scale factor
75
+ fc = ed.Flowchart(
76
+ width=400,
77
+ height=150,
78
+ direction="LR", # 'TB' (top-to-bottom, default) or 'LR' (left-to-right)
79
+ scale_factor=1.0, # Optional manual override for text/box sizing (default: auto-computed)
80
+ )
81
+ fc.terminal("start", "START")
82
+ fc.process("calc", "Compute Sum")
83
+ fc.decision("check", "Sum > 100?")
84
+ fc.terminal("end", "END")
85
+
86
+ fc.edge("start", "calc")
87
+ fc.edge("calc", "check")
88
+ fc.edge("check", "end", branch="yes")
89
+ fc.edge("check", "calc", branch="no", orthogonal=True)
90
+ ```
91
+
92
+ ### 2. Sequence Diagram
93
+ Draw actor interactions over lifelines.
94
+
95
+ ```python
96
+ import engrapha_diagrams as ed
97
+
98
+ seq = ed.SequenceDiagram(width=400, height=220)
99
+ seq.actor("c", "Client")
100
+ seq.actor("s", "Server")
101
+
102
+ seq.activate("c")
103
+ seq.message("c", "s", "HTTP GET /index.html")
104
+ seq.activate("s")
105
+ seq.divider("Internal Processing")
106
+ # Arrow styles: 'solid' (default), 'dashed', 'solid_open', 'dashed_open'
107
+ seq.message("s", "c", "200 OK (HTML Document)", arrow="dashed")
108
+ seq.deactivate("s")
109
+ seq.deactivate("c")
110
+ ```
111
+
112
+
113
+ ### 3. Layered Stack
114
+ Draw OSI stacks, memory hierarchies, or layered architectures.
115
+
116
+ ```python
117
+ import engrapha_diagrams as ed
118
+
119
+ stack = ed.LayeredStack(width=300, height=180)
120
+ stack.layer("Application", sublabel="HTTP, DNS")
121
+ stack.layer("Transport", sublabel="TCP, UDP")
122
+ stack.divider() # Draw a thicker divider line after Transport layer
123
+ stack.layer("Network", sublabel="IP, ICMP")
124
+ stack.layer("Link", sublabel="Ethernet")
125
+ ```
126
+
127
+
128
+ ### 4. Network Diagram
129
+ Draw network topologies with hosts, clouds, switches, routers, and firewalls.
130
+
131
+ ```python
132
+ import engrapha_diagrams as ed
133
+
134
+ net = ed.NetworkDiagram(width=500, height=220)
135
+ net.node("inet", "Internet", x=50, y=110, kind="cloud")
136
+ net.node("fw", "Firewall", x=160, y=110, kind="firewall")
137
+ net.node("sw", "Core Switch", x=270, y=110, kind="switch")
138
+ net.node("srv", "Web Server", x=380, y=150, kind="server")
139
+ net.node("db", "Database", x=380, y=70, kind="database")
140
+
141
+ net.link("inet", "fw")
142
+ net.link("fw", "sw")
143
+ net.link("sw", "srv")
144
+ net.link("sw", "db")
145
+
146
+ # Also supports building standard topologies programmatically:
147
+ # net.star_topology(center_id="sw", center_label="Switch", spoke_ids=["h1", "h2", "h3"])
148
+ # net.bus_topology(node_ids=["n1", "n2", "n3"])
149
+ # net.ring_topology(node_ids=["r1", "r2", "r3"])
150
+ # net.mesh_topology(node_ids=["m1", "m2", "m3"])
151
+ # net.tree_topology(parent_child_map={"root": ["child1", "child2"]})
152
+ ```
153
+
154
+
155
+ ### 5. UML Class Diagram
156
+ Draw UML class diagrams with visibility, attributes, and methods.
157
+
158
+ ```python
159
+ import engrapha_diagrams as ed
160
+
161
+ cd = ed.ClassDiagram(width=400, height=250, class_w=120)
162
+ cd.uml_class("Shape", "Shape", stereotype="abstract", methods=["+ area(): double"])
163
+ cd.uml_class("Circle", "Circle", attributes=["- radius: double"], methods=["+ area(): double"])
164
+ # Relationship kinds: 'inheritance', 'realization', 'composition', 'aggregation', 'association', 'dependency'
165
+ cd.relate("Circle", "Shape", kind="inheritance")
166
+ ```
167
+
168
+
169
+ ### 6. Entity-Relationship Diagram (ER)
170
+ Draw entity-relationship diagrams (Chen notation) with cardinalities.
171
+
172
+ ```python
173
+ import engrapha_diagrams as ed
174
+
175
+ er = ed.ERDiagram(width=450, height=200)
176
+ er.entity("Customer")
177
+ er.relationship("Buys")
178
+ er.entity("Product")
179
+ er.entity_attributes("Customer", [("ID", {"pk": True}), "Name"])
180
+ er.entity_attributes("Product", [("SKU", {"pk": True}), "Price"])
181
+ er.connect("Customer", "Buys", card_from="1", card_to="N")
182
+ er.connect("Product", "Buys", card_from="1", card_to="N")
183
+ ```
184
+
185
+ ### 7. State Machine (DFA / Process Transitions)
186
+ Draw finite state automata or lifecycle models.
187
+
188
+ ```python
189
+ import engrapha_diagrams as ed
190
+
191
+ sm = ed.StateMachine(width=400, height=180)
192
+ sm.state("s0", "Init", x=70, y=90, initial=True)
193
+ sm.state("s1", "Active", x=200, y=90)
194
+ sm.state("s2", "Success", x=330, y=90, accepting=True)
195
+
196
+ sm.transition("s0", "s1", label="start")
197
+ sm.transition("s1", "s1", label="process")
198
+ sm.transition("s1", "s2", label="complete")
199
+ ```
200
+
201
+ ### 8. Timing Diagram
202
+ Draw digital timing signal waveforms.
203
+
204
+ ```python
205
+ import engrapha_diagrams as ed
206
+
207
+ td = ed.TimingDiagram(width=400, height=150)
208
+ td.clock("CLK", period=20.0, cycles=6)
209
+ td.signal("RESET", transitions=[(0, 1), (15, 0)])
210
+ td.signal("DATA", transitions=[(0, 0), (35, 1), (75, 0)])
211
+ ```
212
+
213
+ ### 9. Database Schema Diagram
214
+ Draw database table structures with primary/foreign keys and relationships.
215
+
216
+ ```python
217
+ import engrapha_diagrams as ed
218
+
219
+ schema = ed.SchemaDiagram(width=450, height=200)
220
+ schema.table("users", [
221
+ ("id", "INTEGER", {"pk": True}),
222
+ ("email", "VARCHAR", {}),
223
+ ("created_at", "TIMESTAMP", {})
224
+ ])
225
+ schema.table("orders", [
226
+ ("id", "INTEGER", {"pk": True}),
227
+ ("user_id", "INTEGER", {"fk": True}),
228
+ ("total", "DECIMAL", {})
229
+ ])
230
+ schema.relation("orders", "user_id", "users", "id")
231
+ ```
232
+
233
+ ### 10. Service Architecture Diagram
234
+ Draw multi-tier system topologies (clients, microservices, databases, queues) with automatic or manual layouts.
235
+
236
+ ```python
237
+ import engrapha_diagrams as ed
238
+
239
+ # Supports orientation: 'horizontal' (default) or 'vertical'
240
+ arch = ed.ArchitectureDiagram(width=450, height=220, orientation="horizontal")
241
+ arch.client("web", "Web Client")
242
+ arch.service("api", "Gateway API")
243
+ arch.database("db", "Main Database")
244
+ arch.queue("q", "Message Broker")
245
+
246
+ arch.connect("web", "api", "HTTPS")
247
+ arch.connect("api", "db", "TCP/3306")
248
+ arch.connect("api", "q", "AMQP")
249
+ ```
250
+
251
+
252
+ ### 11. C4 Container Diagram
253
+ Draw C4 Model Container views to document software systems, containers, technologies, and relationships.
254
+
255
+ ```python
256
+ import engrapha_diagrams as ed
257
+
258
+ c4 = ed.C4ContainerDiagram(width=400, height=200)
259
+ c4.system("user", "Customer")
260
+ c4.container("web", "SPA (React)", "Provides shopping UI")
261
+ c4.container("api", "API Application (Go)", "Handles business logic")
262
+ c4.container("db", "Database (Postgres)", "Stores order data")
263
+
264
+ c4.relate("user", "web", "Uses")
265
+ c4.relate("web", "api", "Makes API calls to")
266
+ c4.relate("api", "db", "Reads/Writes to")
267
+ ```
268
+
269
+ ### 12. Git Branch Flow Diagram
270
+ Draw commits, branch lanes, merges, and timelines horizontally.
271
+
272
+ ```python
273
+ import engrapha_diagrams as ed
274
+
275
+ git = ed.GitDiagram(width=400, height=150)
276
+ git.commit("main", "C1: Initial Commit")
277
+ git.branch("main", "feature")
278
+ git.commit("feature", "C2: Implement login")
279
+ git.commit("main", "C3: Hotfix bug")
280
+ git.merge("feature", "main", "C4: Merge feature/login")
281
+ ```
282
+
283
+ ### 13. AWS Diagram
284
+ Draw AWS cloud infrastructure diagrams using vector-native AWS icons.
285
+
286
+ ```python
287
+ import engrapha_diagrams as ed
288
+
289
+ # Supports orientation: 'horizontal' (default) or 'vertical'
290
+ aws = ed.AWSDiagram(width=450, height=220, orientation="horizontal")
291
+ # Supported node methods: ec2(), rds(), s3(), lambda_fn(), sqs()
292
+ aws.ec2("web", "Web Server")
293
+ aws.rds("db", "RDS PostgreSQL")
294
+ aws.s3("bucket", "S3 Storage")
295
+ aws.sqs("queue", "Job Queue")
296
+
297
+ aws.connect("web", "db", "SQL Connection")
298
+ aws.connect("web", "bucket", "Uploads")
299
+ aws.connect("web", "queue", "Events")
300
+ ```
301
+
302
+
303
+ ---
304
+
305
+ ## 🎨 Diagram Theming & Integration
306
+
307
+ `engrapha_diagrams` comes with built-in dark and light themes, and can dynamically inherit themes from `engrapha_notes` for consistent visual layouts.
308
+
309
+ ### 1. Using Preset Diagram Themes
310
+ Apply a theme directly to your builder instance:
311
+
312
+ ```python
313
+ import engrapha_diagrams as ed
314
+
315
+ # Use preset theme (ed.DARK or ed.LIGHT)
316
+ diagram = ed.Flowchart(width=300, height=200, theme=ed.LIGHT)
317
+ ```
318
+
319
+ ### 2. Matching Notes Theme (Integration)
320
+ Derive matching diagram settings from the active document notes theme:
321
+
322
+ ```python
323
+ import engrapha_notes as en
324
+ import engrapha_diagrams as ed
325
+
326
+ # 1. Set the notes theme
327
+ en.set_theme(en.OCEAN_DARK)
328
+
329
+ # 2. Derive the matching diagram theme
330
+ diag_theme = ed.DiagramTheme.from_notes_theme(en.get_theme())
331
+
332
+ # 3. Apply it to your diagrams
333
+ fc = ed.Flowchart(width=400, height=200, theme=diag_theme)
334
+ ```
335
+
336
+ ### 3. Customizing & Overriding Themes
337
+ Modify a theme on the fly using `model_copy(update={...})`:
338
+
339
+ ```python
340
+ # Create a print-optimized black-and-white diagram theme
341
+ bw_theme = ed.DiagramTheme.from_notes_theme(en.get_theme()).model_copy(
342
+ update={
343
+ "stack_colors": ("#ffffff", "#ffffff", "#ffffff"),
344
+ "stack_stroke": "#000000",
345
+ "stack_text": "#000000",
346
+ "stack_sublabel_text": "#000000",
347
+ "bg": "#ffffff",
348
+ "text": "#000000",
349
+ "node_fill": "#ffffff",
350
+ "node_stroke": "#000000",
351
+ "node_text": "#000000",
352
+ "font_name": "Times-Roman",
353
+ "font_name_bold": "Times-Bold",
354
+ "font_name_italic": "Times-Italic",
355
+ }
356
+ )
357
+ # Apply to stack diagram
358
+ stack = ed.LayeredStack(width=300, height=180, theme=bw_theme)
359
+ ```
360
+
361
+ ---
362
+
363
+ ## 💾 Standalone Export
364
+
365
+ Export your diagrams directly to vector or raster formats without a ReportLab story:
366
+
367
+ ```python
368
+ diagram = ed.Flowchart(width=300, height=200)
369
+ diagram.terminal("s", "START").terminal("e", "END").edge("s", "e")
370
+
371
+ # Save to PDF (vector)
372
+ diagram.save("output.pdf")
373
+
374
+ # Save to SVG (vector)
375
+ diagram.save("output.svg")
376
+
377
+ # Save to PNG (raster)
378
+ diagram.save("output.png")
379
+ ```
380
+
381
+ ---
382
+
383
+ ## 📝 Integration with `engrapha_notes`
384
+
385
+ To embed a vector diagram into an Engrapha notes document, call `.as_flowable()` and pass it to `en.add(...)`:
386
+
387
+ ```python
388
+ import engrapha_notes as en
389
+ import engrapha_diagrams as ed
390
+
391
+ fc = ed.Flowchart(width=en.CW, height=200)
392
+ fc.terminal("s", "START").terminal("e", "END").edge("s", "e")
393
+
394
+ # Add the diagram flowables directly
395
+ en.add(fc.as_flowable())
396
+ ```
397
+
398
+ ### Static Type-Checking (Pyright / Pylance)
399
+ If you see static type warnings in your IDE:
400
+ > `Argument of type "list[Unknown]" cannot be assigned to parameter "x" of type "Flowable" in function "add"`
401
+
402
+ This happens because `.as_flowable()` returns a `list[Flowable]` (which packages the drawing flowable along with its optional caption `Paragraph` flowable) rather than a single raw `Flowable`.
403
+
404
+ `engrapha_notes` handles this union type cleanly. Calling `en.add(diagram.as_flowable())` is type-safe and fully compliant.
405
+
406
+ ---
407
+
408
+ ## 📋 Requirements & License
409
+
410
+ * **Python** >= 3.11
411
+ * **reportlab** >= 4.5.1
412
+ * **pydantic** >= 2.13.4
413
+ * Licensed under the **MIT License**.
414
+