A two component pyre example

From DANSE

Requested: "...post a sample component pair, e.g., something which reads a three-column ascii data file, then sends it to the next component that writes it".


Here are two components, a reader which uses the new "csv" module to read comma-separated input, and a generic writer (csv has writers, too, I haven't used one for no particular reason). These are written for pythia version 0.6+.


Table of contents

Reader

(suppose it lives in csv_reader.py) Note that I changed a line in __init__:
Component.__init__( self, 'csv_reader', 'csv_reader')
became
Component.__init__( self, 'csv_reader', 'reader')

#!/usr/bin/env python

from pyre.inventory.Component import Component

class csv_reader(Component):

    """Component that opens a file with comma-separated values and reads
    the lines into a list.
    """

    class Inventory( Component.Inventory):

        import pyre.inventory
        from csv_writer import csv_writer
        filename = pyre.inventory.str( 'filename', default='example.txt')
        writer = pyre.inventory.facility( 'writer', default = csv_writer())
                                          

    def read( self, *args, **kwds):
        
        import csv   # comma-separated-values file reader/writer

        infile = open( self.inventory.filename, 'r')
        reader = csv.reader( infile)
        for line in reader:
            self._lines.append(line)
            print line
        infile.close()

        self.inventory.writer.write( self._lines)
        return

    def getLines( self): return self._lines


    def __init__(self, *args, **kwds):
        Component.__init__( self, 'csv_reader', 'reader')
        return


    def _init( self):
        self._lines = []
        return

# End of file


Writer

writer (in file csv_writer.py).

#!/usr/bin/env python

from pyre.inventory.Component import Component

class csv_writer(Component):

    """Component that writes a list of lines to an ASCII file.
    """

    class Inventory( Component.Inventory):

        import pyre.inventory

        filename = pyre.inventory.str( 'filename',
                                       default='new_output.txt')
        
        

    def write( self, listOLines):
        outfile = open( self.inventory.filename, 'w')
        for line in listOLines:
            outfile.write(','.join(line)+'\n')
        outfile.close()
        return


    def __init__(self, *args, **kwds):
        Component.__init__( self, 'csv_writer', 'writer')
        return


    def _init( self):
        return

# End of file


Driver

An application that drives reader, which in turn drives writer
(I put this in CSV.py, don't mask csv)

#!/usr/bin/env python

from pyre.applications.Application import Application


class CsvApp(Application):

    """Application that drives csv_reader
    """


    def run(self, *args, **kwds):
        self._reader.read()
        return


    def __init__(self):
        Application.__init__(self, 'csv')
        return


    def _init(self):
        self._reader = self.inventory.reader
        return


    class Inventory(Application.Inventory):

        import pyre.inventory
        from csv_reader import csv_reader
        reader = pyre.inventory.facility('reader', default=csv_reader())

# main
if __name__ == '__main__':
    app = CsvApp()
    app.main()


# version
__id__ = "$Id$"

# Generated automatically by PythonMill on Thu Jul 15 12:00:11 2004

# End of file 

Sample input (example.txt)

first, second, third
1, 2, 3
4, 5, 6


Discussion

Example command line:
assumes input in file called example.txt, writes to new_output.txt

./CSV.py

change input filename:

./CSV.py --reader.filename=other.txt

change output filename

./CSV.py --reader.writer.filename=differentOutput.txt

change both

./CSV.py --reader.filename=other.txt --reader.writer.filename=differentOutput.txt 

This illustrates an important feature of pyre: nesting components. When a component wants to make use of another component, it creates a facility in its inventory, perhaps specifying a default component that can serve. Then it just uses the facility. It is the framework's responsibility to find the right component and bind it to the facility.

A related question is, how does one component configure a subcomponent? The answer is, very carefully: the parent must make changes to the child's inventory before the child uses its inventory. Prior to pythia 0.6, the parent component could do this when overriding _default() and be certain that the changes would show up by the time the child component ran _init. For pythia 0.6, I am uncertain about the correct order of initialization calls; someone who does know should comment on this.

-- Tim

Personal tools
Document Uploads/Links