###############
#  RRDpipe.py #
###############

#
#  Simple python interface for Tobi Oetiker's RRDTOOL
#  program. This module emulates the RRD Pipes perl module,
#  creating a python wrapper for piped calls.
#
#  This module is pipes wrapper, which is ideal for portability.
#  For a faster, compiled C module,  check out:
#	PyRRDTool
#    or
#  	PyRRD - http://www.untz.net/rrdmodule.html
#
#  Author: Franco Gasperino
#
#  Create Date: 03/27/01
#
#  Revision: $Revision: 1.1.1.1 $
#  Last Modified: $Date: 2001/04/22 22:58:33 $
#  Last Committer: $Author: franco $
# 
#  Copyright (C) 2001 Franco Gasperino
#
#  This program is free software; you can redistribute it and/or modify it under
#  the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2, or (at your option) any later
#  version.
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
#  more details.
#
#  You should have received a copy of the GNU General Public License along with
#  this program; if not, write to the Free Software Foundation, Inc., 67
#  Mass Ave, Cambridge, MA 02139, USA.
#

####################
# Imported Modules #
####################

import os
import errno

###########
# Classes #
###########

class RRDpipe:

    #
    #  members:
    #    response - STDOUT stream from rrdtool binary
    #    path     - absolute path to rrdtool binary
    #

    """
    Class to interface with rrdtool binary via named pipes. Allows for a
    binary-independent, portable module for accessing rrdtool calls from
    within an application. This class closely emulates the Perl RRD Pipes
    module. An Error exception is thrown in emergencies.
    """

    RRDTOOL_BINARY = "rrdtool"

    #
    #  __init__()
    #
    
    def __init__(self, path = None):

        """
        Instance initialization and resource allocation
        """

        self.response = None
        self.path     = self.RRDTOOL_BINARY
        
    #
    #  start()
    #
    
    def start(self, path = None):

        #  params:
        #    path - absolute path to rrdtool binary

        """
        Sets up path to rrdtool binary, provided for compatability
        """

        self.path = path

    #
    #  end()
    #
    
    def end(self):

        """
        Dummy function, provided for compatability
        """

        pass

    #
    #  read()
    #
    
    def read(self):

        """
        Reads output captured from pipe, provided for compatability
        """

        if not self.response:
            return None

        return self.response

    #
    #  cmd()
    #
    
    def cmd(self, command = None):

        #  params:
        #    command - rrdtool parameters to be issued at the command line
        #              as ARGV

        """
        Executes a command against the pipe. See perl module documentation
        for more information.
        """

        try:
            # assert that we have a command to send
            if not command:
                raise Error("Failed to send command to RRDpipe pipe: No command specified!")

            # create a pipe, send the command
            pipe = os.popen(("%s %s" % (self.path, command)), 'r')

            if not pipe: # returned no data
                return

            self.response = pipe.read()

        except os.error, (errnum, errmsg):
            raise Error("Failed to write to RRDpipe pipe: %s (ERRNO: %i)!" % (errmsg, errnum))

        except IOError, (errnum, errmsg):
            raise Error("Failed to write to RRDpipe pipe: %s (ERRNO: %i)!" % (errmsg, errnum))

class Error (Exception):

    """
    Class used to handle exceptions within the RRDpipe class.
    """

    #
    #  __init__()
    #
    
    def __init__(self, mesg = None, fatal = 1):

        #  params:
        #    mesg  - Error message provided by thrower
        #    fatal - Boolean describing the fatality of the exception

        """
        Instance initialization and resource allocation
        """

        self.mesg  = mesg
        self.fatal = fatal

    #
    #  __str__()
    #
    
    def __str__(self):

        """
        Returns a string representation of the exception thrown
        """

        if not self.mesg:
            return "An unknown error has occurred!"

        return self.mesg

