Revision 70516d86

b/pithos/backends/lib_alchemy/node.py
240 240
           Clears out nodes with no remaining versions.
241 241
        """
242 242
        #update statistics
243
        #TODO handle before=inf
244 243
        c1 = select([self.nodes.c.node],
245 244
            self.nodes.c.parent == parent)
246 245
        where_clause = and_(self.versions.c.node.in_(c1),
......
275 274
            and_(self.nodes.c.parent == parent,
276 275
                 select([func.count(self.versions.c.serial)],
277 276
                    self.versions.c.node == self.nodes.c.node).as_scalar() == 0))
278
        r = self.conn.execute(s)
279
        nodes = r.fetchall()
280
        r.close()
277
        rp = self.conn.execute(s)
278
        nodes = [r[0] for r in rp.fetchall()]
279
        rp.close()
281 280
        s = self.nodes.delete().where(self.nodes.c.node.in_(nodes))
282 281
        self.conn.execute(s).close()
283 282
        
......
388 387
        size += presize
389 388
        
390 389
        #insert or replace
390
        #TODO better upsert
391 391
        u = self.statistics.update().where(and_(self.statistics.c.node==node,
392 392
                                           self.statistics.c.cluster==cluster))
393 393
        u = u.values(population=population, size=size, mtime=mtime)
......
522 522
        r = self.conn.execute(s)
523 523
        props = r.fetchone()
524 524
        r.close()
525
        if not props:
525
        if props:
526 526
            return props
527 527
        return None
528 528
    
......
590 590
           Othwerise, return only those specified.
591 591
        """
592 592
        
593
        execute = self.execute
594 593
        if keys:
595 594
            attrs = self.attributes.alias()
596 595
            s = select([attrs.c.key, attrs.c.value])
......
609 608
        """Set the attributes of the version specified by serial.
610 609
           Receive attributes as an iterable of (key, value) pairs.
611 610
        """
612
        values = [{'serial':serial, 'key':k, 'value':v} for k, v in items]
613
        self.conn.execute(self.attributes.insert(), values).close()
611
        #insert or replace
612
        #TODO better upsert
613
        for k, v in items:
614
            s = self.attributes.update()
615
            s = s.where(and_(self.attributes.c.serial == serial,
616
                             self.attributes.c.key == k))
617
            s = s.values(value = v)
618
            rp = self.conn.execute(s)
619
            rp.close()
620
            if rp.rowcount == 0:
621
                s = self.attributes.insert()
622
                s = s.values(serial=serial, key=k, value=v)
623
                self.conn.execute(s).close()
614 624
    
615 625
    def attribute_del(self, serial, keys=()):
616 626
        """Delete attributes of the version specified by serial.
......
676 686
        if conj:
677 687
            s = s.where(or_(*conj))
678 688
        rp = self.conn.execute(s)
679
        r = rp.fetchall()
689
        rows = rp.fetchall()
680 690
        rp.close()
681
        return [r[0] for r in self.fetchall()]
691
        return [r[0] for r in rows]
682 692
    
683 693
    def latest_version_list(self, parent, prefix='', delimiter=None,
684 694
                            start='', limit=10000, before=inf,
b/pithos/backends/modular_alchemy.py
91 91
            raise RuntimeError("Cannot open database at '%s'" % (db,))
92 92
        
93 93
        connection_str = 'postgresql://%s:%s@%s/%s' % db_options
94
        engine = create_engine(connection_str, echo=True)
94
        #engine = create_engine(connection_str, echo=True)
95
        engine = create_engine(connection_str)
95 96
        self.con = engine.connect()
96 97
        
97 98
        params = {'blocksize': self.block_size,
......
234 235
            start, limit = self._list_limits(allowed, marker, limit)
235 236
            return allowed[start:start + limit]
236 237
        node = self.node.node_lookup(account)
237
        return [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, [], until)]
238
        l = [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, [], until)]
239
        l.sort()
240
        return l
238 241
    
239 242
    @backend_method
240 243
    def get_container_meta(self, user, account, container, until=None):
......
738 741
        objects = [(x[0][len(cont_prefix):], x[1]) for x in objects]
739 742
        
740 743
        start, limit = self._list_limits([x[0] for x in objects], marker, limit)
741
        return objects[start:start + limit]
744
        l = objects[start:start + limit]
745
        l.sort()
746
        return l
742 747
    
743 748
    # Policy functions.
744 749
    
b/tools/test
1331 1331
        for c in self.containers:
1332 1332
            self.client.create_container(c)
1333 1333
        self.obj = self.upload_random_data(self.containers[0], o_names[0])
1334
    
1335
    def tearDown(self):
1336
        pass
1337
    
1334
        
1338 1335
    def test_copy(self):
1339 1336
        with AssertMappingInvariant(self.client.retrieve_object_metadata,
1340 1337
                             self.containers[0], self.obj['name']):

Also available in: Unified diff