"""DBF header definition. TODO: - handle encoding of the character fields (encoding information stored in the DBF header) """ """History (most recent first): 16-sep-2010 [als] fromStream: fix century of the last update field 11-feb-2007 [als] added .ignoreErrors 10-feb-2007 [als] added __getitem__: return field definitions by field name or field number (zero-based) 04-jul-2006 [als] added export declaration 15-dec-2005 [yc] created """ __version__ = "$Revision: 1.6 $"[11:-2] __date__ = "$Date: 2010/09/16 05:06:39 $"[7:-2] __all__ = ["DbfHeader"] import datetime import io import struct import sys from . import fields from .utils import getDate class DbfHeader: """Dbf header definition. For more information about dbf header format visit `http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT` Examples: Create an empty dbf header and add some field definitions: dbfh = DbfHeader() dbfh.addField(("name", "C", 10)) dbfh.addField(("date", "D")) dbfh.addField(DbfNumericFieldDef("price", 5, 2)) Create a dbf header with field definitions: dbfh = DbfHeader([ ("name", "C", 10), ("date", "D"), DbfNumericFieldDef("price", 5, 2), ]) """ __slots__ = ("signature", "fields", "lastUpdate", "recordLength", "recordCount", "headerLength", "changed", "_ignore_errors") # instance construction and initialization methods def __init__(self, fields=None, headerLength=0, recordLength=0, recordCount=0, signature=0x03, lastUpdate=None, ignoreErrors=False): """Initialize instance. Arguments: fields: a list of field definitions; recordLength: size of the records; headerLength: size of the header; recordCount: number of records stored in DBF; signature: version number (aka signature). using 0x03 as a default meaning "File without DBT". for more information about this field visit ``http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_NOTE_1_TARGET`` lastUpdate: date of the DBF's update. this could be a string ('yymmdd' or 'yyyymmdd'), timestamp (int or float), datetime/date value, a sequence (assuming (yyyy, mm, dd, ...)) or an object having callable ``ticks`` field. ignoreErrors: error processing mode for DBF fields (boolean) """ self.signature = signature if fields is None: self.fields = [] else: self.fields = list(fields) self.lastUpdate = getDate(lastUpdate) self.recordLength = recordLength self.headerLength = headerLength self.recordCount = recordCount self.ignoreErrors = ignoreErrors # XXX: I'm not sure this is safe to # initialize `self.changed` in this way self.changed = bool(self.fields) # @classmethod def fromString(cls, string): """Return header instance from the string object.""" return cls.fromStream(io.StringIO(str(string))) fromString = classmethod(fromString) # @classmethod def fromStream(cls, stream): """Return header object from the stream.""" stream.seek(0) first_32 = stream.read(32) if type(first_32) != bytes: _data = bytes(first_32, sys.getfilesystemencoding()) _data = first_32 (_cnt, _hdrLen, _recLen) = struct.unpack("