annotate bindings/python/pyadb.py @ 625:448b28a598e3

added the first pass of the native python access class, open, close and insert supported, query still to come. Also, on account of a definite memory leak (yet to be sorted out) when using the modulw in the interpreter, sometimes exit() will segfault...
author map01bf
date Tue, 22 Sep 2009 12:35:24 +0000
parents
children 356d7b319ae8
rev   line source
map01bf@625 1 #!/usr/bin/env python
map01bf@625 2 # encoding: utf-8
map01bf@625 3 """
map01bf@625 4 pyadb.py
map01bf@625 5
map01bf@625 6 public access and class structure for python audioDb api bindings.
map01bf@625 7
map01bf@625 8 Created by Benjamin Fields on 2009-09-22.
map01bf@625 9 Copyright (c) 2009 Goldsmith University of London.
map01bf@625 10 """
map01bf@625 11
map01bf@625 12 import sys
map01bf@625 13 import os, os.path
map01bf@625 14 import unittest
map01bf@625 15 import _pyadb
map01bf@625 16
map01bf@625 17 ADB_HEADER_FLAG_L2NORM = 0x1#annoyingly I can't find a means
map01bf@625 18 ADB_HEADER_FLAG_POWER = 0x4#around defining these flag definitions
map01bf@625 19 ADB_HEADER_FLAG_TIMES = 0x20#as they aren't even exported to the
map01bf@625 20 ADB_HEADER_FLAG_REFERENCES = 0x40#api, so this is the only way to get them.
map01bf@625 21
map01bf@625 22 class Usage(Exception):
map01bf@625 23 def __init__(self, msg):
map01bf@625 24 self.msg = msg
map01bf@625 25
map01bf@625 26 class Pyadb:
map01bf@625 27
map01bf@625 28 def __init__(self, path, mode='w'):
map01bf@625 29 self.path = path
map01bf@625 30 if not (mode=='w' or mode =='r'):
map01bf@625 31 raise(ValueError, "if specified, mode must be either\'r\' or \'w\'.")
map01bf@625 32 if os.path.exists(path):
map01bf@625 33 self._db = _pyadb._pyadb_open(path, mode)
map01bf@625 34 else:
map01bf@625 35 self._db = _pyadb._pyadb_create(path,0,0,0)
map01bf@625 36 self._updateDBAttributes()
map01bf@625 37 return
map01bf@625 38
map01bf@625 39 def insert(self, featFile=None, powerFile=None, timesFile=None, featData=None, powerData=None, timesData=None, key=None):
map01bf@625 40 """Insert features into database. Can be done with data provided directly or by giving a path to a binary fftExtract style feature file. If power and/or timing is engaged in the database header, it must be provided (via the same means as the feature) or a Usage exception will be raised. Power files should be of the same binary type as features. Times files should be the ascii number length of time in seconds from the begining of the file to segment start, one per line.\n---Note that direct data insertion is not yet implemented.---"""
map01bf@625 41 #While python normally advocates leaping before looking, these check are nessecary as
map01bf@625 42 #it is very difficult to assertain why the insertion failed once it has been called.
map01bf@625 43 if (self.hasPower and (((featFile) and powerFile==None) or ((featData) and powerData==None))):
map01bf@625 44 raise(Usage, "The db you are attempting an insert on (%s) expects power and you either\
map01bf@625 45 haven't provided any or have done so in the wrong format."%self.path)
map01bf@625 46 if (self.hasTimes and (((timesFile) and timesFile==None) or ((timesData) and timesData==None))):
map01bf@625 47 raise(Usage, "The db you are attempting an insert on (%s) expects times and you either\
map01bf@625 48 haven't provided any or have done so in the wrong format."%self.path)
map01bf@625 49 args = {"db":self._db}
map01bf@625 50 if featFile:
map01bf@625 51 args["features"] = featFile
map01bf@625 52 elif featData:
map01bf@625 53 args["features"] = featData
map01bf@625 54 else:
map01bf@625 55 raise(Usage, "Must provide some feature data!")
map01bf@625 56 if self.hasPower:
map01bf@625 57 if featFile:
map01bf@625 58 args["power"]=powerFile
map01bf@625 59 elif featData:
map01bf@625 60 pass
map01bf@625 61 if self.hasTimes:
map01bf@625 62 if featFile:
map01bf@625 63 args["times"]=timesFile
map01bf@625 64 elif timesData:
map01bf@625 65 pass
map01bf@625 66 if key:
map01bf@625 67 args["key"]=str(key)
map01bf@625 68 if featFile:
map01bf@625 69 if not _pyadb._pyadb_insertFromFile(**args):
map01bf@625 70 raise(RuntimeError, "Insertion failed for an unknown reason.")
map01bf@625 71 else:
map01bf@625 72 self._updateDBAttributes()
map01bf@625 73 return
map01bf@625 74 elif featData:
map01bf@625 75 raise(NotImplementedError, "direct data insertion not yet implemented")
map01bf@625 76
map01bf@625 77
map01bf@625 78 ###internal methods###
map01bf@625 79 def _updateDBAttributes(self):
map01bf@625 80 '''run _pyadb_status to fill/update the database level flags and info'''
map01bf@625 81 rawFlags = long(0)
map01bf@625 82 (self.numFiles,
map01bf@625 83 self.dims,
map01bf@625 84 self.dudCount,
map01bf@625 85 self.nullCount,
map01bf@625 86 rawFlags,
map01bf@625 87 self.length,
map01bf@625 88 self.data_region_size) = _pyadb._pyadb_status(self._db)
map01bf@625 89 self.l2Normed = bool(rawFlags & ADB_HEADER_FLAG_L2NORM)
map01bf@625 90 self.hasPower = bool(rawFlags & ADB_HEADER_FLAG_POWER)
map01bf@625 91 self.hasTimes = bool(rawFlags & ADB_HEADER_FLAG_TIMES)
map01bf@625 92 self.usesRefs = bool(rawFlags & ADB_HEADER_FLAG_REFERENCES)
map01bf@625 93 return
map01bf@625 94
map01bf@625 95
map01bf@625 96
map01bf@625 97
map01bf@625 98 class Result:
map01bf@625 99 def __init__(self):
map01bf@625 100 pass
map01bf@625 101
map01bf@625 102 class untitledTests(unittest.TestCase):
map01bf@625 103 def setUp(self):
map01bf@625 104 pass
map01bf@625 105
map01bf@625 106
map01bf@625 107 if __name__ == '__main__':
map01bf@625 108 unittest.main()