Package dbf
[hide private]

Source Code for Package dbf

  1  """ 
  2  Copyright 
  3  ========= 
  4      - Copyright: 2008-2009 Ad-Mail, Inc -- All rights reserved. 
  5      - Author: Ethan Furman 
  6      - Contact: ethanf@admailinc.com 
  7      - Organization: Ad-Mail, Inc. 
  8      - Version: 0.85.005 as of 29 Oct 2009 
  9   
 10  Redistribution and use in source and binary forms, with or without 
 11  modification, are permitted provided that the following conditions are met: 
 12      - Redistributions of source code must retain the above copyright 
 13        notice, this list of conditions and the following disclaimer. 
 14      - Redistributions in binary form must reproduce the above copyright 
 15        notice, this list of conditions and the following disclaimer in the 
 16        documentation and/or other materials provided with the distribution. 
 17      - Neither the name of Ad-Mail, Inc nor the 
 18        names of its contributors may be used to endorse or promote products 
 19        derived from this software without specific prior written permission. 
 20   
 21  THIS SOFTWARE IS PROVIDED BY Ad-Mail, Inc ''AS IS'' AND ANY 
 22  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 23  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 24  DISCLAIMED. IN NO EVENT SHALL Ad-Mail, Inc BE LIABLE FOR ANY 
 25  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 26  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 28  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 29  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 30  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 31   
 32  B{I{Summary}} 
 33   
 34  Python package for reading/writing dBase III and VFP 6 tables and memos 
 35   
 36  The entire table is read into memory, and all operations occur on the in-memory 
 37  table, with data changes being written to disk as they occur. 
 38   
 39  Goals:  programming style with databases 
 40      - C{table = dbf.table('table name' [, fielddesc[, fielddesc[, ....]]])} 
 41          - fielddesc examples:  C{name C(30); age N(3,0); wisdom M; marriage D} 
 42      - C{record = [ table.current() | table[int] | table.append() | table.[next|prev|top|bottom|goto]() ]} 
 43      - C{record.field | record['field']} accesses the field 
 44   
 45  NOTE:  Of the VFP data types, auto-increment and null settings are not implemented. 
 46  """ 
 47  import os 
 48   
 49  from dbf.dates import Date, DateTime, Time 
 50  from dbf.exceptions import DbfWarning, Bof, Eof, DbfError, DataOverflow, FieldMissing 
 51  from dbf.tables import DbfTable, Db3Table, VfpTable, DbfList, DbfCsv 
 52  from dbf.tables import ascii, codepage, encoding, version_map 
 53   
 54  version = (0, 86, 0) 
 55   
 56  __docformat__ = 'epytext' 
 57   
58 -def Table(filename, field_specs='', memo_size=128, ignore_memos=False, \ 59 read_only=False, keep_memos=False, meta_only=False, type='db3', codepage=None):
60 "returns an open table of the correct type, or creates it if field_specs is given" 61 type = type.lower() 62 if field_specs: 63 if type == 'db3': 64 return Db3Table(filename, field_specs, memo_size, ignore_memos) 65 elif type == 'vfp': 66 return VfpTable(filename, field_specs, memo_size, ignore_memos) 67 elif type == 'dbf': 68 return DbfTable(filename, field_specs) 69 else: 70 raise TypeError("Unknown table type: %s" % type) 71 else: 72 base, ext = os.path.splitext(filename) 73 if ext == '': 74 filename = base + '.dbf' 75 if not os.path.exists(filename): 76 raise DbfError("File %s not found, field_specs not specified" % filename) 77 fd = open(filename) 78 version = fd.read(1) 79 fd.close() 80 fd = None 81 if not version in version_map: 82 raise TypeError("Unknown dbf type: %x" % ord(version)) 83 for tabletype in (Db3Table, VfpTable): 84 if version in tabletype._supported_tables: 85 return tabletype(filename, field_specs, memo_size, ignore_memos, \ 86 read_only, keep_memos, meta_only) 87 else: 88 raise TypeError("Tables of type <%s [%x]> are not supported." % (version_map.get(version, 'Unknown: %s' % version), ord(version)))
89 -def table_type(filename):
90 "returns text representation of a table's dbf version" 91 base, ext = os.path.splitext(filename) 92 if ext == '': 93 filename = base + '.dbf' 94 if os.path.exists(filename): 95 fd = open(filename) 96 version = fd.read(1) 97 fd.close() 98 fd = None 99 if not version in version_map: 100 raise TypeError("Unknown dbf type: %s (%x)" % (version, ord(version))) 101 return version_map[version] 102 return 'File %s not found' % filename
103 -def add_fields(table, field_specs):
104 "adds fields to an existing table" 105 table = Table(table) 106 try: 107 table.add_fields(field_specs) 108 finally: 109 table.close()
110 -def delete_fields(table, field_names):
111 "deletes fields from an existing table" 112 table = Table(table) 113 try: 114 table.delete_fields(field_names) 115 finally: 116 table.close()
117 -def export(table, filename='', fields='', format='csv', header=True):
118 "creates a csv or tab-delimited file from an existing table" 119 table = Table(table) 120 try: 121 table.export(filename, fields, format, header) 122 finally: 123 table.close()
124 -def first_record(table):
125 "prints the first record of a table" 126 table = Table(table) 127 try: 128 print str(table[0]) 129 finally: 130 table.close()
131 -def from_csv(csvfile, to_disk=False, filename=None, field_names=None):
132 "creates a Character table from a csv file" 133 reader = csv.reader(open(csvfile)) 134 if field_names is None: 135 field_names = ['f0'] 136 else: 137 field_names = field_names.replace(', ',',').split(',') 138 mtable = Table(':memory:', '%s M' % field_names[0]) 139 field_count = 1 140 for row in reader: 141 while field_count < len(row): 142 if field_count == len(field_names): 143 field_names.append('f%d' % field_count) 144 mtable.add_fields('%s M' % field_names[field_count]) 145 field_count += 1 146 mtable.append(tuple(row)) 147 if to_disk: 148 if filename is None: 149 filename = os.path.splitext(csvfile)[0] 150 length = [1] * field_count 151 for record in mtable: 152 for i in range(field_count): 153 length[i] = max(length[i], len(record[i])) 154 fields = mtable.field_names 155 fielddef = [] 156 for i in range(field_count): 157 if length[i] < 255: 158 fielddef.append('%s C(%d)' % (fields[i], length[i])) 159 else: 160 fielddef.append('%s M' % (fields[i])) 161 csvtable = Table(filename, ','.join(fielddef)) 162 for record in mtable: 163 csvtable.append(record.scatter_fields()) 164 return mtable
165 -def get_fields(table):
166 "returns the list of field names of a table" 167 table = Table(table) 168 return table.field_names
169 -def info(table):
170 "prints table info" 171 table = Table(table) 172 print str(table)
173 -def rename_field(table, oldfield, newfield):
174 "renames a field in a table" 175 table = Table(table) 176 try: 177 table.rename_field(oldfield, newfield) 178 finally: 179 table.close()
180 -def structure(table, field=None):
181 "returns the definition of a field (or all fields)" 182 table = Table(table) 183 return table.structure(field)
184 -def hex_dump(records):
185 "just what it says ;)" 186 for index,dummy in enumerate(records): 187 chars = dummy._data 188 print "%2d: " % index, 189 for char in chars[1:]: 190 print " %2x " % ord(char), 191 print
192