def onSuccess(self, fields, REQUEST=None, loopstop=False): """ saves data. """ now = tzawarenow() soup = self.get_soup() modified_fields = list() iid = self.REQUEST.cookies.get('PFGSOUP_POST', None) if iid: iid = int(iid) data = soup.get(iid) else: data = OOBTNode() for field in fields: if field.isLabel(): continue field_name = field.getFieldFormName() if field.isFileField(): file_value = REQUEST.form.get('%s_file' % field_name) raise NotImplementedError('FileField Not Yet Done') value = REQUEST.form.get(field_name, '') if iid: if data.attrs.get(field_name, None) == value: continue modified_fields.append(field_name) data.attrs[field_name] = value sm = getSecurityManager() if iid: if modified_fields: data.attrs['_auto_last_modified'] = now log = {} log['user'] = sm.getUser().getId() log['date'] = now log['fields'] = modified_fields if '_auto_log' not in data.attrs: data.attrs['_auto_log'] = PersistentList() data.attrs['_auto_log'].append(log) self.REQUEST.response.expireCookie('PFGSOUP_POST', path='/') # XXX redirect to table # self.REQUEST.response.redirect(...) return data.attrs['_auto_created'] = now data.attrs['_auto_last_modified'] = now data.attrs['_auto_userid'] = sm.getUser().getId() data.attrs['_auto_log'] = PersistentList() soup.add(data)
def test_OOBTNode(self): # Based on OOBTree as storage oobtnode = OOBTNode(name='oobtnode') # Interface check self.assertTrue(IZODBNode.providedBy(oobtnode)) # Storage check self.assertTrue(isinstance(oobtnode.storage, OOBTodict)) self.assertTrue(isinstance(oobtnode._storage, OOBTodict)) # Structure check root = self.open() root[oobtnode.__name__] = oobtnode oobtnode['child'] = OOBTNode(name='child') self.assertEqual(sorted(root.keys()), ['oobtnode']) self.assertEqual(oobtnode.keys(), ['child']) self.assertEqual(oobtnode.values(), [oobtnode['child']]) self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: child\n')) self.checkOutput( """\ OOBTodict([('child', <OOBTNode object 'child' at ...>)]) """, repr(oobtnode.storage)) # Reopen database connection and check again self.close() root = self.open() self.assertEqual(sorted(root.keys()), ['oobtnode']) oobtnode = root['oobtnode'] self.assertEqual(oobtnode.keys(), ['child']) self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: child\n')) self.assertTrue(oobtnode['child'].__parent__ is oobtnode) # Delete child node del oobtnode['child'] transaction.commit() self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n')) # Check node attributes self.assertTrue(isinstance(oobtnode.attrs, OOBTNodeAttributes)) self.assertEqual(oobtnode.attrs.name, '_attrs') oobtnode.attrs['foo'] = 1 bar = oobtnode.attrs['bar'] = OOBTNode() self.assertEqual(oobtnode.attrs.values(), [1, bar]) # Check attribute access for node attributes oobtnode.attribute_access_for_attrs = True self.assertEqual(oobtnode.attrs.foo, 1) # Check whether flag has been persisted self.close() root = self.open() oobtnode = root['oobtnode'] self.assertEqual(oobtnode.attrs.foo, 1) self.assertEqual(oobtnode.attrs.bar, oobtnode.attrs['bar']) oobtnode.attrs.foo = 2 self.assertEqual(oobtnode.attrs.foo, 2) oobtnode.attribute_access_for_attrs = False # Check attrs storage self.checkOutput( """\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs.storage)) self.checkOutput( """\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs._storage)) self.assertTrue(oobtnode.attrs.storage is oobtnode.attrs._storage) self.close() root = self.open() oobtnode = root['oobtnode'] oobtnode.attribute_access_for_attrs = False self.checkOutput( """\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs.storage)) # Check internal datastructure of attrs storage = oobtnode.attrs.storage dict_ = storage._dict_impl() self.assertTrue(dict_ is OOBTree) self.assertEqual(sorted(dict_.keys(storage)), ['____lh', '____lt', 'bar', 'foo']) # values ``foo`` and ``bar`` are list tail and list head values self.assertEqual(dict_.__getitem__(storage, '____lh'), 'foo') self.assertEqual(dict_.__getitem__(storage, '____lt'), 'bar') attrs = oobtnode.attrs self.assertEqual(dict_.__getitem__(storage, 'bar'), ['foo', attrs['bar'], _nil]) self.assertEqual(dict_.__getitem__(storage, 'foo'), [_nil, 2, 'bar']) self.assertEqual(storage.lt, 'bar') self.assertEqual(storage.lh, 'foo') # Add attribute, reopen database connection and check again oobtnode.attrs['baz'] = 'some added value' self.close() root = self.open() oobtnode = root['oobtnode'] storage = oobtnode.attrs.storage dict_ = storage._dict_impl() self.assertEqual(dict_.__getitem__(storage, '____lh'), 'foo') self.assertEqual(dict_.__getitem__(storage, '____lt'), 'baz') attrs = oobtnode.attrs self.assertEqual(dict_.__getitem__(storage, 'bar'), ['foo', attrs['bar'], 'baz']) self.assertEqual(dict_.__getitem__(storage, 'baz'), ['bar', 'some added value', _nil]) self.assertEqual(dict_.__getitem__(storage, 'foo'), [_nil, 2, 'bar']) self.assertEqual(storage.lt, 'baz') self.assertEqual(storage.lh, 'foo') # Test copy and detach oobtnode['c1'] = OOBTNode() oobtnode['c2'] = OOBTNode() oobtnode['c3'] = OOBTNode() self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n')) # Detach c1 c1 = oobtnode.detach('c1') self.assertTrue(isinstance(c1, OOBTNode)) self.assertEqual(c1.name, 'c1') self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n')) # Add c1 as child to c2 oobtnode['c2'][c1.name] = c1 self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n')) # Reopen database connection and check again self.close() root = self.open() oobtnode = root['oobtnode'] self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n')) # Copy c1 c1_copy = oobtnode['c2']['c1'].copy() self.assertFalse(c1_copy is oobtnode['c2']['c1']) oobtnode['c1'] = c1_copy self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n')) oobtnode['c4'] = oobtnode['c2'].copy() self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c4\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n')) self.assertFalse(oobtnode['c2']['c1'] is oobtnode['c4']['c1']) self.assertFalse( oobtnode['c2']['c1'].attrs is oobtnode['c4']['c1'].attrs) transaction.commit() # Swap nodes oobtnode.swap(oobtnode['c1'], oobtnode['c3']) oobtnode.swap(oobtnode['c1'], oobtnode['c2']) self.assertEqual(oobtnode.treerepr(), ('<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c4\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n')) st = oobtnode.storage self.assertIsInstance(dict_.__getitem__(st, 'c1'), PersistentList) self.assertIsInstance(dict_.__getitem__(st, 'c2'), PersistentList) self.assertIsInstance(dict_.__getitem__(st, 'c3'), PersistentList) # Calling nodes does nothing, persisting is left to transaction # mechanism oobtnode() # Fill root with some OOBTNodes and check memory usage old_size = self.storage.getSize() root['large'] = OOBTNode() for i in range(1000): root['large'][str(i)] = OOBTNode() self.assertEqual(len(root['large']), 1000) transaction.commit() new_size = self.storage.getSize() self.assertTrue((new_size - old_size) / 1000 <= 914) self.close()
def create_booking(self, order, cart_data, uid, count, comment): brain = get_catalog_brain(self.context, uid) # brain could be None if uid for item in cookie which no longer exists. if not brain: return buyable = brain.getObject() item_state = get_item_state(buyable, self.request) if not item_state.validate_count(count): msg = u'Item no longer available {0}'.format(buyable.id) logger.warning(msg) raise CheckoutError(msg) item_stock = get_item_stock(buyable) # stock not applied, state new if item_stock is None: available = None state = ifaces.STATE_NEW # calculate state from stock else: if item_stock.available is not None: item_stock.available -= float(count) available = item_stock.available state = ifaces.STATE_NEW if available is None or available >= 0.0\ else ifaces.STATE_RESERVED item_data = get_item_data_provider(buyable) vendor = acquire_vendor_or_shop_root(buyable) booking = OOBTNode() booking.attrs['email'] = order.attrs['personal_data.email'] booking.attrs['uid'] = uuid.uuid4() booking.attrs['buyable_uid'] = uid booking.attrs['buyable_count'] = count booking.attrs['buyable_comment'] = comment booking.attrs['order_uid'] = order.attrs['uid'] booking.attrs['vendor_uid'] = uuid.UUID(IUUID(vendor)) booking.attrs['creator'] = order.attrs['creator'] booking.attrs['created'] = order.attrs['created'] booking.attrs['exported'] = False booking.attrs['title'] = brain and brain.Title or 'unknown' booking.attrs['net'] = item_data.net booking.attrs['vat'] = item_data.vat # XXX: in order to be able to reliably modify bookings, item discount # rules for this booking must be stored instead of the actual # calculated discount. booking.attrs['discount_net'] = item_data.discount_net(count) booking.attrs['currency'] = cart_data.currency booking.attrs['quantity_unit'] = item_data.quantity_unit booking.attrs['remaining_stock_available'] = available booking.attrs['state'] = state booking.attrs['salaried'] = ifaces.SALARIED_NO booking.attrs['tid'] = 'none' shipping_info = queryAdapter(buyable, IShippingItem) if shipping_info: booking.attrs['shippable'] = shipping_info.shippable else: booking.attrs['shippable'] = False trading_info = queryAdapter(buyable, ifaces.ITrading) if trading_info: booking.attrs['item_number'] = trading_info.item_number booking.attrs['gtin'] = trading_info.gtin else: booking.attrs['item_number'] = None booking.attrs['gtin'] = None return booking
def create_booking(self, order, cart_data, uid, count, comment): brain = get_catalog_brain(self.context, uid) # brain could be None if uid for item in cookie which no longer exists. if not brain: return buyable = brain.getObject() item_state = get_item_state(buyable, self.request) if not item_state.validate_count(item_state.aggregated_count): raise CheckoutError(u'Item no longer available') item_stock = get_item_stock(buyable) if item_stock.available is not None: item_stock.available -= float(count) available = item_stock.available state = (available is None or available >= 0) and ifaces.STATE_NEW\ or ifaces.STATE_RESERVED item_data = get_item_data_provider(buyable) vendor = acquire_vendor_or_shop_root(buyable) booking = OOBTNode() booking.attrs['uid'] = uuid.uuid4() booking.attrs['buyable_uid'] = uid booking.attrs['buyable_count'] = count booking.attrs['buyable_comment'] = comment booking.attrs['order_uid'] = order.attrs['uid'] booking.attrs['vendor_uid'] = uuid.UUID(IUUID(vendor)) booking.attrs['creator'] = order.attrs['creator'] booking.attrs['created'] = order.attrs['created'] booking.attrs['exported'] = False booking.attrs['title'] = brain and brain.Title or 'unknown' booking.attrs['net'] = item_data.net booking.attrs['vat'] = item_data.vat booking.attrs['discount_net'] = item_data.discount_net(count) booking.attrs['currency'] = cart_data.currency booking.attrs['quantity_unit'] = item_data.quantity_unit booking.attrs['remaining_stock_available'] = available booking.attrs['state'] = state booking.attrs['salaried'] = ifaces.SALARIED_NO booking.attrs['tid'] = 'none' return booking
def __init__(self, name=None, parent=None): OOBTNode.__init__(self, name=name, parent=parent) self.attrs['title'] = 'foo'
def testSetUp(self): self['storage'] = OOBTNode()
def __init__(self, name=None, parent=None): OOBTNode.__init__(self, name=name, parent=parent) self.attrs["uid"] = uuid.uuid4() self.attrs["title"] = "foo" self.state = "state_1"
def create_booking(self, order, cart_data, uid, count, comment): brain = get_catalog_brain(self.context, uid) # brain could be None if uid for item in cookie which no longer exists. if not brain: return buyable = brain.getObject() item_state = get_item_state(buyable, self.request) if not item_state.validate_count(count): msg = u'Item no longer available {0}'.format(buyable.id) logger.warning(msg) raise CheckoutError(msg) item_stock = get_item_stock(buyable) # stock not applied, state new if item_stock is None: available = None state = ifaces.STATE_NEW # calculate state from stock else: if item_stock.available is not None: item_stock.available -= float(count) available = item_stock.available state = ifaces.STATE_NEW if available is None or available >= 0.0\ else ifaces.STATE_RESERVED item_data = get_item_data_provider(buyable) vendor = acquire_vendor_or_shop_root(buyable) booking = OOBTNode() booking.attrs['email'] = order.attrs['personal_data.email'] booking.attrs['uid'] = uuid.uuid4() booking.attrs['buyable_uid'] = uid booking.attrs['buyable_count'] = count booking.attrs['buyable_comment'] = comment booking.attrs['order_uid'] = order.attrs['uid'] booking.attrs['vendor_uid'] = uuid.UUID(IUUID(vendor)) booking.attrs['creator'] = order.attrs['creator'] booking.attrs['created'] = order.attrs['created'] booking.attrs['exported'] = False booking.attrs['title'] = brain and brain.Title or 'unknown' booking.attrs['net'] = item_data.net booking.attrs['vat'] = item_data.vat booking.attrs['discount_net'] = item_data.discount_net(count) booking.attrs['currency'] = cart_data.currency booking.attrs['quantity_unit'] = item_data.quantity_unit booking.attrs['remaining_stock_available'] = available booking.attrs['state'] = state booking.attrs['salaried'] = ifaces.SALARIED_NO booking.attrs['tid'] = 'none' shipping_info = queryAdapter(buyable, IShippingItem) if shipping_info: booking.attrs['shippable'] = shipping_info.shippable else: booking.attrs['shippable'] = False trading_info = queryAdapter(buyable, ifaces.ITrading) if trading_info: booking.attrs['item_number'] = trading_info.item_number booking.attrs['gtin'] = trading_info.gtin else: booking.attrs['item_number'] = None booking.attrs['gtin'] = None return booking
def test_OOBTNode(self): # Based on OOBTree as storage oobtnode = OOBTNode('oobtnode') # Interface check self.assertTrue(IZODBNode.providedBy(oobtnode)) # Storage check self.assertTrue(isinstance(oobtnode.storage, OOBTodict)) self.assertTrue(isinstance(oobtnode._storage, OOBTodict)) # Structure check root = self.open() root[oobtnode.__name__] = oobtnode oobtnode['child'] = OOBTNode('child') self.assertEqual(sorted(root.keys()), ['oobtnode']) self.assertEqual(oobtnode.keys(), ['child']) self.assertEqual(oobtnode.values(), [oobtnode['child']]) self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: child\n' )) self.check_output("""\ OOBTodict([('child', <OOBTNode object 'child' at ...>)]) """, repr(oobtnode.storage)) # Reopen database connection and check again self.close() root = self.open() self.assertEqual(sorted(root.keys()), ['oobtnode']) oobtnode = root['oobtnode'] self.assertEqual(oobtnode.keys(), ['child']) self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: child\n' )) self.assertTrue(oobtnode['child'].__parent__ is oobtnode) # Delete child node del oobtnode['child'] transaction.commit() self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' )) # Check node attributes self.assertTrue(isinstance(oobtnode.attrs, OOBTNodeAttributes)) self.assertEqual(oobtnode.attrs.name, '_attrs') oobtnode.attrs['foo'] = 1 bar = oobtnode.attrs['bar'] = OOBTNode() self.assertEqual(oobtnode.attrs.values(), [1, bar]) # Check attribute access for node attributes oobtnode.attribute_access_for_attrs = True self.assertEqual(oobtnode.attrs.foo, 1) # Check whether flag has been persisted self.close() root = self.open() oobtnode = root['oobtnode'] self.assertEqual(oobtnode.attrs.foo, 1) self.assertEqual(oobtnode.attrs.bar, oobtnode.attrs['bar']) oobtnode.attrs.foo = 2 self.assertEqual(oobtnode.attrs.foo, 2) oobtnode.attribute_access_for_attrs = False # Check attrs storage self.check_output("""\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs.storage)) self.check_output("""\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs._storage)) self.assertTrue(oobtnode.attrs.storage is oobtnode.attrs._storage) self.close() root = self.open() oobtnode = root['oobtnode'] oobtnode.attribute_access_for_attrs = False self.check_output("""\ OOBTodict([('foo', 2), ('bar', <OOBTNode object 'bar' at ...>)]) """, repr(oobtnode.attrs.storage)) # Check internal datastructure of attrs storage = oobtnode.attrs.storage cls = storage._dict_impl() self.assertTrue(cls is OOBTree) self.assertEqual( sorted(cls.keys(storage)), ['____lh', '____lt', 'bar', 'foo'] ) # values ``foo`` and ``bar`` are list tail and list head values self.assertEqual(cls.__getitem__(storage, '____lh'), 'foo') self.assertEqual(cls.__getitem__(storage, '____lt'), 'bar') attrs = oobtnode.attrs self.assertEqual( cls.__getitem__(storage, 'bar'), ['foo', attrs['bar'], _nil] ) self.assertEqual( cls.__getitem__(storage, 'foo'), [_nil, 2, 'bar'] ) self.assertEqual(storage.lt, 'bar') self.assertEqual(storage.lh, 'foo') # Add attribute, reopen database connection and check again oobtnode.attrs['baz'] = 'some added value' self.close() root = self.open() oobtnode = root['oobtnode'] storage = oobtnode.attrs.storage cls = storage._dict_impl() self.assertEqual(cls.__getitem__(storage, '____lh'), 'foo') self.assertEqual(cls.__getitem__(storage, '____lt'), 'baz') attrs = oobtnode.attrs self.assertEqual( cls.__getitem__(storage, 'bar'), ['foo', attrs['bar'], 'baz'] ) self.assertEqual( cls.__getitem__(storage, 'baz'), ['bar', 'some added value', _nil] ) self.assertEqual( cls.__getitem__(storage, 'foo'), [_nil, 2, 'bar'] ) self.assertEqual(storage.lt, 'baz') self.assertEqual(storage.lh, 'foo') # Test copy and detach oobtnode['c1'] = OOBTNode() oobtnode['c2'] = OOBTNode() oobtnode['c3'] = OOBTNode() self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' )) # Detach c1 c1 = oobtnode.detach('c1') self.assertTrue(isinstance(c1, OOBTNode)) self.assertEqual(c1.name, 'c1') self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' )) # Add c1 as child to c2 oobtnode['c2'][c1.name] = c1 self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' )) # Reopen database connection and check again self.close() root = self.open() oobtnode = root['oobtnode'] self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' )) # Copy c1 c1_copy = oobtnode['c2']['c1'].copy() self.assertFalse(c1_copy is oobtnode['c2']['c1']) oobtnode['c1'] = c1_copy self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' )) oobtnode['c4'] = oobtnode['c2'].copy() self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c4\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' )) self.assertFalse(oobtnode['c2']['c1'] is oobtnode['c4']['c1']) self.assertFalse( oobtnode['c2']['c1'].attrs is oobtnode['c4']['c1'].attrs ) transaction.commit() # Swap nodes oobtnode.swap(oobtnode['c1'], oobtnode['c3']) oobtnode.swap(oobtnode['c1'], oobtnode['c2']) self.assertEqual(oobtnode.treerepr(), ( '<class \'node.ext.zodb.OOBTNode\'>: oobtnode\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c2\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' ' <class \'node.ext.zodb.OOBTNode\'>: c3\n' ' <class \'node.ext.zodb.OOBTNode\'>: c4\n' ' <class \'node.ext.zodb.OOBTNode\'>: c1\n' )) # Calling nodes does nothing, persisting is left to transaction # mechanism oobtnode() # Fill root with some OOBTNodes and check memory usage old_size = self.storage.getSize() root['large'] = OOBTNode() for i in range(1000): root['large'][str(i)] = OOBTNode() self.assertEqual(len(root['large']), 1000) transaction.commit() new_size = self.storage.getSize() # ZODB 3 and ZODB 5 return different sizes so check whether lower or # equal higher value self.assertTrue((new_size - old_size) / 1000 <= 160) self.close()