From 97fcdafd617cc51a642f8ca2f239b25e9823d423 Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Tue, 12 Apr 2016 12:00:58 -0700
Subject: [PATCH] Getting pykat piping sorted. Changing version to v1.0.0,
 which should be used with Finesse v2.1 or more. Removed printerr and printout
 from the kat.run() command. The stderr and stdout can now be found in the
 output object, out.stdout and out.stderr.

---
 pykat/__init__.py |   2 +-
 pykat/finesse.py  | 161 +++++++++++++++++++---------------------------
 setup.py          |   2 +-
 3 files changed, 69 insertions(+), 96 deletions(-)

diff --git a/pykat/__init__.py b/pykat/__init__.py
index 7a8eb2a..bbcc325 100644
--- a/pykat/__init__.py
+++ b/pykat/__init__.py
@@ -3,7 +3,7 @@ from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
 
-__version__ = "0.8.10"
+__version__ = "1.0.0"
 
 # This flag is used to switch on the gui features in pkat at import time
 USE_GUI = False
diff --git a/pykat/finesse.py b/pykat/finesse.py
index fd4bf9f..f0cd571 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -28,6 +28,7 @@ from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
 
+import uuid
 import sys
 import os
 import subprocess
@@ -47,6 +48,8 @@ import collections
 import re
 import copy
 
+from subprocess import Popen, PIPE
+
 try:
     # Python 2
     from itertools import izip_longest
@@ -73,6 +76,7 @@ from pykat.components import Component
 from pykat.commands import Command, xaxis
 from pykat.SIfloat import *
 from pykat.param import Param, AttrParam
+from pykat.external import progressbar
 
 import pykat.external.six as six
 
@@ -206,7 +210,7 @@ class KatBatch(object):
         if "cmd_args" in kwargs:
             kw["cmd_args"] = kwargs["cmd_args"]
         
-        return kat.run(printerr=1, **kw)
+        return kat.run(**kw)
     
     def addKat(self, kat, **kwargs):
         import os
@@ -492,6 +496,8 @@ class katRun2D(object):
         self.zlabels = None
         self.katScript = None
         self.katVersion = None
+        self.stderr = None
+        self.stdout = None
         
     def saveKatRun(self, filename):
         with open(filename,'w') as outfile:
@@ -1326,13 +1332,11 @@ class kat(object):
         except pkex.BasePyKatException as ex:
             print (ex)
 
