def test_keys_are_sorted(keys):
    items = [(key, key + 1) for key in keys]
    sorted_items = sorted(items)
    sorted_keys = sorted(keys)
    d = SortedDict(items)
    assert sorted(d) == sorted_keys
    assert sorted(d.keys()) == sorted_keys
    assert d.items() == sorted(items)
    assert d.values() == sorted(v for k, v in items)
Exemple #2
0
def test_keys_are_sorted(keys):
    items = [(key, key + 1) for key in keys]
    sorted_items = sorted(items)
    sorted_keys = sorted(keys)
    d = SortedDict(items)
    assert sorted(d) == sorted_keys
    assert sorted(d.keys()) == sorted_keys
    assert d.items() == sorted(items)
    assert d.values() == sorted(v for k, v in items)
Exemple #3
0
class DBF(object):

    version = 3
    header_fmt = '<BBBBLHH20x'
    fields_fmt = '<11sc4xBB14x'
    
    def __init__(self, db, fieldspecs=None):
        if isinstance(db, basestring):
            db = open(db, 'w+b')
        self.db = db
        self.fields = fieldspecs

        # try to read the header infos from the db
        header = db.read(32)
        if header:
            header = struct.unpack(self.header_fmt, header)

        # if the user passed fieldspecs
        if self.fields:
            # obtain dbf meta data from them
            self.numfields = len(self.fields)
            self.lenheader = self.numfields * 32 + 33
            
            self.lenrecord = 1
            self.record_fmt = '1s'
            for field in self.fields.itervalues():
                self.lenrecord += field.size
                self.record_fmt += '%ds' % field.size

            # if we have an header
            if header:
                # check the header's infos with the ones we have obtained from
                # our fieldspecs
                self.numrec, lenheader, lenrecord = header[-3:]
                assert (lenheader == self.lenheader and
                        lenrecord == self.lenrecord), \
                        "database's fields doesn't match provided fields"
            # if no header is present, write it
            else:
                self.numrec = 0

                # header
                now = datetime.datetime.now()
                y, m, d = now.year-1900, now.month, now.day
                header = struct.pack(self.header_fmt, self.version, y, m, d,
                                     self.numrec, self.lenheader, self.lenrecord)
                self.db.write(header)

                # field specs
                for fname, field in self.fields.iteritems():
                    fname = fname.ljust(11, '\0')
                    field = struct.pack(self.fields_fmt, fname, field.type,
                                        field.size, field.deci)
                    self.db.write(field)
                self.db.write('\r\x1A')
        else:
            # if we have no fieldspecs, but we have an header in our dbf,
            # obtain the fieldspecs from it.
            if header:
                self.numrec, self.lenheader, self.lenrecord = header[-3:]
                self.numfields = (self.lenheader - 33) // 32
                self.fields = SortedDict()
                self.record_fmt = '1s'
                for fieldno in xrange(self.numfields):
                    fieldinfo = struct.unpack(self.fields_fmt, db.read(32))
                    name, type, size, deci = fieldinfo
                    name = name.partition('\0')[0]
                    self.fields[name] = fields.guessField(type, size, deci)
                    self.record_fmt += '%ds' % size

            else:
                # if we have no header and no fieldspecs, we can't help it ...
                raise TypeError("nor fields or header present")

        i = 0
        self._fieldpos = []
        for field in self.fields.itervalues():
            self._fieldpos.append(i)
            i += field.size

    def gotoField(self, fname):
        i = self.fields.keyOrder.index(fname)
        self.db.seek(self._currec + 1 + self._fieldpos[i])

    def newID(self):
        """
        return a new record ID.
        """
        self.db.seek(4)
        self.numrec = struct.unpack('<L', self.db.read(4))[0]
        return self.numrec

    def increase_numrec(self):
        self.numrec += 1
        self.db.seek(4)
        self.db.write(struct.pack('<L', self.numrec))

    def gotoRecord(self, recIndex):
        """
        move before the record specified by the index recIndex
        """
        if recIndex > self.numrec:
            raise KeyError(recIndex)
        self._currec = self.lenheader + self.lenrecord * (recIndex)
        self.db.seek(self._currec)

    def update(self, record):
        recId = record['pk']
        self.gotoRecord(recId)

        dflag = self.db.read(1)

        for fname, field in self.fields.iteritems():
            if fname in record:
                self.db.write(field.encode(record[fname]))
                self.db.flush()
            else:
                self.db.seek(field.size, 1)
        self.db.flush()

    def insert(self, record):
        recId = self.newID()
        self.gotoRecord(recId)
        record['pk'] = recId

        self.db.write(' ')
        data = ''
        for fname, field in self.fields.iteritems():
            data += field.encode(record[fname])
        self.db.write(data)
        
        self.db.write('\x1A')
        self.increase_numrec()

        self.db.flush()

    def _iterselect(self, fields=None):
        for recId in xrange(self.numrec):
            yield self.select(recId, fields)
 
    def select(self, recId=None, fields=None):
        if recId is None:
            return self._iterselect(fields)

        if not recId in self:
            raise KeyError(recId)
        
        if not fields:
            fields = self.fields.keys()

        self.gotoRecord(recId)
        res = {'pk': recId}

        self.db.read(1)
        for fname, field in self.fields.iteritems():
            if fname in fields:
                res[fname] = field.decode(self.db.read(field.size))
            else:
                self.db.seek(field.size, 1)
        return res

    def close(self):
        self.db.close()

    def __contains__(self, recId):
        if isinstance(recId, int) and recId < self.numrec:
            return True
        return False

    def __iter__(self):
        for i in xrange(self.numrec):
            yield self.select(i)

    def __len__(self):
        return self.numrec

    def __getitem__(self, recordID):
        return self.select(recordID)

    def __setitem__(self, recordID, dict):
        self.select(recordID, dict)
