def tearDown(self): CommonParts.tearDown(self) # make sure stores are unmounted to kill sync if Connector().enum().isMounted(STORE1): Connector().unmount(STORE1) if Connector().enum().isMounted(STORE2): Connector().unmount(STORE2)
def setUp(self): # make sure stores are unmounted to kill sync if Connector().enum().isMounted(STORE1): Connector().unmount(STORE1) if Connector().enum().isMounted(STORE2): Connector().unmount(STORE2) CommonParts.setUp(self)
def __addCreateActions(self, menu): newMenu = menu.addMenu(QtGui.QIcon("icons/filenew.png"), "New document") action = newMenu.addAction(QtGui.QIcon("icons/uti/folder.png"), "Folder") action.triggered.connect(self.__doCreateFolder) newMenu.addSeparator() items = {} sysStore = Connector().enum().sysStore().sid sysDict = struct.Folder(connector.DocLink(sysStore, sysStore)) templatesDoc = sysDict.get("templates") if templatesDoc: templatesDict = struct.Folder(templatesDoc.update(sysStore)) items = templatesDict.items() items.sort(key=lambda item: item[0]) if items: for (name, link) in items: rev = link.rev() icon = QtGui.QIcon(Registry().getIcon( Connector().stat(rev).type())) action = newMenu.addAction(icon, name) action.triggered.connect( lambda x, r=rev, n=name: self.__doCreateFromTemplate( sysStore, r, n)) else: action = newMenu.addAction("No templates found") action.setEnabled(False)
def performSync(self, doc, strategy): watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync(strategy, self.store1, self.store2) # first wait until the doc gets changed while True: watch.reset() self.assertTrue(watch.waitForWatch()) l = Connector().lookupDoc(doc) if len(l.revs()) == 1: break self.assertEqual(len(l.stores()), 2) self.assertTrue(self.store1 in l.stores()) self.assertTrue(self.store2 in l.stores()) # wait until sync_worker moved on result = self.erlCall( """peerdrive_sync_locks:lock(<<16#""" + doc.encode("hex") + """:128>>), peerdrive_sync_locks:unlock(<<16#""" + doc.encode("hex") + """:128>>).""" ) self.assertEqual(result, "{ok, ok}") return l
def test_sync_merge(self): (doc, rev1, rev2) = self.createMerge( "org.peerdrive.folder", {"META": struct.dumps({"a": 1}), "PDSD": struct.dumps([{"": 1}, {"": 2}])}, {"META": struct.dumps({"a": 4, "b": 2}), "PDSD": struct.dumps([{"": 1}, {"": 2}, {"": 3}])}, {"META": struct.dumps({"a": 1, "c": 3}), "PDSD": struct.dumps([{"": 2}])}, ) l = self.performSync(doc, "merge") rev = l.revs()[0] s = Connector().stat(rev) self.assertEqual(len(s.parents()), 2) self.assertTrue(rev1 in s.parents()) self.assertTrue(rev2 in s.parents()) # all revs on all stores? l = Connector().lookupRev(rev1) self.assertTrue(self.store1 in l) self.assertTrue(self.store2 in l) l = Connector().lookupRev(rev2) self.assertTrue(self.store1 in l) self.assertTrue(self.store2 in l) # see if merge was ok with Connector().peek(self.store1, rev) as r: meta = struct.loads(self.store1, r.readAll("META")) if "org.peerdrive.annotation" in meta: del meta["org.peerdrive.annotation"] self.assertEqual(meta, {"a": 4, "b": 2, "c": 3}) pdsd = sorted(struct.loads(self.store1, r.readAll("PDSD"))) self.assertEqual(pdsd, [{"": 2}, {"": 3}])
def __addReplicateActions(self, menu, link): c = Connector() try: allVolumes = set(c.lookupRev(self.rev())) if isinstance(link, connector.DocLink): lookup = c.lookupDoc(link.doc()) curVolumes = set(lookup.stores()) try: for rev in lookup.revs(): curVolumes = curVolumes & set(c.lookupRev(rev, curVolumes)) except IOError: curVolumes = set() else: curVolumes = set(c.lookupRev(link.rev())) except IOError: return if not curVolumes: return srcVol = list(curVolumes)[0] repVolumes = allVolumes - curVolumes for store in repVolumes: name = struct.readTitle(connector.DocLink(store, store), "Unknown store") action = menu.addAction("Replicate item to '%s'" % name) action.triggered.connect( lambda x,l=link,s=store: self.__doReplicate(srcVol, l, s))
def __updateColumns(self, stat=None): # This makes only sense if we're a valid entry if not self.__valid: return try: if stat is None: stat = Connector().stat(self.__rev) with Connector().peek(self.__store, self.__rev) as r: try: metaData = r.getData("/org.peerdrive.annotation") except: metaData = {} for i in xrange(len(self.__columnDefs)): column = self.__columnDefs[i] if column.derived(): self.__columnValues[i] = column.extract(stat, metaData) self.__metaData = metaData except IOError: self.__metaData = None for i in xrange(len(self.__columnDefs)): column = self.__columnDefs[i] if column.derived(): self.__columnValues[i] = column.default()
def test_suspend(self): (doc, rev1, rev2) = self.createSuspendDoc() l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev2, {'FILE' : 'update'})
def test_create(self): w = self.create(self.store1, creator="test.foo") w.commit() doc = w.getDoc() rev = w.getRev() s = Connector().stat(rev) self.assertEqual(s.creator(), "test.foo")
def test_create(self): w = self.create(self.store1) w.commit() self.assertEqual(w.getFlags(), set()) rev = w.getRev() s = Connector().stat(rev) self.assertEqual(s.flags(), set())
def test_forward(self): (doc, rev1) = self.createCommon([self.store1, self.store2]) with Connector().update(self.store1, doc, rev1) as w: w.writeAll('FILE', 'update') w.commit() rev2 = w.getRev() Connector().forwardDoc(self.store2, doc, rev1, rev2, self.store1) self.assertEqual(Connector().lookupDoc(doc).revs(), [rev2])
def test_resume_wrong(self): (doc, rev1, rev2) = self.createSuspendDoc() self.assertRaises(IOError, Connector().resume, self.store1, doc, rev1) l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev2, {'FILE' : 'update'})
def test_mtime(self): w = self.create(self.store1) w.writeAll('FILE', "fubar") w.commit() rev = w.getRev() s = Connector().stat(rev) now = datetime.datetime.now() self.assertTrue(s.mtime() <= now) self.assertTrue(s.mtime() > now - datetime.timedelta(seconds=3))
def test_create(self): w = self.create(self.store1, "test.format") self.assertEqual(w.getType(), "test.format") w.commit() doc = w.getDoc() rev = w.getRev() s = Connector().stat(rev) self.assertEqual(s.type(), "test.format")
def assertRevContent(self, store, rev, content): with Connector().peek(store, rev) as r: for (part, data) in content.items(): revData = r.readAll(part) self.assertEqual(revData, data) s = Connector().stat(rev, [store]) for part in s.parts(): self.assertTrue(part in content)
def test_sync_merge_fallback(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {"FILE": "left3"}, {"FILE": "right3"}) l = self.performSync(doc, "merge") rev = l.revs()[0] s = Connector().stat(rev) self.assertEqual(len(s.parents()), 2) self.assertTrue(rev1 in s.parents()) self.assertTrue(rev2 in s.parents()) self.assertRevContent(self.store1, rev, {"FILE": "left3"})
def test_not_updatable(self): (doc, rev1) = self.createCommon([self.store1, self.store2]) with Connector().update(self.store1, doc, rev1) as w: w.writeAll('FILE', 'update') w.commit() rev2 = w.getRev() self.assertRaises(IOError, Connector().forwardDoc, self.store1, doc, rev1, rev2, self.store2) self.assertEqual(Connector().lookupDoc(doc).rev(self.store1), rev2) self.assertEqual(Connector().lookupDoc(doc).rev(self.store2), rev1)
def load(self, store, rev): try: stat = Connector().stat(rev, [store]) self.__typeLabel.setText(Registry().getDisplayString(stat.type())) self.__crtimeLabel.setText(str(stat.crtime())) self.__mtimeLabel.setText(str(stat.mtime())) size = stat.dataSize() for a in stat.attachments(): size += stat.size(a) for unit in ["Bytes", "KiB", "MiB", "GiB"]: if size < (1 << 10): break else: size = size >> 10 sizeText = "%d %s (%d attachments)" % (size, unit, len(stat.attachments())) self.__sizeLabel.setText(sizeText) if stat.flags(): flagsText = reduce( lambda x, y: x + ", " + y, [flagToText.get(f, "<" + str(f) + ">") for f in stat.flags()] ) else: flagsText = "-" self.__flagsLabel.setText(flagsText) except IOError: self.__typeLabel.setText("n/a") self.__mtimeLabel.setText("n/a") self.__sizeLabel.setText("n/a")
def __loadComment(self, rev): try: stat = Connector().stat(rev, [self.__store]) mtime = str(stat.mtime()) comment = stat.comment() if comment: return mtime + " - " + comment else: return mtime except IOError: return "???"
def test_sync_merge_fallback(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {'FILE' : "left3"}, {'FILE' : "right3"}) l = self.performSync(doc, 'merge') rev = l.revs()[0] s = Connector().stat(rev) self.assertEqual(len(s.parents()), 2) self.assertTrue(rev1 in s.parents()) self.assertTrue(rev2 in s.parents()) self.assertRevContent(self.store1, rev, {'FILE' : 'left3'})
def test_sync_latest(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {'FILE' : "left2"}, {'FILE' : "right2"}) l = self.performSync(doc, 'latest') rev = l.revs()[0] s = Connector().stat(rev) self.assertEqual(len(s.parents()), 2) self.assertTrue(rev1 in s.parents()) self.assertTrue(rev2 in s.parents()) self.assertRevContent(self.store1, rev, {'FILE' : 'left2'})
def __doReplicate(self, srcStore, link, dstStore): if isinstance(link, connector.DocLink): Connector().replicateDoc(srcStore, link.doc(), dstStore, verbose=True) else: Connector().replicateRev(srcStore, link.rev(), dstStore, verbose=True)
def test_update_change(self): w = self.create(self.store1) w.commit() doc = w.getDoc() rev = w.getRev() with Connector().update(self.store1, doc, rev) as w: w.setFlags([0, 3, 8]) w.commit() rev = w.getRev() s = Connector().stat(rev) self.assertEqual(s.flags(), set([0, 3, 8]))
def __init__(self, link, parent=None): super(PropertiesDialog, self).__init__(parent) mainLayout = QtGui.QVBoxLayout() # mainLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize) self.__doc = link.doc() self.__rev = link.rev() if self.__doc: isDoc = True banner = "document" l = Connector().lookupDoc(self.__doc) stores = [s for s in l.stores() if Connector().lookupRev(l.rev(s), [s]) == [s]] else: isDoc = False banner = "revision" stores = Connector().lookupRev(self.__rev) if len(stores) == 0: QtGui.QMessageBox.warning(self, "Missing document", "The requested document was not found on any store.") sys.exit(1) self.__docTab = DocumentTab(link.store(), stores, banner) self.__docTab.switchStore.connect(self.__switchStore) self.__revTab = RevisionTab() self.__annoTab = AnnotationTab(isDoc) self.__annoTab.changed.connect(self.__changed) self.__hisTab = HistoryTab() tabWidget = QtGui.QTabWidget() tabWidget.addTab(self.__annoTab, "Annotation") tabWidget.addTab(self.__hisTab, "History") if isDoc: self.__buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Close) self.__buttonBox.button(QtGui.QDialogButtonBox.Save).setEnabled(False) self.__buttonBox.accepted.connect(self.__save) self.__buttonBox.rejected.connect(self.reject) else: self.__buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok) self.__buttonBox.accepted.connect(self.accept) mainLayout.addWidget(self.__docTab) mainLayout.addWidget(self.__revTab) mainLayout.addWidget(tabWidget) mainLayout.addWidget(self.__buttonBox) self.setLayout(mainLayout) self.__switchStore(self.__docTab.activeStore()) self.setWindowTitle("Properties of %s" % (self.__annoTab.getTitle()))
def test_update_change(self): w = self.create(self.store1, creator="test.foo") w.commit() doc = w.getDoc() rev1 = w.getRev() with Connector().update(self.store1, doc, rev1, "test.baz") as w: w.commit() rev2 = w.getRev() s = Connector().stat(rev1) self.assertEqual(s.creator(), "test.foo") s = Connector().stat(rev2) self.assertEqual(s.creator(), "test.baz")
def test_collect(self): # deliberately close handle after creating! with Connector().create(self.store1, "public.data", "test.ignore") as w: w.commit() doc = w.getDoc() rev = w.getRev() # perform a GC cycle self.gc(self.store1) l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), []) self.assertEqual(l.preRevs(), []) self.assertRaises(IOError, Connector().stat, rev)
def __doCreate(self, srcStore, srcRev): info = Connector().stat(srcRev, [srcStore]) dstStore = self.store() with Connector().create(dstStore, info.type(), info.creator()) as w: with Connector().peek(srcStore, srcRev) as r: for part in info.parts(): w.write(part, r.readAll(part)) w.setFlags(r.getFlags()) w.commit() destDoc = w.getDoc() # add link self.model().insertLink(struct.DocLink(dstStore, destDoc)) # save immediately self.save()
def test_suspend_multi(self): (doc, rev1, rev_s1) = self.createSuspendDoc() with Connector().update(self.store1, doc, rev1) as w: w.writeAll('FILE', 'forward') w.commit() rev2 = w.getRev() with Connector().update(self.store1, doc, rev2) as w: w.writeAll('FILE', 'Hail to the king, baby!') w.suspend() rev_s2 = w.getRev() l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev2]) self.assertEqual(len(l.preRevs()), 2) self.assertTrue(rev_s1 in l.preRevs()) self.assertTrue(rev_s2 in l.preRevs()) s = Connector().stat(rev_s1) self.assertEqual(s.parents(), [rev1]) s = Connector().stat(rev_s2) self.assertEqual(s.parents(), [rev2]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev_s1, {'FILE' : 'update'}) self.assertRevContent(self.store1, rev2, {'FILE' : 'forward'}) self.assertRevContent(self.store1, rev_s2, {'FILE' : 'Hail to the king, baby!'})
def test_create_keep_handle(self): with Connector().create(self.store1, "public.data", "test.ignore") as w: w.commit() doc = w.getDoc() rev = w.getRev() # perform a GC cycle self.gc(self.store1) l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev]) self.assertEqual(l.preRevs(), []) Connector().stat(rev)
def test_update_keep(self): w = self.create(self.store1, creator="test.foo") w.commit() doc = w.getDoc() rev1 = w.getRev() with Connector().update(self.store1, doc, rev1) as w: w.write('FILE', 'update') w.commit() rev2 = w.getRev() s = Connector().stat(rev1) self.assertEqual(s.creator(), "test.foo") s = Connector().stat(rev2) self.assertEqual(s.creator(), "test.foo")
def test_fork(self): w = self.create(self.store1, creator="test.foo") w.commit() doc1 = w.getDoc() rev1 = w.getRev() w = self.fork(self.store1, rev1, "test.bar") w.commit() doc2 = w.getDoc() rev2 = w.getRev() s = Connector().stat(rev1) self.assertEqual(s.creator(), "test.foo") s = Connector().stat(rev2) self.assertEqual(s.creator(), "test.bar")
def __loadComment(self, rev): stat = Connector().stat(rev, [self.__store]) mtime = str(stat.mtime()) comment = "" if 'META' in stat.parts(): try: with Connector().peek(self.__store, rev) as r: metaData = struct.loads(self.__store, r.readAll('META')) comment = extractMetaData( metaData, ["org.peerdrive.annotation", "comment"], "") except IOError: pass return mtime + " - " + comment
def __doCreateFromTemplate(self, srcStore, srcRev, name): info = Connector().stat(srcRev, [srcStore]) dstStore = self.store() with Connector().create(dstStore, info.type(), info.creator()) as w: with Connector().peek(srcStore, srcRev) as r: w.set_data('', r.get_data('')) for att in info.attachments(): w.write(att, r.readAll(att)) w.setFlags(r.stat().flags()) w.commit("Created from template") destDoc = w.getDoc() # add link self.model().insertLink(connector.DocLink(dstStore, destDoc)) # save immediately self.save("Added '"+name+"' from templates")
def test_sync_ff_err(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {"FILE": "left1"}, {"FILE": "right1"}) watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync("ff", self.store1, self.store2) self.startSync("ff", self.store2, self.store1) self.assertFalse(watch.waitForWatch(1)) # check that doc is not synced l = Connector().lookupDoc(doc) self.assertEqual(len(l.revs()), 2) self.assertEqual(l.rev(self.store1), rev1) self.assertEqual(l.rev(self.store2), rev2)
def __update(self): if self.__seen: self.__unwatch() self.__available = len(Connector().lookupRev(self.__rev)) > 0 else: self.__available = False try: stat = Connector().stat(self.__rev) self.__mtime = stat.mtime() self.__seen = True self.__available = True self.__view._addParents(stat.parents()) self.__unwatch() except IOError: self.__watch() return
def test_fork(self): w = self.create(self.store1) w.setFlags([1, 2, 3]) w.commit() rev1 = w.getRev() w = self.fork(self.store1, rev1) w.writeAll('FILE', "asdfafd") self.assertEqual(w.getFlags(), set([1, 2, 3])) w.commit() rev2 = w.getRev() s = Connector().stat(rev1) self.assertEqual(s.flags(), set([1, 2, 3])) s = Connector().stat(rev2) self.assertEqual(s.flags(), set([1, 2, 3]))
def test_sync_ff_err(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {'FILE' : "left1"}, {'FILE' : "right1"}) watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync('ff', self.store1, self.store2) self.startSync('ff', self.store2, self.store1) self.assertFalse(watch.waitForWatch(1)) # check that doc is not synced l = Connector().lookupDoc(doc) self.assertEqual(len(l.revs()), 2) self.assertEqual(l.rev(self.store1), rev1) self.assertEqual(l.rev(self.store2), rev2)
def __setViewHandler(self, link): link.update() try: type = Connector().stat(link.rev()).type() executables = Registry().getExecutables(type) except IOError: executables = [] if not executables: # Probably a bad idea to leave the current view widget, but what # else can we do? return for executable in executables: if executable in BrowserWindow.TYPES: break handler = BrowserWindow.TYPES[executable] if self.__viewHandler: if isinstance(self.__viewHandler, handler): return self.__viewHandler.delete() self.__viewHandler = handler(self) self.setCentralWidget(self.__viewHandler.getView()) self.__viewHandler.getView().distributionChanged.connect( self.__updateStoreButtons)
def test_resume_suspend_orig(self): (doc, rev1, rev2) = self.createSuspendDoc() with Connector().resume(self.store1, doc, rev2) as w: w.suspend() rev3 = w.getRev() l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev3]) s = Connector().stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev3, {'FILE' : 'update'})
def test_resume_commit(self): (doc, rev1, rev2) = self.createSuspendDoc() with Connector().resume(self.store1, doc, rev2) as w: w.writeAll('FILE', 'What are you waiting for, christmas?') w.commit() rev3 = w.getRev() l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev3]) self.assertEqual(len(l.preRevs()), 0) s = Connector().stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev3, {'FILE' : 'What are you waiting for, christmas?'})
def update(self, updateItem=True): # reset everything self.__valid = False self.__icon = None for i in xrange(len(self.__columnDefs)): column = self.__columnDefs[i] if column.derived(): self.__columnValues[i] = column.default() # determine revision needMerge = False isReplicated = False if self.__doc: l = Connector().lookupDoc(self.__doc) isReplicated = len(l.stores()) > 1 revisions = l.revs() if len(revisions) == 0: return elif len(revisions) > 1: needMerge = True if updateItem: self.__item[''].update() self.__rev = self.__item[''].rev() # stat try: s = Connector().stat(self.__rev) except IOError: return self.__uti = s.type() if needMerge or isReplicated: image = QtGui.QImage(Registry().getIcon(s.type())) painter = QtGui.QPainter() painter.begin(image) if needMerge: painter.drawImage(0, 16, QtGui.QImage("icons/emblems/split.png")) elif isReplicated: painter.drawImage( 0, 16, QtGui.QImage("icons/emblems/distributed.png")) painter.end() self.__icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image)) else: self.__icon = QtGui.QIcon(Registry().getIcon(s.type())) self.__isFolder = Registry().conformes(self.__uti, "org.peerdrive.folder") self.__replacable = not needMerge and not self.__isFolder self.__valid = True self.__updateColumns(s)
def __switchStore(self, store): if self.__doc: self.__rev = Connector().lookupDoc(self.__doc, [store]).rev(store) self.__store = store self.__revTab.load(store, self.__rev) self.__annoTab.load(store, self.__rev) self.__hisTab.load(store, self.__rev)
def createMerge(self, type, base, left, right): (doc, rev1) = self.createCommon([self.store1, self.store2], type, data=base) with Connector().update(self.store1, doc, rev1) as w: for (part, data) in left.items(): w.writeAll(part, data) w.commit() rev2 = w.getRev() with Connector().update(self.store2, doc, rev1) as w: for (part, data) in right.items(): w.writeAll(part, data) w.commit() rev3 = w.getRev() # verify the merge condition l = Connector().lookupRev(rev1) self.assertTrue(self.store1 in l) self.assertTrue(self.store2 in l) self.assertEqual(Connector().lookupRev(rev2), [self.store1]) self.assertEqual(Connector().lookupRev(rev3), [self.store2]) self.assertEqual(Connector().stat(rev2).parents(), [rev1]) self.assertEqual(Connector().stat(rev3).parents(), [rev1]) return (doc, rev2, rev3)
def createFastForward(self): (doc, rev1) = self.createCommon([self.store1, self.store2]) with Connector().update(self.store1, doc, rev1) as w: w.writeAll('FILE', 'forward') w.commit() rev2 = w.getRev() return (doc, rev2)
def _extractMetaData(self): caption = self._view.metaDataGetField(DocumentView.HPA_TITLE, "Unnamed") if not self._view.doc() and self._view.rev(): try: mtime = Connector().stat(self._view.rev()).mtime() caption = caption + " @ " + str(mtime) except IOError: pass self._main.setCaption(caption)
def __doubleClicked(self, index): link = self.model().getItemLink(self.modelMapIndex(index)) if link: try: uti = Connector().stat(link.rev()).type() executables = Registry().getExecutables(uti) except IOError: executables = [] self.itemOpen.emit(link, None, "org.peerdrive.browser.py" in executables)
def setAutoClean(self, autoClean): self.__autoClean = autoClean if autoClean and self.__mutable: removed = [x for x in self._listing if not x.isValid()] self._listing = [x for x in self._listing if x.isValid()] if len(removed) > 0: self.__changedContent = True for item in removed: Connector().unwatch(item) self.reset()
def removeRows(self, position, rows, parent): if not self.__mutable: return False self.__changedContent = True self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1) for i in range(rows): Connector().unwatch(self._listing[position]) del self._listing[position] self.endRemoveRows() return True
def test_resume_abort(self): (doc, rev1, rev2) = self.createSuspendDoc() with Connector().resume(self.store1, doc, rev2) as w: w.writeAll('FILE', 'Hail to the king, baby!') l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) w.close() l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) self.assertRevContent(self.store1, rev1, {'FILE' : 'ok'}) self.assertRevContent(self.store1, rev2, {'FILE' : 'update'})
def createCommon(self, stores, type="public.data", creator="org.peerdrive.test-py", data={}): leadStore = stores.pop() w = self.create(leadStore, type, creator) for (part, blob) in data.items(): w.writeAll(part, blob) w.commit() doc = w.getDoc() rev = w.getRev() for store in stores: w = self.create(store) w.writeAll('PDSD', struct.dumps([struct.DocLink(store, doc)])) w.commit() Connector().replicateDoc(leadStore, doc, store) # verify the common document on all stores l = Connector().lookupDoc(doc) self.assertEqual(l.revs(), [rev]) for store in stores: self.assertTrue(store in l.stores()) return (doc, rev)