Package dbf :: Module io
[hide private]
[frames] | no frames]

Source Code for Module dbf.io

  1  """Routines for saving, retrieving, and creating fields""" 
  2   
  3  import struct 
  4  from dbf.exceptions import DataOverflow 
  5  from dbf.dates import Date, DateTime, Time 
  6   
  7  __docformat__ = 'restructuredtext' 
  8   
  9  # Constants 
 10  VFPTIME = 1721425 
 11   
12 -def packShortInt(value, bigendian=False):
13 "Returns a two-bye integer from the value, or raises DbfError" 14 # 256 / 65,536 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)
21 -def packLongInt(value, bigendian=False):
22 "Returns a four-bye integer from the value, or raises DbfError" 23 # 256 / 65,536 / 16,777,216 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)
30 -def packDate(date):
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)
33 -def packStr(string):
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())
38 -def unpackShortInt(bytes, bigendian=False):
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]
44 -def unpackLongInt(bytes, bigendian=False):
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])
50 -def unpackDate(bytestr):
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)
55 -def unpackStr(chars):
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()
58 -def convertToBool(value):
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)
65 -def unsupportedType(something, field, memo=None):
66 "called if a data type is not supported for that style of table" 67 raise DbfError('field type is not supported.')
68 -def retrieveCharacter(bytes, fielddef={}, memo=None):
69 "Returns the string in bytes with trailing white space removed" 70 return bytes.tostring().rstrip()
71 -def updateCharacter(string, fielddef, memo=None):
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()
76 -def retrieveCurrency(bytes, fielddef={}, memo=None):
77 value = struct.unpack('<q', bytes)[0] 78 return Decimal("%de-4" % value)
79 -def updateCurrency(value, fielddef={}, memo=None):
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)
84 -def retrieveDate(bytes, fielddef={}, memo=None):
85 "Returns the ascii coded date as a Date object" 86 return Date.fromymd(bytes.tostring())
87 -def updateDate(moment, fielddef={}, memo=None):
88 "returns the Date or datetime.date object ascii-encoded (yyyymmdd)" 89 if moment: 90 return "%04d%02d%02d" % moment.timetuple()[:3] 91 return ' '
92 -def retrieveDateTime(bytes, fielddef={}, memo=None):
93 """returns the date/time stored in bytes; dates <= 01/01/1981 00:00:00 94 may not be accurate; BC dates are nulled.""" 95 # two four-byte integers store the date and time. 96 # millesecords are discarded from time 97 time = retrieveInteger(bytes[4:]) 98 microseconds = (time % 1000) * 1000 99 time = time // 1000 # int(round(time, -3)) // 1000 discard milliseconds 100 hours = time // 3600 101 mins = time % 3600 // 60 102 secs = time % 3600 % 60 103 time = Time(hours, mins, secs, microseconds) 104 possible = retrieveInteger(bytes[:4]) 105 possible -= VFPTIME 106 possible = max(0, possible) 107 date = Date.fromordinal(possible) 108 return DateTime.combine(date, time)
109 -def updateDateTime(moment, fielddef={}, memo=None):
110 """sets the date/time stored in moment 111 moment must have fields year, month, day, hour, minute, second, microsecond""" 112 bytes = [0] * 8 113 hour = moment.hour 114 minute = moment.minute 115 second = moment.second 116 millisecond = moment.microsecond // 1000 # convert from millionths to thousandths 117 time = ((hour * 3600) + (minute * 60) + second) * 1000 + millisecond 118 bytes[4:] = updateInteger(time) 119 bytes[:4] = updateInteger(moment.toordinal() + VFPTIME) 120 return ''.join(bytes)
121 -def retrieveDouble(bytes, fielddef={}, memo=None):
122 return struct.unpack('<d', bytes)[0]
123 -def updateDouble(value, fielddef={}, memo=None):
124 if not (type(value) in (int, long, float)): 125 raise DbfError("incompatible type: %s" % type(value)) 126 return struct.pack('<d', value)
127 -def retrieveInteger(bytes, fielddef={}, memo=None):
128 "Returns the binary number stored in bytes in little-endian format" 129 return struct.unpack('<i', bytes)[0]
130 -def updateInteger(value, fielddef={}, memo=None):
131 "returns value in little-endian binary format" 132 if not (type(value) in (int, long)): 133 raise DbfError("incompatible type: %s" % type(value)) 134 if not -2147483648 < value < 2147483647: 135 raise DataOverflow("Integer size exceeded. Possible: -2,147,483,648..+2,147,483,647. Attempted: %d" % value) 136 return struct.pack('<i', value)
137 -def retrieveLogical(bytes, fielddef={}, memo=None):
138 "Returns True if bytes is 't', 'T', 'y', or 'Y', and False otherwise" 139 return bytes.tostring() in ['t','T','y','Y']
140 -def updateLogical(logical, fielddef={}, memo=None):
141 "Returs 'T' if logical is True, 'F' otherwise" 142 if type(logical) != bool: 143 logical = convertToBool(logical) 144 if type(logical) <> bool: 145 raise DbfError('Value %s is not logical.' % logical) 146 return logical and 'T' or 'F'
147 -def retrieveMemo(bytes, fielddef, memo):
148 "Returns the block of data from a memo file" 149 stringval = bytes.tostring() 150 if stringval.strip(): 151 block = int(stringval.strip()) 152 else: 153 block = 0 154 return memo.getMemo(block, fielddef)
155 -def updateMemo(string, fielddef, memo):
156 "Writes string as a memo, returns the block number it was saved into" 157 block = memo.putMemo(string) 158 if block == 0: 159 block = '' 160 return "%*s" % (fielddef['length'], block)
161 -def retrieveNumeric(bytes, fielddef, memo=None):
162 "Returns the number stored in bytes as integer if field spec for decimals is 0, float otherwise" 163 string = bytes.tostring() 164 if not string.strip(): 165 string = '0' 166 if fielddef['decimals'] == 0: 167 return int(string) 168 else: 169 return float(string)
170 -def updateNumeric(value, fielddef, memo=None):
171 "returns value as ascii representation, rounding decimal portion as necessary" 172 if not (type(value) in (int, long, float)): 173 raise DbfError("incompatible type: %s" % type(value)) 174 decimalsize = fielddef['decimals'] 175 if decimalsize: 176 decimalsize += 1 177 maxintegersize = fielddef['length']-decimalsize 178 integersize = len("%.0f" % value) 179 if integersize > maxintegersize: 180 raise DataOverflow('Integer portion too big') 181 return "%*.*f" % (fielddef['length'], fielddef['decimals'], value)
182 -def retrieveVfpMemo(bytes, fielddef, memo):
183 "Returns the block of data from a memo file" 184 block = struct.unpack('<i', bytes)[0] 185 return memo.getMemo(block, fielddef)
186 -def updateVfpMemo(string, fielddef, memo):
187 "Writes string as a memo, returns the block number it was saved into" 188 block = memo.putMemo(string) 189 return struct.pack('<i', block)
190 -def addCharacter(format):
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
198 -def addDate(format):
199 length = 8 200 decimals = 0 201 return length, decimals
202 -def addLogical(format):
203 length = 1 204 decimals = 0 205 return length, decimals
206 -def addMemo(format):
207 length = 10 208 decimals = 0 209 return length, decimals
210 -def addNumeric(format):
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
219 -def addVfpCurrency(format):
220 length = 8 221 decimals = 0 222 return length, decimals
223 -def addVfpDateTime(format):
224 length = 8 225 decimals = 8 226 return length, decimals
227 -def addVfpDouble(format):
228 length = 8 229 decimals = 0 230 return length, decimals
231 -def addVfpInteger(format):
232 length = 4 233 decimals = 0 234 return length, decimals
235 -def addVfpMemo(format):
236 length = 4 237 decimals = 0 238 return length, decimals
239 -def addVfpNumeric(format):
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