python_uml_class 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +86 -0
- data/LICENSE +21 -0
- data/README.md +2 -0
- data/Rakefile +8 -0
- data/bin/start_python_uml_class.rb +52 -0
- data/bin/start_python_uml_class.rbw +52 -0
- data/lib/app_load.rb +2 -0
- data/lib/config/browser.json +4 -0
- data/lib/config/setting.json +47 -0
- data/lib/config.ru +107 -0
- data/lib/create_uml_class.rb +352 -0
- data/lib/css/index.css +178 -0
- data/lib/del_comment.py +36 -0
- data/lib/html/index.html +80 -0
- data/lib/js/main.js +466 -0
- data/lib/my_app_sample.rb +36 -0
- data/lib/python_uml_class/version.rb +5 -0
- data/lib/python_uml_class.rb +55 -0
- data/lib/server.rb +58 -0
- data/lib/server_app_base.rb +63 -0
- data/lib/start.rb +130 -0
- data/lib/wsserver.rb +148 -0
- data/python_uml_class.gemspec +43 -0
- data/sig/PythonUmlClass.rbs +4 -0
- metadata +102 -0
@@ -0,0 +1,352 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "facter"
|
3
|
+
|
4
|
+
CStruct = Struct.new(:type,
|
5
|
+
:file_name,
|
6
|
+
:name,
|
7
|
+
:block_count,
|
8
|
+
:var_list,
|
9
|
+
:method_list,
|
10
|
+
:inherit_list,
|
11
|
+
:composition_list)
|
12
|
+
|
13
|
+
def get_formatter_path
|
14
|
+
return @config["formatter_path"] if @config["formatter_path"].to_s != ""
|
15
|
+
|
16
|
+
""
|
17
|
+
end
|
18
|
+
|
19
|
+
def print_uml(out, out_list)
|
20
|
+
out_list.each do |o_list|
|
21
|
+
if o_list.type == :class_start
|
22
|
+
# nop
|
23
|
+
elsif o_list.type == :module_start
|
24
|
+
out.push "namespace \"#{o_list.name}\" {"
|
25
|
+
elsif o_list.type == :class_end
|
26
|
+
pp o_list if o_list.name == ""
|
27
|
+
out.push "class \"#{o_list.name}\" {"
|
28
|
+
# インスタンス変数の出力
|
29
|
+
o_list.var_list.uniq.each do |iv|
|
30
|
+
out.push iv
|
31
|
+
end
|
32
|
+
# メソッドの出力
|
33
|
+
o_list.method_list.each do |ml|
|
34
|
+
out.push ml
|
35
|
+
end
|
36
|
+
out.push "}"
|
37
|
+
# 継承リストの出力
|
38
|
+
o_list.inherit_list.each do |ih|
|
39
|
+
out.push "\"#{o_list.name}\" -[##{@config["inherit_color"]}]-|> \"#{ih}\""
|
40
|
+
end
|
41
|
+
# compo
|
42
|
+
o_list.composition_list.uniq.each do |co|
|
43
|
+
out.push "\"#{o_list.name}\" *-[##{@config["composition_color"]}]- \"#{co}\""
|
44
|
+
end
|
45
|
+
elsif o_list.type == :module_end
|
46
|
+
# インスタンス変数がある場合はモジュール名と同じクラスを定義
|
47
|
+
if o_list.var_list.size != 0 or
|
48
|
+
o_list.method_list.size != 0 or
|
49
|
+
o_list.inherit_list.size != 0 or
|
50
|
+
o_list.composition_list.size != 0
|
51
|
+
pp o_list if o_list.name == ""
|
52
|
+
out.push "class #{o_list.name} {"
|
53
|
+
# インスタンス変数の出力
|
54
|
+
o_list.var_list.uniq.each do |iv|
|
55
|
+
out.push iv
|
56
|
+
end
|
57
|
+
# メソッドの出力
|
58
|
+
o_list.method_list.each do |ml|
|
59
|
+
out.push ml
|
60
|
+
end
|
61
|
+
out.push "}"
|
62
|
+
# 継承リストの出力
|
63
|
+
o_list.inherit_list.each do |ih|
|
64
|
+
out.push "\"#{o_list.name}\" -[##{@config["inherit_color"]}]-|> \"#{ih}\""
|
65
|
+
end
|
66
|
+
# compo
|
67
|
+
o_list.composition_list.uniq.each do |co|
|
68
|
+
out.push "\"#{o_list.name}\" *-[##{@config["composition_color"]}]- \"#{co}\""
|
69
|
+
end
|
70
|
+
end
|
71
|
+
out.push "}"
|
72
|
+
else
|
73
|
+
# error
|
74
|
+
puts "error!"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
out
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_uml_class(in_dir, _out_file)
|
81
|
+
out = []
|
82
|
+
out.push "@startuml"
|
83
|
+
|
84
|
+
puts "in_dir = #{in_dir}"
|
85
|
+
global_var = []
|
86
|
+
out_list = []
|
87
|
+
def_list = []
|
88
|
+
import_list = []
|
89
|
+
|
90
|
+
Dir.glob("#{in_dir}/**/*.py") do |f|
|
91
|
+
import_list.push File.basename(f).split(".")[0]
|
92
|
+
end
|
93
|
+
|
94
|
+
Dir.glob("#{in_dir}/**/*.py") do |f|
|
95
|
+
puts f
|
96
|
+
puts @config["exclude_path"]
|
97
|
+
if @config["exclude_path"] != ""
|
98
|
+
if f =~ Regexp.new(@config["exclude_path"])
|
99
|
+
puts "skip #{f}"
|
100
|
+
next
|
101
|
+
end
|
102
|
+
end
|
103
|
+
buf = ""
|
104
|
+
file_name = File.basename(f).split(".")[0]
|
105
|
+
Tempfile.create("pylint") do |tmp_file|
|
106
|
+
# FileUtils.cp(f, tmp_file.path)
|
107
|
+
kernel = Facter.value(:kernel)
|
108
|
+
if kernel == "windows"
|
109
|
+
open("|#{get_formatter_path} #{f} > #{tmp_file.path}") do |ff|
|
110
|
+
if ff.read.to_s != ""
|
111
|
+
puts "pylint error #{ff}"
|
112
|
+
return
|
113
|
+
else
|
114
|
+
buf = File.binread tmp_file.path
|
115
|
+
end
|
116
|
+
end
|
117
|
+
else
|
118
|
+
open("|#{get_formatter_path} #{f} > #{tmp_file.path}") do |ff|
|
119
|
+
puts "|#{get_formatter_path} #{f} > #{tmp_file.path}"
|
120
|
+
if ff.read.to_s != ""
|
121
|
+
puts "pylint error #{ff}"
|
122
|
+
return
|
123
|
+
else
|
124
|
+
buf = File.binread tmp_file.path
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
cstruct_list = []
|
131
|
+
block_count = 0
|
132
|
+
method_type = :public
|
133
|
+
class_name = ""
|
134
|
+
file_struct_list = []
|
135
|
+
file_struct_list.push CStruct.new(:class_start, file_name, file_name + ".global", block_count, [], [], [], [])
|
136
|
+
file_struct_list.push CStruct.new(:class_end, file_name, file_name + ".global", block_count, [], [], [], [])
|
137
|
+
is_def = false
|
138
|
+
|
139
|
+
# ソースを解析
|
140
|
+
buf.each_line do |line|
|
141
|
+
next if line =~ /^[\r\n]*$/ # 空行は対象外
|
142
|
+
|
143
|
+
line.chomp!
|
144
|
+
# ブロックの開始/終了
|
145
|
+
indent_num = line.match(/^ +/).to_s.size / 4
|
146
|
+
puts "block_count=#{indent_num} cstruct_size=#{cstruct_list.size} is_def=#{is_def} #{line}"
|
147
|
+
if block_count == indent_num
|
148
|
+
# 変化なし
|
149
|
+
elsif block_count > indent_num
|
150
|
+
# ブロックの終了
|
151
|
+
block_count = indent_num
|
152
|
+
# 関数の終了
|
153
|
+
if is_def == true and def_list[-1].block_count >= block_count
|
154
|
+
is_def = false
|
155
|
+
method_type = :public
|
156
|
+
end
|
157
|
+
# クラスの終了
|
158
|
+
if cstruct_list.size != 0 && cstruct_list[-1].block_count >= block_count # block_countが一致
|
159
|
+
puts "end of #{cstruct_list[-1].name}"
|
160
|
+
out_list.push cstruct_list[-1]
|
161
|
+
cstruct_list.slice!(-1) # 最後の要素を削除
|
162
|
+
method_type = :public
|
163
|
+
end
|
164
|
+
else
|
165
|
+
# ブロックの開始
|
166
|
+
block_count = indent_num
|
167
|
+
end
|
168
|
+
#puts "block_count=#{indent_num} class_count=#{cstruct_list.size} def_count=#{def_list.size} #{line}"
|
169
|
+
|
170
|
+
# method_type
|
171
|
+
if line =~ /@staticmethod/
|
172
|
+
method_type = :private
|
173
|
+
end
|
174
|
+
|
175
|
+
# import
|
176
|
+
line.match(/import \S+/) do |m|
|
177
|
+
import_name = m.to_s.gsub(/import /, "")
|
178
|
+
if 0 != import_list.select { |im| im == import_name }.size and file_name != import_name
|
179
|
+
if cstruct_list.size != 0
|
180
|
+
cstruct_list[-1].composition_list.push import_name
|
181
|
+
else
|
182
|
+
file_struct_list[-1].composition_list.push import_name
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# クラスの開始
|
188
|
+
if line =~ /^\s*class.*:/
|
189
|
+
work = line.gsub(/class\s/, "")
|
190
|
+
class_name = work.split("\(")[0].to_s.gsub(/:/, "")
|
191
|
+
base_name = work.match(/\(.*\)/).to_s.gsub(/[()]/, "")
|
192
|
+
class_name = "#{file_name}.#{class_name}"
|
193
|
+
puts "class_name=#{class_name}"
|
194
|
+
puts "base_name=#{base_name}"
|
195
|
+
out_list.push CStruct.new(:class_start, file_name, class_name, block_count, [], [], [], [])
|
196
|
+
cstruct_list.push CStruct.new(:class_end, file_name, class_name, block_count, [], [], [], [])
|
197
|
+
# pp line if class_name == ""
|
198
|
+
if base_name != ""
|
199
|
+
if base_name =~ /,/
|
200
|
+
base_name.split(",").each do |name|
|
201
|
+
cstruct_list[-1].inherit_list.push name
|
202
|
+
end
|
203
|
+
else
|
204
|
+
cstruct_list[-1].inherit_list.push base_name
|
205
|
+
end
|
206
|
+
end
|
207
|
+
next
|
208
|
+
end
|
209
|
+
|
210
|
+
if line =~ /^\s*private$/
|
211
|
+
method_type = :private
|
212
|
+
elsif line =~ /^\s*protected$/
|
213
|
+
method_type = :protected
|
214
|
+
elsif line =~ /^\s*public$/
|
215
|
+
method_type = :public
|
216
|
+
end
|
217
|
+
|
218
|
+
if line =~ /^\s*def\s/
|
219
|
+
# 関数名を取り出す
|
220
|
+
method = line.chomp.gsub(/\s*def\s*/, "")
|
221
|
+
unless method =~ /\(/
|
222
|
+
# 関数名にカッコをつける
|
223
|
+
sp = method.split(" ")
|
224
|
+
method = if sp.size > 1
|
225
|
+
sp[0].to_s + "(" + sp[1..-1].to_s + ")"
|
226
|
+
else
|
227
|
+
method + "()"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
if cstruct_list.size != 0
|
231
|
+
method_list = cstruct_list[-1].method_list
|
232
|
+
case method_type
|
233
|
+
when :public
|
234
|
+
method_list.push "+ #{method}"
|
235
|
+
when :private
|
236
|
+
method_list.push "- #{method}"
|
237
|
+
when :protected
|
238
|
+
method_list.push "# #{method}"
|
239
|
+
end
|
240
|
+
else
|
241
|
+
method_list = file_struct_list[-1].method_list
|
242
|
+
method_list.push "+ #{method}"
|
243
|
+
end
|
244
|
+
def_list.push CStruct.new(:method_start, file_name, method, block_count, [], [], [], [])
|
245
|
+
is_def = true
|
246
|
+
end
|
247
|
+
|
248
|
+
# composition_list
|
249
|
+
# クラスの呼び出し箇所
|
250
|
+
line.match(/\s([A-Z][a-zA-Z]+)\.[a-z]/) do |m|
|
251
|
+
c_name = m.to_s.split(".")[0].gsub(/ /, "")
|
252
|
+
puts "compo c_name=#{c_name}"
|
253
|
+
if cstruct_list.size != 0
|
254
|
+
cstruct_list[-1].composition_list.push c_name
|
255
|
+
else
|
256
|
+
file_struct_list[-1].composition_list.push c_name
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# クラスの初期化箇所
|
261
|
+
line.match(/[\s\.][A-Z][A-Za-z]+\(/) do |m|
|
262
|
+
c_name = m.to_s.gsub(/\(/, "").gsub(/[\s\.]/, "")
|
263
|
+
puts "compo c_name=#{c_name}"
|
264
|
+
if cstruct_list.size != 0
|
265
|
+
cstruct_list[-1].composition_list.push c_name
|
266
|
+
else
|
267
|
+
file_struct_list[-1].composition_list.push c_name
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# インスタンス変数
|
272
|
+
if line =~ /^\s*self\.[a-zA-Z0-9_]+\s+=/ and cstruct_list.size != 0
|
273
|
+
line.match(/self\.[a-zA-Z0-9_]+/) do |m|
|
274
|
+
instance_var = cstruct_list[-1].var_list
|
275
|
+
val = m.to_s.gsub(/self\./, "")
|
276
|
+
case method_type
|
277
|
+
when :public
|
278
|
+
instance_var.push "+ #{val}"
|
279
|
+
when :private
|
280
|
+
instance_var.push "- #{val}"
|
281
|
+
when :protected
|
282
|
+
instance_var.push "# #{val}"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# クラス変数
|
288
|
+
if line =~ /^\s*[a-zA-Z0-9_]+\s+=/ and cstruct_list.size != 0 and is_def == false
|
289
|
+
line.match(/[a-zA-Z0-9_]+/) do |m|
|
290
|
+
instance_var = cstruct_list[-1].var_list
|
291
|
+
val = m.to_s
|
292
|
+
instance_var.push "- #{val}"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# 外部変数
|
297
|
+
if line =~ /^\s*[a-zA-Z0-9_]+\s+=/ and cstruct_list.size == 0 and is_def == false
|
298
|
+
line.match(/\$*[a-zA-Z0-9_]+/) do |m|
|
299
|
+
file_struct_list[-1].var_list.push "+ #{m}"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# ファイルの終了
|
305
|
+
if block_count != 0
|
306
|
+
puts "endf of #{f}"
|
307
|
+
# クラスの終了
|
308
|
+
if cstruct_list.size != 0
|
309
|
+
puts "end of #{cstruct_list[-1].name}"
|
310
|
+
out_list.push cstruct_list[-1]
|
311
|
+
cstruct_list.slice!(-1) # 最後の要素を削除
|
312
|
+
end
|
313
|
+
file_struct_list.each do |fs|
|
314
|
+
out_list.push fs
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# 継承リストとコンポジションリストのチュエック
|
320
|
+
out_list.each_index do |i|
|
321
|
+
out_list[i].composition_list.each_index do |j|
|
322
|
+
# compo_nameがfile_name.class_nameに変更可能かチェック
|
323
|
+
compo_name = out_list[i].composition_list[j]
|
324
|
+
out_list.select { |a| a.name.split(".")[-1] == compo_name }.each do |m|
|
325
|
+
puts "m=#{m.name}"
|
326
|
+
out_list[i].composition_list[j] = m.name
|
327
|
+
end
|
328
|
+
def_list.each do |def_struct|
|
329
|
+
# comp_nameが自分で定義した関数名の場合は削除
|
330
|
+
#puts "#{compo_name} == #{def_struct.name.split("(")[0]}"
|
331
|
+
if compo_name == def_struct.name.split("(")[0]
|
332
|
+
puts "match_def #{compo_name} == #{def_struct.name.split("(")[0]}"
|
333
|
+
out_list[i].composition_list.delete_at(j)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
out_list[i].inherit_list.each_index do |j|
|
338
|
+
# compo_nameがfile_name.class_nameに変更可能かチェック
|
339
|
+
inherit_name = out_list[i].inherit_list[j]
|
340
|
+
out_list.select { |a| a.name.split(".")[-1] == inherit_name }.each do |m|
|
341
|
+
puts "m=#{m.name}"
|
342
|
+
out_list[i].inherit_list[j] = m.name
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# UMLの出力
|
348
|
+
out = print_uml(out, out_list)
|
349
|
+
|
350
|
+
out.push "@enduml"
|
351
|
+
out.join("\n")
|
352
|
+
end
|
data/lib/css/index.css
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
body {
|
2
|
+
color: #000000;
|
3
|
+
background-color: #cac3ec4f;
|
4
|
+
overflow: hidden;
|
5
|
+
font-size: 12px;
|
6
|
+
}
|
7
|
+
|
8
|
+
hr {
|
9
|
+
color: #ffffff;
|
10
|
+
background-color: #000000;
|
11
|
+
height: 1px;
|
12
|
+
/* 線の太さ */
|
13
|
+
border: 1px;
|
14
|
+
/* 枠の太さ */
|
15
|
+
border-style: solid;
|
16
|
+
/* 枠の種類 */
|
17
|
+
}
|
18
|
+
|
19
|
+
.error {
|
20
|
+
color: red;
|
21
|
+
}
|
22
|
+
|
23
|
+
.outarea {
|
24
|
+
background-color: #FFFFFF;
|
25
|
+
margin: 5px;
|
26
|
+
padding: 5px;
|
27
|
+
width: 95vw;
|
28
|
+
height: 50vh;
|
29
|
+
overflow: auto;
|
30
|
+
}
|
31
|
+
|
32
|
+
.inarea {
|
33
|
+
border: thin solid #000000;
|
34
|
+
margin: 5px;
|
35
|
+
padding: 5px;
|
36
|
+
width: 98%;
|
37
|
+
}
|
38
|
+
|
39
|
+
input.long {
|
40
|
+
width: 98%;
|
41
|
+
background-color: #FAFAFA;
|
42
|
+
margin: 5px;
|
43
|
+
padding: 5px;
|
44
|
+
}
|
45
|
+
|
46
|
+
textarea.long {
|
47
|
+
width: 95vw;
|
48
|
+
height: 50vh;
|
49
|
+
}
|
50
|
+
|
51
|
+
.ui-widget {
|
52
|
+
font-size: 12px;
|
53
|
+
}
|
54
|
+
|
55
|
+
.ui-autocomplete {
|
56
|
+
max-height: 45vh;
|
57
|
+
max-width: 90wh;
|
58
|
+
overflow-y: auto;
|
59
|
+
overflow-x: auto;
|
60
|
+
padding-right: 10px;
|
61
|
+
}
|
62
|
+
|
63
|
+
#jquery-ui-autocomplete label {
|
64
|
+
float: left;
|
65
|
+
margin-right: 0.5em;
|
66
|
+
color: black;
|
67
|
+
}
|
68
|
+
|
69
|
+
.ui-autocomplete.ui-front {
|
70
|
+
max-height: 250px;
|
71
|
+
overflow-y: auto;
|
72
|
+
/* prevent horizontal scrollbar */
|
73
|
+
overflow-x: hidden;
|
74
|
+
/* add padding to account for vertical scrollbar */
|
75
|
+
z-index: 1000 !important;
|
76
|
+
}
|
77
|
+
|
78
|
+
.ui-dialog {
|
79
|
+
position: absolute;
|
80
|
+
top: 0;
|
81
|
+
left: 0;
|
82
|
+
padding: .2em;
|
83
|
+
outline: 0;
|
84
|
+
}
|
85
|
+
|
86
|
+
.long {
|
87
|
+
width: 90%;
|
88
|
+
}
|
89
|
+
|
90
|
+
#setting_dialog {
|
91
|
+
color: #ffffff;
|
92
|
+
background-color: #000000;
|
93
|
+
}
|
94
|
+
|
95
|
+
.setting_name {
|
96
|
+
width: 200px;
|
97
|
+
color: #ffffff;
|
98
|
+
background-color: #000000;
|
99
|
+
}
|
100
|
+
|
101
|
+
.setting_value {
|
102
|
+
width: 300px;
|
103
|
+
color: #ffffff;
|
104
|
+
background-color: #000000;
|
105
|
+
}
|
106
|
+
|
107
|
+
.setting_checkbox {
|
108
|
+
color: #ffffff;
|
109
|
+
background-color: #000000;
|
110
|
+
}
|
111
|
+
|
112
|
+
ul.log {
|
113
|
+
list-style-type: none;
|
114
|
+
font-size: 12px;
|
115
|
+
color: #000000;
|
116
|
+
}
|
117
|
+
|
118
|
+
input[type="search"] {
|
119
|
+
-webkit-appearance: searchfield;
|
120
|
+
}
|
121
|
+
|
122
|
+
input[type="search"]::-webkit-search-cancel-button {
|
123
|
+
-webkit-appearance: searchfield-cancel-button;
|
124
|
+
}
|
125
|
+
|
126
|
+
/* menu */
|
127
|
+
.menu {
|
128
|
+
display: flex;
|
129
|
+
justify-content: flex-start;
|
130
|
+
list-style-type: none;
|
131
|
+
color: #393737;
|
132
|
+
padding: 0;
|
133
|
+
font-size: 12px;
|
134
|
+
font-weight: bold;
|
135
|
+
}
|
136
|
+
|
137
|
+
.menu li {
|
138
|
+
position: relative;
|
139
|
+
width: 100px;
|
140
|
+
margin-left: 1px;
|
141
|
+
padding: 5px;
|
142
|
+
background: #d8dada;
|
143
|
+
list-style-type: none;
|
144
|
+
}
|
145
|
+
|
146
|
+
.menu li a {
|
147
|
+
color: rgb(20, 114, 192);
|
148
|
+
}
|
149
|
+
|
150
|
+
.menu li a:hover {
|
151
|
+
background: #eba399;
|
152
|
+
}
|
153
|
+
|
154
|
+
.menuSub {
|
155
|
+
position: absolute;
|
156
|
+
margin-left: -6px;
|
157
|
+
padding: 0;
|
158
|
+
display: none;
|
159
|
+
}
|
160
|
+
|
161
|
+
/*.openが付与された時、表示の設定*/
|
162
|
+
.menuSub.open {
|
163
|
+
display: block;
|
164
|
+
}
|
165
|
+
|
166
|
+
.menuSub li a {
|
167
|
+
padding: 5px;
|
168
|
+
margin-left: -5px;
|
169
|
+
margin-right: -5px;
|
170
|
+
margin-bottom: -5px;
|
171
|
+
display: block;
|
172
|
+
color: rgb(20, 114, 192);
|
173
|
+
text-decoration: none;
|
174
|
+
}
|
175
|
+
|
176
|
+
.menuSub li a:hover {
|
177
|
+
background: #eba399;
|
178
|
+
}
|
data/lib/del_comment.py
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
import sys
|
4
|
+
import ast
|
5
|
+
import astor
|
6
|
+
import pprint
|
7
|
+
|
8
|
+
def remove_comments_from_code(code):
|
9
|
+
# コードをASTに変換
|
10
|
+
tree = ast.parse(code)
|
11
|
+
|
12
|
+
#print("----------")
|
13
|
+
#print(ast.dump(tree, indent=4))
|
14
|
+
#print("----------")
|
15
|
+
|
16
|
+
# ASTを操作してコメントを削除
|
17
|
+
for node in ast.walk(tree):
|
18
|
+
|
19
|
+
#print(vars(node))
|
20
|
+
#print("--------------------------------------------------")
|
21
|
+
#pprint.pprint(vars(node))
|
22
|
+
if isinstance(node, ast.Expr) and isinstance(node.value, ast.Str) and isinstance(node.value.s, str):
|
23
|
+
# 文字列としてコメントが格納されているExprノードを削除
|
24
|
+
if node.value.s.startswith(("#", '"""', "'''")):
|
25
|
+
node.value.s = "" # コメントを空文字列に設定
|
26
|
+
|
27
|
+
# ASTからコードに変換
|
28
|
+
modified_code = astor.to_source(tree)
|
29
|
+
|
30
|
+
return modified_code
|
31
|
+
|
32
|
+
if __name__ == "__main__":
|
33
|
+
file = sys.argv[1]
|
34
|
+
f = open(file, "r")
|
35
|
+
code_without_comments = remove_comments_from_code(f.read())
|
36
|
+
print(code_without_comments)
|
data/lib/html/index.html
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>PythonUMLClass</title>
|
8
|
+
<!-- jQuery -->
|
9
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
10
|
+
<!-- jQuery UI -->
|
11
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
12
|
+
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
13
|
+
|
14
|
+
<script src="js/main.js"></script>
|
15
|
+
<link rel="stylesheet" href="css/index.css" type="text/css">
|
16
|
+
</head>
|
17
|
+
|
18
|
+
<body>
|
19
|
+
<div id="msg_dialog" style="display:none;">
|
20
|
+
<div id="msg_text">message</div>
|
21
|
+
</div>
|
22
|
+
<hr>
|
23
|
+
<!-- menu -->
|
24
|
+
<div id="setting_dialog" style="display:none;">
|
25
|
+
<dl id="wrap"></dl>
|
26
|
+
</div>
|
27
|
+
<div>
|
28
|
+
<ul class="menu">
|
29
|
+
<Li><a href="#" id="exec" name="exec">実行</a></li>
|
30
|
+
<li><a href="#" id="stop" name="stop">停止</a></li>
|
31
|
+
<li>
|
32
|
+
設定
|
33
|
+
<ul class="menuSub">
|
34
|
+
<li><a href="#" id="setting">設定</a></li>
|
35
|
+
<li><a href="#" id="save_setting">設定保存</a></li>
|
36
|
+
<li><a href="#" id="load_setting">設定読み込み</a></li>
|
37
|
+
</ul>
|
38
|
+
</li>
|
39
|
+
<!--
|
40
|
+
<li>
|
41
|
+
menu3
|
42
|
+
<ul class="menuSub">
|
43
|
+
<li><a href="#">menu3-1</a></li>
|
44
|
+
<li><a href="#">menu3-2</a></li>
|
45
|
+
</ul>
|
46
|
+
</li>
|
47
|
+
-->
|
48
|
+
</ul>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<table>
|
52
|
+
<tr>
|
53
|
+
<td>
|
54
|
+
<div id="dialog1" style="display:none;">
|
55
|
+
<input class="inarea" type="search" name="search_str" id="search_str">
|
56
|
+
</div>
|
57
|
+
</td>
|
58
|
+
<td class="long"><input class="inarea" type="search" id="inDir" name="inDir"></td>
|
59
|
+
<td><input type="button" id="select_dir" value="対象フォルダ" /></td>
|
60
|
+
</tr>
|
61
|
+
<tr>
|
62
|
+
<td>
|
63
|
+
<div id="dialog2" style="display:none;">
|
64
|
+
<input class="inarea" type="search" name="search_str2" id="search_str2">
|
65
|
+
</div>
|
66
|
+
</td>
|
67
|
+
<td class="long"><input class="inarea" type="search" id="outFile" name="outFile"></td>
|
68
|
+
<td><input type="button" id="select_file" value="出力ファイル" /></td>
|
69
|
+
<td><input type="button" id="open_file" value="開く" /></td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
|
73
|
+
<div class="outarea">
|
74
|
+
<ul name="log" id="log" class="log">
|
75
|
+
</ul>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
</body>
|
79
|
+
|
80
|
+
</html>
|