Next / Previous / Contents / Shipman's homepage

15.10. Hier.__init__(): Constructor

nomcompile3
# - - -   H i e r . _ _ i n i t _ _

    def __init__ ( self, ranksFileName ):
        '''Constructor: reads the ranks file.
        '''

The first order of business is to set up our invariants, and initialize self.txKeyLen to zero so we can sum up the lengths of the subfields of the taxonomic key. We also interrogate the Log() object to get its current error count, so we can check later whether any errors have been issued while scanning the ranks file.

nomcompile3
        #-- 1 --
        # [ self.txKeyLen  :=  0
        #   self.__rankList  :=  a new, empty list
        #   self.__rankMap  :=  a new, empty dictionary
        #   errCount  :=  the current error count from Log() ]
        self.txKeyLen = 0
        self.__rankList = []
        self.__rankMap = {}
        errCount = Log().count()

Next we open and read through the ranks file. Each valid line is converted to a Rank instance and added to self.__rankList. See Section 15.11, “Hier.__readRanksFile(): Read the ranks file”.

nomcompile3
        #-- 2 --
        # [ if ranksFileName can be opened for reading ->
        #     self.__rankList  +:=  Rank instances representing
        #         the valid lines of that file in the same order
        #     self.txKeyLen  +:=  key lengths of those Rank
        #         instances
        #     Log()  +:=  error message(s) about invalid lines
        #         of that file, if any ]
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise IOError ]
        self.__readRanksFile ( ranksFileName )

Now add entries to self.__rankMap for each of the child ranks. Also, check for duplicate rank codes.

nomcompile3
        #-- 3 --
        # [ self.__rankMap  +:=  entries whose keys are the
        #       unique rank codes in self.__rankList and each related
        #       value is the corresponding element of the first
        #       element of self.__rankList with that value
        #   Log()  +:=  messages about duplicate rank codes in
        #       self.__rankList, if any ]
        for rank in self.__rankList:
            #-- 3 body --
            # [ if rank.code is a key in self.__rankMap ->
            #     Log()  +:=  error message
            #   else ->
            #     self.__rankMap[rank.code]  :=  rank
            #   In any case ->
            #     self.txKeyLen  +:=  rank.keyLen ]
            if rank.code in self.__rankMap:
                Log().error ( "Duplicate rank code: '%s'" %
                              rank.code )
            else:
                self.__rankMap[rank.code] = rank

As the specification states, genus and species ranks are not optional. Enforce this.

nomcompile3
        #-- 4 --
        # [ if self.__rankMap has keys GENUS_CODE and SPECIES_CODE ->
        #     I
        #   else ->
        #     Log()  +:=  error message ]
        for requiredCode in (GENUS_CODE, SPECIES_CODE):
            if not requiredCode in self.__rankMap:
                Log().error ( "Your file is missing required "
                    "rank '%s'." % requiredCode )

If any error messages have been issued since the beginning of this method, we raise IOError; otherwise we complete normally.

nomcompile3
        #-- 5 --
        # [ if errCount < (error count from Log()) ->
        #     raise IOError
        #   else -> I ]
        netErrCount = Log().count() - errCount
        if netErrCount > 0:
            raise IOError ( "There were %d errors in the ranks "
                "file '%s'." % (netErrCount, ranksFileName ) )