33import argparse
44import base64
55import random
6+ import signal
67import string
78import sys
89from datetime import datetime , timedelta
910from typing import List , Union , Callable
1011
1112import requests
1213
14+ signal .signal (signal .SIGINT , signal .SIG_DFL ) # allow to be closed with sigint, see https://stackoverflow.com/a/6072360/3112139
15+
1316MACHINE = "devmachine"
1417UA = 'wakatime/13.0.7 (Linux-4.15.0-91-generic-x86_64-with-glibc2.4) Python3.8.0.final.0 generator/1.42.1 generator-wakatime/4.0.0'
1518LANGUAGES = {
1619 'Go' : 'go' ,
1720 'Java' : 'java' ,
1821 'JavaScript' : 'js' ,
1922 'Python' : 'py' ,
20- # https://github.com/muety/wakapi/issues/172
2123 'PHP' : 'php' ,
22- 'Blade' : 'blade.php' ,
24+ 'Blade' : 'blade.php' , # https://github.com/muety/wakapi/issues/172
2325 '?' : 'astro' , # simulate language unknown to wakatime-cli
2426}
2527BRANCHES = ['master' , 'feature-1' , 'feature-2' ]
@@ -95,16 +97,14 @@ def post_data_sync(data: List[Heartbeat], url: str, api_key: str):
9597 'Authorization' : f'Basic { encoded_key } ' ,
9698 'X-Machine-Name' : MACHINE ,
9799 })
98- if r .status_code != 201 :
99- print (r .text )
100- sys .exit (1 )
100+ r .raise_for_status ()
101101
102102
103103def make_gui (callback : Callable [[ConfigParams , Callable [[int ], None ]], None ]) -> ('QApplication' , 'QWidget' ):
104104 # https://doc.qt.io/qt-5/qtwidgets-module.html
105105 from PyQt5 .QtCore import Qt
106106 from PyQt5 .QtWidgets import QApplication , QWidget , QFormLayout , QHBoxLayout , QVBoxLayout , QGroupBox , QLabel , \
107- QLineEdit , QSpinBox , QProgressBar , QPushButton , QCheckBox
107+ QLineEdit , QSpinBox , QProgressBar , QPushButton , QCheckBox , QMessageBox
108108
109109 # Main app
110110 app = QApplication ([])
@@ -126,7 +126,7 @@ def make_gui(callback: Callable[[ConfigParams, Callable[[int], None]], None]) ->
126126
127127 api_key_input_label = QLabel ('API Key:' )
128128 api_key_input = QLineEdit ()
129- api_key_input .setPlaceholderText (f'{ "x" * 8 } -{ "x" * 4 } -{ "x" * 4 } -{ "x" * 4 } -{ "x" * 12 } ' )
129+ api_key_input .setPlaceholderText (f'{ "x" * 8 } -{ "x" * 4 } -{ "x" * 4 } -{ "x" * 4 } -{ "x" * 12 } ' )
130130
131131 form_layout_1 .addRow (url_input_label , url_input )
132132 form_layout_1 .addRow (api_key_input_label , api_key_input )
@@ -171,6 +171,7 @@ def make_gui(callback: Callable[[ConfigParams, Callable[[int], None]], None]) ->
171171
172172 start_button = QPushButton ('Generate' )
173173 progress_bar = QProgressBar ()
174+ progress_bar .setValue (0 )
174175
175176 bottom_layout .addWidget (progress_bar )
176177 bottom_layout .addWidget (start_button )
@@ -183,17 +184,6 @@ def make_gui(callback: Callable[[ConfigParams, Callable[[int], None]], None]) ->
183184
184185 window .setLayout (container_layout )
185186
186- # Done dialog
187- done_dialog = QWidget ()
188- done_dialog .setWindowTitle ('Done' )
189- done_ok_button = QPushButton ('Ok' )
190- done_layout = QVBoxLayout ()
191- done_layout .addWidget (QLabel ('Done!' ), alignment = Qt .AlignCenter )
192- done_layout .addWidget (done_ok_button , alignment = Qt .AlignCenter )
193- done_dialog .setFixedSize (done_dialog .sizeHint ())
194- done_ok_button .clicked .connect (done_dialog .close )
195- done_dialog .setLayout (done_layout )
196-
197187 # Logic
198188 def parse_params () -> ConfigParams :
199189 params = ConfigParams ()
@@ -209,18 +199,30 @@ def parse_params() -> ConfigParams:
209199 def update_progress (inc = 1 ):
210200 current = progress_bar .value ()
211201 updated = current + inc
212- if updated == progress_bar .maximum () - 1 :
202+ progress_bar .setValue (updated )
203+ if updated == progress_bar .maximum ():
213204 progress_bar .setValue (0 )
214205 start_button .setEnabled (True )
215- done_dialog .show ()
206+
207+ dlg = QMessageBox ()
208+ dlg .setWindowTitle ('Success' )
209+ dlg .setText ('Done' )
210+ dlg .exec ()
211+
216212 return
217- progress_bar .setValue (updated )
213+
214+ def on_error (e ):
215+ dlg = QMessageBox ()
216+ dlg .setWindowTitle ('Error' )
217+ dlg .setText (e )
218+ btn = dlg .exec ()
218219
219220 def call_back ():
220221 params = parse_params ()
221222 progress_bar .setMaximum (params .n )
223+ progress_bar .setValue (0 )
222224 start_button .setEnabled (False )
223- callback (params , update_progress )
225+ callback (params , update_progress , on_error )
224226
225227 start_button .clicked .connect (call_back )
226228
@@ -261,7 +263,7 @@ def randomword(length: int) -> str:
261263 return '' .join (random .choice (letters ) for _ in range (length ))
262264
263265
264- def run (params : ConfigParams , update_progress : Callable [[int ], None ]):
266+ def run (params : ConfigParams , update_progress : Callable [[int ], None ], on_error : Callable [[ str ], None ] ):
265267 random .seed (params .seed )
266268 data : List [Heartbeat ] = generate_data (
267269 params .n ,
@@ -270,13 +272,16 @@ def run(params: ConfigParams, update_progress: Callable[[int], None]):
270272 )
271273
272274 # batch-mode won't work when using sqlite backend
273- if params .batch :
274- post_data_sync (data , f'{ params .api_url } /heartbeats' , params .api_key )
275- update_progress (len (data ))
276- else :
277- for d in data :
278- post_data_sync ([d ], f'{ params .api_url } /heartbeats' , params .api_key )
279- update_progress (1 )
275+ try :
276+ if params .batch :
277+ post_data_sync (data , f'{ params .api_url } /heartbeats' , params .api_key )
278+ update_progress (len (data ))
279+ else :
280+ for d in data :
281+ post_data_sync ([d ], f'{ params .api_url } /heartbeats' , params .api_key )
282+ update_progress (1 )
283+ except requests .exceptions .HTTPError as e :
284+ on_error (str (e ))
280285
281286
282287if __name__ == '__main__' :
0 commit comments