py-kms Gui: matched all terminal options so far done; added modes onlyserver / only client

Introduced option for asynchronous messages
Slimmed down parsing process with improved errors catching
This commit is contained in:
Matteo ℱan 2020-05-04 23:51:46 +02:00
parent b4b57af092
commit 00793064bc
No known key found for this signature in database
GPG key ID: 3C30A05BC133D9B6
8 changed files with 825 additions and 327 deletions

View file

@ -5,6 +5,7 @@ import re
import sys
import os
from collections import OrderedDict
import logging
try:
# Python 2.x imports
@ -16,6 +17,7 @@ except ImportError:
import queue as Queue
pyver = sys.version_info[:2]
#----------------------------------------------------------------------------------------------------------------------------------------------------------
def enco(strg, typ = 'latin-1'):
@ -195,13 +197,15 @@ if pyver < (3, 3):
file = kwargs.get('file', sys.stdout)
file.flush() if file is not None else sys.stdout.flush()
# based on: https://ryanjoneil.github.io/posts/2014-02-14-capturing-stdout-in-a-python-child-process.html,
# but not using threading/multiprocessing so:
# 1) message visualization order preserved.
# 2) newlines_count function output not wrong.
# based on: https://ryanjoneil.github.io/posts/2014-02-14-capturing-stdout-in-a-python-child-process.html
queue_print = Queue.Queue()
class ShellMessage(object):
view = True
count, remain, numlist = (0, 0, [])
viewsrv, viewclt = (True for _ in range(2))
asyncmsgsrv, asyncmsgclt = (False for _ in range(2))
indx, count, remain, numlist = (0, 0, 0, [])
loggersrv_pty = logging.getLogger('logsrvpty')
loggerclt_pty = logging.getLogger('logcltpty')
class Collect(StringIO):
# Capture string sent to stdout.
@ -215,8 +219,9 @@ class ShellMessage(object):
self.put_text = put_text
self.where = where
self.plaintext = []
self.path = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_newlines.txt'
self.print_queue = Queue.Queue()
self.path_nl = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_newlines.txt'
self.path_clean_nl = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_clean_newlines.txt'
self.queue_get = Queue.Queue()
def formatter(self, msgtofrmt):
if self.newlines:
@ -236,14 +241,14 @@ class ShellMessage(object):
def newlines_file(self, mode, *args):
try:
with open(self.path, mode) as file:
with open(self.path_nl, mode) as file:
if mode in ['w', 'a']:
file.write(args[0])
elif mode == 'r':
data = [int(i) for i in [line.rstrip('\n') for line in file.readlines()]]
self.newlines, ShellMessage.remain = data[0], sum(data[1:])
except:
with open(self.path, 'w') as file:
with open(self.path_nl, 'w') as file:
pass
def newlines_count(self, num):
@ -265,40 +270,114 @@ class ShellMessage(object):
self.continuecount = True
elif num in [-2 ,-4]:
self.newlines_file('r')
if num == 21:
ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, [])
os.remove(self.path)
def run(self):
# view = False part.
if not ShellMessage.view:
if self.get_text:
self.newlines = 0
if self.put_text is not None:
for msg in self.put_text:
self.formatter(msg)
else:
for num in self.nshell:
self.formatter(MsgMap[num])
return self.plaintext
self.newlines_clean(num)
def newlines_clean(self, num):
if num == 0:
with open(self.path_clean_nl, 'w') as file:
file.write('clean newlines')
try:
with open(self.path_clean_nl, 'r') as file:
some = file.read()
if num == 21:
ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, [])
os.remove(self.path_nl)
os.remove(self.path_clean_nl)
except:
if num == 19:
ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, [])
os.remove(self.path_nl)
def putter(self, aqueue, toput):
try:
aqueue.put_nowait(toput)
except Queue.Full:
pass
def execute(self):
self.manage()
ShellMessage.indx += 1
def print_logging_setup(self, logger, async_flag, formatter = logging.Formatter('%(name)s %(message)s')):
from pykms_GuiBase import gui_redirector
stream = gui_redirector(StringIO())
handler = logging.StreamHandler(stream)
handler.name = 'LogStream'
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
if logger.handlers:
logger.handlers = []
if async_flag:
from pykms_Misc import MultiProcessingLogHandler
logger.addHandler(MultiProcessingLogHandler('Thread-AsyncMsg{0}'.format(handler.name), handler = handler))
else:
logger.addHandler(handler)
logger.setLevel(logging.INFO)
def print_logging(self, toprint):
if (self.nshell and ((0 in self.nshell) or (2 in self.nshell and not ShellMessage.viewclt))) or ShellMessage.indx == 0:
from pykms_GuiBase import gui_redirector_setup, gui_redirector_clear
gui_redirector_setup()
gui_redirector_clear()
self.print_logging_setup(ShellMessage.loggersrv_pty, ShellMessage.asyncmsgsrv)
self.print_logging_setup(ShellMessage.loggerclt_pty, ShellMessage.asyncmsgclt)
if self.where == 'srv':
ShellMessage.loggersrv_pty.info(toprint)
elif self.where == 'clt':
ShellMessage.loggerclt_pty.info(toprint)
def notview(self):
if self.get_text:
self.newlines = 0
if self.put_text is not None:
for msg in self.put_text:
self.formatter(msg)
else:
for num in self.nshell:
self.formatter(MsgMap[num])
self.putter(self.queue_get, self.plaintext)
def manage(self):
if not ShellMessage.viewsrv:
# viewsrv = False, viewclt = True.
if ShellMessage.viewclt:
if self.where == 'srv':
self.notview()
return
else:
# viewsrv = False, viewclt = False.
self.notview()
return
else:
# viewsrv = True, viewclt = False.
if not ShellMessage.viewclt:
if self.where == 'clt':
self.notview()
return
else:
# viewsrv = True, viewclt = True.
pass
# Do job.
self.produce()
toprint = self.consume(timeout = 0.1)
# Redirect output.
toprint = self.consume(queue_print, timeout = 0.1)
if sys.stdout.isatty():
print(toprint)
print(toprint, flush = True)
else:
try:
# Import after variables creation.
from pykms_GuiBase import gui_redirect
gui_redirect(toprint, self.where)
self.print_logging(toprint)
except:
print(toprint)
print(toprint, flush = True)
# Get string/s printed.
if self.get_text:
return self.plaintext
self.putter(self.queue_get, self.plaintext)
return
def produce(self):
# Save everything that would otherwise go to stdout.
@ -327,15 +406,12 @@ class ShellMessage(object):
finally:
# Restore stdout and send content.
sys.stdout = sys.__stdout__
try:
self.print_queue.put(outstream.getvalue())
except Queue.Full:
pass
self.putter(queue_print, outstream.getvalue())
def consume(self, timeout = None):
def consume(self, aqueue, timeout = None):
try:
toprint = self.print_queue.get(block = timeout is not None, timeout = timeout)
self.print_queue.task_done()
toprint = aqueue.get(block = timeout is not None, timeout = timeout)
aqueue.task_done()
return toprint
except Queue.Empty:
return None
@ -381,11 +457,13 @@ def pretty_printer(**kwargs):
options['get_text'] = False
# Process messages.
plain_messages = ShellMessage.Process(options['num_text'],
get_text = options['get_text'],
put_text = options['put_text'],
where = options['where']).run()
shmsg = ShellMessage.Process(options['num_text'],
get_text = options['get_text'],
put_text = options['put_text'],
where = options['where'])
shmsg.execute()
plain_messages = shmsg.consume(shmsg.queue_get, timeout = None)
if options['log_obj']:
for plain_message in plain_messages:
options['log_obj'](plain_message)