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  from math import floor 
  8   
  9   
 10   
 11  VFPTIME = 1721425 
 12   
 14          "Returns a two-bye integer from the value, or raises DbfError" 
 15           
 16          if value > 65535: 
 17              raise DateOverflow("Maximum Integer size exceeded.  Possible: 65535.  Attempted: %d" % value) 
 18          if bigendian: 
 19              return struct.pack('>H', value) 
 20          else: 
 21              return struct.pack('<H', value) 
  23          "Returns a four-bye integer from the value, or raises DbfError" 
 24           
 25          if value > 4294967295: 
 26              raise DateOverflow("Maximum Integer size exceeded.  Possible: 4294967295.  Attempted: %d" % value) 
 27          if bigendian: 
 28              return struct.pack('>L', value) 
 29          else: 
 30              return struct.pack('<L', value) 
  32          "Returns a group of three bytes, in integer form, of the date" 
 33          return "%c%c%c" % (date.year-1900, date.month, date.day) 
  35          "Returns an 11 byte, upper-cased, null padded string suitable for field names; raises DbfError if the string is bigger than 10 bytes" 
 36          if len(string) > 10: 
 37              raise DbfError("Maximum string size is ten characters -- %s has %d characters" % (string, len(string))) 
 38          return struct.pack('11s', string.upper())        
  40          "Returns the value in the two-byte integer passed in" 
 41          if bigendian: 
 42              return struct.unpack('>H', bytes)[0] 
 43          else: 
 44              return struct.unpack('<H', bytes)[0] 
  46          "Returns the value in the four-byte integer passed in" 
 47          if bigendian: 
 48              return int(struct.unpack('>L', bytes)[0]) 
 49          else: 
 50              return int(struct.unpack('<L', bytes)[0]) 
  52          "Returns a Date() of the packed three-byte date passed in" 
 53          year, month, day = struct.unpack('<BBB', bytestr) 
 54          year += 1900 
 55          return Date(year, month, day) 
  57          "Returns a normal, lower-cased string from a null-padded byte string" 
 58          return struct.unpack('%ds' % len(chars), chars)[0].replace('\x00','').lower() 
  60      """Returns boolean true or false; normal rules apply to non-string values; string values 
 61      must be 'y','t', 'yes', or 'true' (case insensitive) to be True""" 
 62      if type(value) == str: 
 63          return bool(value.lower() in ['t', 'y', 'true', 'yes']) 
 64      else: 
 65          return bool(value) 
  67      "called if a data type is not supported for that style of table" 
 68      raise DbfError('field type is not supported.') 
  70      "Returns the string in bytes with trailing white space removed" 
 71      return bytes.tostring().rstrip() 
  73      "returns the string, truncating if string is longer than it's field" 
 74      if type(string) != str: 
 75          raise DbfError("incompatible type: %s" % type(string)) 
 76      return string.rstrip() 
  78      value = struct.unpack('<q', bytes)[0] 
 79      return Decimal("%de-4" % value) 
  81      currency = int(value * 10000) 
 82      if not -9223372036854775808 < currency < 9223372036854775808: 
 83          raise DataOverflow("value %s is out of bounds" % value) 
 84      return struct.pack('<q', currency) 
  86      "Returns the ascii coded date as a Date object" 
 87      return Date.fromymd(bytes.tostring()) 
  89      "returns the Date or datetime.date object ascii-encoded (yyyymmdd)" 
 90      if moment: 
 91          return "%04d%02d%02d" % moment.timetuple()[:3] 
 92      return '        ' 
  94      return struct.unpack('<d', bytes)[0] 
  96      if not (type(value) in (int, long, float)): 
 97          raise DbfError("incompatible type: %s" % type(value)) 
 98      return struct.pack('<d', value) 
 100      "Returns the binary number stored in bytes in little-endian format" 
101      return struct.unpack('<i', bytes)[0] 
 103      "returns value in little-endian binary format" 
104      if not (type(value) in (int, long)): 
105          raise DbfError("incompatible type: %s" % type(value)) 
106      if not -2147483648 < value < 2147483647: 
107          raise DataOverflow("Integer size exceeded.  Possible: -2,147,483,648..+2,147,483,647.  Attempted: %d" % value) 
108      return struct.pack('<i', value) 
 110      "Returns True if bytes is 't', 'T', 'y', or 'Y', None if '?', and False otherwise" 
