Example #1
0
    def setUp(self):
        # This setup is needed because we'd like to be able to use
        # --locale on the command line to test a given locale. So,
        # basically the code below is copy-and-pasted out of Utility.py
        # to make sure that everything gets initialized in the right
        # order.
        needInit = self.view is None

        # We always store a list of all failures, so that we can report them
        # all rather than fail on the first.
        self.failures = []

        if needInit:
            Utility.initLogging(Globals.options)
            type(self).view = NullRepositoryView()

            parcelPath = Utility.initParcelEnv(Globals.options, Globals.chandlerDirectory)
            pluginEnv, pluginEggs = Utility.initPluginEnv(Globals.options, Globals.options.pluginPath)

            Utility.initI18n(Globals.options)

            Utility.initParcels(Globals.options, self.view, parcelPath)
            Utility.initPlugins(Globals.options, self.view, pluginEnv, pluginEggs)
        # We don't want to import these globally, because they will
        # trigger parcel loading, and that will cause i18n to be set
        # up before the above call to initI18n, which will mean --locale
        # won't work on the command line. So, instead, we stash these
        # in instance variables.
        self.Menu = schema.importString("osaf.framework.blocks.Menu")
        self.MenuItem = schema.importString("osaf.framework.blocks.MenuItem")
Example #2
0
    def setUp(self):
        # This setup is needed because we'd like to be able to use
        # --locale on the command line to test a given locale. So,
        # basically the code below is copy-and-pasted out of Utility.py
        # to make sure that everything gets initialized in the right
        # order.
        needInit = (self.view is None)

        # We always store a list of all failures, so that we can report them
        # all rather than fail on the first.
        self.failures = []

        if needInit:
            Utility.initLogging(Globals.options)
            type(self).view = NullRepositoryView()

            parcelPath = Utility.initParcelEnv(Globals.options,
                                               Globals.chandlerDirectory)
            pluginEnv, pluginEggs = Utility.initPluginEnv(
                Globals.options, Globals.options.pluginPath)

            Utility.initI18n(Globals.options)

            Utility.initParcels(Globals.options, self.view, parcelPath)
            Utility.initPlugins(Globals.options, self.view, pluginEnv,
                                pluginEggs)
        # We don't want to import these globally, because they will
        # trigger parcel loading, and that will cause i18n to be set
        # up before the above call to initI18n, which will mean --locale
        # won't work on the command line. So, instead, we stash these
        # in instance variables.
        self.Menu = schema.importString('osaf.framework.blocks.Menu')
        self.MenuItem = schema.importString('osaf.framework.blocks.MenuItem')
Example #3
0
    def __getValueWrapper(self, attr):
    
        for change in self.changes or []:
            # See if we have a change pending for this attribute
            if change[2] == attr:
                return change[0]
    
        target = self.proxiedItem.__class__
        descriptor = getattr(target, attr, None)
        
        if descriptor is None and attr.find(".") != -1:
            try:
                descriptor = schema.importString(attr)
            except ImportError:
                pass

        if isinstance(descriptor, schema.Descriptor):
            if attr == stamping.Stamp.stampCollections.name:
                attrStore = StampCollectionsValue(descriptor)
            elif getattr(descriptor, 'cardinality', 'single') == 'single':
                attrStore = SimpleValue(descriptor)
            else:
                attrStore = MultiValue(descriptor)
        elif isinstance(descriptor, schema.Calculated):
            attrStore = SimpleValue(descriptor)
        elif inspect.ismethod(descriptor):
            attrStore = MethodWrapper(descriptor)
        else:
            return None
        return attrStore
