Browse Source

Moved client execution/processing code into own module; minor cleanup

pull/150/head
chriskiehl 9 years ago
parent
commit
7e2dba496e
1 changed files with 80 additions and 0 deletions
  1. 80
      gooey/gui/processor.py

80
gooey/gui/processor.py

@ -0,0 +1,80 @@
import os
import re
import subprocess
from functools import partial
from multiprocessing.dummy import Pool
from gooey.gui.pubsub import pub
from gooey.gui.util.casting import safe_float
from gooey.gui.util.functional import unit, bind
class ProcessController(object):
def __init__(self, progress_regex, progress_expr):
self._process = None
self.progress_regex = progress_regex
self.progress_expr = progress_expr
def was_success(self):
self._process.communicate()
return self._process.returncode == 0
def poll(self):
if not self._process:
raise Exception('Not started!')
self._process.poll()
def run(self, command):
env = os.environ.copy()
env["GOOEY"] = "1"
self._process = subprocess.Popen(command, bufsize=1, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, shell=True, env=env)
Pool(1).apply_async(self._forward_stdout, (self._process,))
def _forward_stdout(self, process):
'''
Reads the stdout of `process` and forwards lines and progress
to any interested subscribers
'''
while True:
line = process.stdout.readline()
if not line:
break
pub.send_message('console_update', msg=line)
pub.send_message('progress_update', progress=self._extract_progress(line))
pub.send_message('execution_complete')
def _extract_progress(self, text):
'''
Finds progress information in the text using the
user-supplied regex and calculation instructions
'''
# monad-ish dispatch to avoid the if/else soup
find = partial(re.search, string=text.strip())
regex = unit(self.progress_regex)
match = bind(regex, find)
result = bind(match, self._calculate_progress)
return result
def _calculate_progress(self, match):
'''
Calculates the final progress value found by the regex
'''
if not self.progress_expr:
return safe_float(match.group(1))
else:
return self._eval_progress(match)
def _eval_progress(self, match):
'''
Runs the user-supplied progress calculation rule
'''
_locals = {k: safe_float(v) for k, v in match.groupdict().items()}
if "x" not in _locals:
_locals["x"] = [safe_float(x) for x in match.groups()]
try:
return int(eval(self.progress_expr, {}, _locals))
except:
return None
Loading…
Cancel
Save