ASCII database (was Re: Should I prefer an external database)

Aahz aahz at pythoncraft.com
Wed Apr 23 10:13:09 EDT 2003


In article <u3ckbymri.fsf at mail.afm.dtu.dk>,
Brian Elmegaard  <brian at rk-speed-rugby.dk> wrote:
>
>I am working on a script for organizing a program for a conference. I
>started out using a connection to mySQL, but then I thought that it
>would be easier to keep it within python. 

This seems like a good place to mention that I'm currently rolling my
own database.  I'm doing it because I want to keep the DB online in my
shell account, and it's a PITA using anything other than a simple text
editor to update bits within it.  So I'm using a simple RFC-822 layout
for the fields with '%%\n' as the record separator; fields are permitted
to have multiple instances.  There are no required fields in the design;
each record is free-form.

The fun part was implementing the search engine.  I wanted to implement
something usable, so I allow both includes and excludes.  Excludes are
always ORed; includes are ANDed; search terms are separated by commas.
An include can have an embedded pipe ('|'), which turns it into a list
of ORed terms.  Excludes are prepended with an exclamation point ('!').
(Yes, I don't like the visual confusion, but those are standard chars
and the location makes the intent clear.)

So here's my filter function:

class Excluded(StandardError):
    pass

class Found(StandardError):
    pass

class NotFound(StandardError):
    pass

# Includes by default are ANDed; excludes are always ORed
# Use "|" to OR includes; "!" indicates exclude
def filter(db, FilterString=None, fields=None, FuzzyMatch=True):
    includes, excludes = _buildFilters(FilterString)
    if fields is not None:
        fields = re_comma_field.split(fields)
        for i in range(len(fields)):
            fields[i] = fields[i].lower()
    if FuzzyMatch:
        match = _fuzzy_match
    else:
        match = _exact_match
    result = []
    for record in db:
        if fields is None:
            curr_fields = record.keys()
        else:
            curr_fields = []
            for field in fields:
                if field in record:
                    curr_fields.append(field)
        try:
            for field in curr_fields:
                for item in record[field]:
                    item = item.lower()
                    for filter in excludes:
                        if match(item, filter):
                            raise Excluded
        except Excluded:
            continue
        try:
            for ORlist in includes:
                try:
                    for filter in ORlist:
                        for field in curr_fields:
                            for item in record[field]:
                                if item.lower().find(filter) >= 0:
                                    raise Found
                    else:
                        raise NotFound
                except Found:
                    continue
        except NotFound:
            continue
        else:
            result.append(record)
    return result



def _fuzzy_match(string, filter):
    return string.find(filter) >= 0


def _exact_match(string, filter):
    return string == filter



re_filters = re.compile(r', *')
NOT = '!'
OR = '|'

# Each set of filter words is separated by comma
def _buildFilters(FilterString):
    if FilterString is None:
        return [], []
    else:
        FilterString = FilterString.lower()
        FilterList = re_filters.split(FilterString)
        includes, excludes = [], []
        for filter in FilterList:
            if filter[0] == NOT:
                excludes.append(filter[1:])
            else:
                includes.append(filter.split(OR))
        return includes, excludes
-- 
Aahz (aahz at pythoncraft.com)           <*>         http://www.pythoncraft.com/

Why is this newsgroup different from all other newsgroups?




More information about the Python-list mailing list