From: alexander s. <a1...@us...> - 2010-12-14 11:07:55
|
Update of /cvsroot/dbfpy/dbfpy/dbfpy In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv17227 Modified Files: header.py Log Message: added Memo file support Index: header.py =================================================================== RCS file: /cvsroot/dbfpy/dbfpy/dbfpy/header.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** header.py 16 Sep 2010 05:06:39 -0000 1.6 --- header.py 14 Dec 2010 11:07:45 -0000 1.7 *************** *** 7,10 **** --- 7,11 ---- """ """History (most recent first): + 14-dec-2010 [als] added Memo file support 16-sep-2010 [als] fromStream: fix century of the last update field 11-feb-2007 [als] added .ignoreErrors *************** *** 138,141 **** --- 139,150 ---- day = property(lambda self: self.lastUpdate.day) + @property + def hasMemoField(self): + """True if at least one field is a Memo field""" + for _field in self.fields: + if _field.isMemo: + return True + return False + def ignoreErrors(self, value): """Update `ignoreErrors` flag on self and all fields""" *************** *** 187,191 **** # wanna add any of the definitions -- all will be ignored) _defs = [] ! _recordLength = 0 for _def in defs: if isinstance(_def, fields.DbfFieldDef): --- 196,200 ---- # wanna add any of the definitions -- all will be ignored) _defs = [] ! _recordLength = self.recordLength for _def in defs: if isinstance(_def, fields.DbfFieldDef): *************** *** 194,198 **** (_name, _type, _len, _dec) = (tuple(_def) + (None,) * 4)[:4] _cls = fields.lookupFor(_type) ! _obj = _cls(_name, _len, _dec, ignoreErrors=self._ignore_errors) _recordLength += _obj.length --- 203,207 ---- (_name, _type, _len, _dec) = (tuple(_def) + (None,) * 4)[:4] _cls = fields.lookupFor(_type) ! _obj = _cls(_name, _len, _dec, _recordLength, ignoreErrors=self._ignore_errors) _recordLength += _obj.length *************** *** 201,208 **** # update record length self.fields += _defs ! return _recordLength ## interface methods def addField(self, *defs): """Add field definition to the header. --- 210,247 ---- # update record length self.fields += _defs ! return (_recordLength - self.recordLength) ! ! def _calcHeaderLength(self): ! """Update self.headerLength attribute after change to header contents ! """ ! # recalculate headerLength ! self.headerLength = 32 + (32 * len(self.fields)) + 1 ! if self.signature == 0x30: ! # Visual FoxPro files have 263-byte zero-filled field for backlink ! self.headerLength += 263 ## interface methods + def setMemoFile(self, memo): + """Attach MemoFile instance to all memo fields; check header signature + """ + _has_memo = False + for _field in self.fields: + if _field.isMemo: + _field.file = memo + _has_memo = True + # for signatures list, see + # http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_NOTE_1_TARGET + # http://www.dbf2002.com/dbf-file-format.html + # If memo is attached, will use 0x30 for Visual FoxPro file, + # 0x83 for dBASE III+. + if _has_memo \ + and (self.signature not in (0x30, 0x83, 0x8B, 0xCB, 0xE5, 0xF5)): + if memo.is_fpt: + self.signature = 0x30 + else: + self.signature = 0x83 + self._calcHeaderLength() + def addField(self, *defs): """Add field definition to the header. *************** *** 219,230 **** """ ! _oldLen = self.recordLength self.recordLength += self._addField(*defs) ! if not _oldLen: ! self.recordLength += 1 ! # XXX: may be just use: ! # self.recordeLength += self._addField(*defs) + bool(not _oldLen) ! # recalculate headerLength ! self.headerLength = 32 + (32 * len(self.fields)) + 1 self.changed = True --- 258,265 ---- """ ! if not self.recordLength: ! self.recordLength = 1 self.recordLength += self._addField(*defs) ! self._calcHeaderLength() self.changed = True *************** *** 235,242 **** --- 270,286 ---- stream.write("".join([_fld.toString() for _fld in self.fields])) stream.write(chr(0x0D)) # cr at end of all hdr data + _pos = stream.tell() + if _pos < self.headerLength: + stream.write("\0" * (self.headerLength - _pos)) self.changed = False def toString(self): """Returned 32 chars length string with encoded header.""" + # FIXME: should keep flag and code page marks read from file + if self.hasMemoField: + _flag = "\x02" + else: + _flag = "\0" + _codepage = "\0" return struct.pack("<4BI2H", self.signature, *************** *** 246,250 **** self.recordCount, self.headerLength, ! self.recordLength) + "\0" * 20 def setCurrentDate(self): --- 290,294 ---- self.recordCount, self.headerLength, ! self.recordLength) + "\0" * 16 + _flag + _codepage + "\0\0" def setCurrentDate(self): |