# - - - 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.
#-- 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”.
#-- 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.
#-- 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.
#-- 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.
#-- 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 ) )