Given a code that is a direct equivalent of some other code, this method attempts to find the actual taxon to which the code refers.
There are just two significant complications. The first is that this code may be referenced to another direct equivalent, which points to yet another direct equivalent, and so on. So we need to chase this chain of references until it leads to an actual taxon.
The second complication is that faulty input data may create a cycle in the reference relation. For example, suppose these two lines are in an alt forms file:
BAROWL=BRNOWL BRNOWL=BAROWL
If someone calls this .lookup() method on the
first code, we must avoid the infinite loop that would result
from chasing references until we reach a taxon.
To prevent this, we use a recursive function
(Section 28.5, “EqBind.__chainClosure(): Recursive lookup
function”) that keeps
track of which codes we've already seen. If the next
level of reference leads to one of the codes already in the
chain of references, that's an error.
# - - - E q B i n d . l o o k u p
def lookup ( self ):
'''To which taxon is this code related?
[ if self is related, possibly indirectly, to a
taxon ->
return that taxon as a Taxon instance
else ->
raise ValueError ]
'''
The recursive function takes as its first argument a Python
Set instance containing the codes already
visited. We start with self.abbr as a
singleton set. The .__chainClosure() method
either returns a taxon or raises ValueError.
#-- 1 --
# [ if self is related, possibly indirectly, to a taxon ->
# return that taxon as a Taxon instance
# else if self.prefSym or any further references are in
# the set containing self ->
# raise ValueError ]
return self.__chainClosure ( set([self.abbr]), self.prefSym )