Example #4
0
    def _appendFailure(self, msg, *args):
        # Method used to append an failure to self.failures.
        # msg is the usual python-style format string, while we process
        # some args specially:
        #
        # - Any Menu/MenuItem is pretty-printed, in the form:
        #
        #  Root >> Sub&menu >> &Item
        #
        # - A 2-element tuple is a hack used for marking a "toggleTitle"
        #   menu item title (i.e. an alternative to the menu title when some
        #   state has changed) used when reporting mnemonic problems. We'll
        # print out a [toggleTitle] in the error message here to clarify
        # whhere the problem lies.
        blockClass = schema.importString("osaf.framework.blocks.Block.Block")

        def _itemPath(obj):
            if isinstance(obj, tuple):
                obj, title = obj

                yield "%s[toggle]" % (title,)
                obj = obj.parentBlock

            while obj is not None:
                try:
                    yield obj.getAttributeValue("title")
                except AttributeError:
                    if not isinstance(obj, blockClass):
                        yield unicode(obj)
                obj = getattr(obj, "parentBlock", None)

        prettyArgs = tuple(" >> ".join(reversed(tuple(_itemPath(arg)))) for arg in args)
        self.failures.append(msg % prettyArgs)
    def getByline(self):
        lastModification = self.lastModification
        assert lastModification in self.BYLINE_FORMATS

        fmt, noUserFmt = self.BYLINE_FORMATS[lastModification]

        # fall back to createdOn
        view = self.itsView
        lastModified = (self.lastModified or getattr(self, 'createdOn', None)
                        or datetime.now(view.tzinfo.default))

        shortDateTimeFormat = schema.importString(
            "osaf.pim.shortDateTimeFormat")
        date = shortDateTimeFormat.format(view, lastModified)

        tzPrefs = schema.ns('osaf.pim', view).TimezonePrefs
        if tzPrefs.showUI:
            from calendar.TimeZone import shortTZ
            tzName = shortTZ(view, lastModified)
        else:
            tzName = u''

        user = self.lastModifiedBy
        if user:
            result = fmt % dict(user=user.getLabel(), date=date, tz=tzName)
        else:
            result = noUserFmt % dict(date=date, tz=tzName)
        return result.strip()
Example #6
0
    def _appendFailure(self, msg, *args):
        # Method used to append an failure to self.failures.
        # msg is the usual python-style format string, while we process
        # some args specially:
        #
        # - Any Menu/MenuItem is pretty-printed, in the form:
        #
        #  Root >> Sub&menu >> &Item
        #
        # - A 2-element tuple is a hack used for marking a "toggleTitle"
        #   menu item title (i.e. an alternative to the menu title when some
        #   state has changed) used when reporting mnemonic problems. We'll
        # print out a [toggleTitle] in the error message here to clarify
        # whhere the problem lies.
        blockClass = schema.importString('osaf.framework.blocks.Block.Block')

        def _itemPath(obj):
            if isinstance(obj, tuple):
                obj, title = obj

                yield "%s[toggle]" % (title, )
                obj = obj.parentBlock

            while obj is not None:
                try:
                    yield obj.getAttributeValue('title')
                except AttributeError:
                    if not isinstance(obj, blockClass):
                        yield unicode(obj)
                obj = getattr(obj, 'parentBlock', None)

        prettyArgs = tuple(" >> ".join(reversed(tuple(_itemPath(arg))))
                           for arg in args)
        self.failures.append(msg % prettyArgs)
Example #7
0
    def getByline(self):
        lastModification = self.lastModification
        assert lastModification in self.BYLINE_FORMATS
        
        fmt, noUserFmt = self.BYLINE_FORMATS[lastModification]

        # fall back to createdOn
        view = self.itsView
        lastModified = (self.lastModified or getattr(self, 'createdOn', None) or
                        datetime.now(view.tzinfo.default))

        shortDateTimeFormat = schema.importString("osaf.pim.shortDateTimeFormat")
        date = shortDateTimeFormat.format(view, lastModified)

        tzPrefs = schema.ns('osaf.pim', view).TimezonePrefs
        if tzPrefs.showUI:
            from calendar.TimeZone import shortTZ            
            tzName = shortTZ(view, lastModified)
        else:
            tzName = u''
            
        user = self.lastModifiedBy
        if user:
            result = fmt % dict(user=user.getLabel(), date=date, tz=tzName)
        else:
            result = noUserFmt % dict(date=date, tz=tzName)
        return result.strip()
Example #8
0
    def __getValueWrapper(self, attr):

        for change in self.changes or []:
            # See if we have a change pending for this attribute
            if change[2] == attr:
                return change[0]

        target = self.proxiedItem.__class__
        descriptor = getattr(target, attr, None)

        if descriptor is None and attr.find(".") != -1:
            try:
                descriptor = schema.importString(attr)
            except ImportError:
                pass

        if isinstance(descriptor, schema.Descriptor):
            if attr == stamping.Stamp.stampCollections.name:
                attrStore = StampCollectionsValue(descriptor)
            elif getattr(descriptor, 'cardinality', 'single') == 'single':
                attrStore = SimpleValue(descriptor)
            else:
                attrStore = MultiValue(descriptor)
        elif isinstance(descriptor, schema.Calculated):
            attrStore = SimpleValue(descriptor)
        elif inspect.ismethod(descriptor):
            attrStore = MethodWrapper(descriptor)
        else:
            return None
        return attrStore
