In KirbyBase there is a method that uses string exceptions for control, even though it has a defined exception. Is there any reason the string exceptions below could not be replaced? i.e. in code below replace: raise "No Match" with: raise KBError() and except 'No Match': with: except KBError:
I have pasted the relevant method and the class definition of KBError below #---------------------------------------------------------------------- # _getMatches #---------------------------------------------------------------------- def _getMatches(self, fptr, fields, patterns, useRegExp): # Initialize a list to hold all records that match the search # criteria. match_list = [] # If one of the fields to search on is 'recno', which is the # table's primary key, then search just on that field and return # at most one record. if 'recno' in fields: return self._getMatchByRecno(fptr,patterns) # Otherwise, search table, using all search fields and patterns # specified in arguments lists. else: new_patterns = [] fieldNrs = [self.field_names.index(x) for x in fields] for fieldPos, pattern in zip(fieldNrs, patterns): if self.field_types[fieldPos] == str: # If useRegExp is True, compile the pattern to a # regular expression object and add it to the # new_patterns list. Otherwise, just add it to # the new_patterns list. This will be used below # when matching table records against the patterns. if useRegExp: new_patterns.append(re.compile(pattern)) # the pattern can be a tuple with re flags like re.I else: new_patterns.append(pattern) elif self.field_types[fieldPos] == bool: # If type is boolean, I am going to coerce it to be # either True or False by applying bool to it. This # is because it could be '' or []. Next, I am going # to convert it to the string representation: either # 'True' or 'False'. The reason I do this is because # that is how it is stored in each record of the table # and it is a lot faster to change this one value from # boolean to string than to change possibly thousands # of table values from string to boolean. And, if they # both are either 'True' or 'False' I can still # compare them using the equality test and get the same # result as if they were both booleans. new_patterns.append(str(bool(pattern))) else: # If type is int, float, date, or datetime, this next # bit of code will split the the comparison string # into the string representing the comparison # operator (i.e. ">=" and the actual value we are going # to compare the table records against from the input # pattern, (i.e. "5"). So, for example, ">5" would be # split into ">" and "5". r = re.search('[\s]*[\+-]?\d', pattern) if self.field_types[fieldPos] == int: patternValue = int(pattern[r.start():]) elif self.field_types[fieldPos] == float: patternValue = float(pattern[r.start():]) else: patternValue = pattern[r.start():] new_patterns.append( [self.cmpFuncs[pattern[:r.start()]], patternValue] ) fieldPos_new_patterns = zip(fieldNrs, new_patterns) maxfield = max(fieldNrs)+1 # Record current position in table. Then read first detail # record. fpos = fptr.tell() line = fptr.readline() # Loop through entire table. while line: # Strip off newline character and any trailing spaces. line = line[:-1].strip() try: # If blank line, skip this record. if line == "": raise 'No Match' # Split the line up into fields. record = line.split("|", maxfield) # Foreach correspond field and pattern, check to see # if the table record's field matches successfully. for fieldPos, pattern in fieldPos_new_patterns: # If the field type is string, it # must be an exact match or a regular expression, # so we will compare the table record's field to it # using either '==' or the regular expression # engine. Since it is a string field, we will need # to run it through the unencodeString function to # change any special characters back to their # original values. if self.field_types[fieldPos] == str: try: if useRegExp: if not pattern.search( self._unencodeString(record [fieldPos]) ): raise 'No Match' else: if record[fieldPos] != pattern: raise 'No Match' except Exception: raise KBError( 'Invalid match expression for %s' % self.field_names[fieldPos]) # If the field type is boolean, then I will simply # do an equality comparison. See comments above # about why I am actually doing a string compare # here rather than a boolean compare. elif self.field_types[fieldPos] == bool: if record[fieldPos] != pattern: raise 'No Match' # If it is not a string or a boolean, then it must # be a number or a date. else: # Convert the table's field value, which is a # string, back into it's native type so that # we can do the comparison. if record[fieldPos] == '': tableValue = None elif self.field_types[fieldPos] == int: tableValue = int(record[fieldPos]) elif self.field_types[fieldPos] == float: tableValue = float(record[fieldPos]) # I don't convert datetime values from strings # back into their native types because it is # faster to just leave them as strings and # convert the comparison value that the user # supplied into a string. Comparing the two # strings works out the same as comparing two # datetime values anyway. elif self.field_types[fieldPos] in ( datetime.date, datetime.datetime): tableValue = record[fieldPos] else: # If it falls through to here, then, # somehow, a bad field type got put into # the table and we show an error. raise KBError('Invalid field type for %s' % self.field_names[fieldPos]) # Now we do the actual comparison. I used to # just do an eval against the pattern string # here, but I found that eval's are VERY slow. # So, now I determine what type of comparison # they are trying to do and I do it directly. # This sped up queries by 40%. if not pattern[0](tableValue, pattern[1]): raise 'No Match' # If a 'No Match' exception was raised, then go to the # next record, otherwise, add it to the list of matches. except 'No Match': pass else: match_list.append([line, fpos]) # Save the file position BEFORE we read the next record, # because after a read it is pointing at the END of the # current record, which, of course, is also the BEGINNING # of the next record. That's why we have to save the # position BEFORE we read the next record. fpos = fptr.tell() line = fptr.readline() # After searching, return the list of matched records. return match_list #---------------------------------------------------------------------- #-------------------------------------------------------------------------- # KBError Class #-------------------------------------------------------------------------- class KBError(Exception): """Exception class for Database Management System. Public Methods: __init__ - Create an instance of exception. """ #---------------------------------------------------------------------- # init #---------------------------------------------------------------------- def __init__(self, value): self.value = value def __str__(self): return `self.value` # I overrode repr so I could pass error objects from the server to the # client across the network. def __repr__(self): format = """KBError("%s")""" return format % (self.value) -- http://mail.python.org/mailman/listinfo/python-list