2
# -*- coding: utf-8 -*-
4
# LORZE erasandcad, a 2D CAD with an intuitive user interface, simple and easy.
5
# http://erasand.jimdo.com/python-programme/lorze/
6
# (C) 2012, Andreas Ulrich
8
# This file is part of “LORZE erasandcad“
10
# “LORZE erasandcad“ is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
12
# “LORZE erasandcad“ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License along with LORZE erasandcad. If not, see <http://www.gnu.org/licenses/>.
18
class CodeAnalizer(): # CodeAnalizer for LORZE erasandcad scripts
22
self.__scriptlist= [] # list with python scripts
23
self.__codedict= {} # dictionairy for codes
24
self.__analizedict= {} # dictionairy for analized code
27
def GetScriptList(self):
28
os.chdir('../Modules') # get python script list / change to script directory
29
dirlist= os.listdir('./') # read the directory list
31
for i in dirlist: # get all files
32
if i.endswith('.py'): # python script found
33
self.__scriptlist.append(i) # add to scriptlist
36
def ReadScripts(self):
37
for i in self.__scriptlist: # read python scripts in the scriptlist / read all files
38
pyfile= open(i, 'r') # open script
39
self.__codedict[i]= pyfile.read() # read text
40
pyfile.close() # close script
43
def AnalizeCode(self): # analize code in codedict
44
self.__analizedict= {} # clear analizedict
46
self.__analizedict['0_files']= [] # prepare list for files
47
self.__analizedict['zzz_trash']= [] # prepare list for trash
49
for pyfile, codetxt in self.__codedict.items(): # each python script in codedict
51
#~ attributes= set() # 1st try with regular expresions
52
#~ classpattern= re.compile('class.+:?')
53
#~ attrpattern= re.compile('__.+=?')
54
#~ methpattern= re.compile('def.+:?')
57
#~ print('-'* len(pyfile))
58
#~ print(classpattern.findall(codetxt))
59
#~ print(attrpattern.findall(codetxt))
60
#~ print(methpattern.findall(codetxt))
63
# classes in 1.py: FirstA, FirstB
64
# codedict, {'0_files':['1.py', '2.py'], '1.py/class':['FirstA', 'FirstB'], '2.py/class':['SecondA', 'SecondB'], '1.py/class/FirstA/methods':[..], '1.py/class/FirstA/attributes':[..], '1.py/class/FirstB/methods':[..], '1.py/class/FirstB/attributes':[..], .., '/trash':['All otther lines', ..]}
66
self.__analizedict['0_files'].append(pyfile) # store filename in list with key '0_files'
67
self.__analizedict[pyfile+ '/class']= [] # prepare list for classes
69
for i in codetxt.splitlines(): # each line seperatly
70
linetxt= i.lstrip() # without whitespaces on the left side
72
if linetxt[:5]== 'class': # class found
73
classtxt= linetxt[5:len(linetxt)- 1] # without 'class' & ':'
74
classtxt= classtxt.lstrip().rstrip() # without whitespaces
76
self.__analizedict[pyfile+ '/class'].append(classtxt) # store in dict
77
self.__analizedict[pyfile+ '/class/'+ classtxt+ '/methods']= [] # prepare list for methods
78
self.__analizedict[pyfile+ '/class/'+ classtxt+ '/attributes']= [] # prepare list for attributes
80
elif linetxt[:3]== 'def': # method found
81
methodtxt= linetxt[3:] # without 'def'
82
methodtxt= methodtxt.replace('(self, ', '(') # '(self, ' > '('
83
methodtxt= methodtxt.replace('(self,', '(') # '(self,' > '('
84
methodtxt= methodtxt.replace('(self)', '()') # '(self)' > '()'
86
foundend1= methodtxt.find('):') # search '):'
87
foundend2= methodtxt.find(') :') # search ') :'
89
if foundend1!= -1: # '):' is found
90
methodtxt= methodtxt[:foundend1+ 2]
91
elif foundend2!= -1: # ') :' is found
92
methodtxt= methodtxt[:foundend2+ 2]
94
self.__analizedict[pyfile+ '/class/'+ classtxt+ '/methods'].append(methodtxt.lstrip().rstrip()) # store without whitespaces
96
elif linetxt[:7]== 'self.__': # private attribute found
97
attributetxt= linetxt[5:len(linetxt)] # without 'self.'
98
foundequal= attributetxt.find('=') # search 1st '='
100
if foundequal!= -1: # '=' is found
101
attributetxt= attributetxt[:foundequal] # all characters on the left side
102
attributetxt= attributetxt.lstrip().rstrip()
104
if attributetxt not in self.__analizedict[pyfile+ '/class/'+ classtxt+ '/attributes']: # attribute already in list?
105
self.__analizedict[pyfile+ '/class/'+ classtxt+ '/attributes'].append(attributetxt) # store new attribute
107
self.ToTrash(linetxt)
109
else: # nothing found
110
self.ToTrash(linetxt)
113
def ToTrash(self, linetxt): # store linetext to dict as trash
114
trashtxt= linetxt.lstrip().rstrip() # without whitespaces
115
if trashtxt not in self.__analizedict['zzz_trash']: # trash already in list?
116
self.__analizedict['zzz_trash'].append(trashtxt) # store to trash
119
def FileOutput(self): # write analizedict sorted to analysis.txt
120
keylist= self.__analizedict.keys() # get all keys from dict
121
keylist.sort() # sort keys
123
os.chdir('../Documentation') # back to documentation directory
125
txtfile= open('CodeAnalysis.txt', 'w') # open file to write
127
for i in keylist: # each key on a seperate line
128
txtfile.write(i+ '\n') # write key
129
underline= '-'* len(i) # underline key
130
txtfile.write(underline+ '\n') # write underline
132
for j in self.__analizedict[i]: # each value in list
133
txtfile.write(j+ '\n') # write value
135
txtfile.write('\n') # empty line at the end
137
txtfile.close() # close file
140
def UmlOutput(self): # write analizedict sorted for uml to analysis.txt
141
os.chdir('../Develop_Docu') # back to documentation directory
142
txtfile= open('CodeAnalysis.txt', 'w') # open file to write
144
self.__analizedict['0_files'].sort() # sort scriptlist
148
for pyscript in self.__analizedict['0_files']: # on each script
149
txtfile.write(pyscript+ '\n') # write script
150
#~ txtfile.write(line2+ '\n') # write ===
152
for classtxt in self.__analizedict[pyscript+ '/class']: # on each class
153
txtfile.write(line2+ '\n') # write ===
154
txtfile.write(classtxt+ '\n') # write class
155
txtfile.write(line1+ '\n') # write ---
157
self.__analizedict[pyscript+ '/class/'+ classtxt+ '/attributes'].sort() # sort attributes
158
for attributetxt in self.__analizedict[pyscript+ '/class/'+ classtxt+ '/attributes']: # on each attribute
159
txtfile.write(attributetxt+ '\n') # write attribute
160
txtfile.write(line1+ '\n') # write ---
162
methodlist= self.__analizedict[pyscript+ '/class/'+ classtxt+ '/methods']
163
init= methodlist[0] # get method '__init__'
164
del methodlist[0] # delete method '__init__'
165
methodlist.sort() # sort methodes
166
methodlist.insert(0, init) # insert '__init__' on top
167
for methodtxt in methodlist: # on each attribute
168
txtfile.write(methodtxt+ '\n') # write methode
169
txtfile.write(line2+ '\n') # write ===
170
txtfile.write('\n\n') # write 2 empty lines
172
txtfile.write('TRASH\n') # write title
173
txtfile.write('*****\n') # underline title
174
for txt in self.__analizedict['zzz_trash']: # on each line
175
txtfile.write(txt+ '\n') # write trash
177
txtfile.close() # close file
180
if __name__== '__main__':
188
print('CodeAnalizer')
189
print('------------')
191
print('The file "CodeAnalysis.txt" as a preparation for the uml illustration has been successfully written')