Example #9
0
 def persistent_load((uri, module)):
     try:
         return uri_registry[uri]
     except KeyError:
         pass
     # It wasn't in the registry by URI, see if we can import it
     if module not in sys.modules:
         try:
             schema.importString(module)
         except ImportError:
             pass
     try:
         # Maybe it's in the registry now...
         return uri_registry[uri]
     except KeyError:
         # Create a dummy record type for the object
         # XXX this really should try some sort of persistent registry
         #     before falling back to a fake record type
         #
         rtype = type("Unknown", (UnknownRecord,), dict(URI=uri))
         uri_registry[uri] = rtype
         return rtype
Example #10
0
 def persistent_load((uri, module)):
     try:
         return uri_registry[uri]
     except KeyError:
         pass
     # It wasn't in the registry by URI, see if we can import it
     if module not in sys.modules:
         try:
             schema.importString(module)
         except ImportError:
             pass
     try:
         # Maybe it's in the registry now...
         return uri_registry[uri]
     except KeyError:
         # Create a dummy record type for the object
         # XXX this really should try some sort of persistent registry
         #     before falling back to a fake record type
         #
         rtype = type("Unknown", (UnknownRecord,), dict(URI=uri))
         uri_registry[uri] = rtype
         return rtype
    def startup(self):
        docRoot = self.path

        # Need to convert from unicode to bytes
        root = static.File(docRoot.encode("UTF-8"))

        # .rpy files are twisted's version of a cgi
        root.ignoreExt(".rpy")
        root.processors = {".rpy": script.ResourceScript}

        logger.info(u"Activating web server on port %s with docroot %s" % \
         (self.port, docRoot))

        # Hook up all associated resources to a location under the docroot
        for res in self.resources:
            logger.info(u"   Hooking up /%s to resource '%s'" % \
             (res.location, res.itsName))
            resourceInstance = res.getResource()

            # Give the main thread repository view to the resource instance
            resourceInstance.repositoryView = self.itsView

            # Also give the twisted web resource a handle to the resource
            # item
            resourceInstance.resourceItem = res
            root.putChild(res.location, resourceInstance)

        # Hook up all associated directories to a location under the docroot
        for directory in self.directories:
            module = schema.importString(directory.module)
            moduleDir = os.path.dirname(module.__file__)
            docRoot = os.path.join(moduleDir, directory.path)
            logger.info(u"   Hooking up /%s to directory %s" %
                        (directory.location, docRoot))
            root.putChild(directory.location, static.File(docRoot))

        site = server.Site(root)
        try:
            reactor.callFromThread(reactor.listenTCP, self.port, site)
            self.activated = True
        except twisted.internet.error.CannotListenError, e:
            logger.error("Twisted error: %s" % str(e))
            print e
Example #12
0
    def startup(self):
        docRoot = self.path
       
        # Need to convert from unicode to bytes 
        root = static.File(docRoot.encode("UTF-8"))

        # .rpy files are twisted's version of a cgi
        root.ignoreExt(".rpy")
        root.processors = {".rpy" : script.ResourceScript}

        logger.info(u"Activating web server on port %s with docroot %s" % \
         (self.port, docRoot))

        # Hook up all associated resources to a location under the docroot
        for res in self.resources:
            logger.info(u"   Hooking up /%s to resource '%s'" % \
             (res.location, res.itsName))
            resourceInstance = res.getResource()

            # Give the main thread repository view to the resource instance
            resourceInstance.repositoryView = self.itsView

            # Also give the twisted web resource a handle to the resource
            # item
            resourceInstance.resourceItem = res
            root.putChild(res.location, resourceInstance)

        # Hook up all associated directories to a location under the docroot
        for directory in self.directories:
            module = schema.importString(directory.module)
            moduleDir = os.path.dirname(module.__file__)
            docRoot = os.path.join(moduleDir, directory.path)
            logger.info(u"   Hooking up /%s to directory %s" %
                (directory.location, docRoot))
            root.putChild(directory.location, static.File(docRoot))

        site = server.Site(root)
        try:
            reactor.callFromThread(reactor.listenTCP, self.port, site)
            self.activated = True
        except twisted.internet.error.CannotListenError, e:
            logger.error("Twisted error: %s" % str(e))
            print e
