Next / Previous / Contents / Shipman's homepage

19.3. BaseCompiler.__init__(): Constructor

Anticipating that derived classes may do almost anything differently from each other, we try to restrict the code in the constructor to contain only operations that are always the same. Accordingly, the constructor calls a few generalized methods, any of which can be replaced in a derived class.

baseclasses.py
# - - -   B a s e C o m p i l e r . _ _ i n i t _ _   - - -

    def __init__(self, fileName, stationSet, speciesSet):
        '''Constructor for BaseCompiler.
        '''

One thing we'll always do is to remember the station and species authority objects, and initialize all the internal state items.

baseclasses.py
        #-- 1 --
        self.fileName     = fileName
        self.stationSet   = stationSet
        self.speciesSet   = speciesSet
        self.pageHeader   = None
        self.prefix       = None
        self.oldEncounter = None

Next we need to analyze the fileName to insure that it conforms to the batch file naming scheme. This step will also set the .location and .station state items. See Section 19.4, “BaseCompiler.parseFileName(): Parse the batch file name”.

baseclasses.py
        #-- 2 --
        # [ if self.fileName conforms to the batch file naming scheme and
        #   represents a multi-station location in self.stationSet ->
        #     self.location  :=  a Location object representing that
        #                        location
        #     self.station   :=  None
        #     self.year      :=  year from self.fileName
        #   else if self.fileName conforms to the batch file naming
        #   scheme and represents a single-station location in
        #   self.stationSet ->
        #     self.location  :=  None
        #     self.station   :=  a Station object representing that
        #                        station
        #     self.year      :=  year from self.fileName
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise ValueError ]
        self.parseFileName()

All that remains is to attempt to open the input file for reading, using the Scan class. The callback keyword argument is used to report our current band size and page number as part of each error message; see Section 19.8, “BaseCompiler.scanCallback(): Error localization string”.

This is an interesting use of Python's “bound method” feature. The reference to self.scanCallback gives us an object of function type, but the current value of “self” is bound into it. Hence, it can be called by the scan object, even though scan has no idea where to find the BaseCompiler object that contains the band size and page number that we need to see in any syntax error message.

baseclasses.py
        #-- 3 --
        # [ if self.fileName can be opened for reading ->
        #     self.scan  :=  a Scan object pointing at the start
        #                    of that file
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise ValueError ]
        try:
            self.scan = Scan(self.fileName,
                                 callback=self.scanCallback)
        except IOError, detail:
            message  = ("Can't open input file '%s': %s" %
                          (self.fileName, detail))
            Log().error(message)
            raise ValueError, message

Processing will continue when the caller calls our .__iter__() method.