kongalib 2.0.4__cp314-cp314t-macosx_10_15_universal2.whl

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.

Potentially problematic release.


This version of kongalib might be problematic. Click here for more details.

kongalib/scripting.py ADDED
@@ -0,0 +1,766 @@
1
+ # -*- coding: utf-8 -*-
2
+ # _ _ _ _
3
+ # | | | (_) |
4
+ # | | _____ _ __ __ _ __ _| |_| |__
5
+ # | |/ / _ \| '_ \ / _` |/ _` | | | '_ \
6
+ # | < (_) | | | | (_| | (_| | | | |_) |
7
+ # |_|\_\___/|_| |_|\__, |\__,_|_|_|_.__/
8
+ # __/ |
9
+ # |___/
10
+ #
11
+ # Konga client library, by EasyByte Software
12
+ #
13
+ # https://github.com/easybyte-software/kongalib
14
+
15
+
16
+ from __future__ import print_function
17
+ from __future__ import absolute_import
18
+
19
+ from kongalib import Error
20
+ from _kongalib import get_application_log_path, set_interpreter_timeout, get_interpreter_timeout, get_interpreter_time_left, _set_process_foreground
21
+
22
+ import sys
23
+ import os
24
+ import atexit
25
+ import io
26
+ import threading
27
+ import multiprocessing
28
+ import multiprocessing.connection
29
+ import asyncio
30
+ import signal
31
+ import logging
32
+ import logging.handlers
33
+ import time
34
+
35
+
36
+ DEBUG = False
37
+
38
+ gConnFamily = None
39
+ gConnFamilyOverride = False
40
+
41
+ _DLL_PATHS = []
42
+
43
+
44
+ class BadConnection(Exception):
45
+ def __init__(self):
46
+ self._bad_connection = True
47
+
48
+
49
+ class InterpreterTimeout(Exception):
50
+ pass
51
+
52
+
53
+
54
+ class InterpreterError(Exception):
55
+ def __init__(self, exc_info):
56
+ self._exc_info = exc_info
57
+ def get_exc_info(self):
58
+ return self._exc_info
59
+
60
+
61
+
62
+ def debug_log(text):
63
+ try:
64
+ _logger.debug(text)
65
+ except:
66
+ try:
67
+ sys.__stderr__.write('%s\n' % text)
68
+ except:
69
+ pass
70
+ # sys.__stderr__.write(text + '\n')
71
+
72
+
73
+
74
+ class _TimeoutBlocker(object):
75
+ def __init__(self):
76
+ self.timeout = 0
77
+ self.lock = threading.RLock()
78
+ def __enter__(self):
79
+ try:
80
+ self.timeout = get_interpreter_time_left() or 0
81
+ set_interpreter_timeout(0)
82
+ except:
83
+ self.timeout = 0
84
+ self.lock.acquire()
85
+ def __exit__(self, exc_type, exc_value, exc_traceback):
86
+ self.lock.release()
87
+ if _State.restore_timeout:
88
+ try:
89
+ set_interpreter_timeout(self.timeout)
90
+ except:
91
+ pass
92
+ else:
93
+ _State.restore_timeout = True
94
+
95
+
96
+ class Proxy(object):
97
+ def __init__(self):
98
+ self._conn = None
99
+ self._lock = _TimeoutBlocker()
100
+
101
+ def _initialize(self):
102
+ conn_type = str(sys.argv.pop(1))
103
+ address = str(sys.argv.pop(1))
104
+ if conn_type == 'AF_INET':
105
+ colon = address.rfind(':')
106
+ address = (address[:colon], int(address[colon+1:]))
107
+ debug_log("[Proxy] init: %s" % repr(address))
108
+ try:
109
+ self._conn = multiprocessing.connection.Client(address, conn_type)
110
+ except:
111
+ import traceback
112
+ _logger.error("[Proxy] init error: %s" % traceback.format_exc())
113
+ raise
114
+ debug_log("[Proxy] connection established")
115
+
116
+ def is_valid(self):
117
+ return self._conn is not None
118
+
119
+ def close(self):
120
+ if self._conn is not None:
121
+ sys.stdout.flush()
122
+ sys.stderr.flush()
123
+ self._conn.close()
124
+ self._conn = None
125
+ debug_log("[Proxy] connection closed")
126
+
127
+ def __getattr__(self, name):
128
+ return _MethodHandler(self._conn, self._lock, name)
129
+
130
+
131
+ class _State(object):
132
+ handler = None
133
+ controller = None
134
+ io = []
135
+ restore_timeout = True
136
+
137
+
138
+ proxy = Proxy()
139
+ _logger = logging.getLogger("script")
140
+
141
+
142
+ def timeout_handler():
143
+ if proxy.builtin.handle_timeout():
144
+ raise InterpreterTimeout
145
+ else:
146
+ timeout = _State.controller.timeout
147
+ set_interpreter_timeout(timeout)
148
+
149
+
150
+
151
+ def init_interpreter():
152
+ _State.io.append((sys.stdout, sys.stderr, sys.stdin))
153
+ try:
154
+ proxy._initialize()
155
+ sys.stdout = _ProxyStdOut()
156
+ sys.stderr = _ProxyStdErr()
157
+ # sys.stdout = io.TextIOWrapper(_ProxyStdOut(), 'utf-8', line_buffering=True)
158
+ # sys.stderr = io.TextIOWrapper(_ProxyStdErr(), 'utf-8', line_buffering=True)
159
+ sys.stdin = _ProxyStdIn()
160
+ sys.prefix, sys.exec_prefix = proxy.builtin.get_prefixes()
161
+ sys.is_kongalib_interpreter = True
162
+ except:
163
+ raise BadConnection()
164
+
165
+ import getpass
166
+ getpass.getpass = proxy.builtin.getpass
167
+
168
+ def excepthook(type, value, tb):
169
+ import traceback
170
+ # debug_log('EXCEPTHOOK:\n%s' % '\n'.join(traceback.format_exception(type, value, tb)))
171
+ tb = traceback.extract_tb(tb)
172
+ def do_filter(entry):
173
+ filename = entry[0].replace('\\', '/')
174
+ if filename.endswith('kongalib/scripting.py'):
175
+ return False
176
+ return True
177
+ tb = list(filter(do_filter, tb))
178
+ try:
179
+ proxy.builtin.print_exception(type, value, tb)
180
+ except:
181
+ debug_log('proxy.builtin.print_exception exception:\n%s' % traceback.format_exc())
182
+ sys.excepthook = excepthook
183
+
184
+ def close_proxy():
185
+ try:
186
+ proxy.close()
187
+ except:
188
+ pass
189
+ atexit.register(close_proxy)
190
+
191
+
192
+ def exit_interpreter():
193
+ sys.stdout, sys.stderr, sys.stdin = _State.io.pop()
194
+ # proxy.close()
195
+
196
+
197
+ class _Controller(threading.Thread):
198
+ QUIT_REQUEST = (None, None, None, None, None)
199
+
200
+ def __init__(self, conn, sem):
201
+ self.conn = conn
202
+ self.sem = sem
203
+ self.lock = threading.RLock()
204
+ self.request_cond = threading.Condition(self.lock)
205
+ self.request = None
206
+ self.exc_info = None
207
+ self.timeout = None
208
+ def terminate(signo=None, stack_frame=None):
209
+ self.execute(*_Controller.QUIT_REQUEST)
210
+ signal.signal(signal.SIGTERM, terminate)
211
+ super(_Controller, self).__init__()
212
+
213
+ def get_execute_request(self):
214
+ with self.lock:
215
+ while not self.request_cond.wait(0.5):
216
+ if self.request is not None:
217
+ break
218
+ request = self.request
219
+ self.request = None
220
+ return request
221
+
222
+ def run(self):
223
+ name = None
224
+ while name != 'exit':
225
+ try:
226
+ ready = multiprocessing.connection.wait([ self.conn ], 0.5)
227
+ if not ready:
228
+ if self.request == _Controller.QUIT_REQUEST:
229
+ break
230
+ continue
231
+ data = self.conn.recv()
232
+ handler, name, args, kwargs = data
233
+ msg = repr(args)
234
+ if len(msg) > 80:
235
+ msg = msg[:80] + '[...]'
236
+ except IOError:
237
+ return
238
+ except EOFError:
239
+ return
240
+ except KeyboardInterrupt:
241
+ return
242
+ result = getattr(self, name)(*args, **kwargs)
243
+ try:
244
+ self.conn.send((None, result))
245
+ except IOError:
246
+ return
247
+ except EOFError:
248
+ return
249
+ except KeyboardInterrupt:
250
+ return
251
+ except:
252
+ import traceback
253
+ _logger.debug(traceback.format_exc())
254
+ sys.exit(0)
255
+
256
+ def set_timeout(self, timeout, restore=True):
257
+ _State.restore_timeout = restore
258
+ self.timeout = timeout
259
+ return set_interpreter_timeout(timeout)
260
+
261
+ def get_time_left(self):
262
+ return get_interpreter_time_left() or 0
263
+
264
+ def execute(self, args, path, timeout, script, cwd):
265
+ with self.lock:
266
+ self.request = (args, path, timeout, script, cwd)
267
+ self.request_cond.notify()
268
+
269
+ def set_exc_info(self, exc_info):
270
+ with self.lock:
271
+ self.exc_info = exc_info
272
+
273
+ def get_exc_info(self):
274
+ with self.lock:
275
+ return self.exc_info
276
+
277
+ def exit(self):
278
+ self.sem.release()
279
+
280
+
281
+
282
+ def _trampoline(conn, sem, foreground, env, dll_paths, queue, level):
283
+ logging.getLogger().setLevel(level)
284
+ logger = logging.getLogger('script._trampoline')
285
+ handler = logging.handlers.QueueHandler(queue)
286
+ handler.setLevel(level)
287
+ logger.addHandler(handler)
288
+ logger.debug('entering interpreter process')
289
+ try:
290
+ _set_process_foreground(foreground)
291
+ for path in dll_paths:
292
+ try:
293
+ os.add_dll_directory(path)
294
+ logger.debug('added DLL directory: %s' % path)
295
+ except:
296
+ if sys.platform == 'win32':
297
+ logger.error('error adding DLL directory: %s' % path)
298
+ for key, value in (env or {}).items():
299
+ key = str(key)
300
+ value = str(value)
301
+ os.environ[key] = value
302
+ logger.debug('added env variable %s=%s' % (key, value))
303
+
304
+ _State.controller = _Controller(conn, sem)
305
+ _State.controller.start()
306
+
307
+ while True:
308
+ request = _State.controller.get_execute_request()
309
+ if request == _Controller.QUIT_REQUEST:
310
+ break
311
+ args, path, timeout, script, cwd = request
312
+ sys.argv = args
313
+ sys.path = path
314
+ filename = args[0]
315
+ if cwd:
316
+ os.chdir(cwd)
317
+ init_interpreter()
318
+ try:
319
+ script = compile(script, filename, 'exec', dont_inherit=1)
320
+ exc = None
321
+ _State.controller.set_timeout(timeout)
322
+ exec(script, { '__file__': filename, '__name__': '__main__' })
323
+ except Exception as e:
324
+ import traceback
325
+ exc_type, exc_value, exc_tb = sys.exc_info()
326
+ exc_tb = traceback.extract_tb(exc_tb)
327
+ exc_info = ( exc_type, exc_value, exc_tb )
328
+ else:
329
+ exc_info = None
330
+ _State.controller.set_timeout(0)
331
+ _State.controller.set_exc_info(exc_info)
332
+ exit_interpreter()
333
+ sem.release()
334
+ try:
335
+ conn.close()
336
+ conn = None
337
+ except:
338
+ pass
339
+ _State.controller.join()
340
+ except KeyboardInterrupt:
341
+ logger.debug('user issued a keyboard interrupt')
342
+ except Exception as e:
343
+ import traceback
344
+ logger.critical('unhandled error in interpreter process: %s' % traceback.format_exc())
345
+ finally:
346
+ if conn is not None:
347
+ try:
348
+ conn.close()
349
+ except:
350
+ pass
351
+ logger.debug('exiting interpreter process')
352
+
353
+
354
+ class _ControllerProxy(Proxy):
355
+ class NullLocker(object):
356
+ def __enter__(self):
357
+ pass
358
+ def __exit__(self, exc_type, exc_value, exc_traceback):
359
+ pass
360
+ def __init__(self, conn):
361
+ self._conn = conn
362
+ self._lock = _ControllerProxy.NullLocker()
363
+
364
+
365
+ class Interpreter(object):
366
+ def __init__(self, foreground=True, env=None):
367
+ self.proc = None
368
+ self.exc_info = None
369
+ self.conn = None
370
+ self.lock = threading.RLock()
371
+ self.sem = multiprocessing.Semaphore(0)
372
+ self.queue = multiprocessing.Queue()
373
+ self.proxy = None
374
+ self.foreground = foreground
375
+ self.env = env
376
+ self.logger_listener = logging.handlers.QueueListener(self.queue, *logging.getLogger().handlers, respect_handler_level=True)
377
+
378
+ def __del__(self):
379
+ with self.lock:
380
+ if self.proc is not None:
381
+ if self.proc.is_alive():
382
+ try:
383
+ self.proxy.exit()
384
+ except:
385
+ pass
386
+ try:
387
+ self.logger_listener.stop()
388
+ except:
389
+ pass
390
+
391
+ def ensure_proc(self):
392
+ with self.lock:
393
+ if self.proc is None:
394
+ self.conn, self.client_conn = multiprocessing.Pipe()
395
+ self.proxy = _ControllerProxy(self.conn).controller
396
+ self.logger_listener.start()
397
+ self.proc = multiprocessing.Process(target=_trampoline, args=(self.client_conn, self.sem, self.foreground, self.env, _DLL_PATHS, self.queue, logging.getLogger().level), daemon=True)
398
+ self.proc.start()
399
+ exitcode = self.proc.exitcode
400
+ if exitcode is not None:
401
+ raise RuntimeError('Unable to start interpreter process: exit code %d' % exitcode)
402
+
403
+ def execute(self, script=None, filename=None, argv=None, path=None, timeout=None):
404
+ with self.lock:
405
+ self.ensure_proc()
406
+ self.exc_info = None
407
+ args = argv
408
+ if not args:
409
+ args = [ filename or '<script>' ]
410
+ if (script is None) and filename:
411
+ with open(filename, 'r') as f:
412
+ script = f.read()
413
+ try:
414
+ cwd = os.path.dirname(os.path.abspath(filename))
415
+ except:
416
+ cwd = None
417
+ self.proxy.execute(args, path, timeout, script or '', cwd )
418
+ self.lock.release()
419
+ while not self.sem.acquire(False):
420
+ with self.lock:
421
+ if (self.proc is None) or (not self.proc.is_alive()):
422
+ break
423
+ time.sleep(0.05)
424
+ self.lock.acquire()
425
+ if (self.proc is not None) and self.proc.is_alive():
426
+ self.exc_info = self.proxy.get_exc_info()
427
+ if self.exc_info is not None:
428
+ raise InterpreterError(self.exc_info)
429
+
430
+ def stop(self):
431
+ with self.lock:
432
+ proc = self.proc
433
+ if proc is not None:
434
+ self.proc = None
435
+ self.lock.release()
436
+ try:
437
+ try:
438
+ proc.terminate()
439
+ except:
440
+ pass
441
+ proc.join(3)
442
+ if proc.is_alive():
443
+ try:
444
+ proc.kill()
445
+ except Exception as e:
446
+ debug_log('Interpreter.stop() failed with error: %s' % str(e))
447
+ finally:
448
+ self.lock.acquire()
449
+
450
+ def is_running(self):
451
+ conn = self.conn
452
+ proc = self.proc
453
+ return (conn is None) or ((proc is not None) and proc.is_alive())
454
+
455
+ def set_timeout(self, timeout=None, restore=False):
456
+ with self.lock:
457
+ if self.proxy is not None:
458
+ func = self.proxy.set_timeout
459
+ else:
460
+ func = None
461
+ if func is not None:
462
+ return func(timeout, restore)
463
+
464
+ def get_time_left(self):
465
+ with self.lock:
466
+ return self.proxy.get_time_left()
467
+
468
+ def get_exc_info(self):
469
+ with self.lock:
470
+ return self.exc_info
471
+
472
+
473
+ class _ProxyStdIn(io.StringIO):
474
+ def readline(self, size=-1):
475
+ return proxy.builtin.read_line()
476
+
477
+
478
+ class _ProxyStdOut(io.StringIO):
479
+ def write(self, text):
480
+ proxy.builtin.write_stdout(str(text))
481
+ return len(text)
482
+
483
+ def flush(self):
484
+ try:
485
+ proxy.builtin.flush_stdout()
486
+ except:
487
+ pass
488
+
489
+
490
+ class _ProxyStdErr(io.StringIO):
491
+ def write(self, text):
492
+ sys.__stderr__.write(str(text))
493
+ try:
494
+ proxy.builtin.write_stderr(str(text))
495
+ except:
496
+ pass
497
+ return len(text)
498
+
499
+ def flush(self):
500
+ try:
501
+ proxy.builtin.flush_stderr()
502
+ except:
503
+ pass
504
+
505
+
506
+
507
+ class _MethodHandler(object):
508
+ def __init__(self, conn, lock, name):
509
+ self._conn = conn
510
+ self._lock = lock
511
+ self._name = name
512
+
513
+ def __getattr__(self, name):
514
+ return _Method(self, name)
515
+
516
+
517
+
518
+ class _Method(object):
519
+ def __init__(self, handler, name):
520
+ self.handler = handler
521
+ self.name = name
522
+
523
+ def __call__(self, *args, **kwargs):
524
+ with self.handler._lock:
525
+ if DEBUG:
526
+ s = time.time()
527
+ debug_log('[Proxy] call: %s' % str((self.handler._name, self.name, args, kwargs)))
528
+ self.handler._conn.send((self.handler._name, self.name, args, kwargs))
529
+ if DEBUG:
530
+ debug_log('[Proxy] call sent in %f secs. Waiting reply: %s' % (time.time() - s, str((self.handler._name, self.name))))
531
+
532
+ multiprocessing.connection.wait([ self.handler._conn ])
533
+ e, result = self.handler._conn.recv()
534
+ if DEBUG:
535
+ s = time.time()
536
+ debug_log('[Proxy] got reply in %f secs: %s' % (time.time() - s, str((self.handler._name, self.name, result))))
537
+ if e is None:
538
+ return result
539
+ errmsg, errno = e
540
+ if errno is None:
541
+ raise RuntimeError(errmsg)
542
+ else:
543
+ raise Error(errno, errmsg)
544
+
545
+
546
+ class _ServerProxy(threading.Thread):
547
+ def __init__(self, handlers=None):
548
+ self.handlers = handlers or {}
549
+ self.listener = None
550
+ self.conn = None
551
+ super(_ServerProxy, self).__init__()
552
+
553
+ def start(self):
554
+ if gConnFamilyOverride:
555
+ family = None
556
+ else:
557
+ family = gConnFamily
558
+ try:
559
+ self.listener = multiprocessing.connection.Listener(family=family)
560
+ except:
561
+ raise BadConnection()
562
+ super(_ServerProxy, self).start()
563
+
564
+ def stop(self):
565
+ if self.listener is not None:
566
+ self.listener.close()
567
+ self.listener = None
568
+ if self.conn is not None:
569
+ self.conn.close()
570
+ self.handlers = {}
571
+ if self.is_alive():
572
+ self.join()
573
+
574
+ def run(self):
575
+ debug_log("[ServerProxy] run")
576
+ try:
577
+ self.conn = self.listener.accept()
578
+ debug_log("[ServerProxy] got proxy")
579
+ while True:
580
+ ready = multiprocessing.connection.wait([ self.conn ], 0.5)
581
+ if ready:
582
+ data = self.conn.recv()
583
+ handler, name, args, kwargs = data
584
+ if handler in self.handlers:
585
+ # debug_log("[kongaprint:%s] %s(%s)" % (handler, name, ', '.join([ repr(arg) for arg in args ] + [ '%s=%s' % (key, repr(value)) for key, value in kwargs.iteritems() ])))
586
+ func = getattr(self.handlers[handler], name, None)
587
+ else:
588
+ func = None
589
+ try:
590
+ if func is None:
591
+ raise RuntimeError('Method "%s" unavailable in this context' % name)
592
+ result = func(*args, **kwargs)
593
+ if asyncio.iscoroutine(result):
594
+ try:
595
+ loop = asyncio.get_running_loop()
596
+ except:
597
+ loop = asyncio.get_event_loop_policy().get_event_loop()
598
+ result = asyncio.run_coroutine_threadsafe(result, loop).result()
599
+ result = (None, result)
600
+ except Exception as e:
601
+ import traceback
602
+ _logger.error("[ServerProxy] method error: %s" % traceback.format_exc())
603
+ # sys.__stderr__.write('SCRIPTING EXCEPTION:\n%s\n' % traceback.format_exc())
604
+ if isinstance(e, Error):
605
+ errno = e.errno
606
+ else:
607
+ errno = None
608
+ result = ((str(e), errno), None)
609
+ finally:
610
+ self.conn.send(result)
611
+ except IOError:
612
+ if self.listener is not None:
613
+ import traceback
614
+ debug_log("[ServerProxy] IOError: %s" % traceback.format_exc())
615
+ except EOFError:
616
+ pass
617
+ finally:
618
+ debug_log("[ServerProxy] exiting")
619
+
620
+
621
+ class BuiltinHandler(object):
622
+ def __init__(self):
623
+ self.__interpreter = None
624
+ self.__exit_funcs = []
625
+
626
+ def _set_interpreter(self, interpreter):
627
+ self.__interpreter = interpreter
628
+
629
+ def _get_interpreter(self):
630
+ return self.__interpreter
631
+
632
+ def write_stdout(self, text):
633
+ sys.__stdout__.write(text)
634
+
635
+ def write_stderr(self, text):
636
+ sys.__stderr__.write(text)
637
+
638
+ def flush_stdout(self):
639
+ pass
640
+
641
+ def flush_stderr(self):
642
+ pass
643
+
644
+ def read_line(self):
645
+ sys.__stdin__.readline()
646
+
647
+ def getpass(self, prompt='Password: ', stream=None):
648
+ import getpass
649
+ return getpass.getpass(prompt, stream)
650
+
651
+ def get_prefixes(self):
652
+ return os.getcwd(), os.getcwd()
653
+
654
+ def format_exception(self, type, value, tb):
655
+ import traceback
656
+ if not all([ isinstance(x, str) for x in tb ]):
657
+ tb = traceback.format_list(tb)
658
+ text = [ 'Traceback (most recent call last):\n' ] + tb + traceback.format_exception_only(type, value)
659
+ return ''.join(text)
660
+
661
+ def print_exception(self, type, value, tb):
662
+ print(self.format_exception(type, value, tb))
663
+
664
+ def get_time_left(self):
665
+ if self.__interpreter is not None:
666
+ return self.__interpreter.get_time_left()
667
+ return 0
668
+
669
+ def set_timeout(self, timeout=0, restore=False):
670
+ if self.__interpreter is not None:
671
+ return self.__interpreter.set_timeout(timeout, restore)
672
+
673
+ def handle_timeout(self):
674
+ raise InterpreterTimeout
675
+
676
+ def noop(self):
677
+ pass
678
+
679
+ def atexit(self, func, *args, **kwargs):
680
+ self.__exit_funcs.append((func, args, kwargs))
681
+
682
+ def _atexit(self):
683
+ while self.__exit_funcs:
684
+ func, args, kwargs = self.__exit_funcs.pop()
685
+ func(*args, **kwargs)
686
+
687
+
688
+ def set_connection_family(family):
689
+ global gConnFamily
690
+ gConnFamily = family
691
+
692
+
693
+ def add_dll_directory(path):
694
+ if path not in _DLL_PATHS:
695
+ _DLL_PATHS.append(path)
696
+
697
+
698
+ def execute(script=None, filename=None, argv=None, path=None, timeout=0, handlers=None, interpreter=None):
699
+ import traceback
700
+ if (script is None) and (filename is None):
701
+ raise ValueError('Either script or filename must be specified')
702
+ debug_log("[ServerProxy] launching...")
703
+ if filename is None:
704
+ filename = '<script>'
705
+ if argv is None:
706
+ argv = [ filename ]
707
+ if interpreter is None:
708
+ interpreter = Interpreter()
709
+ debug_log("[ServerProxy] instantiating ServerProxy")
710
+ _handlers = { 'builtin': BuiltinHandler() }
711
+ _handlers.update(handlers or {})
712
+ _handlers['builtin']._set_interpreter(interpreter)
713
+ while True:
714
+ p = _ServerProxy(_handlers)
715
+ try:
716
+ p.start()
717
+ debug_log("[ServerProxy] listener address is: %s" % repr(p.listener.address))
718
+ conn_type = multiprocessing.connection.address_type(p.listener.address)
719
+ if conn_type == 'AF_INET':
720
+ address = '%s:%d' % tuple(p.listener.address)
721
+ else:
722
+ address = p.listener.address
723
+ argv.insert(1, conn_type)
724
+ argv.insert(2, address)
725
+ debug_log("[ServerProxy] waiting proxy: %s" % repr(argv))
726
+
727
+ # import time
728
+ # start = time.time()
729
+ interpreter.execute(script, filename, argv, path or [], timeout)
730
+ # print("Script execution time:", time.time() - start)
731
+ except Exception as e:
732
+ if getattr(e, '_bad_connection', False) and (gConnFamily is not None):
733
+ debug_log("[ServerProxy] bad connection, trying default connection family")
734
+ global gConnFamilyOverride
735
+ gConnFamilyOverride = True
736
+ set_connection_family(None)
737
+ argv[1:3] = []
738
+ continue
739
+ if isinstance(e, InterpreterError):
740
+ type, value, tb = e.get_exc_info()
741
+ else:
742
+ debug_log("[ServerProxy] unhandled execute exception: %s" % traceback.format_exc())
743
+ type, value, tb = sys.exc_info()
744
+ tb = traceback.format_tb(tb)
745
+ def do_filter(entry):
746
+ filename = entry[0].replace('\\', '/')
747
+ if filename.endswith('kongalib/scripting.py') or filename.endswith('__script_host__.py'):
748
+ return False
749
+ return True
750
+ tb = list(filter(do_filter, tb))
751
+ try:
752
+ _handlers['builtin'].print_exception(type, value, tb)
753
+ except:
754
+ debug_log('proxy.builtin.print_exception exception:\n%s' % traceback.format_exc())
755
+ finally:
756
+ _handlers['builtin']._set_interpreter(None)
757
+ interpreter = None
758
+ _handlers['builtin']._atexit()
759
+ try:
760
+ debug_log("[ServerProxy] done")
761
+ finally:
762
+ p.stop()
763
+ break
764
+
765
+
766
+