Py2puml
Generate PlantUML class diagrams to document your Python application.
Install / Use
/learn @lucsorel/Py2pumlREADME
Generate PlantUML class diagrams to document your Python application.
py2puml uses pre-commit hooks and pre-commit.ci Continuous Integration to enforce commit messages, code formatting and linting for quality and consistency sake.
See the code conventions section if you would like to contribute to the project.
Installation
py2puml is a command-line interface (CLI) documentation tool that can be installed as a dependency of your project, or installed globally on your system, or even run in an isolated way.
Install as a project dependency
Install py2puml from PyPI with your favorite installation tool:
pip install py2puml
uv add py2puml
poetry add py2puml
pipenv install py2puml
Run as an isolated binary
Uv can download and install py2puml on your system and run it in an isolated way (no influence on your other Python tools):
uvx --isolated py2puml --help
Usage
The primary purpose of py2puml is to document domain models as PlantUML class diagrams, it focuses on data structures attributes and relationships (inheritance and composition/association).
Documenting methods may come later.
Once py2puml is installed, an eponymous CLI is available in your environment shell.
Generate documentation in the standard output
Give py2puml a package (a folder) or a module (a .py file) to inspect and it will generate the PlantUML diagram either in the standard output or in a file path:
To document the domain model used by py2puml to model data structures:
# at the root of the py2puml project
py2puml --path py2puml/domain
# short-flag version:
py2puml -p py2puml/domain
This outputs the following PlantUML content:
@startuml py2puml.domain
!pragma useIntermediatePackages false
class py2puml.domain.umlitem.UmlItem {
name: str
fqn: str
}
class py2puml.domain.umlrelation.UmlRelation {
source_fqn: str
target_fqn: str
type: RelType
}
class py2puml.domain.inspection.Inspection {
items_by_fqn: Any
relations: Any
}
class py2puml.domain.umlclass.UmlAttribute {
name: str
type: str
static: bool
}
class py2puml.domain.umlclass.UmlClass {
attributes: List[UmlAttribute]
is_abstract: bool
}
class py2puml.domain.umlenum.Member {
name: str
value: str
}
class py2puml.domain.umlenum.UmlEnum {
members: List[Member]
}
enum py2puml.domain.umlrelation.RelType {
COMPOSITION: * {static}
INHERITANCE: <| {static}
}
py2puml.domain.umlrelation.UmlRelation *-- py2puml.domain.umlrelation.RelType
py2puml.domain.umlclass.UmlClass *-- py2puml.domain.umlclass.UmlAttribute
py2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlclass.UmlClass
py2puml.domain.umlenum.UmlEnum *-- py2puml.domain.umlenum.Member
py2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlenum.UmlEnum
footer Generated by //py2puml//
@enduml
Using PlantUML (online or with IDE extensions) renders this content as follows:
Pipe the diagram in a local PlantUML server
Pipe the result of the CLI with a PlantUML server for instantaneous documentation (rendered by ImageMagick):
# runs a local PlantUML server from a docker container:
docker run -d --rm -p 1234:8080 --name plantumlserver plantuml/plantuml-server:jetty
py2puml -p py2puml/domain | curl -X POST --data-binary @- http://localhost:1234/svg/ --output - | display
# stop the container when you don't need it anymore, restart it later
docker stop plantumlserver
docker start plantumlserver
Generate documentation in a file
py2puml --path py2puml/domain --output-file py2puml-domain.puml
# short-flag version:
py2puml -p py2puml/domain -o py2puml-domain.puml
Generate documentation for a specific module
py2puml --path py2puml/domain/umlitem.py
@startuml py2puml.domain.umlitem
!pragma useIntermediatePackages false
class py2puml.domain.umlitem.UmlItem {
name: str
fqn: str
}
footer Generated by //py2puml//
@enduml
Generate documentation for a project with a src folder
Use the --path flag to indicate the path to the root namespace of the project and the --namespace flag to indicate that the "src" part should be ignored:
py2puml -p src/project -n project
Note: py2puml won't handle automatically the "src" part if it is in the middle of the path to inspect.
Use py2puml outside the namespace root
By default, py2puml derives the Python namespace from the given path, assuming the command is called from the root namespace:
py2puml --path py2puml/domain
# is equivalent to:
py2puml --path py2puml/domain --namespace py2puml.domain
# short-flag version
py2puml -p py2puml/domain -n py2puml.domain
But sometimes your shell may be positionned out of the namespace folder, or within it.
In such cases, it is necessary to specify the namespace of the domain to inspect so that py2puml can inspect it properly and follow the imports in the inspected package or modules:
# from your home folder:
# - for a package
py2puml --path repositories/py2puml/py2puml/domain --namespace py2puml.domain
# -> py2puml will move down its "inspection working directory" to repositories/py2puml
# - for a module
py2puml -p repositories/py2puml/py2puml/domain/item.py -n py2puml.domain.umlitem
# from a sub-package of the project to inspect (in py2puml/domain)
# - for a package
py2puml --path . --namespace py2puml.domain
# -> py2puml will move its "inspection working directory" up 2 folders in order to be at the root namespace
# - for a module
py2puml -p umlitem.py -n py2puml.domain.umlitem
Help commands
For a full overview of the CLI, run:
# documents the available flags and their description
py2puml --help
# displays the installed version
py2puml --version
# -> py2puml 0.11.0
Python API
To programatically create the diagram of the py2puml domain classes, import the py2puml function in your script:
from py2puml.py2puml import py2puml
if __name__ == '__main__':
# 1. outputs the PlantUML content in the terminal
print(''.join(py2puml('py2puml/domain', 'py2puml.domain')))
# 2. or writes the PlantUML content in a file
with open('py2puml/py2puml.domain.puml', 'w', encoding='utf8') as puml_file:
puml_file.writelines(py2puml('py2puml/domain', 'py2puml.domain'))
How it works
py2puml internally uses code inspection (also called reflexion in other programming languages) and abstract tree parsing to retrieve relevant information.
Features
From a given path corresponding to a folder containing Python code, py2puml inspects each Python module and generates a PlantUML diagram from the definitions of various data structures using:
-
inspection and type annotations to detect:
- static class attributes and dataclass fields
- fields of namedtuples
- members of enumerations
- composition and inheritance relationships. The detection of composition relationships relies on type annotations only, assigned values or expressions are never evaluated to prevent unwanted side-effects
-
parsing abstract syntax trees to detect the instance attributes defined in
__init__constructors
py2puml outputs diagrams in PlantUML syntax, which can be:
- versioned along your code with a unit-test ensuring its consistency (see the test_py2puml.py's test_assert_domain_documentation example).
You can also use the
assert_py2puml_command_argsutility from py2puml.asserts to check the output of apy2pumlcommand against a versioned file (that you can easily update):
from py2puml.asserts import assert_py2puml_command_args
def test_assert_domain_documentation():
assert_py2puml_command_args('-p py2puml/domain', DOCUMENTATION_PATH / 'py2puml.domain.puml')
# temporarily add the `overwrite_expected_output=True` argument to update the file containing the expected contents
assert_py2puml_command_args('-p py2puml/domain', DOCUMENTATION_PATH / 'py2puml.domain.puml', overwrite_expected_output=True)
- generated and hosted along other code documentation (better option: generated documentation should not be versioned with the codebase
Related Skills
node-connect
347.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
prose
347.2kOpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows.
claude-opus-4-5-migration
108.0kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
108.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
