Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

KirbyBase : replacing string exceptions

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


brendandetracey at yahoo

Nov 23, 2009, 7:22 AM

Post #1 of 3 (199 views)
Permalink
KirbyBase : replacing string exceptions

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


showell30 at yahoo

Nov 23, 2009, 8:21 AM

Post #2 of 3 (178 views)
Permalink
Re: KirbyBase : replacing string exceptions [In reply to]

On Nov 23, 7:22 am, Brendan <brendandetra...@yahoo.com> 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)

--
http://mail.python.org/mailman/listinfo/python-list


brendandetracey at yahoo

Nov 23, 2009, 9:05 AM

Post #3 of 3 (177 views)
Permalink
Re: KirbyBase : replacing string exceptions [In reply to]

On Nov 23, 12:21 pm, Steve Howell <showel...@yahoo.com> wrote:
> On Nov 23, 7:22 am, Brendan <brendandetra...@yahoo.com> 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.
--
http://mail.python.org/mailman/listinfo/python-list

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.