def on_debug_CreateConflictEvent(self, event): selectedItems = self.__getSelectedItems() if len(selectedItems) > 0: for item in selectedItems: if not has_stamp(item, sharing.SharedItem): sharing.SharedItem(item).add() sharing.SharedItem(item).generateConflicts()
def testHolidays(self): holidays = self.getCollection(u"U.S. Holidays") self.failUnless(pim.has_stamp(holidays, sharing.SharedItem)) self.failUnlessEqual(len(list(sharing.SharedItem(holidays).shares)), 1) share = sharing.SharedItem(holidays).shares.first() self.failUnless(share.established) self.failUnless( isinstance(share.conduit, sharing.WebDAVMonolithicRecordSetConduit))
def OnManageDone(self, evt): for share in sharing.SharedItem(self.collection).shares: self._saveAttributeFilterState(share) if self.IsModal(): self.EndModal(False) self.Destroy() share = sharing.getShare(self.collection) needsSync = False if isinstance(share.conduit, sharing.RecordSetConduit): for filter in self.originalFilters: if filter not in share.conduit.filters: # A filter has been removed so we need to re-synchronize needsSync = True break else: if share.filterAttributes != self.originalFilterAttributes: needsSync = True if needsSync: self.view.commit() sharing.scheduleNow(self.view, collection=share.contents, forceUpdate=True)
def testSync(self): def get(): return pkg_resources.resource_string("osaf.app", "us_holidays.ics") holidays = findCollection(self.view, u"U.S. Holidays") share = sharing.SharedItem(holidays).shares.first() # Override get on the conduit so we can simulate getting # back exactly the same data from the server share.conduit.get = get share.sync() for item in holidays: self.failIf(not item.read, "Item %s is unread" % (item, ))
def RoundTrip(self): view0 = self.views[0] view1 = self.views[1] coll0a = view0.findUUID(self.coluuida) coll0b = view0.findUUID(self.coluuidb) item0 = view0.findUUID(self.itemuuid) # Initial publish view0.commit() self.share0a.create() self.share0a.sync() self.share0b.create() self.share0b.sync() view0.commit() # Initial subscribe view1.commit() self.share1a.sync() self.share1b.sync() view1.commit() coll1a = self.share1a.contents coll1b = self.share1b.contents item1 = view1.findUUID(self.itemuuid) self.assert_(item1 in coll1a) self.assert_(item1 in coll1b) # Create two conflicts on displayName item1.displayName = "changed by 1A" view1.commit() self.share1a.sync() view1.commit() item1.displayName = "changed by 1B" view1.commit() self.share1b.sync() view1.commit() item0.displayName = "changed by 0" view0.commit() self.share0a.sync() self.share0b.sync() view0.commit() shared = sharing.SharedItem(item0) conflicts = shared.getConflicts() self.assert_(conflicts)
def RoundTrip(self): filename = "tmp_dump_file" view0 = self.views[0] view1 = self.views[1] # uuids to dump; add your items to this: uuids = set() # Prepare test data coll0 = pim.SmartCollection("testCollection", itsView=view0, displayName="Test Collection") uuids.add(coll0.itsUUID) titles = [ u"dunder", u"mifflin", ] tzinfo = view0.tzinfo.floating createdOn = datetime.datetime(2007, 3, 1, 10, 0, 0, 0, tzinfo) lastModified = datetime.datetime(2007, 3, 1, 12, 0, 0, 0, tzinfo) email = "*****@*****.**" emailAddress = pim.EmailAddress.getEmailAddress(view0, email) count = len(titles) for i in xrange(count): n = pim.Note(itsView=view0) n.createdOn = createdOn n.displayName = titles[i % count] n.body = u"Here is the body" n.lastModifiedBy = emailAddress n.lastModified = lastModified coll0.add(n) uuids.add(n.itsUUID) # Read/unread items readNote = pim.Note(itsView=view0, read=True) unreadNote = pim.Note(itsView=view0, read=False) # "Private" items publicNote = pim.Note(itsView=view0, private=False) privateNote = pim.Note(itsView=view0, private=True) # Mine/Not-Mine/Dashboard directlyInDashboard = pim.Note(itsView=view0) dashboard = schema.ns("osaf.pim", view0).allCollection dashboard.add(directlyInDashboard) aMineCollection = pim.SmartCollection(itsView=view0) schema.ns('osaf.pim', view0).mine.addSource(aMineCollection) inMine = pim.Note(itsView=view0) aMineCollection.add(inMine) aNotMineCollection = pim.SmartCollection(itsView=view0) inNotMine = pim.Note(itsView=view0) aNotMineCollection.add(inNotMine) trash = schema.ns("osaf.pim", view0).trashCollection trashTestCollection = pim.SmartCollection(itsView=view0) trashedItem = pim.Note(itsView=view0) trashTestCollection.add(trashedItem) trash.add(trashedItem) self.assert_(trashedItem in trashTestCollection.inclusions) self.assert_(trashedItem not in trashTestCollection) self.assert_(trashedItem in trash) # Sharing related items account0 = sharing.CosmoAccount(itsView=view0, host="chandler.o11n.org", port=8080, path="/cosmo", username="******", password=Password(itsView=view0), useSSL=True) waitForDeferred(account0.password.encryptPassword('4cc0unt0')) uuids.add(account0.itsUUID) cosmo_conduit0 = sharing.CosmoConduit( itsView=view0, account=account0, shareName=coll0.itsUUID.str16(), translator=sharing.SharingTranslator, serializer=sharing.EIMMLSerializer) uuids.add(cosmo_conduit0.itsUUID) cosmo_share0 = sharing.Share(itsView=view0, contents=coll0, conduit=cosmo_conduit0) uuids.add(cosmo_share0.itsUUID) hub_account0 = sharing.HubAccount( itsView=view0, username="******", password=Password(itsView=view0), ) waitForDeferred(hub_account0.password.encryptPassword('4cc0unt0')) uuids.add(hub_account0.itsUUID) inmemory_conduit0 = sharing.InMemoryDiffRecordSetConduit( itsView=view0, shareName="in_memory", translator=sharing.SharingTranslator, serializer=sharing.EIMMLSerializer) uuids.add(inmemory_conduit0.itsUUID) inmemory_share0 = sharing.Share(itsView=view0, conduit=inmemory_conduit0, contents=coll0) uuids.add(inmemory_share0.itsUUID) # Create some State objects inmemory_share0.create() view0.commit() inmemory_share0.sync() for state in inmemory_share0.states: uuids.add(state.itsUUID) # Set one of the states to be a pendingRemoval pendingRemoval = state.itsUUID state.pendingRemoval = True # Peer states peerNote = pim.Note(itsView=view0) peerAddress = pim.EmailAddress( itsView=view0, fullName="Michael Scott", emailAddress="*****@*****.**") peerState = sharing.State( itsView=view0, conflictFor=peerNote, peer=peerAddress, ) sharing.SharedItem(peerNote).add() sharedPeerNote = sharing.SharedItem(peerNote) sharedPeerNote.peerStates = [] sharedPeerNote.peerStates.append(peerState, peerAddress.itsUUID.str16()) uuids.add(peerNote.itsUUID) uuids.add(peerAddress.itsUUID) uuids.add(peerState.itsUUID) # Sharing proxy proxy = sharing.getProxy(view0) proxy.host = "host" proxy.port = 123 proxy.username = "******" proxy.passwd = "password" proxy.active = True proxy.useAuth = True proxy.bypass = "******" uuids.add(proxy.itsUUID) # Online state schema.ns('osaf.app', view0).prefs.isOnline = False schema.ns('osaf.sharing', view0).prefs.isOnline = False #Mail Accounts imapAddress = mail.EmailAddress.getEmailAddress( view0, "*****@*****.**", "test") popAddress = mail.EmailAddress.getEmailAddress(view0, "*****@*****.**", "test1") smtpOldAddress = mail.EmailAddress.getEmailAddress( view0, "*****@*****.**", "test2") smtpNewAddress = mail.EmailAddress.getEmailAddress( view0, "*****@*****.**", "test3") testFolder = mail.IMAPFolder(itsView=view0, displayName="TestFolder", folderName="INBOX.TestFolder", folderType="MAIL") queuedMessage0 = pim.MailStamp(pim.Note(itsView=view0)) queuedMessage0.add() queuedMessage0.subject = "Test for SMTP Queue" uuids.add(queuedMessage0.itsItem.itsUUID) imapaccount0 = mail.IMAPAccount( itsView=view0, displayName="IMAP Test", host="localhost", port=143, username="******", password=Password(itsView=view0), connectionSecurity="TLS", numRetries=2, pollingFrequency=300, isActive=False, replyToAddress=imapAddress, folders=[testFolder], ) waitForDeferred(imapaccount0.password.encryptPassword('imap4acc0unt0')) uuids.add(imapaccount0.itsUUID) popaccount0 = mail.POPAccount( itsView=view0, displayName="POP Test", host="localhost", port=110, username="******", password=Password(itsView=view0), connectionSecurity="NONE", numRetries=3, pollingFrequency=200, isActive=True, replyToAddress=popAddress, ) waitForDeferred(popaccount0.password.encryptPassword('pop4acc0unt0')) uuids.add(popaccount0.itsUUID) smtpaccount0 = mail.SMTPAccount( itsView=view0, displayName="SMTP Test", host="localhost", port=587, username="******", password=Password(itsView=view0), connectionSecurity="SSL", numRetries=5, pollingFrequency=500, isActive=True, fromAddress=smtpOldAddress, useAuth=True, messageQueue=[queuedMessage0.itsItem], ) waitForDeferred(smtpaccount0.password.encryptPassword('smtp4acc0unt0')) # This orphans smtpOldAddress leaving it as # an old me address which is stored in the # meEmailAddressCollection. # The purpose of this is to test dump and reload # of the meEmailAddressCollection. smtpaccount0.fromAddress = smtpNewAddress uuids.add(smtpaccount0.itsUUID) #Take the mail service offline schema.ns("osaf.pim", view0).MailPrefs.isOnline = False # Calendar prefs pref = schema.ns('osaf.pim', view0).TimezonePrefs pref.showUI = True # change from default pref.showPrompt = False # change from default pref = schema.ns('osaf.framework.blocks.calendar', view0).calendarPrefs pref.hourHeightMode = "auto" pref.visibleHours = 20 # TODO: TimeZoneInfo # passwords pw = Password(itsView=view0) waitForDeferred(pw.encryptPassword('foobar')) uuids.add(pw.itsUUID) # password prefs mpwPrefs = schema.ns("osaf.framework.MasterPassword", view0).masterPasswordPrefs MasterPassword._change('', 'secret', view0, mpwPrefs) mpwPrefs.timeout = 10 # backup on quit preference backupPrefs = schema.ns("osaf.app", view0).prefs self.assertFalse(hasattr(backupPrefs, 'backupOnQuit')) backupPrefs.backupOnQuit = True # tip of the day prefs self.assertFalse(backupPrefs.showTip) self.assertEqual(backupPrefs.tipIndex, 0) backupPrefs.tipIndex = 1 # Ensure sidebar is loaded in view1 sidebar1 = schema.ns("osaf.app", view1).sidebarCollection try: dumpreload.dump(view0, filename) dumpreload.reload(view1, filename, testmode=True) # Ensure the items are now in view1 for uuid in uuids: item0 = view0.findUUID(uuid) item1 = view1.findUUID(uuid) self.assert_(item1 is not None) if hasattr(item0, 'displayName'): self.assertEqual(item0.displayName, item1.displayName) if hasattr(item0, 'body'): self.assertEqual(item0.body, item1.body) # Verify ContentItem.read self.assert_(view1.findUUID(readNote.itsUUID).read is True) self.assert_(view1.findUUID(unreadNote.itsUUID).read is False) # Verify ContentItem.private self.assert_(view1.findUUID(publicNote.itsUUID).private is False) self.assert_(view1.findUUID(privateNote.itsUUID).private is True) # Verify Mine/Not-Mine/Dashboard dashboard = schema.ns("osaf.pim", view1).allCollection self.assert_( view1.findUUID(directlyInDashboard.itsUUID) in dashboard.inclusions) self.assert_(view1.findUUID(inMine.itsUUID) in dashboard) self.assert_(view1.findUUID(inNotMine.itsUUID) not in dashboard) # Verify collection membership: coll1 = view1.findUUID(coll0.itsUUID) for item0 in coll0: item1 = view1.findUUID(item0.itsUUID) self.assert_(item1 in coll1) # Verify trash membership trash = schema.ns("osaf.pim", view1).trashCollection trashedItem = view1.findUUID(trashedItem.itsUUID) self.assert_(trashedItem in trash) trashTestCollection = view1.findUUID(trashTestCollection.itsUUID) self.assert_(trashedItem not in trashTestCollection) self.assert_(trashedItem in trashTestCollection.inclusions) # Verify passwords pw1 = view1.findUUID(pw.itsUUID) self.assertEqual(waitForDeferred(pw1.decryptPassword('secret')), 'foobar') mpwPrefs1 = schema.ns("osaf.framework.MasterPassword", view1).masterPasswordPrefs self.assertEqual(mpwPrefs1.masterPassword, True) self.assertEqual(mpwPrefs1.timeout, 10) pwPrefs1 = schema.ns("osaf.framework.password", view1).passwordPrefs self.assertEqual( len( waitForDeferred( pwPrefs1.dummyPassword.decryptPassword('secret'))), 16) self.assertEqual(str(pwPrefs1.dummyPassword.itsUUID), 'dd555441-9ddc-416c-b55a-77b073c7bd15') dummyByUUID = view1.findUUID( 'dd555441-9ddc-416c-b55a-77b073c7bd15') self.assertEqual(dummyByUUID, pwPrefs1.dummyPassword) count = 0 for item in Password.iterItems(view0): waitForDeferred(item.decryptPassword('secret')) count += 1 count1 = 0 for item in Password.iterItems(view1): waitForDeferred(item.decryptPassword('secret')) count1 += 1 self.assertEqual(count + 2, count1) # XXX Shouldn't count==count1? # Verify sharing account1 = view1.findUUID(account0.itsUUID) self.assertEquals(account1.host, "chandler.o11n.org") self.assertEquals(account1.port, 8080) self.assertEquals(account1.path, "/cosmo") self.assertEquals(account1.username, "test") self.assertEquals(account1.useSSL, True) self.assertEquals( waitForDeferred(account1.password.decryptPassword('secret')), '4cc0unt0') hub_account1 = view1.findUUID(hub_account0.itsUUID) self.assert_(isinstance(hub_account0, sharing.HubAccount)) inmemory_share1 = view1.findUUID(inmemory_share0.itsUUID) self.assert_(inmemory_share1 is not None) self.assertEqual(inmemory_share0.contents.itsUUID, inmemory_share1.contents.itsUUID) self.assertEqual(inmemory_share0.conduit.syncToken, inmemory_share1.conduit.syncToken) for state0 in inmemory_share0.states: state1 = view1.findUUID(state0.itsUUID) self.assert_(state1 in inmemory_share1.states) self.assertEqual(state0.agreed, state1.agreed) self.assertEqual(state0.pending, state1.pending) self.assertEqual(state1.pendingRemoval, state1.itsUUID == pendingRemoval) for item0 in coll0: item1 = view1.findUUID(item0.itsUUID) sharedItem1 = sharing.SharedItem(item1) self.assert_(inmemory_share1 in sharedItem1.sharedIn) # Peer states peerNote1 = view1.findUUID(peerNote.itsUUID) sharedPeerNote1 = sharing.SharedItem(peerNote1) peerAddress1 = view1.findUUID(peerAddress.itsUUID) peerState1 = view1.findUUID(peerState.itsUUID) self.assert_(peerState1 in sharedPeerNote1.peerStates) self.assertEquals(sharedPeerNote1.peerStates.getAlias(peerState1), peerAddress1.itsUUID.str16()) self.assert_(peerState1 in sharedPeerNote1.conflictingStates) self.assert_(isinstance(peerAddress1, pim.EmailAddress)) proxy1 = view1.findUUID(proxy.itsUUID) self.assertEquals(proxy1.host, "host") self.assertEquals(proxy1.port, 123) self.assertEquals(proxy1.username, "username") self.assertEquals(proxy1.bypass, "192.168.1, localhost") pw = waitForDeferred(proxy1.password.decryptPassword('secret')) self.assertEquals(pw, "password") self.assertEquals(proxy1.active, True) self.assertEquals(proxy1.useAuth, True) self.assertEquals( schema.ns('osaf.app', view1).prefs.isOnline, False) self.assertEquals( schema.ns('osaf.sharing', view1).prefs.isOnline, False) # Verify Calendar prefs pref = schema.ns('osaf.pim', view1).TimezonePrefs self.assertEqual(pref.showUI, True) self.assertEqual(pref.showPrompt, False) pref = schema.ns('osaf.framework.blocks.calendar', view1).calendarPrefs self.assertEqual(pref.hourHeightMode, "auto") self.assertEqual(pref.visibleHours, 20) #Verify Mail Accounts imapaccount1 = view1.findUUID(imapaccount0.itsUUID) self.assertEquals(imapaccount1.host, "localhost") self.assertEquals(imapaccount1.port, 143) self.assertEquals(imapaccount1.username, "test") self.assertEquals(imapaccount1.connectionSecurity, "TLS") self.assertEquals(imapaccount1.numRetries, 2) self.assertEquals(imapaccount1.pollingFrequency, 300) self.assertEquals(imapaccount1.isActive, False) self.assertEquals(imapaccount1.replyToAddress.format(), imapAddress.format()) self.assertEquals( waitForDeferred( imapaccount1.password.decryptPassword('secret')), 'imap4acc0unt0') folder = imapaccount1.folders.first() self.assertEquals(folder.displayName, "TestFolder") self.assertEquals(folder.folderName, "INBOX.TestFolder") self.assertEquals(folder.folderType, "MAIL") popaccount1 = view1.findUUID(popaccount0.itsUUID) self.assertEquals(popaccount1.host, "localhost") self.assertEquals(popaccount1.port, 110) self.assertEquals(popaccount1.username, "test1") self.assertEquals(popaccount1.connectionSecurity, "NONE") self.assertEquals(popaccount1.numRetries, 3) self.assertEquals(popaccount1.pollingFrequency, 200) self.assertEquals(popaccount1.isActive, True) self.assertEquals(popaccount1.replyToAddress.format(), popAddress.format()) self.assertEquals( waitForDeferred( popaccount1.password.decryptPassword('secret')), 'pop4acc0unt0') smtpaccount1 = view1.findUUID(smtpaccount0.itsUUID) self.assertEquals(smtpaccount1.host, "localhost") self.assertEquals(smtpaccount1.port, 587) self.assertEquals(smtpaccount1.username, "test2") self.assertEquals(smtpaccount1.connectionSecurity, "SSL") self.assertEquals(smtpaccount1.numRetries, 5) self.assertEquals(smtpaccount1.pollingFrequency, 500) self.assertEquals(smtpaccount1.isActive, True) self.assertEquals(smtpaccount1.useAuth, True) self.assertEquals(smtpaccount1.fromAddress.format(), smtpNewAddress.format()) self.assertEquals( waitForDeferred( smtpaccount1.password.decryptPassword('secret')), 'smtp4acc0unt0') queuedMessage1 = smtpaccount1.messageQueue[0] self.assertEquals(queuedMessage1.itsUUID, queuedMessage0.itsItem.itsUUID) self.assertEquals( schema.ns("osaf.pim", view1).MailPrefs.isOnline, False) col = schema.ns("osaf.pim", view1).meEmailAddressCollection found = False oldAddr = smtpOldAddress.format() # Confirm that the old email address smtpOldAddress # is in the meEmailAddressCollection for calculating # the MailStamp.fromMe and MailStamp.toMe attributes for ea in col: if ea.format() == oldAddr: found = True break self.assertTrue(found) # backup on quit preference backupPrefs1 = schema.ns("osaf.app", view1).prefs self.assertTrue(backupPrefs1.backupOnQuit) # tip of the day prefs self.assertFalse(backupPrefs1.showTip) self.assertEqual(backupPrefs1.tipIndex, 1) finally: try: os.remove(filename) except: pass
def RoundTrip(self): view0 = self.views[0] view1 = self.views[1] item0 = view0.findUUID(self.uuid) pje = schema.Item(itsView=view0, itsName="pje") morgen = schema.Item(itsView=view1, itsName="morgen") item0.setTriageStatus(pim.TriageEnum.later) pim.EventStamp(item0).add() event = pim.EventStamp(item0) event.anyTime = False # morgen sends to pje self.assert_(not pim.has_stamp(item0, sharing.SharedItem)) view0.commit() text = sharing.outbound([pje], item0) view0.commit() self.assert_(pim.has_stamp(item0, sharing.SharedItem)) # pje receives from morgen self.assert_(view1.findUUID(self.uuid) is None) view1.commit() item1 = sharing.inbound(morgen, text) view1.commit() self.assert_(pim.has_stamp(item1, sharing.SharedItem)) self.assertEqual(item1.displayName, "test displayName") self.assertEqual(item1.body, "test body") self.assertEqual(item1.triageStatus, pim.TriageEnum.later) shared0 = sharing.SharedItem(item0) shared1 = sharing.SharedItem(item1) self.assert_(not list(shared0.getConflicts())) # verify inbound filters (URIs defined in model.py) filter = sharing.getFilter(['cid:[email protected]']) item0.setTriageStatus(pim.TriageEnum.now) view0.commit() text = sharing.outbound([pje], item0) view0.commit() view1.commit() sharing.inbound(morgen, text, filter=filter) view1.commit() # triageStatus is unchanged because we filtered it on inbound self.assertEqual(item1.triageStatus, pim.TriageEnum.later) self.assert_(not shared1.conflictingStates) item0.setTriageStatus(pim.TriageEnum.done) view0.commit() text = sharing.outbound([pje], item0, filter=filter) view0.commit() view1.commit() sharing.inbound(morgen, text) view1.commit() # triageStatus is unchanged because we filtered it on outbound self.assertEqual(item1.triageStatus, pim.TriageEnum.later) self.assert_(not shared1.conflictingStates) item0.setTriageStatus(pim.TriageEnum.now) view0.commit() text = sharing.outbound([pje], item0) view0.commit() view1.commit() sharing.inbound(morgen, text) view1.commit() # with no filtering, triageStatus is now changed self.assertEqual(item1.triageStatus, pim.TriageEnum.now) # conflict item0.displayName = "changed by morgen" item1.displayName = "changed by pje" view0.commit() text = sharing.outbound([pje], item0) view0.commit() view1.commit() sharing.inbound(morgen, text) view1.commit() conflicts = list(shared1.getConflicts()) self.assert_(conflicts) # try sending when there are pending conflicts try: sharing.outbound([morgen], item1) except sharing.ConflictsPending: pass # This is what we're expecting else: raise Exception("We were expecting a ConflictsPending exception") # removal view0.commit() text = sharing.outboundDeletion(view0, [pje], self.uuid) view0.commit() # allowDeletion flag False view1.commit() sharing.inbound(morgen, text, allowDeletion=False) view1.commit() # to give a chance for a deleted item to go away self.assert_(view1.findUUID(self.uuid) is not None) # allowDeletion flag True sharing.inbound(morgen, text, allowDeletion=True) view1.commit() # to give a chance for a deleted item to go away self.assert_(view1.findUUID(self.uuid) is None) # adding item back text = sharing.outbound([pje], item0) item1 = sharing.inbound(morgen, text) shared1 = sharing.SharedItem(item1) self.assert_(view1.findUUID(self.uuid) is item1) # overlapping but identical modifications results in no conflicts item0.displayName = "changed" item1.displayName = "changed" view0.commit() text = sharing.outbound([pje], item0) view0.commit() view1.commit() sharing.inbound(morgen, text) view1.commit() # Examine the conflicts and ensure the 'title' field isn't conflicting self.assert_(not shared1.conflictingStates) # Verify that an out of sequence update is ignored before = shared1.getPeerState(morgen, create=False) beforeAgreed = before.agreed # copy the old agreed recordset # item0.displayName is "changed" view0.itsVersion = 2 # Back in time # Now item0.displayName is "test displayName" text = sharing.outbound([pje], item0) try: sharing.inbound(morgen, text, debug=False) except sharing.OutOfSequence: pass # Thisis what we're expecting else: raise Exception("We were expecting an OutOfSequence exception") after = shared1.getPeerState(morgen, create=False) self.assertEqual(beforeAgreed, after.agreed)
def testChange(self): from osaf import sharing from osaf.pim import ListCollection self.tzprefs.showUI = False gayParee = self.view.tzinfo.getInstance("Europe/Paris") master = CalendarEvent(itsView=self.view, anyTime=False, startTime=datetime( 2007, 2, 7, 11, 30, tzinfo=self.view.tzinfo.floating), duration=timedelta(hours=1)) master.rruleset = RecurrenceRuleSet( itsView=self.view, rrules=[RecurrenceRule(itsView=self.view, freq='daily')]) ordinary = CalendarEvent(itsView=self.view, anyTime=False, startTime=datetime( 2007, 2, 7, 11, 30, tzinfo=self.view.tzinfo.floating), duration=timedelta(hours=1)) sharedFloating = CalendarEvent(itsView=self.view, anyTime=False, startTime=datetime( 2002, 12, 22, tzinfo=self.view.tzinfo.floating)) share = sharing.Share(itsView=self.view, hidden=False) item = sharing.SharedItem(sharedFloating) item.add() item.sharedIn = item.shares = [share] nonFloatingOccurrence = master.getNextOccurrence( after=datetime(2007, 5, 2, tzinfo=self.view.tzinfo.floating)) nonFloatingOccurrence.changeThis( EventStamp.startTime.name, nonFloatingOccurrence.startTime.replace(tzinfo=gayParee)) titleMod = nonFloatingOccurrence.getNextOccurrence() titleMod.itsItem.summary = "yabba dabba doo" self.tzprefs.showUI = True tzItem = TimeZoneInfo.get(self.view) # Make sure that floating is no longer the default self.failIfEqual(self.view.tzinfo.default, self.view.tzinfo.floating) self.failIfEqual(tzItem.default, self.view.tzinfo.floating) self.failUnlessEqual(tzItem.default, self.view.tzinfo.default) # Make sure the ordinary and master events acquired the default tz self.failUnlessEqual(ordinary.startTime.tzinfo, self.view.tzinfo.default) self.failUnlessEqual(master.startTime.tzinfo, self.view.tzinfo.default) # Make sure the non-floating occurrence didn't have its tz changed self.failUnlessEqual(nonFloatingOccurrence.startTime.tzinfo, gayParee) # Check the master's occurrences ... for event in map(EventStamp, master.occurrences): # Everything but the modification we just made should have # the default timezone set for startTime ... if event != nonFloatingOccurrence: self.failUnlessEqual(event.startTime.tzinfo, self.view.tzinfo.default) # and recurrenceIDs should always have the master's tzinfo self.failUnlessEqual(event.recurrenceID.tzinfo, self.view.tzinfo.default) # ... and the shared item's tzinfo should not have changed self.failUnlessEqual(sharedFloating.startTime.tzinfo, self.view.tzinfo.floating) self.tzprefs.showUI = False self.failUnlessEqual(tzItem.default, self.view.tzinfo.floating) self.failIfEqual(self.view.tzinfo.floating, self.view.tzinfo.default)
def installParcel(parcel, oldVersion=None): pim_ns = schema.ns('osaf.pim', parcel) sharing_ns = schema.ns('osaf.sharing', parcel) ClientIdentifier.update(parcel, 'clientID') ApplicationPrefs.update(parcel, 'prefs') AutoRestorePrefs.update(parcel, "autoRestorePrefs") message = _(u'User') me = pim.Contact.update( parcel, 'me', # L10N: The word 'Me' is used to represent the # current Chandler user. displayName=_(u'Me'), contactName=pim.ContactName.update( parcel, 'meName', firstName=u'Chandler', #XXX Since the notion of 'me' may be going away # there is no current need to refactor the # last name attribute to the LocalizableString type. # Thus for now will convert the c{Message} object # returned from the c{ChandlerMessageFactory} # to Unicode. This decision will be revisited later. lastName=unicode(message), ), references=[pim_ns.currentContact]) # The Sidebar collection sidebarListCollection = pim.ListCollection.update( parcel, 'sidebarCollection', inclusions=[ pim_ns.allCollection, pim_ns.inCollection, pim_ns.outCollection, pim_ns.trashCollection ]) testReply = pim.mail.EmailAddress.update(parcel, 'TestReplyAddress') # [i18n] Test Accounts are not displayed to the user and # do not require localization testSmtp = pim.mail.SMTPAccount.update(parcel, 'TestSMTPAccount', displayName=u'Test SMTP Account', password=password.Password.update( parcel, 'TestSMTPAccountPassword'), isActive=False) pim.mail.IMAPAccount.update(parcel, 'TestIMAPAccount', displayName=u'Test IMAP mail', replyToAddress=testReply, password=password.Password.update( parcel, 'TestIMAPAccountPassword'), isActive=False) pim.mail.POPAccount.update(parcel, 'TestPOPAccount', displayName=u'Test POP mail', replyToAddress=testReply, defaultSMTPAccount=testSmtp, password=password.Password.update( parcel, 'TestPOPAccountPassword'), isActive=False) osafDev = pim.Contact.update(parcel, 'OSAFContact', emailAddress=u'*****@*****.**', contactName=pim.ContactName.update( parcel, 'OSAFContactName', firstName=u'OSAF', lastName=u'Development')) # OOTB collections and items (bugs 6545, 11772) # http://chandlerproject.org/bin/view/Journal/PreviewOOTBChandlerExperience # # (1) Don't create these in //parcels, or they won't get dumped # (2) Don't create these if reloading, or else there will be endless # duplication of items/events # (3) We do want new UUIDs, so different users can share these # collections/items to the same morsecode server # (4) The Welcome Event should be created regardless of whether # we're reloading, because summaryblocks references it. # (Maybe there's a better way to have it selected in the # detail view?) -- Grant # (5) We create triageWhenValues = [datetime.datetime.now(parcel.itsView.tzinfo.default)] def changeTriage(itemOrStamp, triageValue): triageWhen = triageWhenValues.pop() item = getattr(itemOrStamp, 'itsItem', itemOrStamp) item.setTriageStatus(triageValue, triageWhen) triageWhenValues.append(triageWhen - datetime.timedelta(seconds=5)) # OOTB item: Welcome Event noonToday = datetime.datetime.combine( datetime.date.today(), datetime.time(12, tzinfo=parcel.itsView.tzinfo.floating)) WelcomeEvent = pim.EventStamp.update( parcel, 'WelcomeEvent', # L10N: The Trademark symbol "TM" is represented in Unicode as U+2122 displayName=_(u'Welcome to Chandler\u2122'), startTime=noonToday, duration=datetime.timedelta(minutes=60), anyTime=False, read=False, creator=osafDev, location=pim.Location.update( parcel, "OSAFLocation", displayName="Open Source Applications Foundation", ), ) # L10N: The Trademark symbol "TM" is represented in Unicode as U+2122 body = _( u"""Welcome to Chandler\u2122 %(version)s. Here is a list of resources to help you get started: 1. Get a tour of Chandler (http://chandlerproject.org/tour). 2. Learn how to import calendars and set up Chandler to back up and share (http://chandlerproject.org/getstarted). 3. Back up your data and Share by signing up for a Chandler Hub account (http://hub.chandlerproject.org/signup). 4. Ask for help by sending mail to mailto:[email protected]. 5. Learn more about the project on our wiki (http://chandlerproject.org/wikihome). 6. Get involved and contribute to the project (http://chandlerproject.org/getinvolved). Thank you for trying Chandler! The Chandler Team""") % { 'version': version.version } WelcomeEvent.body = body WelcomeEvent.changeEditState(pim.Modification.created) changeTriage(WelcomeEvent, pim.TriageEnum.now) pim.TaskStamp(WelcomeEvent).add() if Globals.options.reload: schema.ns('osaf.pim', parcel.itsView).allCollection.add(WelcomeEvent) else: # OOTB user defined collections: collections should be in mine mine = schema.ns("osaf.pim", parcel.itsView).mine def makeCollection(name, checked, color): collection = pim.SmartCollection(itsView=parcel.itsView, displayName=name) # include collection in overlays, as spec'ed UserCollection(collection).checked = checked # set the collection color as spec'ed UserCollection(collection).setColor(color) sidebarListCollection.add(collection) mine.addSource(collection) return collection # OOTB user defined collections: Work, Home and Fun work = makeCollection(_(u"Work"), True, u'Blue') home = makeCollection(_(u"Home"), True, u'Red') fun = makeCollection(_(u"Fun"), False, u'Plum') # OOTB shared collection: U.S. Holidays holidays = makeCollection(_(u"U.S. Holidays"), True, u'Green') holidaysPath = pkg_resources.resource_filename(__name__, "us_holidays.ics") sharing.importFile(parcel.itsView, holidaysPath, collection=holidays) dashboard = schema.ns("osaf.pim", parcel.itsView).allCollection # Add Welcome item to OOTB collections home.add(WelcomeEvent) work.add(WelcomeEvent) thisWeek = CalendarUtility.getCalendarRange(noonToday.date()) def getDayInThisWeek(weekday): res = thisWeek[0] while res.weekday() != weekday: res += datetime.timedelta(days=1) return res # OOTB item 1: Next dentist appointment? event1 = pim.CalendarEvent( itsView=parcel.itsView, displayName=_(u"Next dentist appointment?"), startTime=noonToday.replace(hour=9), anyTime=True, collections=[home], read=True, ) event1.itsItem.changeEditState(pim.Modification.created, when=noonToday.replace(hour=8)) changeTriage(event1, pim.TriageEnum.now) # OOTB item #2: Tell a friend about Chandler item2 = pim.Note( itsView=parcel.itsView, displayName=_(u"Tell a friend about Chandler"), read=True, body=_( u"""Try sharing a collection with family, friends or colleagues. Sign up for a Chandler Hub account to get started: http://hub.chandlerproject.org """), ) schema.ns("osaf.pim", parcel.itsView).allCollection.add(item2) item2.changeEditState(pim.Modification.created, when=noonToday.replace(hour=8)) changeTriage(item2, pim.TriageEnum.now) # OOTB item #3: Write-up task3 = pim.Task( itsView=parcel.itsView, displayName=_(u"Write-up..."), collections=[work], read=True, body= _(u"""Start jotting down ideas for that big write-up you should really have started last week! . . . """), ) task3.itsItem.changeEditState(pim.Modification.created) changeTriage(task3, pim.TriageEnum.now) # OOTB item #4: Follow up task4 = pim.Task( itsView=parcel.itsView, displayName=_(u"Follow up with...on..."), read=True, body= _(u"""Maintain a list of things you need to discuss with a colleague: . . . (Click on the clock icon to add this note to the calendar for the next time you're going to meet with them.) """), ) dashboard.add(task4.itsItem) task4.itsItem.changeEditState(pim.Modification.created) changeTriage(task4, pim.TriageEnum.now) # OOTB item #5: Start planning vacation task5 = pim.Task( itsView=parcel.itsView, displayName=_(u"Start planning vacation"), read=True, collections=[home], body=_("""Places you could go? . . . Activities you'd like to try? . . . Interesting travel articles? . . . """), ) changeTriage(task5, pim.TriageEnum.now) task5.itsItem.changeEditState(pim.Modification.created) # OOTB item #6: Bi-Weekly Status Report event5 = pim.CalendarEvent( itsView=parcel.itsView, displayName=_(u"Bi-Weekly Status Report"), startTime=noonToday, anyTime=True, read=True, collections=[work], body=_("""What have you been up to the last couple of weeks? . . . """), ) def makeRecurring(event, **kw): rule = pim.calendar.Recurrence.RecurrenceRule( itsView=parcel.itsView, **kw) event.rruleset = pim.calendar.Recurrence.RecurrenceRuleSet( itsView=parcel.itsView, rrules=[rule]) for item in event.modifications: changeTriage(item, item._triageStatus) pim.TaskStamp(event5).add() event5.itsItem.changeEditState(pim.Modification.created) makeRecurring(event5, freq='weekly', interval=2) # OOTB item #6: Office supplies order startTime6 = datetime.datetime.combine(getDayInThisWeek(4), noonToday.timetz()) event6 = pim.CalendarEvent( itsView=parcel.itsView, displayName=_(u"Office supplies order"), startTime=startTime6, anyTime=True, read=True, collections=[work], body=_(u"""Maintain a list of supplies you need to get every month: . . . (Share it with others so you can all maintain the list together!) """)) changeTriage(event6, pim.TriageEnum.done) event6.itsItem.changeEditState(pim.Modification.created) makeRecurring(event6, freq='monthly') # OOTB item #7: Salsa class startTime7 = noonToday.replace(hour=14, minute=30) delta = 14 + startTime7.date().weekday() - 6 startTime7 -= datetime.timedelta(days=delta) until7 = startTime7 + datetime.timedelta(days=28) event7 = pim.CalendarEvent(itsView=parcel.itsView, displayName=_(u"Salsa Class"), startTime=startTime7, duration=datetime.timedelta(hours=1), anyTime=False, read=True, collections=[home, fun], body=_(u"""Assignment for this week: . . . Remember to bring: . . . """)) event7.itsItem.changeEditState(pim.Modification.created, when=startTime7) changeTriage(event7, pim.TriageEnum.done) makeRecurring(event7, freq='weekly', until=until7) # A hack to get this occurrence to appear in the dashboard event7.getFirstOccurrence().getNextOccurrence().changeThis() for m in sorted(event7.modifications, key=lambda o: pim.EventStamp(o).startTime): changeTriage(m, m._triageStatus) # OOTB item #8: Brunch potluck... startTime8 = datetime.datetime.combine( getDayInThisWeek(6), datetime.time(11, 0, tzinfo=noonToday.tzinfo)) event8 = pim.CalendarEvent( itsView=parcel.itsView, displayName=_(u"Brunch potluck..."), startTime=startTime8, duration=datetime.timedelta(hours=2), anyTime=False, read=True, collections=[home, fun], body=_(u"""Directions . . . Ideas for games to bring... . . . Sign up to bring food... . . . """), ) changeTriage(event8, event8.autoTriage()) event8.itsItem.changeEditState(pim.Modification.created) # OOTB Item #9: Ideas for presents item9 = pim.Note( itsView=parcel.itsView, displayName=_(u"Ideas for presents"), read=True, collections=[home], body= _(u"""Maintain a list of possible presents for family, friends and colleagues so you're never short on ideas! . . . """), ) changeTriage(item9, pim.TriageEnum.later) item9.changeEditState(pim.Modification.edited) # OOTB Item #10: Thank you notes item10 = pim.Note( itsView=parcel.itsView, displayName=_(u"Thank you notes"), read=True, collections=[home], body= _(u"""Who do you need to write thank you notes to? and for what reason? . . . """), ) changeTriage(item10, pim.TriageEnum.later) item10.changeEditState(pim.Modification.created) # OOTB Item #11: Movie list item11 = pim.Note( itsView=parcel.itsView, displayName=_(u"Movie list"), read=True, collections=[fun, home], body=_(u"""Movies you want to see: . . . """), ) changeTriage(item11, pim.TriageEnum.later) item11.changeEditState(pim.Modification.created) # OOTB Item #12: Book list item12 = pim.Note( itsView=parcel.itsView, displayName=_(u"Book list"), read=True, collections=[fun, home], body=_( u"""Book recommendations you've been meaning to follow up on: . . . """), ) changeTriage(item12, pim.TriageEnum.later) item12.changeEditState(pim.Modification.created) # OOTB Item #13: File taxes startTime13 = noonToday.replace(month=4, day=15) alarmTime13 = startTime13.replace(day=1) if alarmTime13 < noonToday: alarmTime13 = alarmTime13.replace(year=alarmTime13.year + 1) startTime13 = startTime13.replace(year=startTime13.year + 1) event13 = pim.CalendarEvent( itsView=parcel.itsView, startTime=startTime13, displayName=_(u"File taxes!"), read=True, collections=[home], body=_(u"""What forms do you have in hand? . . . What are you missing? . . . Questions for your accountant? . . . """), ) pim.TaskStamp(event13).add() event13.itsItem.changeEditState(pim.Modification.created) changeTriage(event13, pim.TriageEnum.later) event13.itsItem.userReminderTime = alarmTime13 # OOTB Item #14: Class Trip: Exhibit on Sound! location14 = pim.Location.update( parcel, "Exploratorium", displayName="Exploratorium", ) startTime14 = datetime.datetime.combine( getDayInThisWeek(6), datetime.time(15, tzinfo=noonToday.tzinfo)) event14 = pim.CalendarEvent( itsView=parcel.itsView, startTime=startTime14, displayName=_(u"Class Trip: Exhibit on Sound!"), read=True, location=location14, collections=[fun], body=_(u"""Directions... . . . """), ) event14.itsItem.changeEditState(pim.Modification.edited, when=startTime14) changeTriage(event14, pim.TriageEnum.done) # OOTB Item #15: Download Chandler! note15 = pim.Note( itsView=parcel.itsView, displayName=_(u"Download Chandler!"), read=True, ) dashboard.add(note15) done15 = datetime.datetime.now(parcel.itsView.tzinfo.default) done15 -= datetime.timedelta(minutes=5) done15 = done15.replace(second=0, microsecond=0) changeTriage(note15, pim.TriageEnum.done) note15.changeEditState(pim.Modification.edited, when=done15) # Set up sharing for holidays share = sharing.Share(itsView=parcel.itsView, mode='get', contents=holidays, established=True) filters = set([ 'cid:[email protected]', 'cid:[email protected]', 'cid:[email protected]', 'cid:[email protected]', 'cid:[email protected]' ]) share.conduit = sharing.WebDAVMonolithicRecordSetConduit( itsParent=share, host=u'hub.chandlerproject.org', port=443, sharePath=u'webcal/collection', shareName=u'7febe2f4-324c-11dd-d9e4-0016cbca6aed?ticket=01q75n1sy0', useSSL=True, filters=filters, translator=sharing.SharingTranslator, serializer=sharing.ICSSerializer) share.conduit.ticketReadOnly = share.conduit.ticket sharing.SharedItem(share.contents).add() sharing.SharedItem(share.contents).shares.append(share) # Set up the main web server from osaf import webserver startup.Startup.update(parcel, "startServers", invoke="osaf.webserver.start_servers") webserver.Server.update( parcel, "mainServer", # Port to listen on. 1888 was the year Raymond Chandler was born. port=1888, # This path specifies the "doc root" of this web server, and is # relative to webserver/servers, but you may also put in an # absolute path if you wish. # path=unicode(os.path.join("parcels", "osaf", "app", "webhome")), resources=[ webserver.Resource.update( parcel, "lobsResource", displayName=u"Lob Server", location=u"lobs", resourceClass=schema.importString( "osaf.servlets.lobviewer.LobViewerResource"), ), webserver.Resource.update( parcel, "photoResource", displayName=u"Photo Viewer", location=u"photos", resourceClass=schema.importString( "osaf.servlets.photo.PhotosResource"), ), webserver.Resource.update(parcel, "repoResource", displayName=u"Repository Viewer", location=u"repo", resourceClass=schema.importString( "osaf.servlets.repo.RepoResource"), autoView=False), webserver.Resource.update(parcel, "prefResource", displayName=u'Preference Editor', location=u"prefs", resourceClass=schema.importString( "osaf.servlets.prefs.PrefResource"), autoView=False), webserver.Resource.update( parcel, "xmlrpcResource", displayName=u'XML-RPC Service', location=u"xmlrpc", resourceClass=schema.importString( "osaf.servlets.xmlrpc.XmlRpcResource"), autoView=False), ]) from osaf.app import updates # Subtract 15 minutes from lastRun so that in a week's # time we don't conflict with the "compact" trask. updates.UpdateCheckTask.update(parcel, 'updateCheckTask', interval=datetime.timedelta(days=1), lastRun=datetime.datetime.now() - datetime.timedelta(minutes=15)) # Compact task should come last from osaf.app import compact compact.CompactTask.update(parcel, 'compactTask')
def RoundTrip(self): view0 = self.views[0] view1 = self.views[1] coll0 = self.coll item = self.share0.contents.first() testUuid = item.itsUUID.str16() item.icalUID = testUuid self.assert_(not pim.has_stamp(item, sharing.SharedItem)) # Initial publish self.share0.create() view0.commit() stats = self.share0.sync() view0.commit() self.assert_( checkStats(stats, ({ 'added': 2, 'modified': 0, 'removed': 0 }, )), "Sync operation mismatch") self.assert_(pim.has_stamp(coll0, sharing.SharedItem)) self.assert_(pim.has_stamp(item, sharing.SharedItem)) self.assert_(self.share0 in sharing.SharedItem(item).sharedIn) # Local modification only item.body = u"CHANGED" view0.commit() stats = self.share0.sync() view0.commit() self.assert_( checkStats(stats, ({ 'added': 0, 'modified': 0, 'removed': 0 }, { 'added': 0, 'modified': 1, 'removed': 0 })), "Sync operation mismatch") ## Initial subscribe view1.commit() stats = self.share1.sync() view1.commit() self.assert_( checkStats(stats, ({ 'added': 2, 'modified': 0, 'removed': 0 }, { 'added': 0, 'modified': 0, 'removed': 0 })), "Sync operation mismatch") # Verify items are imported for icalUID in self.icalUIDs: n = sharing.findUID(view1, icalUID) self.assertEqual(self.icalUIDs[icalUID], n.displayName) item1 = sharing.findUID(view1, testUuid) self.assert_(item1 in self.share1.contents) self.assert_(item1.body == u"CHANGED") self.assert_(pim.has_stamp(item1, sharing.SharedItem)) self.assert_(pim.has_stamp(self.share1.contents, sharing.SharedItem)) # XXX This fails, why? #self.assertEqual(self.share0.contents.itsUUID, #self.share1.contents.itsUUID) # Local and Remote modification, non-overlapping changes - all changes # apply item.body = u"body changed in 0" item1.displayName = u"displayName changed in 1" view0.commit() stats = self.share0.sync() view0.commit() self.assert_( checkStats(stats, ({ 'added': 0, 'modified': 0, 'removed': 0 }, { 'added': 0, 'modified': 1, 'removed': 0 })), "Sync operation mismatch") view1.commit() stats = self.share1.sync() view1.commit() self.assert_( checkStats(stats, ({ 'added': 0, 'modified': 1, 'removed': 0 }, { 'added': 0, 'modified': 1, 'removed': 0 })), "Sync operation mismatch") view0.commit() stats = self.share0.sync() view0.commit() self.assert_( checkStats(stats, ({ 'added': 0, 'modified': 1, 'removed': 0 }, { 'added': 0, 'modified': 0, 'removed': 0 })), "Sync operation mismatch") self.assert_(item.displayName == "displayName changed in 1") self.assert_(item.body == "body changed in 0") self.assert_(item1.displayName == "displayName changed in 1") self.assert_(item1.body == "body changed in 0") self.share0.destroy() # clean up