111      bytes = bytes.tostring() 
112      if bytes == '?': 
113          return None 
114      return bytes in ['t','T','y','Y'] 
 116      "Returs 'T' if logical is True, 'F' otherwise" 
117      if type(logical) != bool: 
118          logical = convertToBool(logical) 
119      if type(logical) <> bool: 
120          raise DbfError('Value %s is not logical.' % logical) 
121      return logical and 'T' or 'F' 
 123      "Returns the block of data from a memo file" 
124      stringval = bytes.tostring() 
125      if stringval.strip(): 
126          block = int(stringval.strip()) 
127      else: 
128          block = 0 
129      return memo.get_memo(block, fielddef) 
 131      "Writes string as a memo, returns the block number it was saved into" 
132      block = memo.put_memo(string) 
133      if block == 0: 
134          block = '' 
135      return "%*s" % (fielddef['length'], block) 
 137      "Returns the number stored in bytes as integer if field spec for decimals is 0, float otherwise" 
138      string = bytes.tostring() 
139      if string[0:1] == '*':   
140          return None 
141      if not string.strip(): 
142          string = '0' 
143      if fielddef['decimals'] == 0: 
144          return int(string) 
145      else: 
146          return float(string) 
 148      "returns value as ascii representation, rounding decimal portion as necessary" 
149      if not (type(value) in (int, long, float)): 
150          raise DbfError("incompatible type: %s" % type(value)) 
151      decimalsize = fielddef['decimals'] 
152      if decimalsize: 
153          decimalsize += 1 
154      maxintegersize = fielddef['length']-decimalsize 
155      integersize = len("%.0f" % floor(value)) 
156      if integersize > maxintegersize: 
157          raise DataOverflow('Integer portion too big') 
158      return "%*.*f" % (fielddef['length'], fielddef['decimals'], value) 
 177      """sets the date/time stored in moment 
178      moment must have fields year, month, day, hour, minute, second, microsecond""" 
179      bytes = [0] * 8 
180      hour = moment.hour 
181      minute = moment.minute 
182      second = moment.second 
183      millisecond = moment.microsecond // 1000        
184      time = ((hour * 3600) + (minute * 60) + second) * 1000 + millisecond 
185      bytes[4:] = updateInteger(time) 
186      bytes[:4] = updateInteger(moment.toordinal() + VFPTIME) 
187      return ''.join(bytes) 
 189      "Returns the block of data from a memo file" 
190      block = struct.unpack('<i', bytes)[0] 
191      return memo.get_memo(block, fielddef) 
 193      "Writes string as a memo, returns the block number it was saved into" 
194      block = memo.put_memo(string) 
195      return struct.pack('<i', block) 
 197      if format[1] != '(' or format[-1] != ')': 
198          raise DbfError("Format for Character field creation is C(n), not %s" % format) 
199      length = int(format[2:-1]) 
200      if not 0 < length < 255: 
201          raise ValueError 
202      decimals = 0 
203      return length, decimals 
 205      length = 8 
206      decimals = 0 
207      return length, decimals 
 209      length = 1 
210      decimals = 0 
211      return length, decimals 
 213      length = 10 
214      decimals = 0 
215      return length, decimals 
 217      if format[1] != '(' or format[-1] != ')': 
218          raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format) 
219      length, decimals = format[2:-1].split(',') 
220      length = int(length) 
221      decimals = int(decimals) 
222      if not 0 < length < 18: 
223          raise ValueError 
224      if decimals and not 0 < decimals <= length - 2: 
225          raise ValueError 
226      return length, decimals 
 228      length = 8 
229      decimals = 0 
230      return length, decimals 
 232      length = 8 
233      decimals = 8 
234      return length, decimals 
 236      length = 8 
237      decimals = 0 
238      return length, decimals 
 240      length = 4 
241      decimals = 0 
242      return length, decimals 
 244      length = 4 
245      decimals = 0 
246      return length, decimals 
 248      if format[1] != '(' or format[-1] != ')': 
249          raise DbfError("Format for Numeric field creation is N(n,n), not %s" % format) 
250      length, decimals = format[2:-1].split(',') 
251      length = int(length) 
252      decimals = int(decimals) 
253      if not 0 < length < 21: 
254          raise ValueError 
255      if decimals and not 0 < decimals <= length - 2: 
256          raise ValueError 
257      return length, decimals 
 258