22import subprocess
33import logging
44import os
5+ import traceback
6+ import sys
57
6- class BugReporter :
7- def __init__ (self , file_path = 'bugs.json' , use_git = True , git = 'git' , git_source = None ):
8- self .commit = None
9- self .git_source = git_source
10- self .bugs = dict ()
11- self .build_state = 'passing'
12- self .bugs_count = 0
13- self .__update_data__ ()
14- self .use_git = use_git
15- self .git = git
16- if use_git :
17- self .get_git_info ()
18- self .file_path = file_path
19- self .load_file (file_path )
8+ commit = None
9+ git_source = None
10+ bugs = dict ()
11+ build_state = 'passing'
12+ bugs_count = 0
13+ file_path = None
14+
15+ def quick_config (file_path_ = 'bugs.json' , use_git_ = True , git_ = 'git' , git_source_ = None ):
16+ global git_source , git , use_git , file_path
17+ file_path = file_path_
18+ use_git = use_git_
19+ git = git_
20+ git_source = git_source_
21+ if use_git_ :
22+ get_git_info ()
23+
24+ load_file (file_path )
2025
21- def __update_data__ ( self ):
22- self . data = {
23- 'commit' :self . commit ,
24- 'bugs' :self . bugs ,
25- 'build_state' :self . build_state ,
26- 'bugs_count' :self . bugs_count
27- }
26+ def get_data ( ):
27+ return {
28+ 'commit' :commit ,
29+ 'bugs' :bugs ,
30+ 'build_state' :build_state ,
31+ 'bugs_count' :bugs_count
32+ }
2833
29- def load_file (self , file_path ):
30- if os .path .exists (file_path ):
31- self .file_path = file_path
32- data = dict ()
33- try :
34- with open (file_path , encoding = 'utf-8' ) as f :
35- data = json .load (f )
36- except :
37- logging .exception ('Can not parse bugs file' )
34+ def load_file (file_path_ ):
35+ global file_path , bugs , build_state , bugs_count
36+ if os .path .exists (file_path_ ):
37+ file_path = file_path_
38+ data = dict ()
39+ try :
40+ with open (file_path , encoding = 'utf-8' ) as f :
41+ data = json .load (f )
42+ except :
43+ logging .exception ('Can not parse bugs file' )
44+ return
45+ if use_git :
46+ #compare commit
47+ if commit != data .get ('commit' ) or not data .get ('commit' ):
3848 return
39- if self .use_git :
40- #compare commit
41- if self .commit != data .get ('commit' ) or not data .get ('commit' ):
42- return
43-
44- self .bugs = data .get ('bugs' ,dict ())
45- self .bugs_count = data .get ('bugs_count' ,0 )
46- self .build_state = 'failing' if self .bugs_count else 'passing'
47- self .__update_data__ ()
4849
50+ bugs = data .get ('bugs' ,dict ())
51+ bugs_count = len (bugs )
52+ build_state = 'failing' if bugs_count else 'passing'
53+
4954
50- def get_git_info (self ):
51- dir = os .path .dirname (__file__ )
52- if dir != '' :
53- os .chdir (dir )
55+ def get_git_info ():
56+ global commit , git_source
57+ dir = os .path .dirname (__file__ )
58+ if dir != '' :
59+ os .chdir (dir )
60+ try :
61+ short_hash = subprocess .check_output ([git , 'describe' , '--always' ], stderr = subprocess .STDOUT ).strip ().decode ()
62+ commit = subprocess .check_output ([git , 'rev-parse' , short_hash ], stderr = subprocess .STDOUT ).strip ().decode ()
63+ except subprocess .CalledProcessError :
64+ logging .error ('There was an error - command exited with non-zero code' )
65+ return
66+ except :
67+ logging .exception ('Unknown error' )
68+ return
69+
70+ if not git_source :
71+ lines = []
5472 try :
55- short_hash = subprocess .check_output ([self .git , 'describe' , '--always' ], stderr = subprocess .STDOUT ).strip ().decode ()
56- self .commit = subprocess .check_output ([self .git , 'rev-parse' , short_hash ], stderr = subprocess .STDOUT ).strip ().decode ()
73+ lines = subprocess .check_output ([git , 'remote' , '-v' ], stderr = subprocess .STDOUT ).decode ().strip ().split ('\n ' )
5774 except subprocess .CalledProcessError :
5875 logging .error ('There was an error - command exited with non-zero code' )
5976 return
6077 except :
6178 logging .exception ('Unknown error' )
6279 return
63-
64- if not self .git_source :
65- lines = []
66- try :
67- lines = subprocess .check_output ([self .git , 'remote' , '-v' ], stderr = subprocess .STDOUT ).decode ().strip ().split ('\n ' )
68- except subprocess .CalledProcessError :
69- logging .error ('There was an error - command exited with non-zero code' )
70- return
71- except :
72- logging .exception ('Unknown error' )
73- return
74- #get first fetch remote
75- for l in lines :
76- r = l .split ()
77- if r [2 ] == '(fetch)' :
78- r = r [1 ]
79- if r .endswith ('.git' ):
80- r = r [:- 4 ]
81- self .git_source = r
82- break
83- self .__update_data__ ()
84-
85- def bug (self , tag_name , message = None , ** more ):
86- tag = self .bugs .get (tag_name ,{'count' :0 ,'message' :None })
87- tag ['message' ] = message
88- tag ['count' ]+= 1
89- tag .update (more )
90- self .bugs [tag_name ] = tag
91- self .bugs_count = len (self .bugs )
92- self .build_state = 'failing'
93- self .__update_data__ ()
80+ #get first fetch remote
81+ for l in lines :
82+ r = l .split ()
83+ if r [2 ] == '(fetch)' :
84+ r = r [1 ]
85+ if r .endswith ('.git' ):
86+ r = r [:- 4 ]
87+ git_source = r
88+ break
9489
95- def dump (self ):
96- json .dump (self .data , open (self .file_path , 'w' , encoding = 'utf8' ), indent = 2 , ensure_ascii = False )
97-
98- def dumps (self ):
99- return json .dumps (self .data , indent = 2 , ensure_ascii = False )
90+ def bug (tag_name , message = None , ** more ):
91+ global bugs , bugs_count , build_state
92+ tag = bugs .get (tag_name ,{'count' :0 ,'message' :None })
93+ tag ['message' ] = message
94+ tag ['count' ]+= 1
95+ tag .update (more )
96+ bugs [tag_name ] = tag
97+ bugs_count = len (bugs )
98+ build_state = 'failing'
99+
100+ def exception (custom_msg = '' , exc_info = None , report = True , ** args ):
101+ exception_type , ex , tb = None , None , None
102+ if isinstance (exc_info , BaseException ):
103+ exc_info = (type (exc_info ), exc_info , exc_info .__traceback__ )
104+ elif not isinstance (exc_info , tuple ):
105+ exc_info = sys .exc_info ()
106+ exception_type , ex , tb = exc_info
107+ tb_list = traceback .format_exception (exception_type , ex , tb )
108+ tb_string = '' .join (tb_list )
109+ s = traceback .extract_tb (tb )
110+ f = s [- 1 ]
111+ lineno = f .lineno
112+ filename = os .path .basename (f .filename )
113+ if report :
114+ bug (f'L{ lineno } @{ filename } : { exception_type } ' , f'{ custom_msg } \n { tb_string } ' , line = lineno , file = filename , ** args )
115+ return {
116+ 'exc_type' : exception_type ,
117+ 'line_no' : lineno ,
118+ 'file_name' : filename ,
119+ 'tb_string' : tb_string ,
120+ 'traceback' : tb
121+ }
122+
123+ def dump ():
124+ json .dump (get_data (), open (file_path , 'w' , encoding = 'utf8' ), indent = 2 , ensure_ascii = False )
125+
126+ def dumps ():
127+ return json .dumps (get_data (), indent = 2 , ensure_ascii = False )
128+
129+
130+ class OnlineReporter :
131+ import cherrypy
132+
133+ @cherrypy .expose
134+ def index (self ):
135+ res = '''
136+ <!DOCTYPE html>
137+ <html>
138+ <head>
139+ <title>Bugs</title>
140+ <link rel="shortcut icon" type="image/png" href="https://bsimjoo.github.io/Telegram-RSS-Bot/media/bug.png"/>
141+ <style>
142+ html, body{
143+ background-color: #1b2631;
144+ color: #d6eaf8;
145+ }
146+ pre, ssh-pre{
147+ width:80%;
148+ max-height: 30%;
149+ margin: auto;
150+ background-color: #873600;
151+ color: white;
152+ border-radius: 10px;
153+ padding: 10px;
154+ overflow-x: auto;
155+ white-space: pre-wrap;
156+ word-wrap: break-word;
157+ }
158+ a:visited{
159+ color: #a569bd
160+ }
161+ </style>
162+ </head>
163+ <body>
164+ <h1 style="background-color: #d6eaf8; border-radius:10px; color:black">🐞 Bugs</h1>
165+ <p><b>What is this?</b> This project uses a simple web
166+ server to report bugs (exceptions) in a running application.</p>
167+ <h6><a href="/json">Show raw JSON</a></h6>'''
168+
169+ if bugs_count :
170+ res += f'<h2>😔 { bugs_count } bug(s) found</h2>'
171+ for tag , content in bugs .items ():
172+ link = ''
173+ if 'file' in content and use_git :
174+ lineno = content ['line' ]
175+ filename = content ['file' ]
176+ if os .path .exists (filename ):
177+ link = f' <a href="{ git_source } /blob/{ commit } /{ filename } #L{ lineno } ">🔸may be here: L{ lineno } @{ filename } </a></h3>'
178+ res += f'<h3>•Tag: <kbd>"{ tag } "</kbd> Count: { content ["count" ]} { link } </h3>'
179+ if content ["message" ]:
180+ res += f'<pre>{ content ["message" ]} </pre>'
181+ else :
182+ res += '<h1 align="center">😃 NO 🐞 FOUND 😉</h1>'
183+
184+ res += '</body></html>'
185+ return res
186+
187+ @cherrypy .expose
188+ @cherrypy .tools .json_out
189+ def json (self ):
190+ return get_data
0 commit comments