-    def run(self, printout=0, printerr=0, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None, getTraceData=False, rethrowExceptions=False):
+    def run(self, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None, getTraceData=False, rethrowExceptions=False):
         """ 
         Runs the current simulation setup that has been built thus far.
         It returns a katRun or katRun2D object which is populated with the various
         data from the simulation run.
-        printout=1 prints the Finesse banner
-        printerr shows the Finesse progress (set kat.verbose=1 to see warnings and errors)
         plot (string) - Sets gnuterm for plotting
         save_output (bool) - if true does not delete out file
         save_kat (bool) - if true does not delete kat file
@@ -1404,13 +1408,12 @@ class kat(object):
                 katfile = open( filepath, 'w' ) 
                 
             katfile.writelines(r.katScript)
-            #katfile.writelines(bytes(r.katScript, 'UTF-8'))
+            
             katfile.flush()
 
-            if printout == 1 or plot != None:
-                cmd=[kat_exec]
-            else:
-                cmd=[kat_exec, '--perl1']
+            pipe_name = katfile.name + str(uuid.uuid4())
+            
+            cmd=[kat_exec, "--pykat=" + pipe_name]
             
             if self.__time_code:
                 cmd.append('--perf-timing')
@@ -1427,85 +1430,68 @@ class kat(object):
             cmd.append('-format=%.15g')
 
             cmd.append(katfile.name)
-                            
-            p=subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-            err = ""
             
-            #if self.verbose: print "Finesse output:"            
-            for aline in iter(p.stderr.readline, b""):
-                if six.PY2:
-                    line = unicode(aline, "utf-8")
-                else:
-                    line = aline
-                    
-                if len(line) > 0:
-                    # remove any ANSI commands
-                    line = re.sub(br'\x1b[^m]*m',b'', line, re.UNICODE)
-
-                    # warnings and errors start with an asterisk 
-                    # so if verbose show them
-                    if line.lstrip().startswith(b'*PROG*'):
-                        line = line[8:-1]
-                        vals = line.split(b"-",1)
-                        action = vals[0].strip()
-                        prc = vals[1].strip()[:]
+            if sys.platform == "win32" or sys.platform == "cygwin":
+            	# Pipes in windows need to be prefixed with a hidden location.
+            	pipe_name = "\\\\.\\pipe\\" + pipe_name
+
+            p = Popen(cmd, stderr=PIPE, stdout=PIPE)
+
+            if self.verbose:
+                pb = progressbar.ProgressBar()
+
+            fifo = None
+
+            start = time.time()
+            duration = 5 # Duration for searching for open pipe
+
+            try:
+                while fifo is None:
+                    try:
+                    	if time.time() < start + duration:
+                    		time.sleep(0.1)
+                    		fifo = open(pipe_name, "r")
+                    	else:
+                    		raise Exception("Could not connect to pykat pipe in {0} seconds.".format(duration))
+                    except FileNotFoundError as ex:
+                    	if self.verbose:
+                            print("Looking for pipe...")
+
+                for line in fifo:
+                    v = line.split(":", 1)
                     
-                        if printerr == 1:
-                            if six.PY2:
-                                sys.stdout.write("\r{0} {1}".format(action, prc))
-                            else:
-                                sys.stdout.write("\r{0} {1}".format(str(action, 'utf-8'), str(prc, 'utf-8')))
-                                
-                    elif line.lstrip().startswith(b'*'):
-                        if self.verbose:
-                            if six.PY2:
-                                sys.stdout.write(line)        
-                            else:
-                                sys.stdout.write(str(line,'utf-8')) 
-                                
-                    elif line.rstrip().endswith(b'%'):
-                        vals = line.split(b'-')
-                        action = vals[0].strip()
-                        prc = vals[1].strip()[:]
+                    if len(v) != 2:
+                        continue    
                         
-                        if printerr == 1:
-                            if six.PY2:
-                                sys.stdout.write("\r{0} {1}".format(action, prc))
-                            else:
-                                sys.stdout.write("\r{0} {1}".format(str(action, 'utf-8'), str(prc, 'utf-8')))
-                            
-                    else:
-                        if six.PY2:
-                            err="".join((err,line))
-                        else:
-                            err="".join((err,str(line, 'utf-8')))
-
-            
-            [out, errpipe] = p.communicate()
+                    (tag, line) = v
+                    
+                    if tag == "version":
+                        r.katVersion = line
+                    elif tag == "progress":
+                        var = line.split("\t")
+
+                        if len(var) == 3 and self.verbose:
+                        	pb.currval = int(var[1])
+                        	pb.update()
+            finally:
+            	if fifo is not None:
+            		fifo.close()
+			
+            (stdout, stderr) = p.communicate()
+
+            r.stdout = stdout.decode('unicode_escape')
+            r.stderr = stderr.decode('unicode_escape')
 
-            if six.PY2:
-                _out = str(out).split("\n")
-            else:
-                _out = str(out).split("\\n")
+            if p.returncode != 0:
+                print(r.stderr)
             
-            for line in _out[::-1]:
+            for line in r.stdout[::-1]:
                 if line.lstrip().startswith('computation time:'):
                     try:
                         r.runtime = float(line.split(":")[1].replace("s",""))
                     except:
                         r.runtime = 0.0
             
-            if printout == 1: 
-                print (out)
-            else:
-                if printerr == 1: print ("")
-
-            # get the version number
-            ix = out.find(b'build ') + 6
-            ix2 = out.find(b')',ix)
-            
-            r.katVersion = out[ix:ix2]
-            
             r.runDateTime = datetime.datetime.now()
 
             # If Finesse returned an error, just print that and exit!
@@ -1614,20 +1600,6 @@ class kat(object):
                 
                 if self.verbose: print ("Kat file saved to '{0}'".format(newkatfile))
                 
-            if self.trace != None and self.trace > 0:
-                #print ("{0}".format(out))
-                #if self.trace & 1:
-                    #search = out.find(' --- highest order of TEM modes')
-                    #if search > -1:
-                        #print ("Trace 1: {0}".format(out[search:]))
-
-                # For now, just try to print the trace block in full.
-                # Converting to unicode so it works in python 3.
-                tmpOut = out.decode('unicode_escape')
-                print (tmpOut[tmpOut.find(' ---') :])
-                # print (out[out.find(' ---') :])
-                
-
             katfile.close()
             perfData = []
 
@@ -1667,8 +1639,9 @@ class kat(object):
             else:
                 pkex.PrintError("Error from pykat:", ex)
         finally:
-            if self.verbose: print ("")
-            if self.verbose: print ("Finished in " + str(datetime.datetime.now()-start))
+            if self.verbose:
+                print ("")
+                print ("Finished in " + str(time.time() + start))
             
     def remove(self, obj):
         try:
@@ -1758,7 +1731,7 @@ class kat(object):
         self.printmatrix = True
         print ("".join(self.generateKatScript()))
         self.verbose = True
-        self.run(printout=1)
+        self.run()
         self.printmatrix = None
         self.noxaxis = prev        
         
diff --git a/setup.py b/setup.py
index 3b048ce..deda7ff 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ setup(
     version=version,
     author='Daniel Brown',
     author_email='ddb@star.sr.bham.ac.uk',
-    packages=['pykat','pykat.testing','pykat.testing.web','pykat.maths','pykat.optics', 'pykat.external', 'pykat.tools'],
+    packages=[x[0].replace("/",".") for x in os.walk("pykat") if "__" not in x[0]],
     url='http://pypi.python.org/pypi/PyKat/',
     license='GPL v2',
     description='Python interface and tools for FINESSE',
-- 
GitLab