#!/usr/bin/python # Copyright (c) 2005-2006 by Mark T. Holder # Florida State University. (see end of file) # New (post April, 2006) file (expected to be clean under pylint) '''Utility routines. * import safe. ''' from cStringIO import StringIO def get_key(dictionary, value): '''Returns the first key in dictionary that maps to an item that is equal to value (or None). Note: uses iteritems, which is not a deterministic mapping, so if there are multiple keys that map to value, then an arbitrary one will be returned.''' for k, v in dictionary.iteritems(): if v == value: return k return None def paddingInsert(li, index, value): '''Like li.insert(index, value), but the list maybe padded with None to make guarantee that li[index] = value. Returns the number of None elements added.''' ll = len(li) if index > ll: d = index - ll li.extend([None] * d) else: d = 0 li.insert(index, value) return d def removeAll(li, el): "Removes all occurrences of el from the list li""" try: prevInd = 0 while True: prevInd = li.index(el, prevInd) li.pop(prevInd) except ValueError: pass return li def chompIter(o): '''Generator that takes an iterator over strings and yields strings with the last character removed (if the last character is \\n''' for i in o: if i[-1] == '\n': yield i[:-1] else: yield i def _getStartBalanced(startStr, openC, closeC, forbidden, sourceIter): "Helper function for getBalancedString(). Reads to the first occurrence of openC or raises an error." currString = startStr prefix = [] while True: currStringIter = iter(currString) for n, c in enumerate(currStringIter): if c == openC: if n > 0: prefix.append(currString[:n]) return n + 1, currString, currStringIter, prefix if c == closeC: raise ValueError, 'Expecting %c before %c' % (openC, closeC) if c in forbidden: raise ValueError, 'Forbidden character %c found before balanced string' % (c) prefix.append(currString) currString = sourceIter.next() def getBalancedString(startStr, openC, closeC, forbidden = '', sourceIter = None): """Returns a tuple of balancedString, prefixList, postfix Where balancedString first balanced strings encountered. A "balanced string" starts with the openC character and has an equal number of openC and closeC characters. "prefixList" is a list of strings passed before the first openC was found "postfix" is what remains of the string being read after the outer closeC was found. ValueError raised if: * closeC is encountered before openC * any character in forbidden is encountered before a balanced string is found. If sourceIter is specified, it will be iterated over to append to startStr. StopIteration raised if startStr and sourceIter are exhausted before a balanced string is found """ if sourceIter is None: sourceIter = iter(()) #find the opening char offset, currString, currStringIter, prefix = _getStartBalanced(startStr, openC, closeC, forbidden, sourceIter) #find the matching number of closeC nOpenToBalance = 1 toReturn = StringIO() toReturn.write(openC) while True: n = -1 for n, c in enumerate(currStringIter): if c == openC: nOpenToBalance += 1 elif c == closeC: nOpenToBalance -= 1 if nOpenToBalance == 0: toReturn.write(currString[offset:offset + n + 1]) return toReturn.getvalue(), prefix, currString[offset + n + 1:] elif c in forbidden: raise ValueError, 'Forbidden character %c found before balanced string' % (c) toWrite = currString[offset:] if toWrite: toReturn.write(toWrite) offset = 0 currString = sourceIter.next() currStringIter = iter(currString) def allElementsEqualLength(mat): '''Takes an iterable and returns True if all elements have the same length.''' if len(mat) > 0: x = iter(mat) fLen = len(x.next()) for i in x: if len(i) != fLen: return False return True if __name__ == '__main__': import doctest doctest.testmod() # This file is part of the PIPRes library # # The PIPRes library is free software; you can redistribute it # and/or modify it under the terms of the GNU Lesser General # Public License as published by the Free Software Foundation; # either version 2.1 of the License, or (at your option) any later # version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA