Somewhat based on the statement by Gordon McMillan:

I don't have much motivation to fix them. People send
in code patches, but doc patches are very, very rare.

I spent some time dumping some of my knowledge of metakit into a small tutorial. If some kind soul could double check the following code and comments I will compile it into a python-style mini-howto. Suggestions are welcome and I will be updating this (read "making it more verbose and adding more examples") as I learn more about metakit.

Cheers.

--
Brian Kelley                                  [EMAIL PROTECTED]
Whitehead Institute for Biomedical Research   617 258-6191

# This is some informal documentation and test for metakit
# It basically is designed so that I can remember what
# the hell I'm doing

import metakit, os, marshal
try: os.remove("test.mk")
except: pass

READONLY = 0
READWRITE = 1
COMMITEXTEND = 2

print "#######################################################"
print "making the database"
db = metakit.storage("test.mk", READWRITE)

# let's make a table
table = db.getas("test[testid:I,string:S,marshal:B]")

# The marshalling stores basic python types
# This needs to be stored as a "B"inary type
data = [(0,"foo",marshal.dumps("I am a foo!")),
        (1,"bar",marshal.dumps(123)),
        (2,"baz",marshal.dumps([3,4,5,3,4,5,6,7,7,8]))]

for row in data:
    # append the data into the rows (all this
    # stuff is coerced to live in the database)
    table.append(row)

db.commit()

print "#######################################################"
print "making temporary table for joining"

# we are going to perform a query by joining two
# tables together
# now let's make a temporary indices list
# and coerrce it into a row
indices = db.getas("_temp[testid:I]")
indices.append(2)


# now we can make a subview of the table as a result
# of this join
subview = table.join(indices, indices.testid)
assert len(subview) == 1

for row in subview:
    print row.testid, row.string, marshal.loads(row.marshal)

# we should probably drop the temporary table
# in case a commit is called later
del indices[:]

# this can also be done indices[:] = []

# I'm committing here just to test whether the indices table has
# been dropped or not later
db.commit()

print "#######################################################"
print "wrapping a sequence of dictionaries"

# alternatively we can "wrap" a python sequence into a
# temporary view.  This wraps a sequences using
# the respective database types.  so below
# [2,...], [metakit.property("I", "testid")...
# the first column is wrapped by an Integer column named testid
indices = metakit.wrap([{"testid":x} for x in [2]],
                       [metakit.property("I", "testid")])
subview = table.join(indices, indices.testid)
#
for row in subview:
    print row.testid, row.string, marshal.loads(row.marshal)

print "\n#######################################################"
print "wrapping a sequence of dictionaries using the tables properties"

# If you don't want to remember how to make the property
# lists, you can just use the ones from another table
indices = metakit.wrap([{"testid":x} for x in [2]],
                       [table.testid])
subview = table.join(indices, indices.testid)
for row in subview:
    print row.testid, row.string, marshal.loads(row.marshal)

del db

# This just tests to see if the temporary
# table we made has been dropped or not
db = metakit.storage("test.mk", READWRITE)
table = db.getas("test[testid:I,string:S,marshal:B]")
test = db.getas("_temp[testid:I]")
assert len(test) == 0

print "\n#############################################################"
print "Things that don't work as I expect"
print
print "select only uses the first two criteria"
v = table.select({"testid":0}, {"testid":1}, {"testid":2})
print len(v), "-> should be 3"

v = table.select({"testid":1}, {"testid":2}, {"string":"foo"})
print len(v), "-> should be 1"

print "\n#############################################################"
print "view.filter doesn't return the whole row, just the matching"
print "indices in a table with an index attribute"
print "Not much can be done with these now, hopefully when the"
print "Mapped Index view is completed we can use this output"
print "to create a subview that has access to the rows of the"
print "original data"

vw = table.filter(lambda x: 1)
metakit.dump(vw)

print "\n#############################################################"
print "here is a version of filter that is a little better,"
print "the returned subview has the same rows but the result"
print "is read only."
print "This is perhaps the most confusing aspect of metakit"
print "Most subview returned are readonly, only selects and"
print "sorts are really tracked in this way.  See"
print "http://www.equi4.com/metakit/wiki.cgi/99";

def filter(view, func):
    result = view
    i = 0
    for row in view:
        if not func(row):
            result = result.minus(view[i:i+1])
        i += 1
    return result

subview = filter(table, lambda x:x.testid<2)
assert len(subview) == 2
try:
    subview[0].string = "changed"
except TypeError:
    print "caught TypeError, this was expected"

print "\n#############################################################"
print "here is an enhanced filter that returns a trackable"
print "subview, view must be a data table not another"
print "subview"
print "You'll see a new column in the database but this won't"
print "be saved when the data is commited"
def filter(view, func):
    view.addproperty(metakit.property("I", "_temp__344_343"))
    for row in view:
        if func(row):
            row._temp__344_343 = 1
        else:
            row._temp__344_343 = 0

    return view.select(_temp__344_343=1)

subview = filter(table, lambda x:x.testid<2)
assert len(subview) == 2
metakit.dump(subview)
subview[0].string = "changed"

Reply via email to