Python to PlantUML
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.
How it works
py2puml
produces a class diagram PlantUML script representing classes properties (static and instance attributes) and their relations (composition and inheritance relationships).
py2puml
internally uses code inspection (also called reflexion in other programming languages) and abstract tree parsing to retrieve relevant information.
Minimum Python versions to run py2puml
p2puml
uses some code-parsing features that are available only since Python 3.8 (like ast.get_source_segment).
If your codebase uses the int | float
syntax to define optional types, then you should use Python 3.10 to run py2puml
.
To sum it up, use at least Python 3.8 to run py2puml, or a higher version if you use syntax features available only in higher versions.
The .python-version file indicates the Python version used to develop the library.
It is a file used by pyenv to define the binary used by the project.
Features
From a given path corresponding to a folder containing Python code, py2puml
processes each Python module and generates a PlantUML script from the definitions of various data structures using:
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_py2puml_model_on_py2uml_domain example)
- generated and hosted along other code documentation (better option: generated documentation should not be versioned with the codebase)
To generate image files, use the PlantUML runtime, a docker image of the runtime (see think/plantuml) or of a server (see the CLI documentation below)
If you like tools related with PlantUML, you may also be interested in this lucsorel/plantuml-file-loader project:
a webpack loader which converts PlantUML files into images during the webpack processing (useful to include PlantUML diagrams in your slides with RevealJS or RemarkJS).
Install
Install from PyPI:
pip install py2puml
poetry add py2puml
pipenv install py2puml
Usage
CLI
Once py2puml
is installed at the system level, an eponymous command is available in your environment shell.
For example, to create the diagram of the classes used by py2puml
, run:
py2puml py2puml/domain py2puml.domain
This outputs the following PlantUML content:
@startuml py2puml.domain
!pragma useIntermediatePackages false
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.umlitem.UmlItem {
name: str
fqn: str
}
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}
}
class py2puml.domain.umlrelation.UmlRelation {
source_fqn: str
target_fqn: str
type: 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
py2puml.domain.umlrelation.UmlRelation *-- py2puml.domain.umlrelation.RelType
footer Generated by //py2puml//
@enduml
Using PlantUML, this content is rendered as in this diagram:
For a full overview of the CLI, run:
py2puml --help
The CLI can also be launched as a python module:
python -m py2puml py2puml/domain py2puml.domain
Pipe the result of the CLI with a PlantUML server for instantaneous documentation (rendered by ImageMagick):
docker run -d --rm -p 1234:8080 --name plantumlserver plantuml/plantuml-server:jetty
py2puml py2puml/domain py2puml.domain | curl -X POST --data-binary @- http://localhost:1234/svg/ --output - | display
docker stop plantumlserver
docker start plantumlserver
Python API
For example, to create the diagram of the domain classes used by py2puml
:
- import the
py2puml
function in your script:
from py2puml.py2puml import py2puml
if __name__ == '__main__':
print(''.join(py2puml('py2puml/domain', 'py2puml.domain')))
with open('py2puml/py2puml.domain.puml', 'w', encoding='utf8') as puml_file:
puml_file.writelines(py2puml('py2puml/domain', 'py2puml.domain'))
- running it outputs the previous PlantUML diagram in the terminal and writes it in a file.
Tests
poetry run pytest -v
python3 -m pytest -v
Code coverage (with missed branch statements):
poetry run pytest -v --cov=py2puml --cov-branch --cov-report term-missing --cov-fail-under 93
Changelog
0.9.1
: improved 0.7.2 by adding the current working directory at the beginning of the sys.path to resolve the module paths of the project being inspected.
Fix url to PlantUML logo on the README.md page0.9.0
: add classes defined in __init__.py
files to plantuml output; replaced yapf by the ruff formatter0.8.1
: delegated the grouping of nested namespaces (see 0.7.0
) to the PlantUML binary, which handles it natively0.8.0
: added support for union types, and github actions (pre-commit hooks + automated tests)0.7.2
: added the current working directory to the import path to make py2puml work in any directory or in native virtual environment (not handled by poetry)0.7.1
: removed obsolete part of documentation: deeply compound types are now well handled (by version 0.7.0
)0.7.0
: improved the generated PlantUML documentation (added the namespace structure of the code base, homogenized type between inspection and parsing), improved relationships management (handle forward references, deduplicate relationships)0.6.1
: handle class names with digits0.6.0
: handle abstract classes0.5.4
: fixed the packaging so that the contribution guide is included in the published package0.5.3
: handle constructors decorated by wrapping decorators (decorators making uses of functools.wrap
)0.5.2
: specify in pyproject.toml that py2puml requires python 3.8+ (ast.get_source_segment
was introduced in 3.8)0.5.1
: prevent from parsing inherited constructors0.5.0
: handle instance attributes in class constructors, add code coverage of unit tests0.4.0
: add a simple CLI0.3.1
: inspect sub-folders recursively0.3.0
: handle classes derived from namedtuples (attribute types are Any
)0.2.0
: handle inheritance relationships and enums0.1.3
: first release, handle all modules of a folder and compositions of domain classes
Licence
Unless stated otherwise all works are licensed under the MIT license, a copy of which is included here.
Contributions
Pull requests
Pull-requests are welcome and will be processed on a best-effort basis.
Pull requests must follow the guidelines enforced by the pre-commit
hooks:
- commit messages must follow the Angular conventions enforced by the
commitlint
hook - code formatting must follow the conventions enforced by the
isort
and ruff-format
hooks - code linting should not detect code smells in your contributions, this is checked by the
ruff
hook
Please also follow the contributing guide to ease your contribution.
Code conventions
The code conventions are described and enforced by pre-commit hooks to maintain consistency across the code base.
The hooks are declared in the .pre-commit-config.yaml file.
Set the git hooks (pre-commit and commit-msg types):
poetry run pre-commit install --hook-type pre-commit --hook-type commit-msg
Before committing, you can check your changes with:
git add -A
poetry run pre-commit run --all-files
poetry run pre-commit run ruff --all-files
Commit messages
Please, follow the conventions of the Angular team for commit messages.
When merging your pull-request, the new version of the project will be derived from the messages.
Code formatting
This project uses isort
and ruff-format
to format the code.
The guidelines are expressed in their respective sections in the pyproject.toml file.
Best practices
This project uses the ruff
linter, which is configured in its section in the pyproject.toml file.
Current limitations
Alternatives
If py2puml
does not meet your needs (suggestions and pull-requests are welcome), you can have a look at these projects which follow other approaches (AST, linting, modeling):