def test_format_compatibility(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) tz_t = datetime.datetime(2010, 8, 28, 13, 45, 56, 123456, tz) # Converting babel's format to strftime format self.assertEqual( tz_t.strftime('%x %H:%M').decode('utf-8'), datefmt.format_datetime(t, 'short', tz)) self.assertEqual( tz_t.strftime('%x').decode('utf-8'), datefmt.format_date(t, 'short', tz)) self.assertEqual( tz_t.strftime('%H:%M').decode('utf-8'), datefmt.format_time(t, 'short', tz)) for f in ('medium', 'long', 'full'): self.assertEqual( tz_t.strftime('%x %X').decode('utf-8'), datefmt.format_datetime(t, f, tz)) self.assertEqual( tz_t.strftime('%x').decode('utf-8'), datefmt.format_date(t, f, tz)) self.assertEqual( tz_t.strftime('%X').decode('utf-8'), datefmt.format_time(t, f, tz))
def test_getusage(self): reader = Reader('tokyo', opener=MockURLopener) result = reader.getusage() self.assertEqual(73, result['usage']) self.assertEqual(u'18:05', format_time(result['datetime'], str('%H:%M'))) self.assertEqual(u'18', format_time(result['start'], str('%H'), utc)) self.assertEqual(u'19', format_time(result['end'], str('%H'), utc))
def get_work_log(self, mode='all'): db = self.env.get_db_cnx() cursor = db.cursor() if mode == 'user': cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'WHERE wl.user=%s ' 'ORDER BY wl.lastchange DESC', (self.authname,)) elif mode == 'summary': cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM (SELECT user,MAX(lastchange) lastchange FROM work_log GROUP BY user) wlt ' 'INNER JOIN work_log wl ON wlt.user=wl.user AND wlt.lastchange=wl.lastchange ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.user') else: cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.user') rv = [] for user,name,starttime,endtime,ticket,summary,status,comment in cursor: starttime = float(starttime) endtime = float(endtime) started = datetime.fromtimestamp(starttime) dispname = user if name: dispname = '%s (%s)' % (name, user) if not endtime == 0: finished = datetime.fromtimestamp(endtime) delta = 'Worked for %s (between %s %s and %s %s)' % \ (pretty_timedelta(started, finished), format_date(starttime), format_time(starttime), format_date(endtime), format_time(endtime)) else: delta = 'Started %s ago (%s %s)' % \ (pretty_timedelta(started), format_date(starttime), format_time(starttime)) rv.append({'user': user, 'name': name, 'dispname': dispname, 'starttime': int(starttime), 'endtime': int(endtime), 'delta': delta, 'ticket': ticket, 'summary': summary, 'status': status, 'comment': comment}) return rv
def get_timeline_events(self, req, start, stop, filters): self.set_reader() result = self.reader.getusage() usage = result['usage'] title = u"使用率 %d%%" % usage desc = u"今日のピーク時間:%s時〜%s時 予想使用率 %d%%" % (format_time(result['start'], str('%H'), utc), format_time(result['end'], str('%H'), utc), result['demand']) add_stylesheet(req, "setsuden4trac/css/setsuden.css") yield (get_css_classname(usage), result['datetime'], self.reader.author(), ('http://www.gosetsuden.jp/', title, unicode(desc)))
def test_with_babel_format(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) for f in ("short", "medium", "long", "full"): self.assertEqual("2010-08-28", datefmt.format_date(t, f, tz, "iso8601")) self.assertEqual("11:45", datefmt.format_time(t, "short", tz, "iso8601")) self.assertEqual("2010-08-28T11:45", datefmt.format_datetime(t, "short", tz, "iso8601")) self.assertEqual("11:45:56", datefmt.format_time(t, "medium", tz, "iso8601")) self.assertEqual("2010-08-28T11:45:56", datefmt.format_datetime(t, "medium", tz, "iso8601")) for f in ("long", "full"): self.assertEqual("11:45:56+02:00", datefmt.format_time(t, f, tz, "iso8601")) self.assertEqual("2010-08-28T11:45:56+02:00", datefmt.format_datetime(t, f, tz, "iso8601"))
def test_format_compatibility(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) tz_t = datetime.datetime(2010, 8, 28, 13, 45, 56, 123456, tz) # Converting babel's format to strftime format self.assertEqual(tz_t.strftime("%x %H:%M").decode("utf-8"), datefmt.format_datetime(t, "short", tz)) self.assertEqual(tz_t.strftime("%x").decode("utf-8"), datefmt.format_date(t, "short", tz)) self.assertEqual(tz_t.strftime("%H:%M").decode("utf-8"), datefmt.format_time(t, "short", tz)) for f in ("medium", "long", "full"): self.assertEqual(tz_t.strftime("%x %X").decode("utf-8"), datefmt.format_datetime(t, f, tz)) self.assertEqual(tz_t.strftime("%x").decode("utf-8"), datefmt.format_date(t, f, tz)) self.assertEqual(tz_t.strftime("%X").decode("utf-8"), datefmt.format_time(t, f, tz))
def test_absolute(self): t = datetime_now(utc) - timedelta(days=1) label = 'on %s at %s' % \ (format_date(t, locale=locale_en, tzinfo=utc), format_time(t, locale=locale_en, tzinfo=utc)) self.assertEqual(label, self._format_chrome(t, 'absolute', False)) self.assertEqual(label, self._format_timeline(t, 'absolute', False))
def testUsage(self): reader = Reader('kansai', opener=MockURLopener) result = reader.usage('instant', 'latest') self.assertEqual({ "code": 200, "usage":38770000,"timestamp":1313226300000}, result) from datetime import datetime dtime = datetime.fromtimestamp(result['timestamp']/1000, utc) self.assertEqual("18:05", format_time(dtime, str('%H:%M')))
def formatter(self, col, cell_value): if col == 'time': return cell_value != '' and format_time(from_utimestamp(long(cell_value))) or '--' if col in ('date', 'created', 'modified'): return cell_value != '' and format_date(from_utimestamp(long(cell_value))) or '--' if col == 'datetime': return cell_value != '' and format_datetime(from_utimestamp(long(cell_value))) or '--' return cell_value
def test_absolute(self): t = datetime.now(utc) - timedelta(days=1) label = "on %s at %s" % ( format_date(t, locale=locale_en, tzinfo=utc), format_time(t, locale=locale_en, tzinfo=utc), ) self.assertEqual(label, self._format_chrome(t, "absolute", False)) self.assertEqual(label, self._format_timeline(t, "absolute", False))
def test_with_iso8601(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) self.assertEqual('2010-08-28', datefmt.format_date(t, 'iso8601', tz, 'iso8601')) self.assertEqual('11:45:56+02:00', datefmt.format_time(t, 'iso8601', tz, 'iso8601')) self.assertEqual('2010-08-28T11:45:56+02:00', datefmt.format_datetime(t, 'iso8601', tz, 'iso8601'))
def test_default(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) self.assertEqual('2010-08-28', datefmt.format_date(t, tzinfo=tz, locale='iso8601')) self.assertEqual('11:45:56+02:00', datefmt.format_time(t, tzinfo=tz, locale='iso8601')) self.assertEqual('2010-08-28T11:45:56+02:00', datefmt.format_datetime(t, tzinfo=tz, locale='iso8601'))
def test_with_babel_format(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) for f in ('short', 'medium', 'long', 'full'): self.assertEqual('2010-08-28', datefmt.format_date(t, f, tz, 'iso8601')) self.assertEqual('11:45', datefmt.format_time(t, 'short', tz, 'iso8601')) self.assertEqual('2010-08-28T11:45', datefmt.format_datetime(t, 'short', tz, 'iso8601')) self.assertEqual('11:45:56', datefmt.format_time(t, 'medium', tz, 'iso8601')) self.assertEqual('2010-08-28T11:45:56', datefmt.format_datetime(t, 'medium', tz, 'iso8601')) for f in ('long', 'full'): self.assertEqual('11:45:56+02:00', datefmt.format_time(t, f, tz, 'iso8601')) self.assertEqual('2010-08-28T11:45:56+02:00', datefmt.format_datetime(t, f, tz, 'iso8601'))
def test_format_compatibility(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) tz_t = datetime.datetime(2010, 8, 28, 13, 45, 56, 123456, tz) # Converting babel's format to strftime format self.assertEqual(tz_t.strftime('%x %H:%M').decode('utf-8'), datefmt.format_datetime(t, 'short', tz)) self.assertEqual(tz_t.strftime('%x').decode('utf-8'), datefmt.format_date(t, 'short', tz)) self.assertEqual(tz_t.strftime('%H:%M').decode('utf-8'), datefmt.format_time(t, 'short', tz)) for f in ('medium', 'long', 'full'): self.assertEqual(tz_t.strftime('%x %X').decode('utf-8'), datefmt.format_datetime(t, f, tz)) self.assertEqual(tz_t.strftime('%x').decode('utf-8'), datefmt.format_date(t, f, tz)) self.assertEqual(tz_t.strftime('%X').decode('utf-8'), datefmt.format_time(t, f, tz))
def formatter(self, col, cell_value): if col == 'time': return cell_value != '' and format_time( from_utimestamp(long(cell_value))) or '--' if col in ('date', 'created', 'modified'): return cell_value != '' and format_date( from_utimestamp(long(cell_value))) or '--' if col == 'datetime': return cell_value != '' and format_datetime( from_utimestamp(long(cell_value))) or '--' return cell_value
def test_format_compatibility(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) tz_t = datetime.datetime(2010, 8, 28, 13, 45, 56, 123456, tz) en_US = Locale.parse("en_US") # Converting default format to babel's format self.assertEqual("Aug 28, 2010 1:45:56 PM", datefmt.format_datetime(t, "%x %X", tz, en_US)) self.assertEqual("Aug 28, 2010", datefmt.format_datetime(t, "%x", tz, en_US)) self.assertEqual("1:45:56 PM", datefmt.format_datetime(t, "%X", tz, en_US)) self.assertEqual("Aug 28, 2010", datefmt.format_date(t, "%x", tz, en_US)) self.assertEqual("1:45:56 PM", datefmt.format_time(t, "%X", tz, en_US))
def get_info(self, event_providers): # TODO: There are supposed benefits to switching from a XML to JSON event source # http://simile.mit.edu/wiki/JSON_event_source:_use_js_Date%28%29_objects self.req.hdf['event_url'] = self.req.href.requirement() # TODO: This needs to be changed to a local source self.req.hdf['event_section'] = 'timeline' # TODO: This needs to be changed to a local source events = [] start = 0 stop = time.time() filters = ['milestone', 'ticket', 'changeset', 'wiki', 'requirement'] for event_provider in event_providers: #try: for kind, href, title, date, author, message in event_provider.get_timeline_events(self.req, start, stop, filters): # TODO: revisit this code... string escaping is still an issue # Strip/escape HTML markup #if isinstance(title, Markup): # title = title.plaintext(keeplinebreaks=False) if not isinstance(title, Markup): title = Markup(title) title = title.plaintext(keeplinebreaks=False) #title = title.stripentities() message = to_unicode(message) events.append({ # Everything but data will be inserted as attributes into an event tag # Data is provided to allow customization of the bubble content # For more information about the XML format, see # http://simile.mit.edu/wiki/How_to_Create_Event_Source_Files 'isDuration': 'false', 'start': time.strftime("%a %b %d %Y %H:%M:%S "+self.get_gmtstring(), time.gmtime(date)), 'title': title, 'data': {'kind': kind, 'title': title, 'href': href, 'author': author or 'anonymous', 'date': format_date(date), 'time': format_time(date, '%H:%M'), 'dateuid': int(date), 'message': message}, 'debug': isinstance(title, Markup), }) #except Exception, e: # cope with a failure of that provider # pass self.req.hdf['events'] = events
def test_format_compatibility(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) tz_t = datetime.datetime(2010, 8, 28, 13, 45, 56, 123456, tz) en_US = Locale.parse('en_US') # Converting default format to babel's format self.assertEqual('Aug 28, 2010 1:45:56 PM', datefmt.format_datetime(t, '%x %X', tz, en_US)) self.assertEqual('Aug 28, 2010', datefmt.format_datetime(t, '%x', tz, en_US)) self.assertEqual('1:45:56 PM', datefmt.format_datetime(t, '%X', tz, en_US)) self.assertEqual('Aug 28, 2010', datefmt.format_date(t, '%x', tz, en_US)) self.assertEqual('1:45:56 PM', datefmt.format_time(t, '%X', tz, en_US))
def test_i18n_format_time(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) en_US = Locale.parse("en_US") en_GB = Locale.parse("en_GB") fr = Locale.parse("fr") ja = Locale.parse("ja") vi = Locale.parse("vi") zh_CN = Locale.parse("zh_CN") self.assertEqual("1:45:56 PM", datefmt.format_time(t, tzinfo=tz, locale=en_US)) self.assertEqual("13:45:56", datefmt.format_time(t, tzinfo=tz, locale=en_GB)) self.assertEqual("13:45:56", datefmt.format_time(t, tzinfo=tz, locale=fr)) self.assertEqual("13:45:56", datefmt.format_time(t, tzinfo=tz, locale=ja)) self.assertEqual("13:45:56", datefmt.format_time(t, tzinfo=tz, locale=vi)) self.assertEqual(u"下午01:45:56", datefmt.format_time(t, tzinfo=tz, locale=zh_CN))
def test_i18n_format_time(self): tz = datefmt.timezone('GMT +2:00') t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, datefmt.utc) en_US = Locale.parse('en_US') en_GB = Locale.parse('en_GB') fr = Locale.parse('fr') ja = Locale.parse('ja') vi = Locale.parse('vi') zh_CN = Locale.parse('zh_CN') self.assertEqual('1:45:56 PM', datefmt.format_time(t, tzinfo=tz, locale=en_US)) self.assertEqual('13:45:56', datefmt.format_time(t, tzinfo=tz, locale=en_GB)) self.assertEqual('13:45:56', datefmt.format_time(t, tzinfo=tz, locale=fr)) self.assertEqual('13:45:56', datefmt.format_time(t, tzinfo=tz, locale=ja)) self.assertEqual('13:45:56', datefmt.format_time(t, tzinfo=tz, locale=vi)) self.assertEqual(u'下午01:45:56', datefmt.format_time(t, tzinfo=tz, locale=zh_CN))
def test_with_iso8601(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) self.assertEqual("2010-08-28", datefmt.format_date(t, "iso8601", tz, "iso8601")) self.assertEqual("11:45:56+02:00", datefmt.format_time(t, "iso8601", tz, "iso8601")) self.assertEqual("2010-08-28T11:45:56+02:00", datefmt.format_datetime(t, "iso8601", tz, "iso8601"))
class TimelineModule(Component): implements(INavigationContributor, IPermissionRequestor, IRequestHandler) event_providers = ExtensionPoint(ITimelineEventProvider) default_daysback = IntOption( 'timeline', 'default_daysback', 30, """Default number of days displayed in the Timeline, in days. (''since 0.9.'')""") # INavigationContributor methods def get_active_navigation_item(self, req): return 'timeline' def get_navigation_items(self, req): if not req.perm.has_permission('TIMELINE_VIEW'): return yield ('mainnav', 'timeline', html.A('Timeline', href=req.href.timeline(), accesskey=2)) # IPermissionRequestor methods def get_permission_actions(self): return ['TIMELINE_VIEW'] # IRequestHandler methods def match_request(self, req): return re.match(r'/timeline/?', req.path_info) is not None def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 0)) # Parse the from date and adjust the timestamp to the last second of # the day t = time.localtime() if req.args.has_key('from'): try: t = time.strptime(req.args.get('from'), '%x') except: pass fromdate = time.mktime( (t[0], t[1], t[2], 23, 59, 59, t[6], t[7], t[8])) try: daysback = max(0, int(req.args.get('daysback', ''))) except ValueError: daysback = self.default_daysback req.hdf['timeline.from'] = format_date(fromdate) req.hdf['timeline.daysback'] = daysback available_filters = [] for event_provider in self.event_providers: available_filters += event_provider.get_timeline_filters(req) filters = [] # check the request or session for enabled filters, or use default for test in (lambda f: req.args.has_key(f[0]), lambda f: req.session.get('timeline.filter.%s' % f[0], '')\ == '1', lambda f: len(f) == 2 or f[2]): if filters: break filters = [f[0] for f in available_filters if test(f)] # save the results of submitting the timeline form to the session if req.args.has_key('update'): for filter in available_filters: key = 'timeline.filter.%s' % filter[0] if req.args.has_key(filter[0]): req.session[key] = '1' elif req.session.has_key(key): del req.session[key] stop = fromdate start = stop - (daysback + 1) * 86400 events = [] for event_provider in self.event_providers: try: events += event_provider.get_timeline_events( req, start, stop, filters) except Exception, e: # cope with a failure of that provider self._provider_failure(e, req, event_provider, filters, [f[0] for f in available_filters]) events.sort(lambda x, y: cmp(y[3], x[3])) if maxrows and len(events) > maxrows: del events[maxrows:] req.hdf['title'] = 'Timeline' # Get the email addresses of all known users email_map = {} for username, name, email in self.env.get_known_users(): if email: email_map[username] = email idx = 0 for kind, href, title, date, author, message in events: event = { 'kind': kind, 'title': title, 'href': href, 'author': author or 'anonymous', 'date': format_date(date), 'time': format_time(date, '%H:%M'), 'dateuid': int(date), 'message': message } if format == 'rss': # Strip/escape HTML markup if isinstance(title, Markup): title = title.plaintext(keeplinebreaks=False) event['title'] = title event['message'] = to_unicode(message) if author: # For RSS, author must be an email address event['author.email'] = '*****@*****.**' # if author.find('@') != -1: # event['author.email'] = author # elif email_map.has_key(author): # event['author.email'] = email_map[author] event['date'] = http_date(date) req.hdf['timeline.events.%s' % idx] = event idx += 1 if format == 'rss': return 'timeline_rss.cs', 'application/rss+xml' add_stylesheet(req, 'common/css/timeline.css') rss_href = req.href.timeline([(f, 'on') for f in filters], daysback=90, max=50, format='rss') add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml', 'rss') for idx, fltr in enumerate(available_filters): req.hdf['timeline.filters.%d' % idx] = { 'name': fltr[0], 'label': fltr[1], 'enabled': int(fltr[0] in filters) } return 'timeline.cs', None
def get_work_log(self, mode='all'): db = self.env.get_db_cnx() cursor = db.cursor() if mode == 'user': cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'WHERE wl.worker=%s ' 'ORDER BY wl.lastchange DESC', (self.authname, )) elif mode == 'summary': cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM (SELECT worker,MAX(lastchange) AS lastchange FROM work_log GROUP BY worker) wlt ' 'INNER JOIN work_log wl ON wlt.worker=wl.worker AND wlt.lastchange=wl.lastchange ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.worker') else: cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.worker') rv = [] for user, name, starttime, endtime, ticket, summary, status, comment in cursor: starttime = float(starttime) endtime = float(endtime) started = datetime.fromtimestamp(starttime) dispname = user if name: dispname = '%s (%s)' % (name, user) if not endtime == 0: finished = datetime.fromtimestamp(endtime) delta = 'Worked for %s (between %s %s and %s %s)' % \ (pretty_timedelta(started, finished), format_date(starttime), format_time(starttime), format_date(endtime), format_time(endtime)) else: delta = 'Started %s ago (%s %s)' % \ (pretty_timedelta(started), format_date(starttime), format_time(starttime)) rv.append({ 'user': user, 'name': name, 'dispname': dispname, 'starttime': int(starttime), 'endtime': int(endtime), 'delta': delta, 'ticket': ticket, 'summary': summary, 'status': status, 'comment': comment }) return rv
def test_default(self): tz = datefmt.timezone("GMT +2:00") t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz) self.assertEqual("2010-08-28", datefmt.format_date(t, tzinfo=tz, locale="iso8601")) self.assertEqual("11:45:56+02:00", datefmt.format_time(t, tzinfo=tz, locale="iso8601")) self.assertEqual("2010-08-28T11:45:56+02:00", datefmt.format_datetime(t, tzinfo=tz, locale="iso8601"))
def iso_time(t): return format_time(from_utimestamp(t), "iso8601")
def iso_time(t): return format_time(from_utimestamp(t), 'iso8601')
def stop_work(self, stoptime=None, comment=''): active = self.get_active_task() if not active: self.explanation = 'You cannot stop working as you appear to be a complete slacker already!' return False if stoptime: if stoptime <= active['starttime']: self.explanation = 'You cannot set your stop time to that value as it is before the start time!' return False elif stoptime >= self.now: self.explanation = 'You cannot set your stop time to that value as it is in the future!' return False else: stoptime = self.now - 1 stoptime = float(stoptime) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( 'UPDATE work_log ' 'SET endtime=%s, lastchange=%s, comment=%s ' 'WHERE worker=%s AND lastchange=%s AND endtime=0', (stoptime, stoptime, comment, self.authname, active['lastchange'])) db.commit() plugtne = self.config.getbool( 'worklog', 'timingandestimation') and self.config.get( 'ticket-custom', 'hours') plughrs = self.config.getbool('worklog', 'trachoursplugin') and self.config.get( 'ticket-custom', 'totalhours') message = '' hours = '0.0' # Leave a comment if the user has configured this or if they have entered # a work log comment. if plugtne or plughrs: round_delta = float(self.config.getint('worklog', 'roundup') or 1) # Get the delta in minutes delta = float(int(stoptime) - int(active['starttime'])) / float(60) # Round up if needed delta = int( round((delta / round_delta) + float(0.5))) * int(round_delta) # This hideous hack is here because I don't yet know how to do variable-DP rounding in python - sorry! # It's meant to round to 2 DP, so please replace it if you know how. Many thanks, MK. hours = str(float(int(100 * float(delta) / 60) / 100.0)) if plughrs: message = 'Hours recorded automatically by the worklog plugin. %s hours' % hours elif self.config.getbool('worklog', 'comment') or comment: started = datetime.fromtimestamp(active['starttime']) finished = datetime.fromtimestamp(stoptime) message = '%s worked on this ticket for %s between %s %s and %s %s.' % \ (self.authname, pretty_timedelta(started, finished), \ format_date(active['starttime']), format_time(active['starttime']), \ format_date(stoptime), format_time(stoptime)) if comment: message += "\n[[BR]]\n" + comment if plugtne or plughrs: if not message: message = 'Hours recorded automatically by the worklog plugin.' tckt = Ticket(self.env, active['ticket']) if plugtne: tckt['hours'] = hours self.save_ticket(tckt, message) message = '' if message: tckt = Ticket(self.env, active['ticket']) self.save_ticket(tckt, message) return True
def __process_ticket_request(self, req, justnumconflictingtickets = False): id = int(req.args.get('id')) req.perm('ticket', id, None).require('TICKET_VIEW') #Get the list of status that have to be ignored when looking for conflicts ignored_statuses = self.__striplist(self.env.config.get("modifiedfiles", "ignored_statuses", "closed").split(",")) #Check if the ticket exists (throws an exception if the ticket does not exist) thisticket = Ticket(self.env, id) #Tickets that are in the ignored states can not be in conflict if justnumconflictingtickets and thisticket['status'] in ignored_statuses: return 0 files = [] revisions = [] ticketsperfile = {} db = self.env.get_db_cnx() cursor = db.cursor() #Retrieve all the revisions which's messages contain "#<TICKETID>" cursor.execute("SELECT rev, time, author, message FROM revision WHERE message LIKE '%%#%s%%'" % id) repos = self.env.get_repository() for rev, time, author, message, in cursor: #Filter out non-related revisions. #for instance, you are lookink for #19, so you don't want #190, #191, #192, etc. to interfere #To filter, check what the eventual char after "#19" is. #If it's a number, we dont' want it (validrevision = False), but if it's text, keep this revision validrevision = True tempstr = message.split("#" + str(id), 1) if len(tempstr[1]) > 0: try: int(tempstr[1][0]) validrevision = False except: pass if validrevision: if not justnumconflictingtickets: date = "(" + format_time(time, str('%d/%m/%Y - %H:%M')) + ")" revisions.append((rev, author, date)) for node_change in repos.get_changeset(rev).get_changes(): files.append(node_change[0]) #Remove duplicated values files = self.__remove_duplicated_elements_and_sort(files) filestatus = {} for file in files: #Get the last status of each file if not justnumconflictingtickets: try: node = repos.get_node(file) filestatus[file] = node.get_history().next()[2] except: #If the node doesn't exist (in the last revision) it means that it has been deleted filestatus[file] = "delete" #Get the list of conflicting tickets per file tempticketslist = [] cursor.execute("SELECT message FROM revision WHERE rev IN (SELECT rev FROM node_change WHERE path='%s')" % file) for message, in cursor: #Extract the ticket number match = re.search(r'#([0-9]+)', message) if match: ticket = int(match.group(1)) #Don't add yourself if ticket != id: tempticketslist.append(ticket) tempticketslist = self.__remove_duplicated_elements_and_sort(tempticketslist) ticketsperfile[file] = [] #Keep only the active tickets for ticket in tempticketslist: try: if Ticket(self.env, ticket)['status'] not in ignored_statuses: ticketsperfile[file].append(ticket) except: pass #Get the global list of conflicting tickets #Only if the ticket is not already closed conflictingtickets=[] ticketsdescription={} ticketsdescription[id] = thisticket['summary'] ticketisclosed = True if thisticket['status'] not in ignored_statuses: ticketisclosed = False for fn, relticketids in ticketsperfile.items(): for relticketid in relticketids: tick = Ticket(self.env, relticketid) conflictingtickets.append((relticketid, tick['status'], tick['owner'])) ticketsdescription[relticketid] = tick['summary'] #Remove duplicated values conflictingtickets = self.__remove_duplicated_elements_and_sort(conflictingtickets) #Close the repository repos.close() #Return only the number of conflicting tickets (if asked for) if justnumconflictingtickets: return len(conflictingtickets) #Separate the deleted files from the others deletedfiles = [] for file in files: if filestatus[file] == "delete": deletedfiles.append(file) for deletedfile in deletedfiles: files.remove(deletedfile) #Return all the needed information return (id, files, deletedfiles, ticketsperfile, filestatus, conflictingtickets, ticketisclosed, revisions, ticketsdescription)
def stop_work(self, stoptime=None, comment=''): active = self.get_active_task() if not active: self.explanation = 'You cannot stop working as you appear to be a complete slacker already!' return False if stoptime: if stoptime <= active['starttime']: self.explanation = 'You cannot set your stop time to that value as it is before the start time!' return False elif stoptime >= self.now: self.explanation = 'You cannot set your stop time to that value as it is in the future!' return False else: stoptime = self.now - 1 stoptime = float(stoptime) db = self.env.get_db_cnx(); cursor = db.cursor() cursor.execute('UPDATE work_log ' 'SET endtime=%s, lastchange=%s, comment=%s ' 'WHERE user=%s AND lastchange=%s AND endtime=0', (stoptime, stoptime, comment, self.authname, active['lastchange'])) db.commit() message = '' # Leave a comment if the user has configured this or if they have entered # a work log comment. if self.config.getbool('worklog', 'comment') or comment: started = datetime.fromtimestamp(active['starttime']) finished = datetime.fromtimestamp(stoptime) message = '%s worked on this ticket for %s between %s %s and %s %s.' % \ (self.authname, pretty_timedelta(started, finished), \ format_date(active['starttime']), format_time(active['starttime']), \ format_date(stoptime), format_time(stoptime)) if comment: message += "\n[[BR]]\n" + comment if self.config.getbool('worklog', 'timingandestimation') and \ self.config.get('ticket-custom', 'hours'): if not message: message = 'Hours recorded automatically by the worklog plugin.' round_delta = float(self.config.getint('worklog', 'roundup') or 1) # Get the delta in minutes delta = float(int(stoptime) - int(active['starttime'])) / float(60) # Round up if needed delta = int(round((delta / round_delta) + float(0.5))) * int(round_delta) db = self.env.get_db_cnx() tckt = Ticket(self.env, active['ticket'], db) # This hideous hack is here because I don't yet know how to do variable-DP rounding in python - sorry! # It's meant to round to 2 DP, so please replace it if you know how. Many thanks, MK. tckt['hours'] = str(float(int(100 * float(delta) / 60) / 100.0)) self.save_ticket(tckt, db, message) message = '' if message: db = self.env.get_db_cnx() tckt = Ticket(self.env, active['ticket'], db) self.save_ticket(tckt, db, message) return True
def iso_time(t): return format_time(t, 'iso8601')
absurls=(format == 'rss')) value['parsed'] = format == 'rss' and unicode(desc) or desc elif column == 'reporter': if cell.find('@') != -1: value['rss'] = cell elif cell in email_map: value['rss'] = email_map[cell] elif column == 'report': value['report_href'] = req.href.report(cell) elif column in ('time', 'date','changetime', 'created', 'modified'): if cell == 'None': value['date'] = value['time'] = cell value['datetime'] = value['gmt'] = cell else: value['date'] = format_date(cell) value['time'] = format_time(cell) value['datetime'] = format_datetime(cell) value['gmt'] = http_date(cell) prefix = 'report.items.%d.%s' % (row_idx, unicode(column)) req.hdf[prefix] = unicode(cell) for key in value.keys(): req.hdf[prefix + '.' + key] = value[key] col_idx += 1 row_idx += 1 req.hdf['report.numrows'] = row_idx if format == 'rss': return 'report_rss.cs', 'application/rss+xml' elif format == 'csv': filename = id and 'report_%s.csv' % id or 'report.csv'
class SimileTimelineModule(Component): implements(ITemplateProvider, IRequestHandler, INavigationContributor) # IRequestHandler methods def match_request(self, req): return req.path_info.startswith('/stimeline') def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 0)) # Parse the from date and adjust the timestamp to the last second of # the day t = time.localtime() if req.args.has_key('from'): try: t = time.strptime(req.args.get('from'), '%x') except: pass fromdate = time.mktime( (t[0], t[1], t[2], 23, 59, 59, t[6], t[7], t[8])) try: daysback = max(0, int(req.args.get('daysback', ''))) except ValueError: daysback = TimelineModule(self.env).default_daysback req.hdf['timeline.from'] = format_date(fromdate) req.hdf['timeline.daysback'] = daysback available_filters = [] for event_provider in TimelineModule(self.env).event_providers: available_filters += event_provider.get_timeline_filters(req) filters = [] # check the request or session for enabled filters, or use default for test in (lambda f: req.args.has_key(f[0]), lambda f: req.session.get('timeline.filter.%s' % f[0], '')\ == '1', lambda f: len(f) == 2 or f[2]): if filters: break filters = [f[0] for f in available_filters if test(f)] # save the results of submitting the timeline form to the session if req.args.has_key('update'): for filter in available_filters: key = 'timeline.filter.%s' % filter[0] if req.args.has_key(filter[0]): req.session[key] = '1' elif req.session.has_key(key): del req.session[key] stop = fromdate start = stop - (daysback + 1) * 86400 events = [] for event_provider in TimelineModule(self.env).event_providers: try: events += event_provider.get_timeline_events( req, start, stop, filters) except Exception, e: # cope with a failure of that provider self._provider_failure(e, req, event_provider, filters, [f[0] for f in available_filters]) events.sort(lambda x, y: cmp(y[3], x[3])) if maxrows and len(events) > maxrows: del events[maxrows:] req.hdf['title'] = 'Timeline' # Get the email addresses of all known users email_map = {} for username, name, email in self.env.get_known_users(): if email: email_map[username] = email idx = 0 for kind, href, title, date, author, message in events: event = { 'kind': kind, 'title': re.sub(r'<[^>]*>', '', unicode(title)), 'href': href, 'author': author or 'anonymous', 'date': format_date(date, '%m/%d/%Y'), 'time': format_time(date, '%H:%M'), 'message': message.replace('…', '...'), 'icon': req.href.chrome('common', kind + '.png') } if format == 'rss': # Strip/escape HTML markup if isinstance(title, Markup): title = title.plaintext(keeplinebreaks=False) event['title'] = title event['message'] = to_unicode(message) if author: # For RSS, author must be an email address if author.find('@') != -1: event['author.email'] = author elif email_map.has_key(author): event['author.email'] = email_map[author] event['date'] = http_date(date) req.hdf['timeline.events.%s' % idx] = event idx += 1 if format == 'rss': return 'timeline_rss.cs', 'application/rss+xml' if format == 'xml': return 'stimeline_xml.cs', 'application/xml' add_stylesheet(req, 'common/css/timeline.css') rss_href = req.href.timeline([(f, 'on') for f in filters], daysback=90, max=50, format='rss') add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml', 'rss') for idx, fltr in enumerate(available_filters): req.hdf['timeline.filters.%d' % idx] = { 'name': fltr[0], 'label': fltr[1], 'enabled': int(fltr[0] in filters) } ## NEW LINES add_script(req, 'stimeline/js/simile/timeline-api.js') #add_abs_script(req, "http://simile.mit.edu/timeline/api/timeline-api.js") add_script(req, 'stimeline/js/simile.js') xml_args = { 'daysback': daysback, 'from': time.strftime('%x', time.localtime(fromdate)), 'format': 'xml', } xml_args.update(dict([(f, 'on') for f in filters])) xml_href = req.href.stimeline(**xml_args) req.hdf['stimeline.xml_href'] = Markup(xml_href) req.hdf['stimeline.href'] = req.href.stimeline() return 'stimeline.cs', None
def _say_hello(self): self.set_reader() result = self.reader.getusage() print u"%s 使用率 %d%% @%s" % (format_time(result['datetime'], str('%H:%M')), result['usage'], self.reader.region) print u"今日のピーク時間:%s時〜%s時 予想使用率 %d%%" % (format_time(result['start'], str('%H'), utc), format_time(result['end'], str('%H'), utc), result['demand'])
value['parsed'] = format == 'rss' and unicode(desc) or desc elif column == 'reporter': if cell.find('@') != -1: value['rss'] = cell elif cell in email_map: value['rss'] = email_map[cell] elif column == 'report': value['report_href'] = req.href.report(cell) elif column in ('time', 'date', 'changetime', 'created', 'modified'): if cell == 'None': value['date'] = value['time'] = cell value['datetime'] = value['gmt'] = cell else: value['date'] = format_date(cell) value['time'] = format_time(cell) value['datetime'] = format_datetime(cell) value['gmt'] = http_date(cell) prefix = 'report.items.%d.%s' % (row_idx, unicode(column)) req.hdf[prefix] = unicode(cell) for key in value.keys(): req.hdf[prefix + '.' + key] = value[key] col_idx += 1 row_idx += 1 req.hdf['report.numrows'] = row_idx if format == 'rss': return 'report_rss.cs', 'application/rss+xml' elif format == 'csv': self._render_csv(req, cols, rows)