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', None if '?', and False otherwise"
110 bytes = bytes.tostring()
111 if bytes == '?':
112 return None
113 return bytes in ['t','T','y','Y']
115 "Returs 'T' if logical is True, 'F' otherwise"
116 if type(logical) != bool:
117 logical = convertToBool(logical)
118 if type(logical) <> bool:
119 raise DbfError('Value %s is not logical.' % logical)
120 return logical and 'T' or 'F'
122 "Returns the block of data from a memo file"
123 stringval = bytes.tostring()
124 if stringval.strip():
125 block = int(stringval.strip())
126 else:
127 block = 0
128 return memo.get_memo(block, fielddef)
130 "Writes string as a memo, returns the block number it was saved into"
131 block = memo.put_memo(string)
132 if block == 0:
133 block = ''
134 return "%*s" % (fielddef['length'], block)
136 "Returns the number stored in bytes as integer if field spec for decimals is 0, float otherwise"
137 string = bytes.tostring()
138 if string[0:1] == '*':
139 return None
140 if not string.strip():
141 string = '0'
142 if fielddef['decimals'] == 0:
143 return int(string)
144 else:
145 return float(string)
147 "returns value as ascii representation, rounding decimal portion as necessary"
148 if not (type(value) in (int, long, float)):
149 raise DbfError("incompatible type: %s" % type(value))
150 decimalsize = fielddef['decimals']
151 if decimalsize:
152 decimalsize += 1
153 maxintegersize = fielddef['length']-decimalsize
154 integersize = len("%.0f" % value)
155 if integersize > maxintegersize:
156 raise DataOverflow('Integer portion too big')
157 return "%*.*f" % (fielddef['length'], fielddef['decimals'], value)
176 """sets the date/time stored in moment
177 moment must have fields year, month, day, hour, minute, second, microsecond"""
178 bytes = [0] * 8
179 hour = moment.hour
180 minute = moment.minute
181 second = moment.second
182 millisecond = moment.microsecond // 1000
183 time = ((hour * 3600) + (minute * 60) + second) * 1000 + millisecond
184 bytes[4:] = updateInteger(time)
185 bytes[:4] = updateInteger(moment.toordinal() + VFPTIME)
186 return ''.join(bytes)
188 "Returns the block of data from a memo file"
189 block = struct.unpack('<i', bytes)[0]
190 return memo.get_memo(block, fielddef)
192 "Writes string as a memo, returns the block number it was saved into"
193 block = memo.put_memo(string)
194 return struct.pack('<i', block)
196 if format[1] != '(' or format[-1] != ')':
197 raise DbfError("Format for Character field creation is C(n), not %s" % format)
198 length = int(format[2:-1])
199 if not 0 < length < 255:
200 raise ValueError
201 decimals = 0
202 return length, decimals
204 length = 8
205 decimals = 0
206 return length, decimals
208 length = 1
209 decimals = 0
210 return length, decimals
212 length = 10
213 decimals = 0
214 return length, decimals
216 if format[1] != '(' or format[-1] != ')':
217 raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format)
218 length, decimals = format[2:-1].split(',')
219 length = int(length)
220 decimals = int(decimals)
221 if not (0 < length < 18 and 0 <= decimals <= length - 2):
222 raise ValueError
223 return length, decimals
225 length = 8
226 decimals = 0
227 return length, decimals
229 length = 8
230 decimals = 8
231 return length, decimals
233 length = 8
234 decimals = 0
235 return length, decimals
237 length = 4
238 decimals = 0
239 return length, decimals
241 length = 4
242 decimals = 0
243 return length, decimals
245 if format[1] != '(' or format[-1] != ')':
246 raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format)
247 length, decimals = format[2:-1].split(',')
248 length = int(length)
249 decimals = int(decimals)
250 if not (0 < length < 21 and 0 <= decimals <= length - 2):
251 raise ValueError
252 return length, decimals
253