Example #13
0
 def getTarget(self):
     """Import the object named by ``invoke`` and return it"""
     return schema.importString(self.invoke)
Example #14
0
def installParcel(parcel, oldVersion=None):

    curDav = Reference.update(parcel, 'currentWebDAVAccount')
    curMail = Reference.update(parcel, 'currentMailAccount')
    curSmtp = Reference.update(parcel, 'currentSMTPAccount')
    curCon = Reference.update(parcel, 'currentContact')

    sharing = schema.ns("osaf.sharing", parcel)
    model = schema.ns("osaf.pim", parcel)
    mail = schema.ns("osaf.pim.mail", parcel)
    photos = schema.ns("osaf.pim.photos", parcel)
    contacts = schema.ns("osaf.pim.contacts", parcel)

    # Items created in osaf.app (this parcel):

    sharing.WebDAVAccount.update(parcel,
                                 'OSAFWebDAVAccount',
                                 displayName=u'OSAF sharing',
                                 host=u'pilikia.osafoundation.org',
                                 path=u'/dev1',
                                 username=u'dev1',
                                 password=u'd4vShare',
                                 useSSL=False,
                                 port=80,
                                 references=[curDav])

    sharing.WebDAVAccount.update(
        parcel,
        'XythosWebDAVAccount',
        displayName=u'Xythos sharing',
        host=u'www.sharemation.com',
        path=u'/OSAFdot5',
        username=u'OSAFdot5',
        password=u'osafdemo',
        useSSL=False,
        port=80,
    )

    sharing.WebDAVAccount.update(
        parcel,
        'VenueWebDAVAccount',
        displayName=u'Venue sharing',
        host=u'webdav.venuecom.com',
        path=u'/calendar/OSAFdot5/calendars',
        username=u'OSAFdot5',
        password=u'demo',
        useSSL=False,
        port=80,
    )

    preReply = mail.EmailAddress.update(parcel, 'PredefinedReplyAddress')

    preSmtp = mail.SMTPAccount.update(parcel,
                                      'PredefinedSMTPAccount',
                                      displayName=u'Outgoing SMTP mail',
                                      references=[curSmtp])

    mail.IMAPAccount.update(parcel,
                            'PredefinedIMAPAccount',
                            displayName=u'Incoming IMAP mail',
                            replyToAddress=preReply,
                            defaultSMTPAccount=preSmtp,
                            references=[curMail])

    mail.POPAccount.update(parcel,
                           'PredefinedPOPAccount',
                           displayName=u'Incoming POP mail',
                           replyToAddress=preReply,
                           defaultSMTPAccount=preSmtp)

    testReply = mail.EmailAddress.update(parcel, 'TestReplyAddress')

    testSmtp = mail.SMTPAccount.update(parcel,
                                       'TestSMTPAccount',
                                       displayName=u'Test SMTP Account',
                                       isActive=False)

    mail.IMAPAccount.update(parcel,
                            'TestIMAPAccount',
                            displayName=u'Test IMAP mail',
                            replyToAddress=testReply,
                            defaultSMTPAccount=testSmtp,
                            isActive=False)

    mail.POPAccount.update(parcel,
                           'TestPOPAccount',
                           displayName=u'Test POP mail',
                           replyToAddress=testReply,
                           defaultSMTPAccount=testSmtp,
                           isActive=False)

    model.ItemCollection.update(parcel,
                                'trash',
                                displayName=_('Trash'),
                                renameable=False)

    welcome = photos.Photo.update(parcel,
                                  'WelcomePhoto',
                                  displayName=u'Welcome to Chandler 0.5',
                                  dateTaken=datetime.datetime.now(),
                                  creator=contacts.Contact.update(
                                      parcel,
                                      'OSAFContact',
                                      emailAddress=u'*****@*****.**',
                                      contactName=contacts.ContactName.update(
                                          parcel,
                                          'OSAFContactName',
                                          firstName=u'OSAF',
                                          lastName=u'Development')))

    welcome.importFromFile(
        os.path.join(os.path.dirname(__file__), "TeamOSAF.jpg"))

    body = u"""Welcome to the Chandler 0.5 Release!

Chandler 0.5 contains support for early adopter developers who want to start building parcels. For example, developers now can create form-based parcels extending the kinds of information that Chandler manages. This release also brings significant improvements to infrastructure areas such as sharing, and to overall performance and reliability.

In addition to the maturing developer infrastructure, Chandler 0.5 begins to focus on fleshing out calendar features and functionality, supporting basic individual and collaborative calendaring tasks.

As you get started, be sure to set up your email and WebDAV account information under the File > Accounts menu.

For a self-guided demo with accompanying screenshots, point your browser to:
   http://www.osafoundation.org/0.5/GuidedTour.htm

For more details on this release, please visit:
    http://wiki.osafoundation.org/bin/view/Chandler/ChandlerZeroPointFiveReadme

Please note, this release is still intended to be experimental, do not trust your real data with this version. An experimental file import/export feature is available to backup your calendar data.

Thank you for trying Chandler. Your feedback is welcome on our mail lists:
    http://wiki.osafoundation.org/bin/view/Chandler/OsafMailingLists

The Chandler Team"""

    welcome.body = welcome.getAttributeAspect('body', 'type').makeValue(body)

    # Set up the main web server
    startup = schema.ns("osaf.startup", parcel)
    webserver = schema.ns("osaf.webserver", parcel)

    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="webhome",
        resources=[
            webserver.Resource.update(
                parcel,
                "lobsterResource",
                displayName="Lob Server",
                location="lobs",
                resourceClass=schema.importString(
                    "osaf.servlets.lobviewer.LobViewerResource"),
            ),
            webserver.Resource.update(
                parcel,
                "photoResource",
                displayName="Photo Viewer",
                location="photos",
                resourceClass=schema.importString(
                    "osaf.servlets.photos.PhotosResource"),
            ),
            webserver.Resource.update(
                parcel,
                "repoResource",
                displayName="Repository Viewer",
                location="repo",
                resourceClass=schema.importString(
                    "osaf.servlets.repo.RepoResource"),
            )
        ])
