Skip to content

Commit 3fceb5c

Browse files
committed
✨ create diagram of classes of given module
1 parent a9e09b0 commit 3fceb5c

18 files changed

+576
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
__pycache__/
3+
.venv/
4+
*.egg-info/
5+
*.puml

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.7.6

README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
Generate Plantuml diagrams to document your python code
2+
3+
# How it works
4+
5+
From a given path corresponding to a folder containing python code, `py2puml` loads each file as a module and generate a class diagram with the [PlantUML](https://plantuml.com/en/class-diagram) using:
6+
7+
* inspection to detect the classes to document (see the [inspect](https://docs.python.org/3/library/inspect.html) module)
8+
* annotations (the python type hinting syntax) to detect the attributes and their types (see the [typing](https://docs.python.org/3/library/typing.html) module)
9+
10+
Current limitations:
11+
12+
* type hinting is optional when writing the code and discarded when it is executed, as mentionned in the official documentation. The quality of the diagram output by `py2puml` depends on the reliability with which the annotations were written
13+
14+
> The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.
15+
16+
* complex type hints with more than one level of genericity are not properly handled for the moment: `List[MyClass]` or `Dict[str, MyClass]` are handled properly, `Dict[str, List[MyClass]]` is not. If your domain classes (also called business objects or DTOs) have attributes with complex type hints, it may be a code smell indicating that you should write a class which would better represent the business logic. But I may improve this part of the library as well 😀
17+
18+
* composition relationships are detected and drawn. Inheritance relationships are not handled for now
19+
20+
* `py2puml` does not inspect sub-folders recursively, but it is planned
21+
22+
* `py2puml` outputs diagrams in PlantUML syntax, which can be saved in text files along your python code and versioned with them. To generate image files, use the PlantUML runtime or a docker image (see [think/plantuml](https://hub.docker.com/r/think/plantuml))
23+
24+
* `py2puml` uses features of python 3 (generators for example) and thus won't work with python 2 runtimes. It relies on native python modules and uses no 3rd-party library, except [pytest](https://docs.pytest.org/en/latest/) as a development dependency for running the unit-tests
25+
26+
You may also be interested in this [lucsorel/plantuml-file-loader](https://github.com/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](https://github.com/lucsorel/markdown-image-loader/blob/master/README.md#web-based-slideshows) with RevealJS or RemarkJS).
27+
28+
# Install
29+
30+
Install from the github repository:
31+
32+
* with `pip`:
33+
34+
```sh
35+
pip3 install git+https://github.com/lucsorel/py2puml.git
36+
```
37+
38+
* with [poetry](https://pipenv.readthedocs.io/en/latest/):
39+
40+
```sh
41+
poetry add git+https://github.com/lucsorel/py2puml.git
42+
```
43+
44+
* with [pipenv](https://pipenv.readthedocs.io/en/latest/):
45+
46+
```sh
47+
# should be installed in editable mode to ensure an up-to-date copy of the repository and that it includes all known dependencies -> '-e'
48+
pipenv install -e git+https://github.com/lucsorel/py2puml.git#egg=py2puml
49+
```
50+
51+
# Usage
52+
53+
For example, to create the diagram of the classes used by `py2puml`:
54+
55+
* import the py2puml function in your script (see [py2puml/example.py](py2puml/example.py)):
56+
57+
```python
58+
from py2puml.py2puml import py2puml
59+
60+
# outputs the PlantUML content in the terminal
61+
print(''.join(py2puml('py2puml/domain', 'py2puml.domain')))
62+
63+
# writes the PlantUML content in a file
64+
with open('py2puml/domain.puml', 'w') as puml_file:
65+
puml_file.writelines(py2puml('py2puml/domain', 'py2puml.domain'))
66+
```
67+
68+
* running it (`python3 -m py2puml.example`) will output the PlantUML diagram in the terminal and write it in a file
69+
70+
```plantuml
71+
@startuml
72+
class py2puml.domain.umlattribute.UmlAttribute {
73+
name: str
74+
type: str
75+
}
76+
class py2puml.domain.umlclass.UmlClass {
77+
name: str
78+
fqdn: str
79+
attributes: List[UmlAttribute]
80+
}
81+
class py2puml.domain.umlcomposition.UmlComposition {
82+
compound_fqdn: str
83+
component_fqdn: str
84+
}
85+
py2puml.domain.umlclass.UmlClass *-- py2puml.domain.umlattribute.UmlAttribute
86+
@enduml
87+
```
88+
89+
# Tests
90+
91+
```sh
92+
poetry run python3 -W ignore::DeprecationWarning -m pytest -v
93+
```
94+
95+
# Licence
96+
97+
Unless stated otherwise all works are licensed under the [MIT license](http://spdx.org/licenses/MIT.html), a copy of which is included [here](LICENSE).
98+
99+
# Contributions
100+
101+
* [Luc Sorel-Giffo](https://github.com/lucsorel)
102+
103+
Pull-requests are welcome and will be processed on a best-effort basis.
104+
105+
106+
# Alternatives
107+
108+
If `py2uml` 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):
109+
110+
* [cb109/pyplantuml](https://github.com/cb109/pyplantuml)
111+
* [deadbok/py-puml-tools](https://github.com/deadbok/py-puml-tools)
112+
* [caballero/genUML](https://github.com/jose-caballero/genUML)

init.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#! /bin/sh
2+
3+
depsinstall='install --no-dev'
4+
5+
while getopts d OPTION "$@"; do
6+
# echo "option ${OPTION}"
7+
case $OPTION in
8+
# also installs development dependencies
9+
d)
10+
depsinstall='install'
11+
;;
12+
\?)
13+
echo "Invalid option: -$OPTION" >&2
14+
;;
15+
esac
16+
done
17+
18+
poetry config virtualenvs.create true --local
19+
poetry config virtualenvs.in-project true --local
20+
echo "$(date '+%Y-%m-%d_%H:%M:%S') $(poetry --version) will be used to install dependencies"
21+
22+
# installs the project dependencies
23+
echo "$(date '+%Y-%m-%d_%H:%M:%S') poetry ${depsinstall}"
24+
poetry ${depsinstall}

poetry.lock

Lines changed: 212 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

py2puml/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = '0.1.0'

py2puml/domain/__init__.py

Whitespace-only changes.

py2puml/domain/umlattribute.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from dataclasses import dataclass
2+
3+
@dataclass
4+
class UmlAttribute(object):
5+
name: str
6+
type: str

py2puml/domain/umlclass.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from typing import List
2+
from dataclasses import dataclass
3+
4+
from py2puml.domain.umlattribute import UmlAttribute
5+
6+
@dataclass
7+
class UmlClass(object):
8+
name: str
9+
fqdn: str
10+
attributes: List[UmlAttribute]

py2puml/domain/umlcomposition.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from dataclasses import dataclass
2+
3+
@dataclass
4+
class UmlComposition(object):
5+
compound_fqdn: str
6+
component_fqdn: str

0 commit comments

Comments
 (0)