Locked History Actions

CustomPublisher

Create a Custom Publisher

There are a number of methods available to override from the Parent class, this shows the minimum needed to implement a file writer. Many other methods are also available to override depending on use.

The code you write should live in a .py file in the same folder as your .xml file. This will make it all much easier to package up. See the PythonPath and Import elements for how to include your new code into your Peach XML file.

NOTE: Never add the code into the Peach source folders! You're welcome to submit them as patches, but otherwise keep them in another folder. This will make it easier to move to another machine, and upgrade Peach in the future.

import os, sys, time
from Peach.publisher import Publisher

class FileWriter(Publisher):
        '''
        Publishes generated data to a file.
        '''
        
        def __init__(self, filename):
                '''
                @type   filename: string
                @param  filename: Filename to write to
                '''
                self._filename = filename)
                self._fd = None
                self._state = 0    # 0 - stopped; 1 - started
        
        def start(self):
                pass
        
        def connect(self):
                if self._state == 1:
                        raise Exception('File::start(): Already started!')
                
                if self._fd != None:
                        self._fd.close()
                
                self.mkdir()
                
                self._fd = open(self._filename, "w+b")
                self._state = 1
        
        def stop(self):
                self.close()
        
        def mkdir(self):
                # lets try and create the folder this file lives in
                delim = ""
                
                if self._filename.find("\\") != -1:
                        delim = '\\'
                elif self._filename.find("/") != -1:
                        delim = '/'
                else:
                        return
                
                # strip filename
                try:
                        path = self._filename[: self._filename.rfind(delim) ]
                        os.mkdir(path)
                except:
                        pass
                
        def close(self):
                if self._state == 0:
                        return
                
                self._fd.close()
                self._fd = None
                self._state = 0
        
        def send(self, data):
                self._fd.write(data)
        
        def receive(self, size = None):
                if size != None:
                        return self._fd.read(size)
                
                return self._fd.read()

This is the parent class. Override methods as needed.

class Publisher:
        '''
        The Publisher object(s) implement a way to send and/or receave
        data by some means.  This could be a TCP connection, a filehandle, or
        SQL, etc.
        
        There are two "types" of publishers, stream based and call based.  This
        base class supports both types.
        
        To support stream based publishing implement everything but "call".
        
        To support call based publishing implement start, stop, and call.
        
        Note: A publisher can support both stream and call based publishing.
        '''
        
        #: Indicates which method should be called.
        withNode = False
        
        def start(self):
                '''
                Change state such that send/receave will work.  For Tcp this
                could be connecting to a remote host
                '''
                pass
        
        def stop(self):
                '''
                Change state such that send/receave will not work.  For Tcp this
                could be closing a connection, for a file it might be closing the
                file handle.
                '''
                pass
        
        def send(self, data):
                '''
                Publish some data
                
                @type   data: string
                @param  data: Data to publish
                '''
                raise PeachException("Action 'send' not supported by publisher")
        
        def sendWithNode(self, data, dataNode):
                '''
                Publish some data
                
                @type   data: string
                @param  data: Data to publish
                @type   dataNode: DataElement
                @param  dataNode: Root of data model that produced data
                '''
                raise PeachException("Action 'send' not supported by publisher")
        
        def receive(self, size = None):
                '''
                Receive some data.
                
                @type   size: integer
                @param  size: Number of bytes to return
                @rtype: string
                @return: data received
                '''
                raise PeachException("Action 'receive' not supported by publisher")
        
        def call(self, method, args):
                '''
                Call a method using arguments.
                
                @type   method: string
                @param  method: Method to call
                @type   args: Array
                @param  args: Array of strings as arguments
                @rtype: string
                @return: data returned (if any)
                '''
                raise PeachException("Action 'call' not supported by publisher")

        def callWithNode(self, method, args, argNodes):
                '''
                Call a method using arguments.
                
                @type   method: string
                @param  method: Method to call
                @type   args: Array
                @param  args: Array of strings as arguments
                @type   argNodes: Array
                @param  argNodes: Array of DataElements
                @rtype: string
                @return: data returned (if any)
                '''
                raise PeachException("Action 'call' not supported by publisher")

        def property(self, property, value = None):
                '''
                Get or set property
                
                @type   property: string
                @param  property: Name of method to invoke
                @type   value: object
                @param  value: Value to set.  If None, return property instead
                '''
                raise PeachException("Action 'property' not supported by publisher")
        
        def propertyWithNode(self, property, value, valueNode):
                '''
                Get or set property
                
                @type   property: string
                @param  property: Name of method to invoke
                @type   value: object
                @param  value: Value to set.  If None, return property instead
                @type   valueNode: DataElement
                @param  valueNode: data model root node that produced value.
                '''
                raise PeachException("Action 'property' not supported by publisher")
        
        def accept(self):
                '''
                Accept incoming connection.  Blocks until incoming connection
                occurs.
                '''
                
                raise PeachException("Action 'accept' not supported by publisher")
        
        def close(self):
                '''
                Close current stream/connection.
                '''
                raise PeachException("Action 'close' not supported by publisher")