1 """Routines for saving, retrieving, and creating fields"""
2
3 import struct
4 from decimal import Decimal
5 from dbf.exceptions import DbfError, DataOverflow
6 from dbf.dates import Date, DateTime, Time
7
8
9
10 VFPTIME = 1721425
11
13 "Returns a two-bye integer from the value, or raises DbfError"
14
15 if value > 65535:
16 raise DateOverflow("Maximum Integer size exceeded. Possible: 65535. Attempted: %d" % value)
17 if bigendian:
18 return struct.pack('>H', value)
19 else:
20 return struct.pack('<H', value)
22 "Returns a four-bye integer from the value, or raises DbfError"
23
24 if value > 4294967295:
25 raise DateOverflow("Maximum Integer size exceeded. Possible: 4294967295. Attempted: %d" % value)
26 if bigendian:
27 return struct.pack('>L', value)
28 else:
29 return struct.pack('<L', value)
31 "Returns a group of three bytes, in integer form, of the date"
32 return "%c%c%c" % (date.year-1900, date.month, date.day)
34 "Returns an 11 byte, upper-cased, null padded string suitable for field names; raises DbfError if the string is bigger than 10 bytes"
35 if len(string) > 10:
36 raise DbfError("Maximum string size is ten characters -- %s has %d characters" % (string, len(string)))
37 return struct.pack('11s', string.upper())
39 "Returns the value in the two-byte integer passed in"
40 if bigendian:
41 return struct.unpack('>H', bytes)[0]
42 else:
43 return struct.unpack('<H', bytes)[0]
45 "Returns the value in the four-byte integer passed in"
46 if bigendian:
47 return int(struct.unpack('>L', bytes)[0])
48 else:
49 return int(struct.unpack('<L', bytes)[0])
51 "Returns a Date() of the packed three-byte date passed in"
52 year, month, day = struct.unpack('<BBB', bytestr)
53 year += 1900
54 return Date(year, month, day)
56 "Returns a normal, lower-cased string from a null-padded byte string"
57 return struct.unpack('%ds' % len(chars), chars)[0].replace('\x00','').lower()
59 """Returns boolean true or false; normal rules apply to non-string values; string values
60 must be 'y','t', 'yes', or 'true' (case insensitive) to be True"""
61 if type(value) == str:
62 return bool(value.lower() in ['t', 'y', 'true', 'yes'])
63 else:
64 return bool(value)
66 "called if a data type is not supported for that style of table"
67 raise DbfError('field type is not supported.')
69 "Returns the string in bytes with trailing white space removed"
70 return bytes.tostring().rstrip()
72 "returns the string, truncating if string is longer than it's field"
73 if type(string) != str:
74 raise DbfError("incompatible type: %s" % type(string))
75 return string.rstrip()
77 value = struct.unpack('<q', bytes)[0]
78 return Decimal("%de-4" % value)
80 currency = int(value * 10000)
81 if not -9223372036854775808 < currency < 9223372036854775808:
82 raise DataOverflow("value %s is out of bounds" % value)
83 return struct.pack('<q', currency)
85 "Returns the ascii coded date as a Date object"
86 return Date.fromymd(bytes.tostring())
88 "returns the Date or datetime.date object ascii-encoded (yyyymmdd)"
89 if moment:
90 return "%04d%02d%02d" % moment.timetuple()[:3]
91 return ' '
93 return struct.unpack('<d', bytes)[0]
95 if not (type(value) in (int, long, float)):
96 raise DbfError("incompatible type: %s" % type(value))
97 return struct.pack('<d', value)
99 "Returns the binary number stored in bytes in little-endian format"
100 return struct.unpack('<i', bytes)[0]
102 "returns value in little-endian binary format"
103 if not (type(value) in (int, long)):
104 raise DbfError("incompatible type: %s" % type(value))
105 if not -2147483648 < value < 2147483647:
106 raise DataOverflow("Integer size exceeded. Possible: -2,147,483,648..+2,147,483,647. Attempted: %d" % value)
107 return struct.pack('<i', value)
109 "Returns True if bytes is 't', 'T', 'y', or 'Y', and False otherwise"
110 return bytes.tostring() in ['t','T','y','Y']
112 "Returs 'T' if logical is True, 'F' otherwise"
113 if type(logical) != bool:
114 logical = convertToBool(logical)
115 if type(logical) <> bool:
116 raise DbfError('Value %s is not logical.' % logical)
117 return logical and 'T' or 'F'
119 "Returns the block of data from a memo file"
120 stringval = bytes.tostring()
121 if stringval.strip():
122 block = int(stringval.strip())
123 else:
124 block = 0
125 return memo.get_memo(block, fielddef)
127 "Writes string as a memo, returns the block number it was saved into"
128 block = memo.put_memo(string)
129 if block == 0:
130 block = ''
131 return "%*s" % (fielddef['length'], block)
133 "Returns the number stored in bytes as integer if field spec for decimals is 0, float otherwise"
134 string = bytes.tostring()
135 if not string.strip():
136 string = '0'
137 if fielddef['decimals'] == 0:
138 return int(string)
139 else:
140 return float(string)
142 "returns value as ascii representation, rounding decimal portion as necessary"
143 if not (type(value) in (int, long, float)):
144 raise DbfError("incompatible type: %s" % type(value))
145 decimalsize = fielddef['decimals']
146 if decimalsize:
147 decimalsize += 1
148 maxintegersize = fielddef['length']-decimalsize
149 integersize = len("%.0f" % value)
150 if integersize > maxintegersize:
151 raise DataOverflow('Integer portion too big')
152 return "%*.*f" % (fielddef['length'], fielddef['decimals'], value)
171 """sets the date/time stored in moment
172 moment must have fields year, month, day, hour, minute, second, microsecond"""
173 bytes = [0] * 8
174 hour = moment.hour
175 minute = moment.minute
176 second = moment.second
177 millisecond = moment.microsecond // 1000
178 time = ((hour * 3600) + (minute * 60) + second) * 1000 + millisecond
179 bytes[4:] = updateInteger(time)
180 bytes[:4] = updateInteger(moment.toordinal() + VFPTIME)
181 return ''.join(bytes)
183 "Returns the block of data from a memo file"
184 block = struct.unpack('<i', bytes)[0]
185 return memo.get_memo(block, fielddef)
187 "Writes string as a memo, returns the block number it was saved into"
188 block = memo.put_memo(string)
189 return struct.pack('<i', block)
191 if format[1] != '(' or format[-1] != ')':
192 raise DbfError("Format for Character field creation is C(n), not %s" % format)
193 length = int(format[2:-1])
194 if not 0 < length < 255:
195 raise ValueError
196 decimals = 0
197 return length, decimals
199 length = 8
200 decimals = 0
201 return length, decimals
203 length = 1
204 decimals = 0
205 return length, decimals
207 length = 10
208 decimals = 0
209 return length, decimals
211 if format[1] != '(' or format[-1] != ')':
212 raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format)
213 length, decimals = format[2:-1].split(',')
214 length = int(length)
215 decimals = int(decimals)
216 if not (0 < length < 18 and 0 <= decimals <= length - 2):
217 raise ValueError
218 return length, decimals
220 length = 8
221 decimals = 0
222 return length, decimals
224 length = 8
225 decimals = 8
226 return length, decimals
228 length = 8
229 decimals = 0
230 return length, decimals
232 length = 4
233 decimals = 0
234 return length, decimals
236 length = 4
237 decimals = 0
238 return length, decimals
240 if format[1] != '(' or format[-1] != ')':
241 raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format)
242 length, decimals = format[2:-1].split(',')
243 length = int(length)
244 decimals = int(decimals)
245 if not (0 < length < 21 and 0 <= decimals <= length - 2):
246 raise ValueError
247 return length, decimals
248