KirbyBase : replacing string exceptions

Discussion in 'Python' started by Brendan, Nov 23, 2009.

  1. Brendan

    Brendan Guest

    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)
     
    Brendan, Nov 23, 2009
    #1
    1. Advertising

  2. Brendan

    Steve Howell Guest

    On Nov 23, 7:22 am, Brendan <> wrote:
    > 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:
    >


    It looks like in some cases KBError() should fall through and only 'No
    Match' was intended to be silently caught.

    I would consider either leaving it alone if it works, or doing more
    serious surgery on the code to simplify the control flow. The method
    is awfully long and nested.

    > 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)
     
    Steve Howell, Nov 23, 2009
    #2
    1. Advertising

  3. Brendan

    Brendan Guest

    On Nov 23, 12:21 pm, Steve Howell <> wrote:
    > On Nov 23, 7:22 am, Brendan <> wrote:
    >
    > > 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:

    >
    > It looks like in some cases KBError() should fall through and only 'No
    > Match' was intended to be silently caught.
    >
    > I would consider either leaving it alone if it works, or doing more
    > serious surgery on the code to simplify the control flow.  The method
    > is awfully long and nested.
    >
    >
    >
    > > 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 (
    > >                            - Hide quoted text -

    >
    > - Show quoted text -...
    >
    > read more »


    Okay. Thanks.
     
    Brendan, Nov 23, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ahmed Moustafa
    Replies:
    5
    Views:
    30,126
    Chris Smith
    Jul 14, 2004
  2. Paul Miller
    Replies:
    3
    Views:
    1,065
    Alex Martelli
    Nov 12, 2003
  3. Replies:
    3
    Views:
    637
    Sherm Pendley
    Apr 16, 2007
  4. Lie
    Replies:
    3
    Views:
    715
  5. Rob Meade

    Replacing - and not Replacing...

    Rob Meade, Apr 5, 2005, in forum: ASP General
    Replies:
    5
    Views:
    315
    Chris Hohmann
    Apr 11, 2005
Loading...

Share This Page