Skip to content

Commit 34bfc95

Browse files
authored
refactor(puml): remove nesting and grouping of namespaces, use "!pragma useIntermediatePackages false" instead (#64)
1 parent a9da0ab commit 34bfc95

File tree

15 files changed

+72
-326
lines changed

15 files changed

+72
-326
lines changed

README.md

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<img width="350px" alt="Python logo"
44
src="https://www.python.org/static/community_logos/python-logo-generic.svg" />
55
</a>
6-
<a href="http://plantuml.com/" target="_blank">
7-
<img width="116px" height="112px" alt="PlantUML logo" src="http://s.plantuml.com/logoc.png" style="margin-bottom: 40px" vspace="40px" />
6+
<a href="https://plantuml.com/" target="_blank">
7+
<img width="116px" height="112px" alt="PlantUML logo" src="https://s.plantuml.com/logoc.png" style="margin-bottom: 40px" vspace="40px" />
88
</a>
99
<h1>Python to PlantUML</h1>
1010
</div>
@@ -94,18 +94,8 @@ This outputs the following PlantUML content:
9494

9595
```plantuml
9696
@startuml py2puml.domain
97-
namespace py2puml.domain {
98-
namespace package {}
99-
namespace umlclass {}
100-
namespace umlitem {}
101-
namespace umlenum {}
102-
namespace umlrelation {}
103-
}
104-
class py2puml.domain.package.Package {
105-
name: str
106-
children: List[Package]
107-
items_number: int
108-
}
97+
!pragma useIntermediatePackages false
98+
10999
class py2puml.domain.umlclass.UmlAttribute {
110100
name: str
111101
type: str
@@ -135,7 +125,6 @@ class py2puml.domain.umlrelation.UmlRelation {
135125
target_fqn: str
136126
type: RelType
137127
}
138-
py2puml.domain.package.Package *-- py2puml.domain.package.Package
139128
py2puml.domain.umlclass.UmlClass *-- py2puml.domain.umlclass.UmlAttribute
140129
py2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlclass.UmlClass
141130
py2puml.domain.umlenum.UmlEnum *-- py2puml.domain.umlenum.Member
@@ -147,7 +136,7 @@ footer Generated by //py2puml//
147136

148137
Using PlantUML, this content is rendered as in this diagram:
149138

150-
![py2puml domain UML Diagram](https://www.plantuml.com/plantuml/png/ZPD1Yzim48Nl-XLpNbWRUZHxs2M4rj1DbZGzbIN8zcmgAikkD2wO9F-zigqWEw1L3i6HPgJlFUdfsH3NrDKIslvBQxz9rTHSAAPuZQRb9TuKuCG0PaLU_k5776S1IicDkLcGk9RaRT4wRPA18Ut6vMyXAuqgW-_2q2_N_kwgWh0s1zNL1UeCXA9n_iAcdnTamQEApnHTUvAVjNmXqgBeAAoB-dOnDiH9b1aKJIETYBj8gvai07xb6kTtfiMRDWTUM38loV62feVpYNWUMWOXkVq6tNxyLMuO8g7g8gIn9Nd5uQw2e7zSTZX7HJUqqjUU3L2FWElvJRZti6wDafDeb5i_shWb-QvaXtBVjpuMg-ths_P7li-tcmmUu3J5uEAg-URRUfVlNpQhTGPFPr-EUlD4ws-tr0XWcawNU5ZS2W1nVKJoi_EWEjspSxYmo8jyU7oCF5eMoxNV8_BCM2INJsUxKOp68WdnOWAfl5j56CBkl4cd9H8pzj4qX1g-eaBD2IieUaXJjp1DsJEgolvZ_m40)
139+
![py2puml domain UML Diagram](https://www.plantuml.com/plantuml/png/ZPBFwzf04CNl-rTChu89z1WyA29jeFx0sbCHcIIZBDtTfBkJWgZ_UyUeuSitO7BQnwxpUSzvcGP6pxKrK9s_Ld96HMbHE_MbydYo27MWr35vIuL6fWtcV_140Ove0YcL6mpXqsmaihcFVbapO_OwgvdWeW0SMaeWi1VDvwhLae9rda1MbaRT-gdpksY8-EA717xemBy_UkuLW0u7pCG5S-xbQoPxnwToTl8U_xf6lfadLzjeIJOZtnd_XwQcGG09i92p8TW6zlfl3_HU07J_GNVUaq7MfOksP7QotuOnNoytwv_fBbsl4XZ1vR7icxoag--BRRgRhUQB12RNzgcRiEiWARTFtRY4ilOv7Tej0J3w4t5xqrR-p2OclGsFnkD17vVgwN9o5L2Vc-hfGyAyxtneYZScQk369Sk0-jMnB9ayV2D77faAoCuGny_1E5PJSeMe_m00)
151140

152141
For a full overview of the CLI, run:
153142

@@ -213,6 +202,7 @@ poetry run pytest -v --cov=py2puml --cov-branch --cov-report term-missing --cov-
213202

214203
# Changelog
215204

205+
* `0.8.1`: delegated the grouping of nested namespaces (see `0.7.0`) to the PlantUML binary, which handles it natively
216206
* `0.8.0`: added support for union types, and github actions (pre-commit hooks + automated tests)
217207
* `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)
218208
* `0.7.1`: removed obsolete part of documentation: deeply compound types are now well handled (by version `0.7.0`)