Exemple #4
0
class DBF(object):

    version = 3
    header_fmt = '<BBBBLHH20x'
    fields_fmt = '<11sc4xBB14x'

    def __init__(self, db, fieldspecs=None):
        if isinstance(db, basestring):
            db = open(db, 'w+b')
        self.db = db
        self.fields = fieldspecs

        # try to read the header infos from the db
        header = db.read(32)
        if header:
            header = struct.unpack(self.header_fmt, header)

        # if the user passed fieldspecs
        if self.fields:
            # obtain dbf meta data from them
            self.numfields = len(self.fields)
            self.lenheader = self.numfields * 32 + 33

            self.lenrecord = 1
            self.record_fmt = '1s'
            for field in self.fields.itervalues():
                self.lenrecord += field.size
                self.record_fmt += '%ds' % field.size

            # if we have an header
            if header:
                # check the header's infos with the ones we have obtained from
                # our fieldspecs
                self.numrec, lenheader, lenrecord = header[-3:]
                assert (lenheader == self.lenheader and
                        lenrecord == self.lenrecord), \
                        "database's fields doesn't match provided fields"
            # if no header is present, write it
            else:
                self.numrec = 0

                # header
                now = datetime.datetime.now()
                y, m, d = now.year - 1900, now.month, now.day
                header = struct.pack(self.header_fmt, self.version, y, m, d,
                                     self.numrec, self.lenheader,
                                     self.lenrecord)
                self.db.write(header)

                # field specs
                for fname, field in self.fields.iteritems():
                    fname = fname.ljust(11, '\0')
                    field = struct.pack(self.fields_fmt, fname, field.type,
                                        field.size, field.deci)
                    self.db.write(field)
                self.db.write('\r\x1A')
        else:
            # if we have no fieldspecs, but we have an header in our dbf,
            # obtain the fieldspecs from it.
            if header:
                self.numrec, self.lenheader, self.lenrecord = header[-3:]
                self.numfields = (self.lenheader - 33) // 32
                self.fields = SortedDict()
                self.record_fmt = '1s'
                for fieldno in xrange(self.numfields):
                    fieldinfo = struct.unpack(self.fields_fmt, db.read(32))
                    name, type, size, deci = fieldinfo
                    name = name.partition('\0')[0]
                    self.fields[name] = fields.guessField(type, size, deci)
                    self.record_fmt += '%ds' % size

            else:
                # if we have no header and no fieldspecs, we can't help it ...
                raise TypeError("nor fields or header present")

        i = 0
        self._fieldpos = []
        for field in self.fields.itervalues():
            self._fieldpos.append(i)
            i += field.size

    def gotoField(self, fname):
        i = self.fields.keyOrder.index(fname)
        self.db.seek(self._currec + 1 + self._fieldpos[i])

    def newID(self):
        """
        return a new record ID.
        """
        self.db.seek(4)
        self.numrec = struct.unpack('<L', self.db.read(4))[0]
        return self.numrec

    def increase_numrec(self):
        self.numrec += 1
        self.db.seek(4)
        self.db.write(struct.pack('<L', self.numrec))

    def gotoRecord(self, recIndex):
        """
        move before the record specified by the index recIndex
        """
        if recIndex > self.numrec:
            raise KeyError(recIndex)
        self._currec = self.lenheader + self.lenrecord * (recIndex)
        self.db.seek(self._currec)

    def update(self, record):
        recId = record['pk']
        self.gotoRecord(recId)

        dflag = self.db.read(1)

        for fname, field in self.fields.iteritems():
            if fname in record:
                self.db.write(field.encode(record[fname]))
                self.db.flush()
            else:
                self.db.seek(field.size, 1)
        self.db.flush()

    def insert(self, record):
        recId = self.newID()
        self.gotoRecord(recId)
        record['pk'] = recId

        self.db.write(' ')
        data = ''
        for fname, field in self.fields.iteritems():
            data += field.encode(record[fname])
        self.db.write(data)

        self.db.write('\x1A')
        self.increase_numrec()

        self.db.flush()

    def _iterselect(self, fields=None):
        for recId in xrange(self.numrec):
            yield self.select(recId, fields)

    def select(self, recId=None, fields=None):
        if recId is None:
            return self._iterselect(fields)

        if not recId in self:
            raise KeyError(recId)

        if not fields:
            fields = self.fields.keys()

        self.gotoRecord(recId)
        res = {'pk': recId}

        self.db.read(1)
        for fname, field in self.fields.iteritems():
            if fname in fields:
                res[fname] = field.decode(self.db.read(field.size))
            else:
                self.db.seek(field.size, 1)
        return res

    def close(self):
        self.db.close()

    def __contains__(self, recId):
        if isinstance(recId, int) and recId < self.numrec:
            return True
        return False

    def __iter__(self):
        for i in xrange(self.numrec):
            yield self.select(i)

    def __len__(self):
        return self.numrec

    def __getitem__(self, recordID):
        return self.select(recordID)

    def __setitem__(self, recordID, dict):
        self.select(recordID, dict)
Exemple #5
0
 def test_keys_values_items(self):
     a = SortedDict({'a': 1, 'b': 2})
     self.assertListEqual(a.keys(), ['a', 'b'])
     self.assertListEqual(a.values(), [1, 2])
     self.assertListEqual(a.items(), [('a', 1), ('b', 2)])