44
44
import unicodedata
45
45
import watchdog .events
46
46
import watchdog .observers
47
+ from loguru import logger
47
48
from udk_configparser import UDKConfigParser
48
49
49
50
import defaults
50
51
51
52
# TODO: leverage pytest?
52
- # TODO: use the logging module.
53
53
# TODO: reduce log spam? More verbose logging to a file,
54
54
# only general info straight to console?
55
55
56
+
57
+ _log_format = "[{time:YYYY-MM-DD HH:mm:ss.SSSZZ}] [{level}] [{function}] {message}"
58
+
59
+ logger .remove ()
60
+ logger .add (
61
+ sys .stdout ,
62
+ format = _log_format ,
63
+ level = "DEBUG" ,
64
+ )
65
+ logger .add (
66
+ "run_udk_tests.log" ,
67
+ format = _log_format ,
68
+ rotation = "50 MB" ,
69
+ level = "DEBUG" ,
70
+ )
71
+
56
72
SCRIPT_DIR = Path (__file__ ).parent
57
73
REPO_DIR = SCRIPT_DIR .parent
58
74
CACHE_DIR = SCRIPT_DIR / ".cache/"
@@ -107,13 +123,13 @@ def state(self) -> State:
107
123
108
124
@state .setter
109
125
def state (self , state : State ):
110
- print ( f "setting state: { state } " )
126
+ logger . info ( "setting state: {}" , state )
111
127
self ._state = state
112
128
self ._pos = 0
113
129
114
130
def on_any_event (self , event : watchdog .events .FileSystemEvent ):
115
131
if Path (event .src_path ).name == self ._log_filename :
116
- print ( f "fs event: { event .event_type } , { event .src_path } " )
132
+ logger . info ( "fs event: {} {}" , event .event_type , event .src_path )
117
133
self ._fh = open (self ._log_file , errors = "replace" , encoding = "utf-8" )
118
134
119
135
# TODO: better state handling, this is a mess ATM.
@@ -125,7 +141,7 @@ def on_modified(self, event: watchdog.events.FileSystemEvent):
125
141
126
142
size = self ._log_file .stat ().st_size
127
143
if size == 0 :
128
- print ("log file cleared" )
144
+ logger . info ("log file cleared" )
129
145
self ._pos = 0
130
146
return
131
147
@@ -152,7 +168,7 @@ def on_modified(self, event: watchdog.events.FileSystemEvent):
152
168
153
169
if os .getenv ("GITHUB_ACTIONS" ):
154
170
line = unicodedata .normalize ("NFKD" , line )
155
- print (line .strip ())
171
+ logger . info (line .strip ())
156
172
157
173
if self ._state == State .BUILDING :
158
174
if "Log file closed" in line :
@@ -162,7 +178,7 @@ def on_modified(self, event: watchdog.events.FileSystemEvent):
162
178
log_end = True
163
179
164
180
if log_end :
165
- print ("setting stop event" )
181
+ logger . info ("setting stop event" )
166
182
if self ._state == State .BUILDING :
167
183
self ._building_event .set ()
168
184
elif self ._state == State .TESTING :
@@ -191,7 +207,7 @@ def resolve_script_path(path: str) -> Path:
191
207
192
208
193
209
def write_cache (file : Path , cache : Cache ):
194
- print ( f "writing cache file: '{ file } '" )
210
+ logger . info ( "writing cache file: '{}'" , file )
195
211
file .write_text (json .dumps (asdict (cache ), indent = 2 ))
196
212
197
213
@@ -202,7 +218,7 @@ def load_cache(path: Path) -> Cache:
202
218
203
219
204
220
def download_file (url : str , out_file : Path , progress_bar : bool = True ):
205
- print ( f "downloading '{ url } '" )
221
+ logger . info ( "downloading: '{}'" , url )
206
222
with out_file .open ("wb" ) as f :
207
223
with httpx .stream (
208
224
"GET" ,
@@ -226,18 +242,18 @@ def download_file(url: str, out_file: Path, progress_bar: bool = True):
226
242
for data in resp .iter_bytes (chunk_size = 4096 ):
227
243
f .write (data )
228
244
229
- print ("download finished" )
245
+ logger . info ("download finished" )
230
246
231
247
232
248
def remove_old_extracted (cache : Cache ):
233
- print ("removing old extracted files, if any" )
249
+ logger . info ("removing old extracted files, if any" )
234
250
235
251
dirs : list [Path ] = []
236
252
237
253
for file in cache .pkg_archive_extracted_files :
238
254
p = Path (file ).resolve ()
239
255
if p .exists () and p .is_file ():
240
- print ( f "removing '{ p } '" )
256
+ logger . info ( "removing '{}'" , p )
241
257
p .unlink (missing_ok = True )
242
258
elif p .is_dir ():
243
259
dirs .append (p )
@@ -247,9 +263,9 @@ def remove_old_extracted(cache: Cache):
247
263
if is_empty :
248
264
shutil .rmtree (d )
249
265
else :
250
- print ( f "not removing non-empty directory: '{ d } '" )
266
+ logger . info ( "not removing non-empty directory: '{}'" , d )
251
267
252
- print ("remove_old_extracted done" )
268
+ logger . info ("remove_old_extracted done" )
253
269
254
270
255
271
def already_extracted (archive_file : str , out_dir : Path , cache : Cache ) -> bool :
@@ -272,12 +288,17 @@ def poke_file(file: Path, event: threading.Event):
272
288
time .sleep (1 )
273
289
274
290
291
+ def move_file (src : Path , dst : Path ):
292
+ logger .info ("{} -> {}" , src , dst )
293
+ shutil .move (src , dst )
294
+
295
+
275
296
async def run_udk_build (
276
297
watcher : LogWatcher ,
277
298
udk_lite_root : Path ,
278
299
building_event : threading .Event ,
279
300
) -> int :
280
- print ("starting UDK build phase" )
301
+ logger . info ("starting UDK build phase" )
281
302
282
303
udk_exe = (udk_lite_root / "Binaries/Win64/UDK.com" ).resolve ()
283
304
@@ -295,7 +316,7 @@ async def run_udk_build(
295
316
],
296
317
)
297
318
298
- print ( f "proc: { proc } " )
319
+ logger . info ( "proc: {}" , proc )
299
320
300
321
ok = building_event .wait (timeout = UDK_TEST_TIMEOUT )
301
322
@@ -306,10 +327,10 @@ async def run_udk_build(
306
327
if not ok :
307
328
raise RuntimeError ("timed out waiting for UDK.exe (building_event) stop event" )
308
329
309
- print ("UDK.exe finished" )
330
+ logger . info ("UDK.exe finished" )
310
331
311
332
ec = await proc .wait ()
312
- print ( f "UDK.exe exited with code: { ec } " )
333
+ logger . info ( "UDK.exe exited with code: {}" , ec )
313
334
314
335
if ec != 0 :
315
336
raise RuntimeError (f"UDK.exe error: { ec } " )
@@ -323,7 +344,7 @@ async def run_udk_server(
323
344
testing_event : threading .Event ,
324
345
udk_args : str ,
325
346
) -> int :
326
- print ("starting UDK testing phase" )
347
+ logger . info ("starting UDK testing phase" )
327
348
328
349
udk_exe_norunaway = (udk_lite_root / "Binaries/Win64/UDK_norunaway.exe" ).resolve ()
329
350
udk_exe = (udk_lite_root / "Binaries/Win64/UDK.exe" ).resolve ()
@@ -334,14 +355,12 @@ async def run_udk_server(
334
355
dst = udk_exe .with_name ("UDK.exe.backup" )
335
356
336
357
if dst .exists ():
337
- print ( f" { dst } exists, assuming runaway loop detection executable already in use" )
358
+ logger . info ( "{ } exists, assuming runaway loop detection executable already in use", dst )
338
359
else :
339
- print ("moving original UDK.exe to backup "
340
- "and replacing it with runaway loop detection patched variant" )
341
- print (f"{ udk_exe } -> { dst } " )
342
- shutil .move (udk_exe , dst )
343
- print (f"{ udk_exe_norunaway } -> { udk_exe } " )
344
- shutil .move (udk_exe_norunaway , udk_exe )
360
+ logger .info ("moving original UDK.exe to backup "
361
+ "and replacing it with runaway loop detection patched variant" )
362
+ move_file (udk_exe , dst )
363
+ move_file (udk_exe_norunaway , udk_exe )
345
364
346
365
watcher .state = State .TESTING
347
366
test_proc = await asyncio .create_subprocess_exec (
@@ -355,7 +374,7 @@ async def run_udk_server(
355
374
],
356
375
)
357
376
358
- print ( f "proc: { test_proc } " )
377
+ logger . info ( "proc: {}" , test_proc )
359
378
360
379
ok = testing_event .wait (timeout = UDK_TEST_TIMEOUT )
361
380
@@ -367,7 +386,7 @@ async def run_udk_server(
367
386
raise RuntimeError ("timed out waiting for UDK.exe (testing_event) stop event" )
368
387
369
388
test_ec = await test_proc .wait ()
370
- print ( f "UDK.exe FCrypto test run exited with code: { test_ec } " )
389
+ logger . info ( "UDK.exe FCrypto test run exited with code: {}" , test_ec )
371
390
372
391
return test_ec
373
392
@@ -377,7 +396,7 @@ def print_udk_processes(event: threading.Event):
377
396
sleep_time = 0.01
378
397
for proc in psutil .process_iter ():
379
398
if "udk" in proc .name ().lower ():
380
- print ( f" \t { '#' * 4 } { proc } " )
399
+ logger . info ( "{} {}" , '#' * 4 , proc )
381
400
sleep_time = 5.0
382
401
383
402
time .sleep (sleep_time )
@@ -391,14 +410,14 @@ async def start_gmp_server(echo_server_path: Path):
391
410
str (echo_server_path )
392
411
)
393
412
394
- print ( f" { FCRYPTO_GMP_SERVER_PROC = } " )
413
+ logger . info ( " FCRYPTO_GMP_SERVER_PROC={}" , FCRYPTO_GMP_SERVER_PROC )
395
414
396
415
397
416
async def stop_gmp_server ():
398
417
if FCRYPTO_GMP_SERVER_PROC :
399
418
FCRYPTO_GMP_SERVER_PROC .terminate ()
400
419
ec = await FCRYPTO_GMP_SERVER_PROC .wait ()
401
- print ( f "FCRYPTO_GMP_SERVER_PROC exited with code: { ec } " )
420
+ logger . info ( "FCRYPTO_GMP_SERVER_PROC exited with code: {}" , ec )
402
421
403
422
404
423
async def main ():
@@ -443,16 +462,17 @@ async def main():
443
462
try :
444
463
cache = load_cache (cache_file )
445
464
except Exception as e :
446
- print (f"error loading cache: { type (e ).__name__ } : { e } " )
447
- print (f"delete the cache file '{ cache_file } ' "
448
- f"or cache directory '{ CACHE_DIR } ' to force a hard reset" )
465
+ logger .error ("error loading cache: {} {}" , type (e ).__name__ , e )
466
+ logger .info ("delete the cache file '{}' "
467
+ "or cache directory '{}' to force a hard reset" ,
468
+ cache_file , CACHE_DIR )
449
469
raise
450
470
else :
451
471
hard_reset = True
452
472
453
473
if hard_reset :
454
- print ("hard reset requested" )
455
- print ( f "removing '{ CACHE_DIR } '" )
474
+ logger . info ("hard reset requested" )
475
+ logger . info ( "removing '{}'" , CACHE_DIR )
456
476
shutil .rmtree (CACHE_DIR , ignore_errors = True )
457
477
CACHE_DIR .mkdir (parents = True , exist_ok = True )
458
478
write_cache (cache_file , cache )
@@ -667,7 +687,7 @@ async def main():
667
687
try :
668
688
asyncio .run (main ())
669
689
except Exception as _e :
670
- print ( f "error running main : { _e } " )
690
+ logger . error ( "error running man : {}" , _e )
671
691
672
692
if BUILDING_EVENT :
673
693
BUILDING_EVENT .set ()
0 commit comments