py2puml/asserts.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,29 @@ def assert_py2puml_is_file_content(domain_path: str, domain_module: str, diagram
1111
assert_py2puml_is_stringio(domain_path, domain_module, expected_puml_file)
1212

1313

14+
def normalize_lines_with_returns(lines_with_returns: Iterable[str]) -> List[str]:
15+
'''
16+
When comparing contents, each piece of contents can either be:
17+
- a formatted string block output by the py2puml command containg line returns
18+
- a single line of contents read from a file, each line ending with a line return
19+
20+
This function normalizes each sequence of contents as a list of string lines,
21+
each one finishing without a line return to ease comparison.
22+
'''
23+
return ''.join(lines_with_returns).split('\n')
24+
25+
1426
def assert_py2puml_is_stringio(domain_path: str, domain_module: str, expected_content_stream: StringIO):
15-
# generates the PlantUML documentation
16-
puml_content = list(py2puml(domain_path, domain_module))
27+
puml_content_lines = normalize_lines_with_returns(py2puml(domain_path, domain_module))
28+
expected_content_lines = normalize_lines_with_returns(expected_content_stream)
1729

18-
assert_multilines(puml_content, expected_content_stream)
30+
assert_multilines(puml_content_lines, expected_content_lines)
1931

2032

21-
def assert_multilines(actual_multilines: List[str], expected_multilines: Iterable[str]):
33+
def assert_multilines(actual_multilines: List[str], expected_multilines: List[str]):
2234
line_index = 0
2335
for line_index, (actual_line, expected_line) in enumerate(zip(actual_multilines, expected_multilines)):
36+
# print(f'{actual_line=}\n{expected_line=}')
2437
assert actual_line == expected_line, f'actual and expected contents have changed at line {line_index + 1}: {actual_line=}, {expected_line=}'
2538

2639
assert line_index + 1 == len(actual_multilines), f'actual and expected diagrams have {line_index + 1} lines'

py2puml/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def run():
1616

1717
argparser = ArgumentParser(description='Generate PlantUML class diagrams to document your Python application.')
1818

19-
argparser.add_argument('-v', '--version', action='version', version='py2puml 0.8.0')
19+
argparser.add_argument('-v', '--version', action='version', version='py2puml 0.8.1')
2020
argparser.add_argument('path', metavar='path', type=str, help='the filepath to the domain')
2121
argparser.add_argument('module', metavar='module', type=str, help='the module name of the domain', default=None)
2222

py2puml/domain/package.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

py2puml/export/namespace.py

Lines changed: 0 additions & 98 deletions
This file was deleted.

py2puml/export/puml.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44
from py2puml.domain.umlenum import UmlEnum
55
from py2puml.domain.umlitem import UmlItem
66
from py2puml.domain.umlrelation import UmlRelation
7-
from py2puml.export.namespace import puml_namespace_content
87

9-
PUML_FILE_START = '@startuml {diagram_name}\n'
10-
PUML_FILE_FOOTER = 'footer Generated by //py2puml//\n'
11-
PUML_FILE_END = '@enduml\n'
12-
PUML_ITEM_START_TPL = '{item_type} {item_fqn} {{\n'
13-
PUML_ATTR_TPL = ' {attr_name}: {attr_type}{staticity}\n'
14-
PUML_ITEM_END = '}\n'
15-
PUML_RELATION_TPL = '{source_fqn} {rel_type}-- {target_fqn}\n'
8+
PUML_FILE_START = '''@startuml {diagram_name}
9+
!pragma useIntermediatePackages false
10+
11+
'''
12+
PUML_FILE_FOOTER = '''footer Generated by //py2puml//
13+
'''
14+
PUML_FILE_END = '''@enduml
15+
'''
16+
PUML_ITEM_START_TPL = '''{item_type} {item_fqn} {{
17+
'''
18+
PUML_ATTR_TPL = ''' {attr_name}: {attr_type}{staticity}
19+
'''
20+
PUML_ITEM_END = '''}
21+
'''
22+
PUML_RELATION_TPL = '''{source_fqn} {rel_type}-- {target_fqn}
23+
'''
1624

1725
FEATURE_STATIC = ' {static}'
1826
FEATURE_INSTANCE = ''
@@ -21,10 +29,6 @@
2129
def to_puml_content(diagram_name: str, uml_items: List[UmlItem], uml_relations: List[UmlRelation]) -> Iterable[str]:
2230
yield PUML_FILE_START.format(diagram_name=diagram_name)
2331

24-
# exports the namespaces
25-
for namespace_line in puml_namespace_content(uml_items):
26-
yield namespace_line
27-
2832
# exports the domain classes and enums
2933
for uml_item in uml_items:
3034
if isinstance(uml_item, UmlEnum):

py2puml/py2puml.domain.puml

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
@startuml py2puml.domain
2-
namespace py2puml.domain {
3-
namespace package {}
4-
namespace umlclass {}
5-
namespace umlitem {}
6-
namespace umlenum {}
7-
namespace umlrelation {}
8-
}
9-
class py2puml.domain.package.Package {
10-
name: str
11-
children: List[Package]
12-
items_number: int
13-
}
2+
!pragma useIntermediatePackages false
3+
144
class py2puml.domain.umlclass.UmlAttribute {
155
name: str
166
type: str
@@ -40,7 +30,6 @@ class py2puml.domain.umlrelation.UmlRelation {
4030
target_fqn: str
4131
type: RelType
4232
}
43-
py2puml.domain.package.Package *-- py2puml.domain.package.Package
4433
py2puml.domain.umlclass.UmlClass *-- py2puml.domain.umlclass.UmlAttribute
4534
py2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlclass.UmlClass
4635
py2puml.domain.umlenum.UmlEnum *-- py2puml.domain.umlenum.Member

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "py2puml"
3-
version = "0.8.0"
3+
version = "0.8.1"
44
description = "Generate PlantUML class diagrams to document your Python application."
55
keywords = ["class diagram", "PlantUML", "documentation", "inspection", "AST"]
66
readme = "README.md"

tests/modules/withnestednamespace/plantuml_namespace.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/modules/withnestednamespace/tests.modules.withnestednamespace.puml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
@startuml tests.modules.withnestednamespace
2-
namespace tests.modules.withnestednamespace {
3-
namespace nomoduleroot.modulechild.leaf {}
4-
namespace tree {}
5-
namespace branches.branch {}
6-
namespace withonlyonesubpackage.underground {
7-
namespace roots.roots {}
8-
}
9-
namespace trunks.trunk {}
10-
}
2+
!pragma useIntermediatePackages false
3+
114
class tests.modules.withnestednamespace.nomoduleroot.modulechild.leaf.CommownLeaf {
125
color: int
136
area: float

0 commit comments

Comments
 (0)