mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 23:10:17 +00:00
190 lines
5.3 KiB
Python
190 lines
5.3 KiB
Python
#!/usr/bin/python
|
|
""".DBF creation helpers.
|
|
|
|
Note: this is a legacy interface. New code should use Dbf class
|
|
for table creation (see examples in dbf.py)
|
|
|
|
TODO:
|
|
- handle Memo fields.
|
|
- check length of the fields accoring to the
|
|
`http://www.clicketyclick.dk/databases/xbase/format/data_types.html`
|
|
|
|
"""
|
|
"""History (most recent first)
|
|
04-jul-2006 [als] added export declaration;
|
|
updated for dbfpy 2.0
|
|
15-dec-2005 [yc] define dbf_new.__slots__
|
|
14-dec-2005 [yc] added vim modeline; retab'd; added doc-strings;
|
|
dbf_new now is a new class (inherited from object)
|
|
??-jun-2000 [--] added by Hans Fiby
|
|
"""
|
|
|
|
__version__ = "$Revision: 1.4 $"[11:-2]
|
|
__date__ = "$Date: 2006/07/04 08:18:18 $"[7:-2]
|
|
|
|
__all__ = ["dbf_new"]
|
|
|
|
from dbf import *
|
|
from fields import *
|
|
from header import *
|
|
from record import *
|
|
|
|
|
|
class _FieldDefinition(object):
|
|
"""Field definition.
|
|
|
|
This is a simple structure, which contains ``name``, ``type``,
|
|
``len``, ``dec`` and ``cls`` fields.
|
|
|
|
Objects also implement get/setitem magic functions, so fields
|
|
could be accessed via sequence iterface, where 'name' has
|
|
index 0, 'type' index 1, 'len' index 2, 'dec' index 3 and
|
|
'cls' could be located at index 4.
|
|
|
|
"""
|
|
|
|
__slots__ = "name", "type", "len", "dec", "cls"
|
|
|
|
# WARNING: be attentive - dictionaries are mutable!
|
|
FLD_TYPES = {
|
|
# type: (cls, len)
|
|
"C": (DbfCharacterFieldDef, None),
|
|
"N": (DbfNumericFieldDef, None),
|
|
"L": (DbfLogicalFieldDef, 1),
|
|
# FIXME: support memos
|
|
# "M": (DbfMemoFieldDef),
|
|
"D": (DbfDateFieldDef, 8),
|
|
# FIXME: I'm not sure length should be 14 characters!
|
|
# but temporary I use it, cuz date is 8 characters
|
|
# and time 6 (hhmmss)
|
|
"T": (DbfDateTimeFieldDef, 14),
|
|
}
|
|
|
|
def __init__(self, name, type, len=None, dec=0):
|
|
_cls, _len = self.FLD_TYPES[type]
|
|
if _len is None:
|
|
if len is None:
|
|
raise ValueError("Field length must be defined")
|
|
_len = len
|
|
self.name = name
|
|
self.type = type
|
|
self.len = _len
|
|
self.dec = dec
|
|
self.cls = _cls
|
|
|
|
def getDbfField(self):
|
|
"Return `DbfFieldDef` instance from the current definition."
|
|
return self.cls(self.name, self.len, self.dec)
|
|
|
|
def appendToHeader(self, dbfh):
|
|
"""Create a `DbfFieldDef` instance and append it to the dbf header.
|
|
|
|
Arguments:
|
|
dbfh: `DbfHeader` instance.
|
|
|
|
"""
|
|
_dbff = self.getDbfField()
|
|
dbfh.addField(_dbff)
|
|
|
|
|
|
class dbf_new(object):
|
|
"""New .DBF creation helper.
|
|
|
|
Example Usage:
|
|
|
|
dbfn = dbf_new()
|
|
dbfn.add_field("name",'C',80)
|
|
dbfn.add_field("price",'N',10,2)
|
|
dbfn.add_field("date",'D',8)
|
|
dbfn.write("tst.dbf")
|
|
|
|
Note:
|
|
This module cannot handle Memo-fields,
|
|
they are special.
|
|
|
|
"""
|
|
|
|
__slots__ = ("fields",)
|
|
|
|
FieldDefinitionClass = _FieldDefinition
|
|
|
|
def __init__(self):
|
|
self.fields = []
|
|
|
|
def add_field(self, name, typ, len, dec=0):
|
|
"""Add field definition.
|
|
|
|
Arguments:
|
|
name:
|
|
field name (str object). field name must not
|
|
contain ASCII NULs and it's length shouldn't
|
|
exceed 10 characters.
|
|
typ:
|
|
type of the field. this must be a single character
|
|
from the "CNLMDT" set meaning character, numeric,
|
|
logical, memo, date and date/time respectively.
|
|
len:
|
|
length of the field. this argument is used only for
|
|
the character and numeric fields. all other fields
|
|
have fixed length.
|
|
FIXME: use None as a default for this argument?
|
|
dec:
|
|
decimal precision. used only for the numric fields.
|
|
|
|
"""
|
|
self.fields.append(self.FieldDefinitionClass(name, typ, len, dec))
|
|
|
|
def write(self, filename):
|
|
"""Create empty .DBF file using current structure."""
|
|
_dbfh = DbfHeader()
|
|
_dbfh.setCurrentDate()
|
|
for _fldDef in self.fields:
|
|
_fldDef.appendToHeader(_dbfh)
|
|
_dbfStream = file(filename, "wb")
|
|
_dbfh.write(_dbfStream)
|
|
_dbfStream.close()
|
|
|
|
def write_stream(self, stream):
|
|
_dbfh = DbfHeader()
|
|
_dbfh.setCurrentDate()
|
|
for _fldDef in self.fields:
|
|
_fldDef.appendToHeader(_dbfh)
|
|
_dbfh.write(stream)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# create a new DBF-File
|
|
dbfn = dbf_new()
|
|
dbfn.add_field("name", 'C', 80)
|
|
dbfn.add_field("price", 'N', 10, 2)
|
|
dbfn.add_field("date", 'D', 8)
|
|
dbfn.write("tst.dbf")
|
|
# test new dbf
|
|
print "*** created tst.dbf: ***"
|
|
dbft = Dbf('tst.dbf', readOnly=0)
|
|
print repr(dbft)
|
|
# add a record
|
|
rec = DbfRecord(dbft)
|
|
rec['name'] = 'something'
|
|
rec['price'] = 10.5
|
|
rec['date'] = (2000, 1, 12)
|
|
rec.store()
|
|
# add another record
|
|
rec = DbfRecord(dbft)
|
|
rec['name'] = 'foo and bar'
|
|
rec['price'] = 12234
|
|
rec['date'] = (1992, 7, 15)
|
|
rec.store()
|
|
|
|
# show the records
|
|
print "*** inserted 2 records into tst.dbf: ***"
|
|
print repr(dbft)
|
|
for i1 in range(len(dbft)):
|
|
rec = dbft[i1]
|
|
for fldName in dbft.fieldNames:
|
|
print '%s:\t %s' % (fldName, rec[fldName])
|
|
print
|
|
dbft.close()
|
|
|
|
# vim: set et sts=4 sw=4 :
|