class TimeZone(trellis.Component, context.Service): default = trellis.attr(ICUtzinfo.default) @trellis.perform def save_default(self): ICUtzinfo.setDefault(self.default) class _FloatingTZInfo(ICUtzinfo): def __init__(self): pass def utcoffset(self, dt): return TimeZone.default.utcoffset(dt) def dst(self, dt): return TimeZone.default.dst(dt) def __repr__(self): return "FloatingTZ(%r)" % (TimeZone.default,) floating = _FloatingTZInfo() def __getitem__(self, key): result = ICUtzinfo.getInstance(key) if result.tzid == 'GMT' and key != 'GMT': return None else: return result ### Helper constants pacific = ICUtzinfo.getInstance("US/Pacific") eastern = ICUtzinfo.getInstance("US/Eastern") utc = ICUtzinfo.getInstance("UTC")
def _makeValidValues(self): """ create valid values of appropriate types""" class myStruct(object): __slots__ = ('name', 'rank') self.uuid = self.attrKind.itsUUID self.uuidString = str(self.uuid) self.pathString = '//Schema/Core/Item' self.path = Path(self.pathString) self.singleRef = SingleRef(self.uuid) self.itemClass = eval('repository.item.Item.Item') self.dateTimeString = '2004-01-08 12:34:56 US/Mountain' self.dateTime = datetime(2004, 1, 8, 12, 34, 56, tzinfo=ICUtzinfo.getInstance('US/Mountain')) self.timeDeltaString= '-8+45.000012' self.timeDelta = timedelta(-8, 45, 12) self.enum = self.types['Enumeration'].newItem('myEnum', self.rep) self.enum.values = ['red', 'green', 'blue'] self.structType = self.types['Struct'].newItem('myStruct', self.rep) self.structType.fields=['name','rank'] self.structType.implementationTypes = {'python': myStruct } self.struct = myStruct() self.lob = self.types['Lob'].makeValue("aba;dsjfa;jfdl;ajru87z.vncxyt89q47654", encoding='utf-8', mimetype='text/plain')
def setUp(self): super(AliasTest, self).setUp() self.kind = self._find(self._KIND_KIND) self.itemKind = self._find(self._ITEM_KIND) self.attrKind = self.itemKind.itsParent['Attribute'] self.newKind = self.kind.newItem('newKind', self.rep) self.typeKind = self._find('//Schema/Core/Type') self.aliasKind = self._find('//Schema/Core/Alias') self.alias = self.aliasKind.newItem('alias', self.rep) self.dateTimeType = self._find('//Schema/Core/DateTime') self.alias.addValue('types', self.dateTimeType) self.intType = self._find('//Schema/Core/Integer') self.alias.addValue('types', self.intType) self.dateTimeString = '2004-01-08 12:34:56-0800' self.dateTime = datetime(2004, 1, 8, 12, 34, 56, tzinfo=ICUtzinfo.getInstance('US/Pacific'))
def readValue(self, itemReader, offset, data, withSchema, view, name, afterLoadHooks): if data[offset] == '\0': return offset+1, None offset, string = itemReader.readString(offset+1, data) return offset, ICUtzinfo.getInstance(string)
def _valueFromFields(self, flds): if 'timezone' in flds: tz = ICUtzinfo.getInstance(flds['timezone']) else: tz = None return time(flds['hour'], flds['minute'], flds['second'], flds['microsecond'], tz)
def _valueFromFields(self, flds): if 'timezone' in flds and flds['timezone'] is not None: tz = ICUtzinfo.getInstance(flds['timezone']) else: tz = None return datetime(flds['year'], flds['month'], flds['day'], flds['hour'], flds['minute'], flds['second'], flds['microsecond'], tz)
def getICUInstance(name): """Return an ICUInstance, or None for false positive GMT results.""" result = None if name is not None: result = ICUtzinfo.getInstance(name) if result is not None and \ result.tzid == 'GMT' and \ name != 'GMT': result = None return result
def makeValue(self, data): values = data.split(' ') count = len(values) if count < 1: raise ValueError, data if count >= 1: (HH, mm, second) = values[0].split(':') tz = None if count >= 2: tz = ICUtzinfo.getInstance(values[1]) ss, us = self.parseSecond(second) return time(int(HH), int(mm), ss, us, tz)
def setUp(self): super(AliasTest, self).setUp() self.kind = self._find(self._KIND_KIND) self.itemKind = self._find(self._ITEM_KIND) self.attrKind = self.itemKind.itsParent['Attribute'] self.newKind = self.kind.newItem('newKind', self.rep) self.typeKind = self._find('//Schema/Core/Type') self.aliasKind = self._find('//Schema/Core/Alias') self.alias = self.aliasKind.newItem('alias', self.rep) self.dateTimeType = self._find('//Schema/Core/DateTime') self.alias.addValue('types',self.dateTimeType) self.intType = self._find('//Schema/Core/Integer') self.alias.addValue('types',self.intType) self.dateTimeString = '2004-01-08 12:34:56-0800' self.dateTime = datetime(2004, 1, 8, 12, 34, 56, tzinfo=ICUtzinfo.getInstance('US/Pacific'))
def test(self): tz = ICUtzinfo.getInstance("America/Los_Angeles") self.failUnlessDatetimesMatch( RFC2822DateToDatetime("Thu, 07 Feb 2008 08:59:39 -0600", tz), datetime(2008, 2, 7, 6, 59, 39, tzinfo=tz) ) # America/Los_Angeles is 2 hours behind -0600 in Feb
def __getitem__(self, key): result = ICUtzinfo.getInstance(key) if result.tzid == 'GMT' and key != 'GMT': return None else: return result
def initOptions(**kwds): """ Load and parse the command line options, with overrides in **kwds. Returns options """ #XXX i18n parcelPath, profileDir could have non-ascii paths # %prog expands to os.path.basename(sys.argv[0]) usage = "usage: %prog [options]" parser = OptionParser(usage=usage, version="%prog") for name, (shortCmd, longCmd, optionType, defaultValue, environName, helpText) in COMMAND_LINE_OPTIONS.iteritems(): if environName and environName in os.environ: if optionType == 'b': defaultValue = True elif optionType == 'v': # If a type 'v' (variable # of args) flag is set via envvar, # treat this as a regular string type, except make the envvar # value a list. The problem with this is that if the command # line also has this flag, it doesn't go through the var-args # callback, and therefore must have one and only one arg. optionType = 's' defaultValue = [os.environ[environName]] else: defaultValue = os.environ[environName] if optionType == 'b': parser.add_option(shortCmd, longCmd, dest=name, action='store_true', default=defaultValue, help=helpText) elif optionType == 'v': # use the above varArgsCallback to handle flags with zero or # more arguments. defaultValue needs to be a list parser.add_option(shortCmd, longCmd, dest=name, action="callback", callback=varArgsCallback, callback_args=(defaultValue, ), help=helpText) else: parser.add_option(shortCmd, longCmd, dest=name, default=defaultValue, help=helpText) if sys.platform == 'darwin': # [Bug:2464] # On the Mac, double-clicked apps are launched with an extra # argument, '-psn_x_y', where x & y are unsigned integers. This # is used to rendezvous between the launched app and the Window Server. # # We remove it from parser's arguments because it conflicts with # the -p (parcel path) option, overriding the PARCELPATH environment # variable if set. args = [arg for arg in sys.argv[1:] if not arg.startswith('-psn_')] (options, args) = parser.parse_args(args=args) else: (options, args) = parser.parse_args() for (opt, val) in kwds.iteritems(): setattr(options, opt, val) # Convert a few options if options.chandlerTestSuite: options.scriptFile = "tools/cats/Functional/FunctionalTestSuite.py" if options.nocatch: options.catch = "tests" # Ensure a profile directory initProfileDir(options) # Load prefs and override default options from prefs prefs = loadPrefs(options).get('options') if prefs: for name, (shortCmd, longCmd, optionType, defaultValue, environName, helpText) in COMMAND_LINE_OPTIONS.iteritems(): if name in prefs and getattr(options, name) == defaultValue: if optionType == 'b': value = prefs[name] in ('True', 'true') else: value = prefs[name] setattr(options, name, value) chandlerDirectory = locateChandlerDirectory() # Resolve pluginPath relative to chandlerDirectory and profileDir # This means that relative paths in options.pluginPath get expanded # twice into options.pluginPath, once relative to chandlerDirectory and # once relative to profileDir, in this order, removing duplicates. pluginPath = [ os.path.expanduser(path) for path in options.pluginPath.split(os.pathsep) ] options.pluginPath = [] for path in itertools.chain( (os.path.join(chandlerDirectory, path) for path in pluginPath), (os.path.join(options.profileDir, path) for path in pluginPath)): path = os.path.abspath(os.path.normpath(path)) if path not in options.pluginPath: options.pluginPath.append(path) # Store up the remaining args options.args = args # --reload implies a few other changes: if options.reload: options.create = True options.restore = None if options.timezone: timezone = ICUtzinfo.getInstance(options.timezone) if str(timezone) != options.timezone: raise ValueError, ("Invalid timezone", options.timezone) options.timezone = timezone return options
clickSucceeded = User.emulate_sidebarClick(app_ns().sidebar, "Generated3000", overlay=False) User.idle() # Switch the timezone (this is the action we are measuring) logger.Start("Switch timezone to Pacific/Honolulu") QAUITestAppLib.SetChoice(calendarBlock.widget.tzChoice, "Pacific/Honolulu") User.idle() logger.Stop() # Verification # @@@ KCP this test could be improved # Currently tests that the default tz is now Pacific/Honolulu if ICUtzinfo.default == ICUtzinfo.getInstance("Pacific/Honolulu"): logger.ReportPass("Timezone switched") else: logger.ReportFailure("Timezone failed to switch") if clickSucceeded: logger.ReportPass("Selected large data calendar") else: logger.ReportFailure("Failed to select large data calendar") logger.SetChecked(True) logger.Report("Switch timezone") finally: logger.Close()
def save_default(self): ICUtzinfo.setDefault(self.default)
class Reminder(schema.Item): """ The base class for reminders. Note that this only supports 'custom' (fixed-time) reminders; the more familiar relative reminders are defined in Calendar.py on as RelativeReminder. This resolves some unfortunate circular import dependency issues we had in the past. """ # Make values we can use for distant (or invalid) reminder times farFuture = datetime.max if farFuture.tzinfo is None: farFuture = farFuture.replace(tzinfo=ICUtzinfo.getInstance('UTC')) distantPast = datetime.min if distantPast.tzinfo is None: distantPast = distantPast.replace(tzinfo=ICUtzinfo.getInstance('UTC')) absoluteTime = schema.One( schema.DateTimeTZ, defaultValue=None, doc="If set, overrides relativeTo as the base time for this reminder" ) # These flags represent what kind of reminder this is: # userCreated promptUser # True True a relative or absolute user reminder, usually # created in the detail view (or possibly, imported # as ICalendar) # False False An internal reminder relative to the # the effectiveStartTime of an event, used # to update its triageStatus when it fires. # # @@@ [grant] For now, userCreated and promptUser are identical... It's # not so clear to me whether we need both. # userCreated = schema.One( schema.Boolean, defaultValue=True, doc="Is a user-created reminder?" ) promptUser = schema.One( schema.Boolean, defaultValue=True, doc="Should we show this reminder to the user when it goes off?") reminderItem = schema.One( defaultValue=None, ) pendingEntries = schema.Sequence( PendingReminderEntry, defaultValue=Empty, inverse=PendingReminderEntry.reminder, doc="What user-created reminders have fired, and not been " \ "dismissed or snoozed?" ) nextPoll = schema.One( schema.DateTimeTZ, doc="When next will something interesting happen with this reminder?" \ "Set to reminder.farFuture if this reminder has expired.", defaultValue=None, ) description = schema.One( schema.Text, doc="End-user text description of this reminder. Currently unused by " "Chandler.", ) duration = schema.One( schema.TimeDelta, doc="Reminder DURATION (a la ICalendar VALARM); unused by Chandler.", defaultValue=timedelta(0), ) repeat = schema.One( schema.Integer, doc="Reminder REPEAT (a la ICalendar VALARM); unused by Chandler.", defaultValue=0, ) schema.addClouds( sharing = schema.Cloud( literal = [absoluteTime, userCreated, promptUser] ), copying = schema.Cloud( literal = [absoluteTime, userCreated, promptUser, nextPoll] ) ) def onItemDelete(self, view, deferring): if self.pendingEntries: pending = list(self.pendingEntries) self.pendingEntries.clear() for entry in pending: entry.delete(recursive=True) def updatePending(self, when=None): """ The method makes sure that the Reminder's list of PendingReminderEntries is up-to-date. This involves adding new entries to the list, via the Remindable.reminderFired() method. Also, the C{nextPoll} attribute is updated to the next time something interesting will happen (i.e. another item should be reminded); this may be C{Reminder.farFuture} if the C{Reminder} has no more items to process. @param when: The time to update to. You can pass C{None}, in which case C{datetime.now()} is used. @type when: C{datetime}. """ if when is None: when = datetime.now(self.itsView.tzinfo.default) if self.nextPoll is None: # No value for nextPoll means we've just been initialized. # If we're in the past, we treat ourselves as expired. if self.absoluteTime >= when: self.nextPoll = self.absoluteTime else: self.nextPoll = self.farFuture if self.nextPoll != self.farFuture and when >= self.absoluteTime: self.reminderItem.reminderFired(self, self.absoluteTime) self.nextPoll = self.farFuture self._checkExpired() def _checkExpired(self): if self.isExpired() and not self.userCreated: self.delete(True) def dismissItem(self, item): pendingEntries = self.pendingEntries toDismiss = list(p for p in pendingEntries if p.item is item) assert len(toDismiss), "Attempt to dismiss item non-pending item %r" % ( item) for item in toDismiss: item.delete(recursive=True) if not self.pendingEntries: self.nextPoll = self.farFuture self._checkExpired() def snoozeItem(self, item, delta): nextPoll = self.nextPoll pendingEntries = self.pendingEntries toSnooze = list(p for p in pendingEntries if p.item is item) assert len(toSnooze), "Attempt to snooze item non-pending item %r" % ( item) when = datetime.now(self.itsView.tzinfo.default) + delta for item in toSnooze: item.when = when item.snoozed = True nextPoll = min(nextPoll, item.when) self.nextPoll = nextPoll def getItemBaseTime(self, item): """ Return the time we would fire for this item (independent of if it has been snoozed?) """ return self.absoluteTime or Reminder.farFuture getReminderTime = getItemBaseTime def isExpired(self): return (not self.pendingEntries and self.nextPoll is not None and self.nextPoll >= Reminder.farFuture) @schema.observer(reminderItem) def reminderItemChanged(self, op, attr): if op == 'remove': if self.pendingEntries: # @@@ [grant] Check this! toRemove = list(p for p in self.pendingEntries if isDead(p.item)) for pending in toRemove: self.pendingEntries.remove(pending) if not self.pendingEntries: self.delete(True) @classmethod def defaultTime(cls, view): """ Something's creating a reminder and needs a default time. We'll return 5PM today if that's in the future; otherwise, 8AM tomorrow. """ # start with today at 5PM t = datetime.now(tz=view.tzinfo.default)\ .replace(hour=17, minute=0, second=0, microsecond=0) now = datetime.now(tz=view.tzinfo.default) if t < now: # Make it tomorrow morning at 8AM (eg, 15 hours later) t += timedelta(hours=15) return t @classmethod def getPendingTuples(cls, view, when): """ Return a list of all reminder tuples with fire times in the past, sorted by reminder time. Each tuple contains (reminderTime, remindable, reminder). """ allFutureReminders = schema.ns('osaf.pim', view).allFutureReminders remindersToPoll = [] for reminder in allFutureReminders.iterindexvalues('reminderPoll'): if reminder.nextPoll is None or reminder.nextPoll <= when: remindersToPoll.append(reminder) else: break for reminder in remindersToPoll: reminder.updatePending(when) pendingKind = PendingReminderEntry.getKind(view) trash = schema.ns("osaf.pim", view).trashCollection resultTuples = [] for entry in pendingKind.iterItems(): thisTuple = tuple(getattr(entry, attr, None) for attr in ('when', 'item', 'reminder')) # Show everything except reminders in the trash, and # reminders that have been snoozed into the future. Also, # don't return any "dead" items in the tuple, and check # for missing attributes (bug 11415). if (thisTuple[0] is not None and not isDead(thisTuple[1]) and not isDead(thisTuple[2]) and not thisTuple[1] in trash and not (entry.snoozed and thisTuple[0] > when)): resultTuples.append(thisTuple) resultTuples.sort(key=lambda t: t[0]) return resultTuples
def testTZ(self): tz = ICUtzinfo.getInstance("Africa/Johannesburg") self.failUnlessEqual( datetimeToRFC2822Date(datetime(2004, 4, 13, 13, 13, 0, tzinfo=tz)), "Tue, 13 Apr 2004 13:13:00 +0200")
def initOptions(**kwds): """ Load and parse the command line options, with overrides in **kwds. Returns options """ #XXX i18n parcelPath, profileDir could have non-ascii paths # %prog expands to os.path.basename(sys.argv[0]) usage = "usage: %prog [options]" parser = OptionParser(usage=usage, version="%prog") for name, (shortCmd, longCmd, optionType, defaultValue, environName, helpText) in COMMAND_LINE_OPTIONS.iteritems(): if environName and environName in os.environ: if optionType == 'b': defaultValue = True elif optionType =='v': # If a type 'v' (variable # of args) flag is set via envvar, # treat this as a regular string type, except make the envvar # value a list. The problem with this is that if the command # line also has this flag, it doesn't go through the var-args # callback, and therefore must have one and only one arg. optionType = 's' defaultValue = [os.environ[environName]] else: defaultValue = os.environ[environName] if optionType == 'b': parser.add_option(shortCmd, longCmd, dest=name, action='store_true', default=defaultValue, help=helpText) elif optionType =='v': # use the above varArgsCallback to handle flags with zero or # more arguments. defaultValue needs to be a list parser.add_option(shortCmd, longCmd, dest=name, action="callback", callback=varArgsCallback, callback_args=(defaultValue,), help=helpText) else: parser.add_option(shortCmd, longCmd, dest=name, default=defaultValue, help=helpText) if sys.platform == 'darwin': # [Bug:2464] # On the Mac, double-clicked apps are launched with an extra # argument, '-psn_x_y', where x & y are unsigned integers. This # is used to rendezvous between the launched app and the Window Server. # # We remove it from parser's arguments because it conflicts with # the -p (parcel path) option, overriding the PARCELPATH environment # variable if set. args = [arg for arg in sys.argv[1:] if not arg.startswith('-psn_')] (options, args) = parser.parse_args(args=args) else: (options, args) = parser.parse_args() for (opt,val) in kwds.iteritems(): setattr(options, opt, val) # Convert a few options if options.chandlerTestSuite: options.scriptFile = "tools/cats/Functional/FunctionalTestSuite.py" if options.nocatch: options.catch = "tests" # Ensure a profile directory initProfileDir(options) # Load prefs and override default options from prefs prefs = loadPrefs(options).get('options') if prefs: for name, (shortCmd, longCmd, optionType, defaultValue, environName, helpText) in COMMAND_LINE_OPTIONS.iteritems(): if name in prefs and getattr(options, name) == defaultValue: if optionType == 'b': value = prefs[name] in ('True', 'true') else: value = prefs[name] setattr(options, name, value) chandlerDirectory = locateChandlerDirectory() # Resolve pluginPath relative to chandlerDirectory and profileDir # This means that relative paths in options.pluginPath get expanded # twice into options.pluginPath, once relative to chandlerDirectory and # once relative to profileDir, in this order, removing duplicates. pluginPath = [os.path.expanduser(path) for path in options.pluginPath.split(os.pathsep)] options.pluginPath = [] for path in itertools.chain((os.path.join(chandlerDirectory, path) for path in pluginPath), (os.path.join(options.profileDir, path) for path in pluginPath)): path = os.path.abspath(os.path.normpath(path)) if path not in options.pluginPath: options.pluginPath.append(path) # Store up the remaining args options.args = args # --reload implies a few other changes: if options.reload: options.create = True options.restore = None if options.timezone: timezone = ICUtzinfo.getInstance(options.timezone) if str(timezone) != options.timezone: raise ValueError, ("Invalid timezone", options.timezone) options.timezone = timezone return options
def testTZ(self): tz = ICUtzinfo.getInstance("Africa/Johannesburg") self.failUnlessEqual( datetimeToRFC2822Date(datetime(2004, 4, 13, 13, 13, 0, tzinfo=tz)), "Tue, 13 Apr 2004 13:13:00 +0200" )
def makeValue(self, data): if data == Type.NoneString: return None return ICUtzinfo.getInstance(data)