Example #15
0
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')
Example #16
0
def installParcel(parcel, oldVersion=None):

    curDav = Reference.update(parcel, 'currentWebDAVAccount')
    curMail = Reference.update(parcel, 'currentMailAccount')
    curSmtp = Reference.update(parcel, 'currentSMTPAccount')
    curCon = Reference.update(parcel, 'currentContact')

    sharing = schema.ns("osaf.sharing", parcel)
    model = schema.ns("osaf.pim", parcel)
    mail = schema.ns("osaf.pim.mail", parcel)
    photos = schema.ns("osaf.pim.photos", parcel)
    contacts = schema.ns("osaf.pim.contacts", parcel)

    # Items created in osaf.app (this parcel):

    sharing.WebDAVAccount.update(parcel, 'OSAFWebDAVAccount',
        displayName=u'OSAF sharing',
        host=u'pilikia.osafoundation.org',
        path=u'/dev1',
        username=u'dev1',
        password=u'd4vShare',
        useSSL=False,
        port=80,
        references=[curDav]
    )

    sharing.WebDAVAccount.update(parcel, 'XythosWebDAVAccount',
        displayName=u'Xythos sharing',
        host=u'www.sharemation.com',
        path=u'/OSAFdot5',
        username=u'OSAFdot5',
        password=u'osafdemo',
        useSSL=False,
        port=80,
    )

    sharing.WebDAVAccount.update(parcel, 'VenueWebDAVAccount',
        displayName=u'Venue sharing',
        host=u'webdav.venuecom.com',
        path=u'/calendar/OSAFdot5/calendars',
        username=u'OSAFdot5',
        password=u'demo',
        useSSL=False,
        port=80,
    )

    preReply = mail.EmailAddress.update(parcel, 'PredefinedReplyAddress')

    preSmtp = mail.SMTPAccount.update(parcel, 'PredefinedSMTPAccount',
        displayName=u'Outgoing SMTP mail',
        references=[curSmtp]
    )

    mail.IMAPAccount.update(parcel, 'PredefinedIMAPAccount',
        displayName=u'Incoming IMAP mail',
        replyToAddress=preReply,
        defaultSMTPAccount=preSmtp,
        references=[curMail]
    )

    mail.POPAccount.update(parcel, 'PredefinedPOPAccount',
        displayName=u'Incoming POP mail',
        replyToAddress=preReply,
        defaultSMTPAccount=preSmtp
    )


    testReply = mail.EmailAddress.update(parcel, 'TestReplyAddress')

    testSmtp = mail.SMTPAccount.update(parcel, 'TestSMTPAccount',
        displayName=u'Test SMTP Account',
        isActive=False
    )

    mail.IMAPAccount.update(parcel, 'TestIMAPAccount',
        displayName=u'Test IMAP mail',
        replyToAddress=testReply,
        defaultSMTPAccount=testSmtp,
        isActive=False
    )

    mail.POPAccount.update(parcel, 'TestPOPAccount',
        displayName=u'Test POP mail',
        replyToAddress=testReply,
        defaultSMTPAccount=testSmtp,
        isActive=False
    )


    model.ItemCollection.update(parcel, 'trash',
        displayName=_('Trash'),
        renameable=False
    )

    welcome = photos.Photo.update(parcel, 'WelcomePhoto',
        displayName=u'Welcome to Chandler 0.5',
        dateTaken=datetime.datetime.now(),
        creator=contacts.Contact.update(parcel, 'OSAFContact',
             emailAddress=u'*****@*****.**',
             contactName=contacts.ContactName.update(parcel, 'OSAFContactName',
                firstName=u'OSAF',
                lastName=u'Development'
             )
        )
    )

    welcome.importFromFile(os.path.join(os.path.dirname(__file__),
        "TeamOSAF.jpg"))

    body = u"""Welcome to the Chandler 0.5 Release!

Chandler 0.5 contains support for early adopter developers who want to start building parcels. For example, developers now can create form-based parcels extending the kinds of information that Chandler manages. This release also brings significant improvements to infrastructure areas such as sharing, and to overall performance and reliability.

In addition to the maturing developer infrastructure, Chandler 0.5 begins to focus on fleshing out calendar features and functionality, supporting basic individual and collaborative calendaring tasks.

As you get started, be sure to set up your email and WebDAV account information under the File > Accounts menu.

For a self-guided demo with accompanying screenshots, point your browser to:
   http://www.osafoundation.org/0.5/GuidedTour.htm

For more details on this release, please visit:
    http://wiki.osafoundation.org/bin/view/Chandler/ChandlerZeroPointFiveReadme

Please note, this release is still intended to be experimental, do not trust your real data with this version. An experimental file import/export feature is available to backup your calendar data.

Thank you for trying Chandler. Your feedback is welcome on our mail lists:
    http://wiki.osafoundation.org/bin/view/Chandler/OsafMailingLists

The Chandler Team"""

    welcome.body = welcome.getAttributeAspect('body', 'type').makeValue(body)


    # Set up the main web server
    startup = schema.ns("osaf.startup", parcel)
    webserver = schema.ns("osaf.webserver", parcel)

    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="webhome",

        resources = [
            webserver.Resource.update(parcel, "lobsterResource",
                displayName="Lob Server",
                location="lobs",
                resourceClass=schema.importString(
                    "osaf.servlets.lobviewer.LobViewerResource"
                ),
            ),
            webserver.Resource.update(parcel, "photoResource",
                displayName="Photo Viewer",
                location="photos",
                resourceClass=schema.importString(
                    "osaf.servlets.photos.PhotosResource"
                ),
            ),
            webserver.Resource.update(parcel, "repoResource",
                displayName="Repository Viewer",
                location="repo",
                resourceClass=schema.importString(
                    "osaf.servlets.repo.RepoResource"
                ),
            )
        ]
    )
Example #17
0
from application import schema
from application.Parcel import Manager as ParcelManager
from application.Parcel import Parcel
from repository.schema.Kind import Kind
from repository.persistence.RepositoryView import NullRepositoryView
import sys, logging, os

# pre-import any command line arguments so errors can be reported sooner
report_on = [(arg, schema.importString(arg))for arg in sys.argv[1:]]
  
for chatty in 'Parcel', 'Inbound':
    # Silence talkative loggers
    logger = logging.getLogger(chatty)
    logger.setLevel(logging.WARNING)

logging.getLogger().addHandler(logging.StreamHandler())

rep = NullRepositoryView()
schema.initRepository(rep)

manager = ParcelManager.get(
    rep, path=[os.path.join(os.path.dirname(__file__),'parcels')]
)

manager.loadParcels() #['http://osafoundation.org/parcels/osaf/contentmodel'])

classKinds = {}
allKinds = set()

def scan_parcel(item):
    for child in item.iterChildren():
Example #18
0
 def getTarget(self):
     """Import the object named by ``invoke`` and return it"""
     return schema.importString(self.invoke)
Example #19
0
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')