erdify 0.3.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.
erdify-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Devsuit GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
erdify-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,637 @@
1
+ Metadata-Version: 2.4
2
+ Name: erdify
3
+ Version: 0.3.0
4
+ Summary: Generate PlantUML ERD diagrams from SQLModel, SQLAlchemy, Pydantic and dataclass models
5
+ Keywords: sqlmodel,sqlalchemy,pydantic,dataclass,erd,plantuml,diagram,database,erdify
6
+ Author: devsuit GmbH, Fabian Clemenz
7
+ Author-email: devsuit GmbH <tech@devsuit.de>, Fabian Clemenz <fabian.clemenz@devsuit.de>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Database
19
+ Classifier: Topic :: Software Development :: Code Generators
20
+ Requires-Dist: pytest ; extra == 'dev'
21
+ Requires-Dist: pytest-cov ; extra == 'dev'
22
+ Requires-Dist: ruff ; extra == 'dev'
23
+ Requires-Dist: mypy ; extra == 'dev'
24
+ Requires-Dist: sqlmodel ; extra == 'dev'
25
+ Requires-Python: >=3.10
26
+ Project-URL: Homepage, https://github.com/devsuit-berlin/erdify
27
+ Project-URL: Repository, https://github.com/devsuit-berlin/erdify
28
+ Project-URL: Documentation, https://github.com/devsuit-berlin/erdify#readme
29
+ Provides-Extra: dev
30
+ Description-Content-Type: text/markdown
31
+
32
+ # πŸ—ƒοΈ erdify
33
+
34
+ [![PyPI version](https://img.shields.io/pypi/v/erdify)](https://pypi.org/project/erdify/)
35
+ [![Python versions](https://img.shields.io/pypi/pyversions/erdify)](https://pypi.org/project/erdify/)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
37
+ [![Tests](https://github.com/devsuit-berlin/erdify/actions/workflows/test.yml/badge.svg)](https://github.com/devsuit-berlin/erdify/actions/workflows/test.yml)
38
+ [![Linting](https://github.com/devsuit-berlin/erdify/actions/workflows/lint.yml/badge.svg)](https://github.com/devsuit-berlin/erdify/actions/workflows/lint.yml)
39
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
40
+ [![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)](https://mypy-lang.org/)
41
+
42
+ > πŸš€ Generate beautiful PlantUML Entity Relationship Diagrams from your SQLModel, SQLAlchemy, Pydantic and dataclass models automatically!
43
+
44
+ **erdify** parses your model files using AST (Abstract Syntax Tree) and generates comprehensive ERD diagrams in PlantUML format. It supports SQLModel, SQLAlchemy 2.0, Pydantic and standard-library dataclasses. No database connection required!
45
+
46
+ ## ✨ Features
47
+
48
+ - πŸ“Š **Automatic ERD Generation** - Parse your models and generate PlantUML diagrams
49
+ - 🧬 **4 Frameworks** - SQLModel, SQLAlchemy 2.0 (`Mapped[...]`/`mapped_column()`), Pydantic and dataclasses
50
+ - πŸ” **AST-Based Parsing** - No imports needed, works with any valid Python code
51
+ - 🎯 **Zero Runtime Dependencies** - Uses only Python standard library
52
+ - πŸ”— **Relationship Detection** - Automatically detects foreign keys and relationships
53
+ - πŸ”‘ **Key Inference** - Optional `--infer-keys` derives PK/FK from field names for keyless models
54
+ - 🚫 **Exclude Patterns** - Filter out entities by class or table name with glob patterns
55
+ - πŸ“¦ **Inheritance Support** - Correctly resolves fields from base classes and mixins
56
+ - 🏷️ **Enum Support** - Includes enum definitions in the diagram
57
+ - πŸ”„ **Link Table Detection** - Identifies many-to-many relationship tables
58
+ - 🎨 **Beautiful Output** - Clean, readable PlantUML with proper styling
59
+
60
+ ## πŸ“¦ Installation
61
+
62
+ ### Using pip
63
+
64
+ ```bash
65
+ pip install erdify
66
+ ```
67
+
68
+ ### Using uv
69
+
70
+ ```bash
71
+ uv add erdify
72
+ ```
73
+
74
+ ### Using pipx (recommended for CLI usage)
75
+
76
+ ```bash
77
+ pipx install erdify
78
+ ```
79
+
80
+ ### Using uvx (no installation needed)
81
+
82
+ ```bash
83
+ # Run directly without installing
84
+ uvx erdify ./src/database -o erd.puml
85
+ ```
86
+
87
+ ## πŸš€ Quick Start
88
+
89
+ ### Command Line
90
+
91
+ ```bash
92
+ # Generate ERD from a models directory
93
+ erdify ./src/database -o erd.puml
94
+
95
+ # With custom title
96
+ erdify ./src/models --title "My Database Schema" -o schema.puml
97
+
98
+ # Output to stdout
99
+ erdify ./src/database
100
+ ```
101
+
102
+ ### Python API
103
+
104
+ ```python
105
+ from pathlib import Path
106
+ from erdify import parse_models_directory, generate_plantuml
107
+
108
+ # Parse your models
109
+ entities, enums = parse_models_directory(Path("./src/database"))
110
+
111
+ # Generate PlantUML
112
+ diagram = generate_plantuml(
113
+ entities=entities,
114
+ enums=enums,
115
+ title="My Database ERD"
116
+ )
117
+
118
+ # Save or use the diagram
119
+ Path("erd.puml").write_text(diagram)
120
+ ```
121
+
122
+ ## πŸ“– Usage
123
+
124
+ ### CLI Options
125
+
126
+ ```bash
127
+ usage: erdify [-h] [-o OUTPUT] [--title TITLE] [--exclude [PATTERN ...]]
128
+ [--infer-keys] [--no-enums] [--no-relationships] [-v]
129
+ input
130
+
131
+ Generate PlantUML ERD diagrams from SQLModel, SQLAlchemy, Pydantic and dataclass models
132
+
133
+ positional arguments:
134
+ input Directory containing model files (searches for models.py recursively)
135
+
136
+ options:
137
+ -h, --help show this help message and exit
138
+ -o OUTPUT, --output OUTPUT
139
+ Output .puml file (default: stdout)
140
+ --title TITLE Diagram title (default: 'Database ERD')
141
+ --exclude [PATTERN ...]
142
+ Glob patterns (case-sensitive) to exclude entities by
143
+ class name or table name, e.g. --exclude '*Link' audit_log
144
+ --infer-keys For keyless models (Pydantic/dataclass), infer a primary
145
+ key from a field named 'id' and a foreign key from '<x>_id'
146
+ --no-enums Skip enum definitions in output
147
+ --no-relationships Skip relationship lines in output
148
+ -v, --version show program's version number and exit
149
+ ```
150
+
151
+ ### Excluding Entities
152
+
153
+ Use `--exclude` to drop tables/entities from the diagram. Each pattern is a
154
+ case-sensitive [glob](https://docs.python.org/3/library/fnmatch.html) tested
155
+ against both the **class name** and the **table name** β€” an entity is excluded
156
+ if either matches. Any relationships pointing at an excluded entity are dropped
157
+ too, so no dangling lines remain.
158
+
159
+ ```bash
160
+ # Exclude all link tables (class names ending in "Link")
161
+ erdify ./src/database --exclude '*Link'
162
+
163
+ # Exclude by table name, with multiple patterns
164
+ erdify ./src/database --exclude audit_log 'tmp_*' Session
165
+ ```
166
+
167
+ > πŸ’‘ Quote patterns containing `*` so your shell doesn't expand them.
168
+
169
+ ### Running as Module
170
+
171
+ ```bash
172
+ python -m erdify ./src/database -o erd.puml
173
+ ```
174
+
175
+ ### Example Models
176
+
177
+ Given these SQLModel definitions:
178
+
179
+ ```python
180
+ from enum import Enum
181
+ from sqlmodel import SQLModel, Field, Relationship
182
+
183
+ class UserRole(Enum):
184
+ ADMIN = "admin"
185
+ USER = "user"
186
+
187
+ class User(SQLModel, table=True):
188
+ __tablename__: str = "user"
189
+
190
+ id: int = Field(primary_key=True)
191
+ name: str
192
+ email: str = Field(index=True)
193
+ role: UserRole = Field(default=UserRole.USER)
194
+
195
+ orders: list["Order"] = Relationship(back_populates="user")
196
+
197
+ class Order(SQLModel, table=True):
198
+ __tablename__: str = "order"
199
+
200
+ id: int = Field(primary_key=True)
201
+ user_id: int = Field(foreign_key="user.id")
202
+ total: float
203
+
204
+ user: "User" = Relationship(back_populates="orders")
205
+ ```
206
+
207
+ The tool generates:
208
+
209
+ ![Example ERD Image](https://raw.githubusercontent.com/devsuit-berlin/erdify/main/example_erd.png "Example ERD Image")
210
+
211
+ with following code:
212
+
213
+ ```plantuml
214
+ @startuml Database ERD
215
+ !define primary_key(x) <b><color:#b8861b><&key></color> x</b>
216
+ !define foreign_key(x) <color:#aaaaaa><&key></color> x
217
+ !define column(x) <color:#efefef><&media-record></color> x
218
+
219
+ skinparam linetype ortho
220
+
221
+ ' Enums
222
+ enum UserRole << (E,#FFCC00) >> {
223
+ ADMIN
224
+ USER
225
+ }
226
+
227
+ ' Entities
228
+ entity "user" as User {
229
+ primary_key(id) : int
230
+ column(name) : str
231
+ column(email) : str
232
+ column(role) : UserRole = USER
233
+ }
234
+
235
+ entity "order" as Order {
236
+ primary_key(id) : int
237
+ foreign_key(user_id) : int
238
+ column(total) : float
239
+ }
240
+
241
+ ' Relationships
242
+ Order }o--|| User : "user_id"
243
+
244
+ @enduml
245
+ ```
246
+
247
+ ## 🧬 One Schema, Four Frameworks
248
+
249
+ erdify supports four model frameworks. The snippets below all describe the
250
+ **same** `User` / `Order` schema β€” only the syntax differs. Each one produces the
251
+ **identical** diagram:
252
+
253
+ ![Framework comparison ERD](https://raw.githubusercontent.com/devsuit-berlin/erdify/main/docs/examples/erd.png "The same ERD from all four frameworks")
254
+
255
+ > ℹ️ The SQLModel and SQLAlchemy versions declare keys explicitly. Pydantic and
256
+ > dataclasses have no key concept, so they are rendered with [`--infer-keys`](#inferring-keys---infer-keys)
257
+ > (`id` β†’ PK, `<x>_id` β†’ FK) to match. The runnable sources live in
258
+ > [`docs/examples/`](https://github.com/devsuit-berlin/erdify/tree/main/docs/examples).
259
+
260
+ <table>
261
+ <tr><th>SQLModel</th><th>SQLAlchemy 2.0</th></tr>
262
+ <tr><td>
263
+
264
+ ```python
265
+ from sqlmodel import (
266
+ Field, Relationship, SQLModel,
267
+ )
268
+
269
+
270
+ class User(SQLModel, table=True):
271
+ __tablename__: str = "user"
272
+ id: int = Field(primary_key=True)
273
+ name: str
274
+ email: str
275
+ orders: list["Order"] = Relationship(
276
+ back_populates="user")
277
+
278
+
279
+ class Order(SQLModel, table=True):
280
+ __tablename__: str = "order"
281
+ id: int = Field(primary_key=True)
282
+ user_id: int = Field(
283
+ foreign_key="user.id")
284
+ total: float
285
+ user: "User" = Relationship(
286
+ back_populates="orders")
287
+ ```
288
+
289
+ </td><td>
290
+
291
+ ```python
292
+ from sqlalchemy import ForeignKey
293
+ from sqlalchemy.orm import (
294
+ DeclarativeBase, Mapped,
295
+ mapped_column, relationship,
296
+ )
297
+
298
+
299
+ class Base(DeclarativeBase): ...
300
+
301
+
302
+ class User(Base):
303
+ __tablename__ = "user"
304
+ id: Mapped[int] = mapped_column(
305
+ primary_key=True)
306
+ name: Mapped[str] = mapped_column()
307
+ email: Mapped[str] = mapped_column()
308
+ orders: Mapped[list["Order"]] = (
309
+ relationship(back_populates="user"))
310
+
311
+
312
+ class Order(Base):
313
+ __tablename__ = "order"
314
+ id: Mapped[int] = mapped_column(
315
+ primary_key=True)
316
+ user_id: Mapped[int] = mapped_column(
317
+ ForeignKey("user.id"))
318
+ total: Mapped[float] = mapped_column()
319
+ user: Mapped["User"] = relationship(
320
+ back_populates="orders")
321
+ ```
322
+
323
+ </td></tr>
324
+ <tr><th>Pydantic <code>--infer-keys</code></th><th>Dataclass <code>--infer-keys</code></th></tr>
325
+ <tr><td>
326
+
327
+ ```python
328
+ from pydantic import BaseModel
329
+
330
+
331
+ class User(BaseModel):
332
+ id: int
333
+ name: str
334
+ email: str
335
+ orders: list["Order"] = []
336
+
337
+
338
+ class Order(BaseModel):
339
+ id: int
340
+ user_id: int
341
+ total: float
342
+ user: "User"
343
+ ```
344
+
345
+ </td><td>
346
+
347
+ ```python
348
+ from dataclasses import dataclass, field
349
+
350
+
351
+ @dataclass
352
+ class User:
353
+ id: int
354
+ name: str
355
+ email: str
356
+ orders: list["Order"] = field(
357
+ default_factory=list)
358
+
359
+
360
+ @dataclass
361
+ class Order:
362
+ id: int
363
+ user_id: int
364
+ total: float
365
+ user: "User" = None
366
+ ```
367
+
368
+ </td></tr>
369
+ </table>
370
+
371
+ **How each framework is detected & parsed:**
372
+
373
+ | Framework | Detected by | Keys | Relationships |
374
+ | --------- | ----------- | ---- | ------------- |
375
+ | SQLModel | `table=True` | `Field(primary_key=…, foreign_key=…)` | `Relationship()` |
376
+ | SQLAlchemy 2.0 | `__tablename__` + `Mapped[...]` columns | `mapped_column(primary_key=…)`, `ForeignKey(...)` | `relationship()` (lowercase) |
377
+ | Pydantic | `BaseModel` subclass (incl. transitive) | `--infer-keys` only | nested model refs (`user: User`, `list["Order"]`) |
378
+ | Dataclass | `@dataclass` decorator | `--infer-keys` only | nested model refs |
379
+
380
+ > ℹ️ Mixins / abstract bases (e.g. a SQLAlchemy mixin without `__tablename__`)
381
+ > are not drawn as tables, but their columns are inherited into concrete
382
+ > entities. Imports aliased to other names (e.g. `mapped_column as mc`) are not
383
+ > detected.
384
+
385
+ ### Inferring keys (`--infer-keys`)
386
+
387
+ Pydantic models and dataclasses have **no database key concept**. By default all
388
+ fields are rendered as plain columns and relationships come only from nested
389
+ model references. If your models follow a database-like naming convention, pass
390
+ `--infer-keys` to derive keys from field names:
391
+
392
+ - a field named **`id`** β†’ **primary key**
393
+ - a field named **`<x>_id`** β†’ **foreign key** targeting table **`<x>`**
394
+
395
+ ```bash
396
+ # Plain columns (default)
397
+ erdify ./src/schemas
398
+
399
+ # Infer PK/FK from id / <x>_id naming
400
+ erdify ./src/schemas --infer-keys
401
+ ```
402
+
403
+ > ℹ️ `--infer-keys` only affects Pydantic/dataclass models. SQLModel and
404
+ > SQLAlchemy keys are always read from the explicit definitions and never
405
+ > overridden.
406
+
407
+ ## 🎨 Viewing the Diagram
408
+
409
+ ### Online
410
+
411
+ 1. Copy the generated `.puml` content
412
+ 2. Paste at [PlantUML Web Server](http://www.plantuml.com/plantuml/uml/)
413
+
414
+ ### Local with PlantUML
415
+
416
+ ```bash
417
+ # Install PlantUML (macOS)
418
+ brew install plantuml
419
+
420
+ # Generate PNG
421
+ plantuml erd.puml
422
+
423
+ # Generate SVG
424
+ plantuml -tsvg erd.puml
425
+ ```
426
+
427
+ ### VS Code Extension
428
+
429
+ Install the [PlantUML extension](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml) for live preview.
430
+
431
+ ## πŸ”§ Advanced Usage
432
+
433
+ ### Programmatic Access
434
+
435
+ ```python
436
+ from erdify import (
437
+ ASTDatabaseParser,
438
+ PlantUMLGenerator,
439
+ EntityInfo,
440
+ FieldInfo,
441
+ EnumInfo,
442
+ )
443
+
444
+ # Low-level parser access
445
+ parser = ASTDatabaseParser(Path("./models"))
446
+ entities, enums = parser.parse_all_models()
447
+
448
+ # Access entity details
449
+ for name, entity in entities.items():
450
+ print(f"Table: {entity.table_name}")
451
+ for field in entity.fields:
452
+ if field.is_primary_key:
453
+ print(f" PK: {field.name}")
454
+ elif field.is_foreign_key:
455
+ print(f" FK: {field.name} -> {field.foreign_table}")
456
+
457
+ # Custom generator with options
458
+ generator = PlantUMLGenerator(
459
+ entities=entities,
460
+ enums=enums,
461
+ title="Custom ERD"
462
+ )
463
+ output = generator.generate()
464
+ ```
465
+
466
+ ### Integration with CI/CD
467
+
468
+ ```yaml
469
+ # .github/workflows/docs.yml
470
+ name: Generate ERD
471
+
472
+ on:
473
+ push:
474
+ paths:
475
+ - 'src/database/**'
476
+
477
+ jobs:
478
+ generate-erd:
479
+ runs-on: ubuntu-latest
480
+ steps:
481
+ - uses: actions/checkout@v4
482
+
483
+ - name: Set up Python
484
+ uses: actions/setup-python@v5
485
+ with:
486
+ python-version: '3.12'
487
+
488
+ - name: Install erdify
489
+ run: pip install erdify
490
+
491
+ - name: Generate ERD
492
+ run: erdify ./src/database --title "Database Schema" -o docs/erd.puml
493
+
494
+ - name: Generate PNG
495
+ run: |
496
+ sudo apt-get install -y plantuml
497
+ plantuml docs/erd.puml
498
+
499
+ - name: Commit changes
500
+ uses: stefanzweifel/git-auto-commit-action@v5
501
+ with:
502
+ commit_message: "docs: update ERD diagram"
503
+ file_pattern: "docs/erd.*"
504
+ ```
505
+
506
+ ### Integration with pre-commit hooks
507
+
508
+ Keep your ERD diagrams automatically updated on every commit using [pre-commit](https://pre-commit.com/):
509
+
510
+ ```yaml
511
+ # .pre-commit-config.yaml
512
+ repos:
513
+ - repo: local
514
+ hooks:
515
+ - id: generate-erd
516
+ name: πŸ—ƒοΈ Generate ERD Diagram
517
+ entry: erdify ./src/database --title "Database Schema" -o docs/erd.puml
518
+ language: system
519
+ files: ^src/database/.*\.py$
520
+ pass_filenames: false
521
+ ```
522
+
523
+ Or using uvx (no installation required):
524
+
525
+ ```yaml
526
+ # .pre-commit-config.yaml
527
+ repos:
528
+ - repo: local
529
+ hooks:
530
+ - id: generate-erd
531
+ name: πŸ—ƒοΈ Generate ERD Diagram
532
+ entry: uvx erdify ./src/database --title "Database Schema" -o docs/erd.puml
533
+ language: system
534
+ files: ^src/database/.*\.py$
535
+ pass_filenames: false
536
+ ```
537
+
538
+ **Setup:**
539
+
540
+ ```bash
541
+ # Install pre-commit
542
+ pip install pre-commit
543
+
544
+ # Install the hooks
545
+ pre-commit install
546
+
547
+ # Run manually on all files
548
+ pre-commit run generate-erd --all-files
549
+ ```
550
+
551
+ **How it works:**
552
+ - πŸ” Only triggers when files in `src/database/` change
553
+ - πŸ“ Automatically regenerates `docs/erd.puml`
554
+ - βœ… Stages the updated diagram with your commit
555
+ - 🚫 Fails if the diagram would change (ensuring docs stay in sync)
556
+
557
+ **Tip:** Add `docs/erd.puml` to your staged files before committing, or use the `--all-files` flag to regenerate.
558
+
559
+ ## πŸ“‹ Supported Features
560
+
561
+ | Feature | Status | Notes |
562
+ | -------- | -------- | ------- |
563
+ | Primary Keys | βœ… | `Field(primary_key=True)` |
564
+ | Foreign Keys | βœ… | `Field(foreign_key="table.column")` |
565
+ | Nullable Fields | βœ… | `str \| None` or `Optional[str]` |
566
+ | Default Values | βœ… | `Field(default=value)` |
567
+ | Indexes | βœ… | `Field(index=True)` |
568
+ | Enums | βœ… | Python `Enum` classes |
569
+ | Relationships | βœ… | `Relationship()` |
570
+ | Inheritance | βœ… | Mixin classes supported |
571
+ | Link Tables | βœ… | Many-to-many detection |
572
+ | Custom Table Names | βœ… | `__tablename__` attribute |
573
+ | Exclude Patterns | βœ… | `--exclude` glob on class/table name |
574
+ | Key Inference | βœ… | `--infer-keys` for Pydantic/dataclass (`id`, `<x>_id`) |
575
+ | SQLModel | βœ… | `Field()` / `Relationship()` |
576
+ | SQLAlchemy 2.0 | βœ… | `Mapped[...]` / `mapped_column()` |
577
+ | Pydantic | βœ… | `BaseModel` subclasses, nested refs as relationships |
578
+ | Dataclass | βœ… | `@dataclass`, nested refs as relationships |
579
+
580
+ ## πŸ—ΊοΈ Roadmap
581
+
582
+ Recently shipped:
583
+
584
+ | Feature | Status | Description |
585
+ | -------- | -------- | ------- |
586
+ | Exclude Option | βœ… Done | Exclude tables or entities from ERD generation using glob patterns |
587
+ | SQLAlchemy Support | βœ… Done | Native support for SQLAlchemy 2.0 (`Mapped` / `mapped_column`) models |
588
+ | Pydantic Support | βœ… Done | Generate ERDs from Pydantic models, with optional `--infer-keys` |
589
+ | Dataclass Support | βœ… Done | Support for standard Python dataclasses with type annotations |
590
+
591
+ Have a feature request? Please open an issue on [GitHub](https://github.com/devsuit-berlin/erdify/issues) to discuss it!
592
+
593
+ ## 🀝 Contributing
594
+
595
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
596
+
597
+ ## πŸ”’ Security
598
+
599
+ For security concerns, please see [SECURITY.md](SECURITY.md).
600
+
601
+ ## πŸ“„ License
602
+
603
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
604
+
605
+ ## πŸ™ Acknowledgments
606
+
607
+ erdify stands on the shoulders of great open-source projects:
608
+
609
+ **Supported model frameworks**
610
+
611
+ - [SQLModel](https://sqlmodel.tiangolo.com/) - The awesome SQL database library
612
+ - [SQLAlchemy](https://www.sqlalchemy.org/) - The Python SQL toolkit and ORM
613
+ - [Pydantic](https://docs.pydantic.dev/) - Data validation using Python type hints
614
+ - [dataclasses](https://docs.python.org/3/library/dataclasses.html) - Python standard-library data classes
615
+
616
+ **Rendering & output**
617
+
618
+ - [PlantUML](https://plantuml.com/) - For the diagram rendering
619
+ - [Graphviz](https://graphviz.org/) - Layout engine behind PlantUML's ER diagrams
620
+
621
+ **Tooling & infrastructure**
622
+
623
+ - [uv](https://docs.astral.sh/uv/) - Packaging, builds and dependency management
624
+ - [Ruff](https://docs.astral.sh/ruff/) - Linting and formatting
625
+ - [mypy](https://mypy-lang.org/) - Static type checking
626
+ - [pytest](https://docs.pytest.org/) - Testing framework
627
+ - [pre-commit](https://pre-commit.com/) - Git hook management
628
+
629
+ **Community**
630
+
631
+ - [Contributor Covenant](https://www.contributor-covenant.org/) - Our Code of Conduct
632
+ - [Keep a Changelog](https://keepachangelog.com/) - Changelog format
633
+ - And everyone who [contributes](CONTRIBUTING.md) issues, ideas and pull requests πŸ’œ
634
+
635
+ ---
636
+
637
+ Made with ❀️ by [Devsuit GmbH](https://github.com/devsuit-berlin)