wxPopen.py
author etisserant
Mon, 10 Dec 2007 17:05:36 +0100
changeset 79 ae06c2da83f7
parent 70 2767bc85aa9a
child 89 0ab2868c6aa6
permissions -rw-r--r--
Some window related enhancements
79
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     1
#!/usr/bin/env python
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     2
# -*- coding: utf-8 -*-
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     3
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     4
#This file is part of Beremiz, a Integrated Development Environment for
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     5
#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     6
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     7
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     8
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
     9
#See COPYING file for copyrights details.
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    10
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    11
#This library is free software; you can redistribute it and/or
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    12
#modify it under the terms of the GNU General Public
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    13
#License as published by the Free Software Foundation; either
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    14
#version 2.1 of the License, or (at your option) any later version.
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    15
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    16
#This library is distributed in the hope that it will be useful,
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    17
#but WITHOUT ANY WARRANTY; without even the implied warranty of
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    18
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    19
#General Public License for more details.
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    20
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    21
#You should have received a copy of the GNU General Public
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    22
#License along with this library; if not, write to the Free Software
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    23
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    24
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    25
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    26
# based on wxPopen.py from boa-constructor
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    27
#
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    28
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    29
import time
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    30
from StringIO import StringIO
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    31
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    32
import wx
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    33
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    34
class ProcessRunnerMix:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    35
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    36
    if wx.VERSION < (2, 6, 0):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    37
        def Bind(self, event, function, id = None):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    38
            if id is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    39
                event(self, id, function)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    40
            else:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    41
                event(self, function)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    42
    
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    43
    def __init__(self, input, handler=None):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    44
        if handler is None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    45
            handler = self
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    46
        self.handler = handler    
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    47
        handler.Bind(wx.EVT_MENU, self.OnIdle)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    48
        handler.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded, id=-1)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    49
        
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    50
        input.reverse() # so we can pop
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    51
        self.input = input
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    52
        
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    53
        self.reset()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    54
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    55
    def reset(self):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    56
        self.process = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    57
        self.pid = -1
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    58
        self.output = []
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    59
        self.errors = []
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    60
        self.inputStream = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    61
        self.errorStream = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    62
        self.outputStream = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    63
        self.outputFunc = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    64
        self.errorsFunc = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    65
        self.finishedFunc = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    66
        self.finished = False
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    67
        self.responded = False
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    68
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    69
    def execute(self, cmd):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    70
        self.process = wx.Process(self.handler)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    71
        self.process.Redirect()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    72
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    73
        self.pid = wx.Execute(cmd, wx.EXEC_ASYNC, self.process)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    74
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    75
        self.inputStream = self.process.GetOutputStream()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    76
        self.errorStream = self.process.GetErrorStream()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    77
        self.outputStream = self.process.GetInputStream()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    78
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    79
        #self.OnIdle()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    80
        wx.WakeUpIdle()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    81
    
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    82
    def setCallbacks(self, output, errors, finished):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    83
        self.outputFunc = output
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    84
        self.errorsFunc = errors
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    85
        self.finishedFunc = finished
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    86
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    87
    def detach(self):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    88
        if self.process is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    89
            self.process.CloseOutput()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    90
            self.process.Detach()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    91
            self.process = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    92
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    93
    def kill(self):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    94
        if self.process is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    95
            self.process.CloseOutput()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    96
            if wx.Process_Kill(self.pid, wx.SIGTERM) != wx.KILL_OK:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    97
                wx.Process_Kill(self.pid, wx.SIGKILL)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    98
            self.process = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
    99
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   100
    def updateStream(self, stream, data):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   101
        if stream and stream.CanRead():
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   102
            if not self.responded:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   103
                self.responded = True
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   104
            text = stream.read()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   105
            data.append(text)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   106
            return text
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   107
        else:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   108
            return None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   109
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   110
    def updateInpStream(self, stream, input):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   111
        if stream and input:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   112
            line = input.pop()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   113
            stream.write(line)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   114
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   115
    def updateErrStream(self, stream, data):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   116
        return self.updateStream(stream, data)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   117
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   118
    def updateOutStream(self, stream, data):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   119
        return self.updateStream(stream, data)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   120
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   121
    def OnIdle(self, event=None):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   122
        if self.process is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   123
            self.updateInpStream(self.inputStream, self.input)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   124
            e = self.updateErrStream(self.errorStream, self.errors)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   125
            if e is not None and self.errorsFunc is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   126
                wx.CallAfter(self.errorsFunc, e)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   127
            o = self.updateOutStream(self.outputStream, self.output)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   128
            if o is not None and self.outputFunc is not None:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   129
                wx.CallAfter(self.outputFunc, o)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   130
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   131
            #wx.WakeUpIdle()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   132
            #time.sleep(0.001)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   133
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   134
    def OnProcessEnded(self, event):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   135
        self.OnIdle()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   136
        pid,exitcode = event.GetPid(), event.GetExitCode()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   137
        if self.process:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   138
            self.process.Destroy()
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   139
            self.process = None
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   140
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   141
        self.finished = True
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   142
        
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   143
        # XXX doesn't work ???
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   144
        #self.handler.Disconnect(-1, wx.EVT_IDLE)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   145
        
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   146
        if self.finishedFunc:
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   147
            wx.CallAfter(self.finishedFunc, pid, exitcode)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   148
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   149
class ProcessRunner(wx.EvtHandler, ProcessRunnerMix):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   150
    def __init__(self, input):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   151
        wx.EvtHandler.__init__(self)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   152
        ProcessRunnerMix.__init__(self, input)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   153
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   154
def wxPopen3(cmd, input, output, errors, finish, handler=None):
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   155
    p = ProcessRunnerMix(input, handler)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   156
    p.setCallbacks(output, errors, finish)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   157
    p.execute(cmd)
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   158
    return p
ae06c2da83f7 Some window related enhancements
etisserant
parents: 70
diff changeset
   159
    
48
6b30cfee163e Enhanced and really multi-platform process logging. Use wxProcess and wxExecute instead of python popen3 (unix only).
etisserant
parents:
diff changeset
   160