-
Notifications
You must be signed in to change notification settings - Fork 40
/
dump_pmodel.py
232 lines (188 loc) · 7.06 KB
/
dump_pmodel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
"""
Old Parser results model structure:
-----------------------------------
The parse model has two properties
class OldParseModel(object):
def __init__(self):
self.classlist = {} # todo should be renamed classes or classes_dict
self.modulemethods = []
where
.classlist {classname:classentry, ...} where classname is a string, classentry is a class containing
.ismodulenotrealclass T/F
.classdependencytuples [(fromclass, toclass), ...]
.classesinheritsfrom [class, ...] # todo should be renamed classinheritsfrom (singular)
.attrs [attrobj, ...]
.attrname
.attrtype [] # todo should be renamed attrtypes plural
.compositedependencies # todo (calculated in real time, should precalc) ?? DOESN'T EXIST?
.defs [method, ...]
.modulemethods = [method, ...]
@startuml
class OldParseModel #AntiqueWhite/Gold {
classlist : {}
modulemethods : [method, ...]
}
note left #AntiqueWhite/Gold : Abstract Language Structure Model = ALSM
class Classes <<Dict>> #Lavender {
key
value
}
hide Classes methods
hide ClassDependency methods
hide ClassName methods
hide MethodName methods
hide AttributeName methods
hide Attribute methods
hide OldParseModel methods
OldParseModel --> Classes : classlist
OldParseModel --> "0..*" MethodName : modulemethods
Classes --> "*" ClassEntry : value
Classes --> "*" ClassName : key
ClassEntry --> "0..*" ClassDependency : classdependencytuples
ClassEntry --> "0..*" ClassName : classesinheritsfrom
ClassEntry --> "0..*" Attribute : attrs
ClassEntry --> "0..*" MethodName : defs
ClassDependency --> ClassName : fromclass
ClassDependency --> ClassName : toclass
Attribute --> AttributeName : attrname
class ClassEntry {
name
ismodulenotrealclass : bool
classdependencytuples : [tuple, ...]
classesinheritsfrom : [class, ...]
attrs : [attrobj, ...]
defs : [method, ...]
---
FindAttribute(attrname)
AddAttribute(attrname, attrtype)
}
class ClassDependency <<Tuple>> #Lavender {
fromclass : string
toclass : string
}
class ClassName <<String>> #DarkSeaGreen {
name : string
}
class Attribute {
attrname : string
attrtype : string 'normal' | 'many'
}
class AttributeName <<String>> #DarkSeaGreen {
name : string
}
class MethodName <<String>> #DarkSeaGreen {
name : string
}
note as N1
<b><color:royalBlue>classdependencytuples</color>
is an array of ClassDependency tuples
[(fromclass, toclass), ...]
<u>fromclass</u> and <u>toclass</u> are strings
The former is the attribute name,
the latter is the class name
end note
note as N2
If <u>moduleasclass</u> on the old parser is true
then the module filenames being parsed are
also added to the 'Classes' dictionary as if they were
a class, and the module methods appear as 'defs' of
the ClassEntry.
end note
N1 .. ClassDependency
@enduml
"""
from beautifultable import BeautifulTable
from termcolor import colored # also install colorama to make this work on windows
# Util
def repair_old_pmodels(pmodel):
# repair old parse models #TODO build this into the old parser so that we don't have to do this
for classname, classentry in list(pmodel.classlist.items()):
classentry.name = classname
# TODO build this into ClassEntry
def calc_classname(classentry):
if classentry.name_long:
return classentry.name_long
else:
return classentry.name
# New dump
def dump_pmodel(pmodel):
t = BeautifulTable(max_width=760)
# subtable = BeautifulTable()
# subtable.column_headers = ["name", "rank", "gender"]
# subtable.append_row(["Jacob", 1, "boy"])
# subtable.append_row(["Isabella", 1, "girl"])
# parent_table = BeautifulTable()
# parent_table.column_headers = ["Heading 1", "Heading 2"]
# parent_table.append_row(["Sample text", "Another sample text"])
# parent_table.append_row([subtable, "More sample text"])
# return parent_table
repair_old_pmodels(pmodel)
t.column_headers = ["class name", "inherits from", "attributes", "methods()", "module methods()", "is module", "class dependencies"]
t.column_alignments["attributes"] = BeautifulTable.ALIGN_LEFT
t.column_alignments["methods()"] = BeautifulTable.ALIGN_LEFT
t.column_alignments["module methods()"] = BeautifulTable.ALIGN_LEFT
have_display_module_methods_once = False
for classname, classentry in sorted(
list(pmodel.classlist.items()), key=lambda kv: calc_classname(kv[1])
):
# Work out sub-tables first
if classentry.classdependencytuples:
t2 = BeautifulTable()
for _from,_to in classentry.classdependencytuples:
t2.append_row([_from,_to])
else:
t2 = ""
if classentry.attrs:
t3 = BeautifulTable()
t3.column_headers = ["name", "type"]
t3.column_alignments["name"] = BeautifulTable.ALIGN_LEFT
t3.row_separator_char = ""
for attrobj in classentry.attrs:
t3.append_row([attrobj.attrname, "\n".join(attrobj.attrtype)])
else:
t3 = ""
# t4 = BeautifulTable()
# t4.column_headers = ["of class", "of module"]
# t4.column_alignments["of class"] = BeautifulTable.ALIGN_LEFT
# t4.column_alignments["of module"] = BeautifulTable.ALIGN_LEFT
# t4.row_separator_char = ""
# t4.append_row(["\n".join(classentry.defs), "\n".join(pmodel.modulemethods)])
t.append_row(
[
calc_classname(classentry),
"\n".join(classentry.classesinheritsfrom),
t3,
"\n".join(classentry.defs),
"\n".join(pmodel.modulemethods) if not have_display_module_methods_once else "",
bool(classentry.ismodulenotrealclass),
t2, #classentry.classdependencytuples,
])
have_display_module_methods_once = True
t.column_alignments[0] = BeautifulTable.ALIGN_LEFT
t.row_separator_char = ""
return t
# Old (non table) dump
def dump_old_structure(pmodel):
res = ""
repair_old_pmodels(pmodel)
for classname, classentry in sorted(
list(pmodel.classlist.items()), key=lambda kv: calc_classname(kv[1])
):
res += "%s (is module=%s) inherits from %s class dependencies %s\n" % (
calc_classname(classentry),
classentry.ismodulenotrealclass,
classentry.classesinheritsfrom,
classentry.classdependencytuples,
)
if classentry.classdependencytuples:
for tup in classentry.classdependencytuples:
res += "%s\n" % (tup,)
for attrobj in classentry.attrs:
res += " %-20s (attrtype %s)\n" % (
attrobj.attrname,
attrobj.attrtype,
) # currently skip calc of self._GetCompositeCreatedClassesFor(attrobj.attrname), arguably it should be precalculated and part of the data structure
for adef in classentry.defs:
res += " %s()\n" % adef
res += " modulemethods %s\n" % (pmodel.modulemethods)
return res