1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
#!/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 = open(filename, "wb")
_dbfh.write(_dbfStream)
_dbfStream.close()
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 :
|