def pretty_dateinfo(date, format=None, dateonly=False): if not date: return '' if format == 'date': absolute = user_time(req, format_date, date) else: absolute = user_time(req, format_datetime, date) now = datetime.datetime.now(localtz) relative = pretty_timedelta(date, now) if not format: format = req.session.get('dateinfo', self.default_dateinfo_format) in_or_ago = _("in %(relative)s", relative=relative) \ if date > now else \ _("%(relative)s ago", relative=relative) if format == 'relative': label = in_or_ago if not dateonly else relative title = absolute else: if dateonly: label = absolute elif req.lc_time == 'iso8601': label = _("at %(iso8601)s", iso8601=absolute) else: label = _("on %(date)s at %(time)s", date=user_time(req, format_date, date), time=user_time(req, format_time, date)) title = in_or_ago return tag.span(label, title=title)
def pretty_dateinfo(date, format=None, dateonly=False): absolute = user_time(req, format_datetime, date) relative = pretty_timedelta(date) if not format: format = req.session.get( 'dateinfo', Chrome(self.env).default_dateinfo_format) if format == 'absolute': if dateonly: label = absolute elif req.lc_time == 'iso8601': label = _("at %(iso8601)s", iso8601=absolute) else: label = _("on %(date)s at %(time)s", date=user_time(req, format_date, date), time=user_time(req, format_time, date)) title = _("See timeline %(relativetime)s ago", relativetime=relative) else: label = _("%(relativetime)s ago", relativetime=relative) \ if not dateonly else relative title = _("See timeline at %(absolutetime)s", absolutetime=absolute) return self.get_timeline_link(req, date, label, precision='second', title=title)
def test_template_data_changes_for_time_field(self): self.env.config.set('ticket-custom', 'timefield', 'time') dt1 = datetime(2015, 7, 8, tzinfo=utc) dt2 = datetime(2015, 12, 11, tzinfo=utc) with self.env.db_transaction: self._insert_ticket(summary='Time fields', timefield=datetime_now(utc)) self.env.db_transaction("UPDATE ticket_custom SET value='invalid' " "WHERE ticket=1 AND name='timefield'") t = Ticket(self.env, 1) t['timefield'] = dt1 t.save_changes('anonymous') t = Ticket(self.env, 1) t['timefield'] = dt2 t.save_changes('anonymous') req = MockRequest(self.env, method='GET', path_info='/ticket/1') self.assertTrue(self.ticket_module.match_request(req)) data = self.ticket_module.process_request(req)[1] changes = data['changes'] dt1_text = user_time(req, format_datetime, dt1) dt2_text = user_time(req, format_datetime, dt2) self.assertEqual(2, len(changes)) self.assertEqual('', changes[0]['fields']['timefield']['old']) self.assertEqual(dt1_text, changes[0]['fields']['timefield']['new']) self.assertEqual(dt1_text, changes[1]['fields']['timefield']['old']) self.assertEqual(dt2_text, changes[1]['fields']['timefield']['new'])
def get_list_pages(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) artifact_id = request.req.args.get('artifact', None) if artifact_id is None: raise Exception("No artifact was specified.") dbp.load_artifact(artifact_id) artifact = dbp.pool.get_item(artifact_id) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts(artifact): page = WikiPage(dbp.env, pagename) results.append( {'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text)} ) data = { 'context': Context.from_request(request.req, resource), 'artifact': artifact, 'results': results, } return 'list_pages.html', data, None
def _prepare_results(self, req, filters, results): page = req.args.get('page', 1) page = as_int(page, default=1, min=1) try: results = Paginator(results, page - 1, self.RESULTS_PER_PAGE) except TracError: add_warning(req, _("Page %(page)s is out of range.", page=page)) page = 1 results = Paginator(results, page - 1, self.RESULTS_PER_PAGE) for idx, result in enumerate(results): results[idx] = { 'href': result[0], 'title': result[1], 'date': user_time(req, format_datetime, result[2]), 'author': result[3], 'excerpt': result[4] } pagedata = [] shown_pages = results.get_shown_pages(21) for shown_page in shown_pages: page_href = req.href.search([(f, 'on') for f in filters], q=req.args.get('q'), page=shown_page, noquickjump=1) pagedata.append([ page_href, None, str(shown_page), _("Page %(num)d", num=shown_page) ]) fields = ['href', 'class', 'string', 'title'] results.shown_pages = [dict(zip(fields, p)) for p in pagedata] results.current_page = { 'href': None, 'class': 'current', 'string': str(results.page + 1), 'title': None } if results.has_next_page: next_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page + 1, noquickjump=1) add_link(req, 'next', next_href, _('Next Page')) if results.has_previous_page: prev_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page - 1, noquickjump=1) add_link(req, 'prev', prev_href, _('Previous Page')) page_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), noquickjump=1) return {'results': results, 'page_href': page_href}
def get_list_pages(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) artifact_id = request.req.args.get('artifact', None) if artifact_id is None: raise Exception("No artifact was specified.") dbp.load_artifact(artifact_id) artifact = dbp.pool.get_item(artifact_id) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts( artifact): page = WikiPage(dbp.env, pagename) results.append({ 'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text) }) data = { 'context': Context.from_request(request.req, resource), 'artifact': artifact, 'results': results, } return 'list_pages.html', data, None
def send_project_index(environ, start_response, parent_dir=None, env_paths=None): req = Request(environ, start_response) loadpaths = [pkg_resources.resource_filename('trac', 'templates')] if req.environ.get('trac.env_index_template'): env_index_template = req.environ['trac.env_index_template'] tmpl_path, template = os.path.split(env_index_template) loadpaths.insert(0, tmpl_path) else: template = 'index.html' data = { 'trac': { 'version': TRAC_VERSION, 'time': user_time(req, format_datetime) }, 'req': req } if req.environ.get('trac.template_vars'): for pair in req.environ['trac.template_vars'].split(','): key, val = pair.split('=') data[key] = val try: href = Href(req.base_path) projects = [] for env_name, env_path in get_environments(environ).items(): try: env = open_environment(env_path, use_cache=not environ['wsgi.run_once']) proj = { 'env': env, 'name': env.project_name, 'description': env.project_description, 'href': href(env_name) } except Exception, e: proj = {'name': env_name, 'description': to_unicode(e)} projects.append(proj) projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) data['projects'] = projects loader = TemplateLoader(loadpaths, variable_lookup='lenient', default_encoding='utf-8') tmpl = loader.load(template) stream = tmpl.generate(**data) if template.endswith('.xml'): output = stream.render('xml') req.send(output, 'text/xml') else: output = stream.render('xhtml', doctype=DocType.XHTML_STRICT, encoding='utf-8') req.send(output, 'text/html')
def _render_link(self, context, name, label, extra=''): if not (name or extra): return tag() try: milestone = Milestone(self.env, name) except ResourceNotFound: milestone = None # Note: the above should really not be needed, `Milestone.exists` # should simply be false if the milestone doesn't exist in the db # (related to #4130) href = context.href.milestone(name) exists = milestone and milestone.exists if exists: if 'MILESTONE_VIEW' in context.perm(milestone.resource): title = None if hasattr(context, 'req'): if milestone.is_completed: title = _("Completed %(duration)s ago (%(date)s)", duration=pretty_timedelta( milestone.completed), date=user_time(context.req, format_datetime, milestone.completed)) elif milestone.is_late: title = _("%(duration)s late (%(date)s)", duration=pretty_timedelta(milestone.due), date=user_time(context.req, format_datetime, milestone.due)) elif milestone.due: title = _("Due in %(duration)s (%(date)s)", duration=pretty_timedelta(milestone.due), date=user_time(context.req, format_datetime, milestone.due)) else: title = _("No date set") closed = 'closed ' if milestone.is_completed else '' return tag.a(label, class_='%smilestone' % closed, href=href + extra, title=title) elif 'MILESTONE_CREATE' in context.perm(self.realm, name): return tag.a(label, class_='missing milestone', href=href + extra, rel='nofollow') return tag.a(label, class_=classes('milestone', missing=not exists))
def send_project_index(environ, start_response, parent_dir=None, env_paths=None): req = Request(environ, start_response) loadpaths = [pkg_resources.resource_filename('trac', 'templates')] if req.environ.get('trac.env_index_template'): env_index_template = req.environ['trac.env_index_template'] tmpl_path, template = os.path.split(env_index_template) loadpaths.insert(0, tmpl_path) else: template = 'index.html' data = { 'trac': { 'version': TRAC_VERSION, 'time': user_time(req, format_datetime) }, 'req': req } if req.environ.get('trac.template_vars'): for pair in req.environ['trac.template_vars'].split(','): key, val = pair.split('=') data[key] = val try: href = Href(req.base_path) projects = [] for env_name, env_path in get_environments(environ).items(): try: env = open_environment(env_path, use_cache=not environ['wsgi.run_once']) proj = { 'env': env, 'name': env.project_name, 'description': env.project_description, 'href': href(env_name) } except Exception as e: proj = {'name': env_name, 'description': to_unicode(e)} projects.append(proj) projects.sort(key=lambda proj: proj['name'].lower()) data['projects'] = projects jenv = jinja2env(loader=FileSystemLoader(loadpaths)) jenv.globals.update(translation.functions) tmpl = jenv.get_template(template) output = valid_html_bytes(tmpl.render(**data).encode('utf-8')) if template.endswith('.xml'): req.send(output, 'text/xml') else: req.send(output, 'text/html') except RequestDone: pass
def validate_ticket(self, req, ticket): # Validate select fields for known values. for field in ticket.fields: if 'options' not in field: continue name = field['name'] if name == 'status': continue if name in ticket and name in ticket._old: value = ticket[name] if value: if value not in field['options']: yield name, _('"%(value)s" is not a valid value', value=value) elif not field.get('optional', False): yield name, _("field cannot be empty") # Validate description length. if len(ticket['description'] or '') > self.max_description_size: yield 'description', _("Must be less than or equal to %(num)s " "characters", num=self.max_description_size) # Validate summary length. if not ticket['summary']: yield 'summary', _("Tickets must contain a summary.") elif len(ticket['summary'] or '') > self.max_summary_size: yield 'summary', _("Must be less than or equal to %(num)s " "characters", num=self.max_summary_size) # Validate custom field length. for field in ticket.custom_fields: field_attrs = ticket.fields.by_name(field) max_size = field_attrs.get('max_size', 0) if 0 < max_size < len(ticket[field] or ''): label = field_attrs.get('label') yield label or field, _("Must be less than or equal to " "%(num)s characters", num=max_size) # Validate time field content. for field in ticket.time_fields: value = ticket[field] if field in ticket.custom_fields and \ field in ticket._old and \ not isinstance(value, datetime): field_attrs = ticket.fields.by_name(field) format = field_attrs.get('format') try: ticket[field] = user_time(req, parse_date, value, hint=format) \ if value else None except TracError as e: # Degrade TracError to warning. ticket[field] = value label = field_attrs.get('label') yield label or field, to_unicode(e)
def send_project_index(environ, start_response, parent_dir=None, env_paths=None): req = Request(environ, start_response) loadpaths = [pkg_resources.resource_filename('trac', 'templates')] if req.environ.get('trac.env_index_template'): env_index_template = req.environ['trac.env_index_template'] tmpl_path, template = os.path.split(env_index_template) loadpaths.insert(0, tmpl_path) else: template = 'index.html' data = {'trac': {'version': TRAC_VERSION, 'time': user_time(req, format_datetime)}, 'req': req} if req.environ.get('trac.template_vars'): for pair in req.environ['trac.template_vars'].split(','): key, val = pair.split('=') data[key] = val try: href = Href(req.base_path) projects = [] for env_name, env_path in get_environments(environ).items(): try: env = open_environment(env_path, use_cache=not environ['wsgi.run_once']) proj = { 'env': env, 'name': env.project_name, 'description': env.project_description, 'href': href(env_name) } except Exception as e: proj = {'name': env_name, 'description': to_unicode(e)} projects.append(proj) projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) data['projects'] = projects loader = TemplateLoader(loadpaths, variable_lookup='lenient', default_encoding='utf-8') tmpl = loader.load(template) stream = tmpl.generate(**data) if template.endswith('.xml'): output = stream.render('xml') req.send(output, 'text/xml') else: output = stream.render('xhtml', doctype=DocType.XHTML_STRICT, encoding='utf-8') req.send(output, 'text/html') except RequestDone: pass
def _render_link(self, context, name, label, extra=''): if not (name or extra): return tag() try: milestone = Milestone(self.env, name) except ResourceNotFound: milestone = None # Note: the above should really not be needed, `Milestone.exists` # should simply be false if the milestone doesn't exist in the db # (related to #4130) href = context.href.milestone(name) if milestone and milestone.exists: if 'MILESTONE_VIEW' in context.perm(milestone.resource): title = None if hasattr(context, 'req'): if milestone.is_completed: title = _( 'Completed %(duration)s ago (%(date)s)', duration=pretty_timedelta(milestone.completed), date=user_time(context.req, format_datetime, milestone.completed)) elif milestone.is_late: title = _('%(duration)s late (%(date)s)', duration=pretty_timedelta(milestone.due), date=user_time(context.req, format_datetime, milestone.due)) elif milestone.due: title = _('Due in %(duration)s (%(date)s)', duration=pretty_timedelta(milestone.due), date=user_time(context.req, format_datetime, milestone.due)) else: title = _('No date set') closed = 'closed ' if milestone.is_completed else '' return tag.a(label, class_='%smilestone' % closed, href=href + extra, title=title) elif 'MILESTONE_CREATE' in context.perm(self.realm, name): return tag.a(label, class_='missing milestone', href=href + extra, rel='nofollow') return tag.a(label, class_='missing milestone')
def test_template_data_for_time_field_with_formats(self): gmt12 = timezone('GMT +12:00') req = MockRequest(self.env, method='GET', path_info='/ticket/1', tz=gmt12) value = datetime(2016, 1, 2, 23, 34, 45, tzinfo=utc) expected = user_time(req, format_datetime, value) self.assertIn('11', expected) # check 11 in hour part self._test_template_data_for_time_field(req, value, expected, None) self._test_template_data_for_time_field(req, value, expected, 'datetime') self._test_template_data_for_time_field(req, value, expected, 'relative')
def post_list_search_relatedpages_json(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) unparsed_spec = request.req.args.get('spec', '') spec_name = json.loads(unparsed_spec) if unparsed_spec else '' attributes = json.loads(request.req.args.get('attributes', '[]')) if attributes is None: raise Exception("No artifacts specified.") artifacts_array = [] for artifact in attributes: try: dbp.load_artifact(artifact) full_artifact = dbp.pool.get_item(artifact) #artifacts_array.append(full_artifact) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts( full_artifact): page = WikiPage(dbp.env, pagename) results.append({ 'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text) }) artifacts_array.append({ 'id': full_artifact.get_id(), 'href': request.req.href.customartifacts('artifact', full_artifact.get_id(), action='view'), 'title': unicode(full_artifact), 'results': results }) except ValueError: continue _return_as_json(request, artifacts_array) return
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) prefix = args[0].strip() if args else None limit = _arg_as_int(args[1].strip(), min=1) if len(args) > 1 else None group = kw.get('group', 'date') sql = """SELECT name, max(version) AS max_version, max(time) AS max_time FROM wiki""" args = [] if prefix: with self.env.db_query as db: sql += " WHERE name %s" % db.prefix_match() args.append(db.prefix_match_value(prefix)) sql += " GROUP BY name ORDER BY max_time DESC" if limit: sql += " LIMIT %s" args.append(limit) entries_per_date = [] prevdate = None for name, version, ts in self.env.db_query(sql, args): if not 'WIKI_VIEW' in formatter.perm('wiki', name, version): continue req = formatter.req date = user_time(req, format_date, from_utimestamp(ts)) if date != prevdate: prevdate = date entries_per_date.append((date, [])) version = int(version) diff_href = None if version > 1: diff_href = formatter.href.wiki(name, action='diff', version=version) page_name = formatter.wiki.format_page_name(name) entries_per_date[-1][1].append((page_name, name, version, diff_href)) items_per_date = ( (date, (tag.li(tag.a(page, href=formatter.href.wiki(name)), tag.small(' (', tag.a(_("diff"), href=diff_href), ')') if diff_href else None, '\n') for page, name, version, diff_href in entries)) for date, entries in entries_per_date) if group == 'date': out = ((tag.h3(date), tag.ul(entries)) for date, entries in items_per_date) else: out = tag.ul(entries for date, entries in items_per_date) return tag.div(out)
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) prefix = args[0].strip() if args else None limit = int(args[1].strip()) if len(args) > 1 else None group = kw.get('group', 'date') sql = """SELECT name, max(version) AS max_version, max(time) AS max_time FROM wiki""" args = [] if prefix: with self.env.db_query as db: sql += " WHERE name %s" % db.prefix_match() args.append(db.prefix_match_value(prefix)) sql += " GROUP BY name ORDER BY max_time DESC" if limit: sql += " LIMIT %s" args.append(limit) entries_per_date = [] prevdate = None for name, version, ts in self.env.db_query(sql, args): if not 'WIKI_VIEW' in formatter.perm('wiki', name, version): continue req = formatter.req date = user_time(req, format_date, from_utimestamp(ts)) if date != prevdate: prevdate = date entries_per_date.append((date, [])) version = int(version) diff_href = None if version > 1: diff_href = formatter.href.wiki(name, action='diff', version=version) page_name = formatter.wiki.format_page_name(name) entries_per_date[-1][1].append((page_name, name, version, diff_href)) items_per_date = ( (date, (tag.li(tag.a(page, href=formatter.href.wiki(name)), tag.small(' (', tag.a(_("diff"), href=diff_href), ')') if diff_href else None, '\n') for page, name, version, diff_href in entries)) for date, entries in entries_per_date) if group == 'date': out = ((tag.h3(date), tag.ul(entries)) for date, entries in items_per_date) else: out = tag.ul(entries for date, entries in items_per_date) return tag.div(out)
def pretty_dateinfo(date, format=None, dateonly=False): absolute = user_time(req, format_datetime, date) relative = pretty_timedelta(date) if not format: format = req.session.get('dateinfo', Chrome(self.env).default_dateinfo_format) if format == 'absolute': if dateonly: label = absolute elif req.lc_time == 'iso8601': label = _("at %(iso8601)s", iso8601=absolute) else: label = _("on %(date)s at %(time)s", date=user_time(req, format_date, date), time=user_time(req, format_time, date)) title = _("See timeline %(relativetime)s ago", relativetime=relative) else: label = _("%(relativetime)s ago", relativetime=relative) \ if not dateonly else relative title = _("See timeline at %(absolutetime)s", absolutetime=absolute) return self.get_timeline_link(req, date, label, precision='second', title=title)
def expand_macro(self, formatter, name, content): prefix = limit = None if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: prefix = argv[0] if len(argv) > 1: limit = int(argv[1]) sql = """SELECT name, max(version) AS max_version, max(time) AS max_time FROM wiki""" args = [] if prefix: sql += " WHERE name LIKE %s" args.append(prefix + '%') sql += " GROUP BY name ORDER BY max_time DESC" if limit: sql += " LIMIT %s" args.append(limit) entries_per_date = [] prevdate = None for name, version, ts in self.env.db_query(sql, args): if not 'WIKI_VIEW' in formatter.perm('wiki', name, version): continue req = formatter.req date = user_time(req, format_date, from_utimestamp(ts)) if date != prevdate: prevdate = date entries_per_date.append((date, [])) version = int(version) diff_href = None if version > 1: diff_href = formatter.href.wiki(name, action='diff', version=version) page_name = formatter.wiki.format_page_name(name) entries_per_date[-1][1].append( (page_name, name, version, diff_href)) return tag.div( (tag.h3(date), tag.ul( tag.li( tag.a(page, href=formatter.href.wiki(name)), ' ', diff_href and tag.small( '(', tag.a('diff', href=diff_href), ')') or None) for page, name, version, diff_href in entries)) for date, entries in entries_per_date)
def expand_macro(self, formatter, name, content): prefix = limit = None if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: prefix = argv[0] if len(argv) > 1: limit = int(argv[1]) sql = """SELECT name, max(version) AS max_version, max(time) AS max_time FROM wiki""" args = [] if prefix: sql += " WHERE name LIKE %s" args.append(prefix + '%') sql += " GROUP BY name ORDER BY max_time DESC" if limit: sql += " LIMIT %s" args.append(limit) entries_per_date = [] prevdate = None for name, version, ts in self.env.db_query(sql, args): if not 'WIKI_VIEW' in formatter.perm('wiki', name, version): continue req = formatter.req date = user_time(req, format_date, from_utimestamp(ts)) if date != prevdate: prevdate = date entries_per_date.append((date, [])) version = int(version) diff_href = None if version > 1: diff_href = formatter.href.wiki(name, action='diff', version=version) page_name = formatter.wiki.format_page_name(name) entries_per_date[-1][1].append((page_name, name, version, diff_href)) return tag.div( (tag.h3(date), tag.ul( tag.li(tag.a(page, href=formatter.href.wiki(name)), ' ', diff_href and tag.small('(', tag.a('diff', href=diff_href), ')') or None) for page, name, version, diff_href in entries)) for date, entries in entries_per_date)
def render_admin_panel(self, req, cat, page, path_info): assert req.perm.has_permission('TRAC_ADMIN') action = req.args.get('action', 'view') if req.method == 'POST': confirm = req.args.get('confirm', 0) if 'purge_threshold' in req.args: purge_threshold_str = req.args.get('purge_threshold', '') purge_threshold = user_time(req, parse_date, purge_threshold_str, hint='datetime') \ if purge_threshold_str else None else: purge_threshold = None if not confirm: self.log.debug('render_admin_panel purge not yet confirmed') if purge_threshold is not None: crashes = CrashDump.query_old_data(self.env, purge_threshold) data = { 'datetime_hint': get_datetime_format_hint(req.lc_time), 'purge_threshold': purge_threshold_str, 'purge_crashes': crashes } return 'crashdump_admin_%s.html' % page, data elif confirm == 'no': self.log.debug('render_admin_panel purge canceled') req.redirect(req.href.admin(cat, page)) elif confirm == 'yes': self.log.debug('render_admin_panel purge confirmed') req.redirect(req.href.admin(cat, page)) else: now = datetime.now(req.tz) purge_threshold = datetime(now.year, now.month, now.day, 0) purge_threshold -= timedelta(days=365) data = { 'datetime_hint': get_datetime_format_hint(req.lc_time), 'purge_threshold': purge_threshold, 'purge_crashes': None, } print('crashdump_admin_%s.html' % page, data) return 'crashdump_admin_%s.html' % page, data
def _process_doc(self, doc): ui_doc = dict(doc) if doc['product']: product_href = ProductEnvironment(self.env, doc['product']).href # pylint: disable=too-many-function-args ui_doc["href"] = product_href(doc['type'], doc['id']) else: ui_doc["href"] = self.req.href(doc['type'], doc['id']) if doc['content']: ui_doc['content'] = shorten_result(doc['content']) if doc['time']: ui_doc['date'] = user_time(self.req, format_datetime, doc['time']) is_free_text_view = self.view is None if is_free_text_view: participant = self.allowed_participants[doc['type']] ui_doc['title'] = participant.format_search_results(doc) return ui_doc
def test_template_data_for_time_field_with_date_format(self): value = datetime(2016, 2, 22, 22, 22, 22, tzinfo=utc) self.env.config.set('ticket-custom', 'timefield', 'time') self.env.config.set('ticket-custom', 'timefield.format', 'date') self._insert_ticket(summary='Time fields', timefield=value) self.assertEqual(value, Ticket(self.env, 1)['timefield']) gmt12 = timezone('GMT +12:00') req = MockRequest(self.env, method='GET', path_info='/ticket/1', tz=gmt12) expected = user_time(req, format_date, value) self.assertIn('23', expected) # check 23 in day part self.assertTrue(self.ticket_module.match_request(req)) data = self.ticket_module.process_request(req)[1] for f in data['fields']: if f['name'] == 'timefield': self.assertEqual(expected, f['edit']) break else: self.fail('Missing timefield field')
def _prepare_results(self, req, filters, results): page = int(req.args.get('page', '1')) results = Paginator(results, page - 1, self.RESULTS_PER_PAGE) for idx, result in enumerate(results): results[idx] = {'href': result[0], 'title': result[1], 'date': user_time(req, format_datetime, result[2]), 'author': result[3], 'excerpt': result[4]} pagedata = [] shown_pages = results.get_shown_pages(21) for shown_page in shown_pages: page_href = req.href.search([(f, 'on') for f in filters], q=req.args.get('q'), page=shown_page, noquickjump=1) pagedata.append([page_href, None, str(shown_page), 'page ' + str(shown_page)]) fields = ['href', 'class', 'string', 'title'] results.shown_pages = [dict(zip(fields, p)) for p in pagedata] results.current_page = {'href': None, 'class': 'current', 'string': str(results.page + 1), 'title':None} if results.has_next_page: next_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page + 1, noquickjump=1) add_link(req, 'next', next_href, _('Next Page')) if results.has_previous_page: prev_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page - 1, noquickjump=1) add_link(req, 'prev', prev_href, _('Previous Page')) page_href = req.href.search( zip(filters, ['on'] * len(filters)), q=req.args.get('q'), noquickjump=1) return {'results': results, 'page_href': page_href}
def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 50 if format == 'rss' else 0)) lastvisit = int(req.session.get('timeline.lastvisit', '0')) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = int( req.session.get('timeline.nextlastvisit', lastvisit)) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = today = datetime_now(req.tz) yesterday = to_datetime( today.replace(tzinfo=None) - timedelta(days=1), req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args['from'].strip() if reqfromdate: try: precisedate = user_time(req, parse_date, reqfromdate) except TracError, e: add_warning(req, e) else: fromdate = precisedate.astimezone(req.tz) precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None
def _prepare_results(self, req, filters, results): page = int(req.args.get("page", "1")) results = Paginator(results, page - 1, self.RESULTS_PER_PAGE) for idx, result in enumerate(results): results[idx] = { "href": result[0], "title": result[1], "date": user_time(req, format_datetime, result[2]), "author": result[3], "excerpt": result[4], } pagedata = [] shown_pages = results.get_shown_pages(21) for shown_page in shown_pages: page_href = req.href.search( [(f, "on") for f in filters], q=req.args.get("q"), page=shown_page, noquickjump=1 ) pagedata.append([page_href, None, str(shown_page), _("Page %(num)d", num=shown_page)]) fields = ["href", "class", "string", "title"] results.shown_pages = [dict(zip(fields, p)) for p in pagedata] results.current_page = {"href": None, "class": "current", "string": str(results.page + 1), "title": None} if results.has_next_page: next_href = req.href.search( zip(filters, ["on"] * len(filters)), q=req.args.get("q"), page=page + 1, noquickjump=1 ) add_link(req, "next", next_href, _("Next Page")) if results.has_previous_page: prev_href = req.href.search( zip(filters, ["on"] * len(filters)), q=req.args.get("q"), page=page - 1, noquickjump=1 ) add_link(req, "prev", prev_href, _("Previous Page")) page_href = req.href.search(zip(filters, ["on"] * len(filters)), q=req.args.get("q"), noquickjump=1) return {"results": results, "page_href": page_href}
def render_admin_panel(self, req, cat, page, path_info): assert req.perm.has_permission('TRAC_ADMIN') action = req.args.get('action', 'view') if req.method == 'POST': confirm = req.args.get('confirm', 0) if 'purge_threshold' in req.args: purge_threshold_str = req.args.get('purge_threshold', '') purge_threshold = user_time(req, parse_date, purge_threshold_str, hint='datetime') \ if purge_threshold_str else None else: purge_threshold = None if not confirm: self.log.debug('render_admin_panel purge not yet confirmed') if purge_threshold is not None: crashes = CrashDump.query_old_data(self.env, purge_threshold) data = { 'datetime_hint': get_datetime_format_hint(req.lc_time), 'purge_threshold': purge_threshold_str, 'purge_crashes': crashes } return 'crashdump_admin_%s.html' % page, data elif confirm == 'no': self.log.debug('render_admin_panel purge canceled') req.redirect(req.href.admin(cat, page)) elif confirm == 'yes': self.log.debug('render_admin_panel purge confirmed') req.redirect(req.href.admin(cat, page)) else: now = datetime.now(req.tz) purge_threshold = datetime(now.year, now.month, now.day, 0) purge_threshold -= timedelta(days=365) data = { 'datetime_hint': get_datetime_format_hint(req.lc_time), 'purge_threshold': purge_threshold, } return 'crashdump_admin_%s.html' % page, data
def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 50 if format == 'rss' else 0)) lastvisit = int(req.session.get('timeline.lastvisit', '0')) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = int(req.session.get('timeline.nextlastvisit', lastvisit)) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = today = datetime.now(req.tz) yesterday = to_datetime(today.replace(tzinfo=None) - timedelta(days=1), req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args['from'].strip() if reqfromdate: try: precisedate = user_time(req, parse_date, reqfromdate) except TracError, e: add_warning(req, e) else: fromdate = precisedate.astimezone(req.tz) precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None
def post_list_search_relatedpages_json(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) unparsed_spec = request.req.args.get('spec', '') spec_name = json.loads(unparsed_spec) if unparsed_spec else '' attributes = json.loads(request.req.args.get('attributes', '[]')) if attributes is None: raise Exception("No artifacts specified.") artifacts_array = [] for artifact in attributes: try: dbp.load_artifact(artifact) full_artifact = dbp.pool.get_item(artifact) #artifacts_array.append(full_artifact) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts(full_artifact): page = WikiPage(dbp.env, pagename) results.append( {'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text)} ) artifacts_array.append( {'id': full_artifact.get_id(), 'href': request.req.href.customartifacts('artifact', full_artifact.get_id(), action='view'), 'title': unicode(full_artifact), 'results' : results}) except ValueError: continue _return_as_json(request, artifacts_array) return
def get_view_artifact(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) artifact_url = request.req.href.customartifacts('artifact/{0}'.format(obj.get_id())) spec_name, spec_url, values = _get_artifact_details(obj, request.req) # Getting wiki pages that refer the artifact related_pages = [] from trac.wiki.formatter import OutlineFormatter from trac.web.chrome import web_context class NullOut(object): def write(self, *args): pass for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts(obj): page = WikiPage(dbp.env, pagename) fmt = OutlineFormatter(dbp.env, web_context(request.req)) fmt.format(page.text, NullOut()) title = '' text = page.text if fmt.outline: title = fmt.outline[0][2] text = re.sub('[=]+[ ]+' + title + '[ ]+[=]+\s?','', text) related_pages.append( {'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': title if title else pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(text)}) # Getting artifacts that this artifact refers to referred_artifacts = [] from AdaptiveArtifacts import get_artifact_id_names_from_text for attribute_name, value in obj.get_values(): for related_artifact_id,related_artifact_text in get_artifact_id_names_from_text(unicode(value)): if dbp.pool.get_item(related_artifact_id) is None: dbp.load_artifact(related_artifact_id) referred_artifacts.append((dbp.pool.get_item(related_artifact_id), "%s (%s)" % (related_artifact_text, attribute_name))) # Getting artifacts whose attribute values refer this artifact referring_artifacts = [] for related_artifact_id, related_artifact_version_id, ref_count in dbp.get_related_artifact_ref_counts(obj): if dbp.pool.get_item(related_artifact_id) is None: dbp.load_artifact(related_artifact_id) artifact = dbp.pool.get_item(related_artifact_id) url = request.req.href.customartifacts('artifact/%d' % (artifact.get_id(),), action='view') rel_spec_name = artifact.__class__.get_name() if not artifact.__class__ is Instance else None rel_spec_url = request.req.href.customartifacts('spec', artifact.__class__.get_id(), action='view'), id_version, time, author, ipnr, comment, readonly = dbp.get_latest_version_details(artifact.get_id()) referring_artifacts.append( {'href': url, 'spec_name': rel_spec_name, 'spec_url': rel_spec_url, 'author': author, 'date': user_time(request.req, format_datetime, time), 'artifact': artifact} ) # Build yuml url class YUMLDiagram(object): def __init__(self): self.classes = [] self.base_url = "http://yuml.me/diagram/plain/class/" self._diagram = "" self.is_incomplete = False def add_class(self, header, body, associations): self.classes.append({'header': header, 'body': body, 'associations': associations}) def serialize(self): for yuml_class in self.classes: yuml_fragment = "[" + yuml_class['header'] if yuml_class['body']: yuml_fragment += "|" + ";".join(yuml_class['body']) yuml_fragment += "]," self._diagram += yuml_fragment if yuml_class['associations']: for association_target,association_label, in yuml_class['associations']: yuml_fragment = "[%s]-%s>[%s]," % (yuml_class['header'], association_label, association_target) self._diagram += yuml_fragment def get_dsl_text(self): return self._diagram.encode('utf8').replace(" ", " ") def get_url(self): #Could be used for GET requests, as long as it doesn't exceed the maximum URL size #return self.base_url + quote(self.get_dsl_text(), "[],;:->=") from urllib2 import Request, urlopen from urllib import urlencode try: image_filename = urlopen(Request(yuml.base_url, data=urlencode({'dsl_text': yuml.get_dsl_text()}))).read() except HTTPError: return "" return self.base_url + image_filename yuml = YUMLDiagram() def artifact_to_yuml_class(rel_artifact, include_values=True): def sanitize(value): if type(value) == list: value = ",".join(value) for i, j in {"[": "(", "]": ")", ",": ".", ";": ".", "->": "-", "|": "\\", }.iteritems(): value = value.replace(i, j) return value if len(value) < 128 else "..." rel_artifact_title = unicode(rel_artifact) rel_spec_name = (u" : " + rel_artifact.__class__.get_name()) if not rel_artifact.__class__ is Instance else u"" header = rel_artifact_title + rel_spec_name body = [] if include_values: for attribute_name, value in rel_artifact.get_values(): body.append("%s = %s" % (sanitize(attribute_name), sanitize(value))) return {'header': sanitize(header), 'body': body, 'associations': []} yuml_class = artifact_to_yuml_class(obj) yuml_class['body'].append('{bg:orange}') # color the main artifact differently yuml_class['associations'] = [(artifact_to_yuml_class(rel_artifact, False)['header'], rel_artifact_text) for rel_artifact, rel_artifact_text in referred_artifacts] yuml.add_class(**yuml_class) for rel_artifact in referring_artifacts: rel_yuml_class = artifact_to_yuml_class(rel_artifact['artifact']) rel_yuml_class['associations'] = [(artifact_to_yuml_class(obj, False)['header'], "")] yuml.add_class(**rel_yuml_class) yuml.serialize() # track access dbp.track_it("artifact", obj.get_id(), "view", request.req.authname, str(datetime.now())) data = { 'context': Context.from_request(request.req, resource), 'spec_name': spec_name, 'spec_url': spec_url, 'artifact': obj, 'artifact_url': artifact_url, 'artifacts_values': values, 'related_pages': related_pages, 'related_artifacts': referring_artifacts, 'show_diagram': dbp.env.config.getbool('asa', 'show_diagram', default=True), 'yuml_url': yuml.get_url(), } return 'view_artifact_%s.html' % (request.get_format(),), data, None
def process_request(self, req): """Process the request """ base = self.get_mypage_base(req.authname) tzinfo = getattr(req, 'tz', None) now = datetime.now(tzinfo or localtz) today = format_date(now, 'iso8601', tzinfo) today_page_name = base + today today_page = WikiPage(self.env, today_page_name) if today_page.exists: req.redirect(req.href.wiki(today_page_name, action='edit')) # create page of the day for today if 'WIKI_CREATE' not in req.perm(today_page.resource): raise ResourceNotFound(_("Can't create the page of the day.")) ws = WikiSystem(self.env) def get_page_text(pagename): if ws.has_page(pagename): page = WikiPage(self.env, pagename) if 'WIKI_VIEW' in req.perm(page.resource): self.log.debug("get_page_text(%s) -> %s", pagename, page.text) return page.text self.log.debug("get_page_text(%s) -> None", pagename) # retrieve page template template_name = 'PageTemplates/MyPage' mytemplate_name = '/'.join([template_name, req.authname]) template_text = get_page_text(mytemplate_name) if template_text is None: template_text = get_page_text(template_name) text = last_page_text = last_page_quoted = None if template_text is not None: # retrieve previous "page of the day", if any all_mypages = self.get_all_mypages(base) last = bisect(all_mypages, today_page_name) - 1 self.log.debug("Pos of today %s in %r is %d", today_page_name, all_mypages, last) last_page_name = all_mypages[last] if last >= 0 else None last_page_link = '' if last_page_name: last_page_link = '[[%s]]' % last_page_name last_page_text = get_page_text(last_page_name) if last_page_text is not None: last_page_quoted = '\n'.join( ['> ' + line for line in last_page_text.splitlines()]) today_user = user_time(req, format_date, now, tzinfo=tzinfo) author = get_reporter_id(req) text = template_text \ .replace(self.tokens['date'][0], today_user) \ .replace(self.tokens['isodate'][0], today) \ .replace(self.tokens['user'][0], req.authname) \ .replace(self.tokens['author'][0], author) \ .replace(self.tokens['lp_link'][0], last_page_link) \ .replace(self.tokens['lp_name'][0], last_page_name or '') \ .replace(self.tokens['lp_text'][0], last_page_text or '') \ .replace(self.tokens['lp_quoted'][0], last_page_quoted or '') req.redirect(req.href.wiki(today_page_name, action='edit', text=text))
def process_request(self, req): req.perm('timeline').require('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 50 if format == 'rss' else 0)) lastvisit = int(req.session.get('timeline.lastvisit', '0')) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = int(req.session.get('timeline.nextlastvisit', lastvisit)) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = today = datetime.now(req.tz) yesterday = to_datetime(today.replace(tzinfo=None) - timedelta(days=1), req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args['from'].strip() if reqfromdate: try: precisedate = user_time(req, parse_date, reqfromdate) except TracError as e: add_warning(req, e) else: fromdate = precisedate.astimezone(req.tz) precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None fromdate = to_datetime(datetime(fromdate.year, fromdate.month, fromdate.day, 23, 59, 59, 999999), req.tz) daysback = as_int(req.args.get('daysback'), 90 if format == 'rss' else None) if daysback is None: daysback = as_int(req.session.get('timeline.daysback'), None) if daysback is None: daysback = self.default_daysback daysback = max(0, daysback) if self.max_daysback >= 0: daysback = min(self.max_daysback, daysback) authors = req.args.get('authors') if authors is None and format != 'rss': authors = req.session.get('timeline.authors') authors = (authors or '').strip() data = {'fromdate': fromdate, 'daysback': daysback, 'authors': authors, 'today': user_time(req, format_date, today), 'yesterday': user_time(req, format_date, yesterday), 'precisedate': precisedate, 'precision': precision, 'events': [], 'filters': [], 'abbreviated_messages': self.abbreviated_messages, 'lastvisit': lastvisit} available_filters = [] for event_provider in self.event_providers: available_filters += event_provider.get_timeline_filters(req) or [] # check the request or session for enabled filters, or use default filters = [f[0] for f in available_filters if f[0] in req.args] if not filters and format != 'rss': filters = [f[0] for f in available_filters if req.session.get('timeline.filter.' + f[0]) == '1'] if not filters: filters = [f[0] for f in available_filters if len(f) == 2 or f[2]] # save the results of submitting the timeline form to the session if 'update' in req.args: for filter_ in available_filters: key = 'timeline.filter.%s' % filter_[0] if filter_[0] in req.args: req.session[key] = '1' elif key in req.session: del req.session[key] stop = fromdate start = to_datetime(stop.replace(tzinfo=None) - timedelta(days=daysback + 1), req.tz) # create author include and exclude sets include = set() exclude = set() for match in self._authors_pattern.finditer(authors): name = (match.group(2) or match.group(3) or match.group(4)).lower() if match.group(1): exclude.add(name) else: include.add(name) # gather all events for the given period of time events = [] for provider in self.event_providers: try: for event in provider.get_timeline_events(req, start, stop, filters) or []: author = (event[2] or '').lower() if (not include or author in include) \ and author not in exclude: events.append(self._event_data(provider, event)) except Exception as e: # cope with a failure of that provider self._provider_failure(e, req, provider, filters, [f[0] for f in available_filters]) # prepare sorted global list events = sorted(events, key=lambda e: e['date'], reverse=True) if maxrows: events = events[:maxrows] data['events'] = events if format == 'rss': rss_context = web_context(req, absurls=True) rss_context.set_hints(wiki_flavor='html', shorten_lines=False) data['context'] = rss_context return 'timeline.rss', data, 'application/rss+xml' else: req.session.set('timeline.daysback', daysback, self.default_daysback) req.session.set('timeline.authors', authors, '') # store lastvisit if events and not revisit: lastviewed = to_utimestamp(events[0]['date']) req.session['timeline.lastvisit'] = max(lastvisit, lastviewed) req.session['timeline.nextlastvisit'] = lastvisit html_context = web_context(req) html_context.set_hints(wiki_flavor='oneliner', shorten_lines=self.abbreviated_messages) data['context'] = html_context add_stylesheet(req, 'common/css/timeline.css') rss_href = req.href.timeline([(f, 'on') for f in filters], daysback=90, max=50, authors=authors, format='rss') add_link(req, 'alternate', auth_link(req, rss_href), _('RSS Feed'), 'application/rss+xml', 'rss') Chrome(self.env).add_jquery_ui(req) for filter_ in available_filters: data['filters'].append({'name': filter_[0], 'label': filter_[1], 'enabled': filter_[0] in filters}) # Navigation to the previous/next period of 'daysback' days previous_start = fromdate.replace(tzinfo=None) - \ timedelta(days=daysback + 1) previous_start = format_date(to_datetime(previous_start, req.tz), format='%Y-%m-%d', tzinfo=req.tz) add_link(req, 'prev', req.href.timeline(from_=previous_start, authors=authors, daysback=daysback), _("Previous Period")) if today - fromdate > timedelta(days=0): next_start = fromdate.replace(tzinfo=None) + \ timedelta(days=daysback + 1) next_start = format_date(to_datetime(next_start, req.tz), format='%Y-%m-%d', tzinfo=req.tz) add_link(req, 'next', req.href.timeline(from_=next_start, authors=authors, daysback=daysback), _("Next Period")) prevnext_nav(req, _("Previous Period"), _("Next Period")) return 'timeline.html', data, None
def process_request(self, req): req.perm('timeline').require('TIMELINE_VIEW') format = req.args.get('format') maxrows = req.args.getint('max', 50 if format == 'rss' else 0) lastvisit = req.session.as_int('timeline.lastvisit', 0) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = req.session.as_int('timeline.nextlastvisit', lastvisit) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = datetime_now(req.tz) today = truncate_datetime(fromdate) yesterday = to_datetime(today.replace(tzinfo=None) - timedelta(days=1), req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args.get('from').strip() if reqfromdate: try: precisedate = user_time(req, parse_date, reqfromdate) except TracError as e: add_warning(req, e) else: fromdate = precisedate.astimezone(req.tz) precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None fromdate = to_datetime(datetime(fromdate.year, fromdate.month, fromdate.day, 23, 59, 59, 999999), req.tz) pref = req.session.as_int('timeline.daysback', self.default_daysback) default = 90 if format == 'rss' else pref daysback = req.args.as_int('daysback', default, min=1, max=self.max_daysback) authors = req.args.get('authors') if authors is None and format != 'rss': authors = req.session.get('timeline.authors') authors = (authors or '').strip() data = {'fromdate': fromdate, 'daysback': daysback, 'authors': authors, 'today': today, 'yesterday': yesterday, 'precisedate': precisedate, 'precision': precision, 'events': [], 'filters': [], 'abbreviated_messages': self.abbreviated_messages} available_filters = [] for event_provider in self.event_providers: with component_guard(self.env, req, event_provider): available_filters += (event_provider.get_timeline_filters(req) or []) # check the request or session for enabled filters, or use default filters = [f[0] for f in available_filters if f[0] in req.args] if not filters and format != 'rss': filters = [f[0] for f in available_filters if req.session.as_int('timeline.filter.' + f[0])] if not filters: filters = [f[0] for f in available_filters if len(f) == 2 or f[2]] # save the results of submitting the timeline form to the session if 'update' in req.args: for filter_ in available_filters: key = 'timeline.filter.%s' % filter_[0] if filter_[0] in req.args: req.session[key] = '1' elif key in req.session: del req.session[key] stop = fromdate start = to_datetime(stop.replace(tzinfo=None) - timedelta(days=daysback + 1), req.tz) # create author include and exclude sets include = set() exclude = set() for match in self._authors_pattern.finditer(authors): name = (match.group(2) or match.group(3) or match.group(4)).lower() if match.group(1): exclude.add(name) else: include.add(name) # gather all events for the given period of time events = [] for provider in self.event_providers: with component_guard(self.env, req, provider): for event in provider.get_timeline_events(req, start, stop, filters) or []: author = (event[2] or '').lower() if ((not include or author in include) and author not in exclude): events.append( self._event_data(req, provider, event, lastvisit)) # prepare sorted global list events = sorted(events, key=lambda e: e['datetime'], reverse=True) if maxrows: events = events[:maxrows] data['events'] = events if format == 'rss': rss_context = web_context(req, absurls=True) rss_context.set_hints(wiki_flavor='html', shorten_lines=False) data['context'] = rss_context return 'timeline.rss', data, {'content_type': 'application/rss+xml'} else: req.session.set('timeline.daysback', daysback, self.default_daysback) req.session.set('timeline.authors', authors, '') # store lastvisit if events and not revisit: lastviewed = to_utimestamp(events[0]['datetime']) req.session['timeline.lastvisit'] = max(lastvisit, lastviewed) req.session['timeline.nextlastvisit'] = lastvisit html_context = web_context(req) html_context.set_hints(wiki_flavor='oneliner', shorten_lines=self.abbreviated_messages) data['context'] = html_context add_stylesheet(req, 'common/css/timeline.css') rss_href = req.href.timeline([(f, 'on') for f in filters], daysback=90, max=50, authors=authors, format='rss') add_link(req, 'alternate', auth_link(req, rss_href), _('RSS Feed'), 'application/rss+xml', 'rss') Chrome(self.env).add_jquery_ui(req) for filter_ in available_filters: data['filters'].append({'name': filter_[0], 'label': filter_[1], 'enabled': filter_[0] in filters}) # Navigation to the previous/next period of 'daysback' days previous_start = fromdate.replace(tzinfo=None) - \ timedelta(days=daysback + 1) previous_start = format_date(previous_start, format='iso8601', tzinfo=req.tz) add_link(req, 'prev', req.href.timeline(from_=previous_start, authors=authors, daysback=daysback), _("Previous Period")) if today - fromdate > timedelta(days=0): next_start = fromdate.replace(tzinfo=None) + \ timedelta(days=daysback + 1) next_start = format_date(to_datetime(next_start, req.tz), format='iso8601', tzinfo=req.tz) add_link(req, 'next', req.href.timeline(from_=next_start, authors=authors, daysback=daysback), _("Next Period")) prevnext_nav(req, _("Previous Period"), _("Next Period")) return 'timeline.html', data
def _do_save(self, req, db, version): version_name = req.args.get('name') version_project = req.args.get('project') old_version_project = self.__SmpModel.get_id_project_version(version.name) if version.exists: req.perm.require('MILESTONE_MODIFY') else: req.perm.require('MILESTONE_CREATE') old_name = version.name new_name = version_name version.description = req.args.get('description', '') time = req.args.get('time', '') if time: version.time = user_time(req, parse_date, time, hint='datetime') else: version.time = None # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name # If the name has changed, check that the version doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: new_version = Version(self.env, new_name, db) if new_version.name == old_name: pass # Creation or no name change elif new_version.name: warn(_('Version "%(name)s" already exists, please ' 'choose another name.', name=new_version.name)) else: warn(_('You must provide a name for the version.')) except: version.name = new_name if warnings: return self._render_editor(req, db, version) # -- actually save changes if version.exists: version.update() if old_name != version.name: self.__SmpModel.rename_version_project(old_name, version.name) if not version_project: self.__SmpModel.delete_version_project(version.name) elif not old_version_project: self.__SmpModel.insert_version_project(version.name, version_project) else: self.__SmpModel.update_version_project(version.name, version_project) else: version.insert() if version_project: self.__SmpModel.insert_version_project(version.name, version_project) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.version(version.name))
def _do_save(self, req, version): resource = Resource('version', version.name) if version.exists: req.perm(resource).require('VERSION_MODIFY') else: req.perm(resource).require('VERSION_CREATE') old_name = version.name new_name = req.args.get('name') version.name = new_name version.description = req.args.get('description', '') time = req.args.get('time', '') # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name if new_name: if new_name != old_name: # check that the version doesn't already exists # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: Version(self.env, new_name) warn( _( 'Version "%(name)s" already exists, please ' 'choose another name', name=new_name)) except ResourceNotFound: pass else: warn(_('You must provide a name for the version.')) # -- check completed date if 'released' in req.args: time = user_time(req, parse_date, time, hint='datetime') \ if time else None if time and time > datetime.now(utc): warn(_("Release date may not be in the future")) else: time = None version.time = time if warnings: return self._render_editor(req, version) # -- actually save changes with self.env.db_transaction as db: if version.exists: if version.name != version._old_name: # Update tickets db( """ UPDATE milestone_version SET version=%s WHERE version=%s """, (version.name, version._old_name)) version.update() else: version.insert() req.redirect(req.href.version(version.name))
def _format_datetime(t, req): return user_time(req, format_datetime, t)
def _do_save(self, req, milestone): if milestone.exists: req.perm(milestone.resource).require('MILESTONE_MODIFY') else: req.perm(milestone.resource).require('MILESTONE_CREATE') old_name = milestone.name new_name = req.args.get('name') milestone.description = req.args.get('description', '') if 'due' in req.args: due = req.args.get('duedate', '') milestone.due = user_time(req, parse_date, due, hint='datetime') \ if due else None else: milestone.due = None completed = req.args.get('completeddate', '') retarget_to = req.args.get('target') or None # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name # If the name has changed, check that the milestone doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: new_milestone = Milestone(self.env, new_name) if new_milestone.name == old_name: pass # Creation or no name change elif new_milestone.name: warn(_('Milestone "%(name)s" already exists, please ' 'choose another name.', name=new_milestone.name)) else: warn(_('You must provide a name for the milestone.')) except ResourceNotFound: milestone.name = new_name # -- check completed date if 'completed' in req.args: completed = user_time(req, parse_date, completed, hint='datetime') if completed else None if completed and completed > datetime.now(utc): warn(_('Completion date may not be in the future')) else: completed = None milestone.completed = completed if warnings: return self._render_editor(req, milestone) # -- actually save changes if milestone.exists: milestone.update(author=req.authname) if completed and 'retarget' in req.args: comment = req.args.get('comment', '') retargeted_tickets = \ milestone.move_tickets(retarget_to, req.authname, comment, exclude_closed=True) add_notice(req, _('The open tickets associated with ' 'milestone "%(name)s" have been retargeted ' 'to milestone "%(retarget)s".', name=milestone.name, retarget=retarget_to)) new_values = {'milestone': retarget_to} comment = comment or \ _("Open tickets retargeted after milestone closed") tn = BatchTicketNotifyEmail(self.env) try: tn.notify(retargeted_tickets, new_values, comment, None, req.authname) except Exception, e: self.log.error("Failure sending notification on ticket " "batch change: %s", exception_to_unicode(e)) add_warning(req, tag_("The changes have been saved, but " "an error occurred while sending " "notifications: %(message)s", message=to_unicode(e)))
def _render_admin_panel(self, req, cat, page, milestone): perm = req.perm('admin', 'ticket/' + self._type) # Detail view? if milestone: mil = model.Milestone(self.env, milestone) if req.method == 'POST': if req.args.get('save'): perm.require('MILESTONE_MODIFY') mil.name = name = req.args.get('name') mil.due = mil.completed = None due = req.args.get('duedate', '') if due: mil.due = user_time(req, parse_date, due, hint='datetime') if req.args.get('completed', False): completed = req.args.get('completeddate', '') mil.completed = user_time(req, parse_date, completed, hint='datetime') if mil.completed > datetime_now(utc): raise TracError( _('Completion date may not be in ' 'the future'), _('Invalid Completion Date')) mil.description = req.args.get('description', '') try: mil.update(author=req.authname) except self.env.db_exc.IntegrityError: raise TracError( _('Milestone "%(name)s" already ' 'exists.', name=name)) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) Chrome(self.env).add_wiki_toolbars(req) data = {'view': 'detail', 'milestone': mil} else: default = self.config.get('ticket', 'default_milestone') if req.method == 'POST': # Add Milestone if req.args.get('add') and req.args.get('name'): perm.require('MILESTONE_CREATE') name = req.args.get('name') try: mil = model.Milestone(self.env, name=name) except ResourceNotFound: mil = model.Milestone(self.env) mil.name = name if req.args.get('duedate'): mil.due = user_time(req, parse_date, req.args.get('duedate'), hint='datetime') mil.insert() add_notice( req, _('The milestone "%(name)s" has been ' 'added.', name=name)) req.redirect(req.href.admin(cat, page)) else: if mil.name is None: raise TracError(_('Invalid milestone name.')) raise TracError( _('Milestone "%(name)s" already ' 'exists.', name=name)) # Remove milestone elif req.args.get('remove'): perm.require('MILESTONE_DELETE') sel = req.args.get('sel') if not sel: raise TracError(_('No milestone selected')) if not isinstance(sel, list): sel = [sel] with self.env.db_transaction: for name in sel: milestone = model.Milestone(self.env, name) milestone.move_tickets(None, req.authname, "Milestone deleted") milestone.delete() add_notice( req, _("The selected milestones have been " "removed.")) req.redirect(req.href.admin(cat, page)) # Set default milestone elif req.args.get('apply'): name = req.args.get('default') if name and name != default: self.log.info("Setting default milestone to %s", name) self.config.set('ticket', 'default_milestone', name) _save_config(self.config, req, self.log) req.redirect(req.href.admin(cat, page)) # Get ticket count milestones = [(milestone, self.env.db_query( """ SELECT COUNT(*) FROM ticket WHERE milestone=%s """, (milestone.name, ))[0][0]) for milestone in model.Milestone.select(self.env)] data = { 'view': 'list', 'milestones': milestones, 'default': default } Chrome(self.env).add_jquery_ui(req) data.update({ 'datetime_hint': get_datetime_format_hint(req.lc_time), }) return 'admin_milestones.html', data
def _render_admin_panel(self, req, cat, page, version): # Detail view? if version: ver = model.Version(self.env, version) if req.method == 'POST': if req.args.get('save'): ver.name = name = req.args.get('name') if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') else: ver.time = None # unset ver.description = req.args.get('description') try: ver.update() except self.env.db_exc.IntegrityError: raise TracError( _('Version "%(name)s" already ' 'exists.', name=name)) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) Chrome(self.env).add_wiki_toolbars(req) data = {'view': 'detail', 'version': ver} else: default = self.config.get('ticket', 'default_version') if req.method == 'POST': # Add Version if req.args.get('add') and req.args.get('name'): name = req.args.get('name') try: ver = model.Version(self.env, name=name) except ResourceNotFound: ver = model.Version(self.env) ver.name = name if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') ver.insert() add_notice( req, _('The version "%(name)s" has been ' 'added.', name=name)) req.redirect(req.href.admin(cat, page)) else: if ver.name is None: raise TracError(_("Invalid version name.")) raise TracError( _('Version "%(name)s" already ' 'exists.', name=name)) # Remove versions elif req.args.get('remove'): sel = req.args.get('sel') if not sel: raise TracError(_("No version selected")) if not isinstance(sel, list): sel = [sel] with self.env.db_transaction: for name in sel: ver = model.Version(self.env, name) ver.delete() add_notice( req, _("The selected versions have been " "removed.")) req.redirect(req.href.admin(cat, page)) # Set default version elif req.args.get('apply'): name = req.args.get('default') if name and name != default: self.log.info("Setting default version to %s", name) self.config.set('ticket', 'default_version', name) _save_config(self.config, req, self.log) req.redirect(req.href.admin(cat, page)) data = { 'view': 'list', 'versions': list(model.Version.select(self.env)), 'default': default } Chrome(self.env).add_jquery_ui(req) data.update({ 'datetime_hint': get_datetime_format_hint(req.lc_time), }) return 'admin_versions.html', data
def save_milestone(self, req, milestone): # Instead of raising one single error, check all the constraints # and let the user fix them by going back to edit mode and showing # the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) milestone.description = req.args.get('description', '') if 'due' in req.args: duedate = req.args.get('duedate') milestone.due = user_time(req, parse_date, duedate, hint='datetime') \ if duedate else None else: milestone.due = None # -- check completed date if 'completed' in req.args: completed = req.args.get('completeddate', '') completed = user_time(req, parse_date, completed, hint='datetime') if completed else None if completed and completed > datetime_now(utc): warn(_("Completion date may not be in the future")) else: completed = None milestone.completed = completed # -- check the name # If the name has changed, check that the milestone doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. new_name = req.args.get('name') try: new_milestone = Milestone(self.env, new_name) except ResourceNotFound: milestone.name = new_name else: if new_milestone.name != milestone.name: if new_milestone.name: warn( _( 'Milestone "%(name)s" already exists, please ' 'choose another name.', name=new_milestone.name)) else: warn(_("You must provide a name for the milestone.")) if warnings: return False # -- actually save changes if milestone.exists: milestone.update(author=req.authname) if completed and 'retarget' in req.args: comment = req.args.get('comment', '') retarget_to = req.args.get('target') or None retargeted_tickets = \ milestone.move_tickets(retarget_to, req.authname, comment, exclude_closed=True) add_notice( req, _( 'The open tickets associated with ' 'milestone "%(name)s" have been retargeted ' 'to milestone "%(retarget)s".', name=milestone.name, retarget=retarget_to)) new_values = {'milestone': retarget_to} comment = comment or \ _("Open tickets retargeted after milestone closed") event = BatchTicketChangeEvent(retargeted_tickets, None, req.authname, comment, new_values, None) try: NotificationSystem(self.env).notify(event) except Exception as e: self.log.error( "Failure sending notification on ticket " "batch change: %s", exception_to_unicode(e)) add_warning( req, tag_( "The changes have been saved, but " "an error occurred while sending " "notifications: %(message)s", message=to_unicode(e))) add_notice(req, _("Your changes have been saved.")) else: milestone.insert() add_notice( req, _('The milestone "%(name)s" has been added.', name=milestone.name)) return True
def _do_actions(self, context, actions): api = TrackerApi() time_interval = self.env.config.getint('tracker', 'time_interval', 10) time_separate = 1 minutes_interval=0 screenshotsWithHourse = [] screenshotsWithMinutes = [] template_hourse = [] minute = 0 min_hourse = 0 max_hourse = 0 allScreenshots=[] for action in actions: if action == 'view': date = datetime.datetime.now(context.req.tz) if 'date' in context.req.args: date_from_calendar = context.req.args['date'].strip() if date_from_calendar: precisedate = user_time(context.req, parse_date, date_from_calendar) date = precisedate.astimezone(context.req.tz) to_date = to_datetime(datetime.datetime(date.year, date.month, date.day, 23, 59, 59, 999999), context.req.tz) to_date_timestamp = to_timestamp(to_date) full_date = { 'from_date': to_date_timestamp - 86400, 'to_date' : to_date_timestamp } context.req.data['fromdate'] = to_date context.req.data['username'] = context.req.args.get('username') screenshot_id = int(context.req.args.get('id') or 0) screenshots = api.get_screenshots(context, context.req.args.get('username'), full_date) context.req.data['id'] = screenshot_id for hourse in range(0, 24): for screenshot in screenshots: screenshot["hourse"] = datetime.datetime.fromtimestamp(screenshot["time"]).strftime('%H') if (int(screenshot["hourse"]) == hourse): if min_hourse == 0: min_hourse = hourse elif min_hourse > hourse: min_hourse = hourse if max_hourse < hourse: max_hourse = hourse screenshotsWithHourse.append({hourse:screenshot}) while (minute <= 59): for screenshotsAll in screenshotsWithHourse: for index in screenshotsAll: screenshotMinute = datetime.datetime.fromtimestamp(float(screenshotsAll[index]["time"])).strftime('%M') if int(screenshotMinute) == minute: screenshotHourse = datetime.datetime.fromtimestamp(screenshotsAll[index]["time"]).strftime('%H') if int(screenshotHourse) not in template_hourse: template_hourse.append(int(screenshotHourse)) screenshotsAll[index]['hourse'] = int(screenshotHourse) screenshotsAll[index]['minute'] = int(screenshotMinute) if len(screenshotsWithMinutes)>0 and screenshotsWithMinutes[0]['minute']==screenshotsAll[index]['minute']: screenshotsWithMinutes.pop() screenshotsWithMinutes.append(screenshotsAll[index]) minute += 10 for hourse in template_hourse: for screenshot in screenshotsWithMinutes: if screenshot['hourse']==hourse: while screenshot['minute']!=minutes_interval: allScreenshots.append({"hourse":hourse,"screen":None,"minute":minutes_interval}) minutes_interval+=10 screenshot["screen"]=1 allScreenshots.append(screenshot) minutes_interval+=10 while (minutes_interval!=60): allScreenshots.append({"hourse":hourse,"screen":None,"minute":minutes_interval}) minutes_interval+=10 minutes_interval=0 context.req.data['allScreenshots'] = allScreenshots context.req.data['template_hourse'] = range(int(min_hourse), int(max_hourse)+time_separate) context.req.data['time_interval'] = time_interval context.req.data['time_separate'] = time_separate context.req.data['template'] = 'user_worklog_view.html' add_stylesheet(context.req, 'trac/css/tracker.css') chrome = Chrome(self.env) chrome.add_jquery_ui(context.req) return 'screenshots', None if action == 'get-file': screenshot_id = int(context.req.args.get('id') or 0) format = context.req.args.get('format') or self.default_format screenshot = api.get_screenshot(context, screenshot_id) if format == 'html': context.req.data['screenshot'] = screenshot return 'screenshot', None else: screenshot_path = screenshot[0]['path'] filename = self.path + '/' + screenshot_path file = open(filename.encode('utf-8'), "r") file_data = file.read(1000) file.close() mimeview = Mimeview(self.env) mime_type = mimeview.get_mimetype(filename, file_data) if not mime_type: mime_type = 'application/octet-stream' if 'charset=' not in mime_type: charset = mimeview.get_charset(file_data, mime_type) mime_type = mime_type + '; charset=' + charset context.req.send_file(filename.encode('utf-8'), mime_type) elif action == 'get-users': context.req.data['users'] = api.get_users(context) context.req.data['template'] = 'user_list.html' context.req.data['client'] = {'download_href': 'jar-tracker/' + calculate_client_package_name()} return 'screenshots', None else: return 'screenshots', None
def test_render_time_field_datetime(self): req = MockRequest(self.env, method='GET', path_info='/ticket/1') value = datetime(2015, 7, 8, 12, 34, 56, tzinfo=utc) expected = user_time(req, format_datetime, value) self._test_render_time_field('datetime', req, value, expected)
def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 50 if format == 'rss' else 0)) lastvisit = int(req.session.get('timeline.lastvisit', '0')) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = int( req.session.get('timeline.nextlastvisit', lastvisit)) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = today = datetime.now(req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args['from'].strip() if reqfromdate: precisedate = user_time(req, parse_date, reqfromdate) fromdate = precisedate precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None fromdate = fromdate.replace(hour=23, minute=59, second=59, microsecond=999999) daysback = as_int(req.args.get('daysback'), 90 if format == 'rss' else None) if daysback is None: daysback = as_int(req.session.get('timeline.daysback'), None) if daysback is None: daysback = self.default_daysback daysback = max(0, daysback) if self.max_daysback >= 0: daysback = min(self.max_daysback, daysback) authors = req.args.get('authors') if authors is None and format != 'rss': authors = req.session.get('timeline.authors') authors = (authors or '').strip() data = { 'fromdate': fromdate, 'daysback': daysback, 'authors': authors, 'today': user_time(req, format_date, today), 'yesterday': user_time(req, format_date, today - timedelta(days=1)), 'precisedate': precisedate, 'precision': precision, 'events': [], 'filters': [], 'abbreviated_messages': self.abbreviated_messages, 'lastvisit': lastvisit } available_filters = [] for event_provider in self.event_providers: available_filters += event_provider.get_timeline_filters(req) or [] # check the request or session for enabled filters, or use default filters = [f[0] for f in available_filters if f[0] in req.args] if not filters and format != 'rss': filters = [ f[0] for f in available_filters if req.session.get('timeline.filter.' + f[0]) == '1' ] if not filters: filters = [f[0] for f in available_filters if len(f) == 2 or f[2]] # save the results of submitting the timeline form to the session if 'update' in req.args: for filter in available_filters: key = 'timeline.filter.%s' % filter[0] if filter[0] in req.args: req.session[key] = '1' elif key in req.session: del req.session[key] stop = fromdate start = stop - timedelta(days=daysback + 1) # create author include and exclude sets include = set() exclude = set() for match in self._authors_pattern.finditer(authors): name = (match.group(2) or match.group(3) or match.group(4)).lower() if match.group(1): exclude.add(name) else: include.add(name) # gather all events for the given period of time events = [] for provider in self.event_providers: try: for event in provider.get_timeline_events( req, start, stop, filters) or []: # Check for 0.10 events author = (event[2 if len(event) < 6 else 4] or '').lower() if (not include or author in include) \ and not author in exclude: events.append(self._event_data(provider, event)) except Exception, e: # cope with a failure of that provider self._provider_failure(e, req, provider, filters, [f[0] for f in available_filters])
def _do_save(self, req, milestone): if milestone.exists: req.perm(milestone.resource).require('MILESTONE_MODIFY') else: req.perm(milestone.resource).require('MILESTONE_CREATE') old_name = milestone.name new_name = req.args.get('name') milestone.description = req.args.get('description', '') if 'due' in req.args: due = req.args.get('duedate', '') milestone.due = user_time(req, parse_date, due, hint='datetime') \ if due else None else: milestone.due = None completed = req.args.get('completeddate', '') retarget_to = req.args.get('target') # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name # If the name has changed, check that the milestone doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: new_milestone = Milestone(self.env, new_name) if new_milestone.name == old_name: pass # Creation or no name change elif new_milestone.name: warn( _( 'Milestone "%(name)s" already exists, please ' 'choose another name.', name=new_milestone.name)) else: warn(_('You must provide a name for the milestone.')) except ResourceNotFound: milestone.name = new_name # -- check completed date if 'completed' in req.args: completed = user_time(req, parse_date, completed, hint='datetime') if completed else None if completed and completed > datetime.now(utc): warn(_('Completion date may not be in the future')) else: completed = None milestone.completed = completed if warnings: return self._render_editor(req, milestone) # -- actually save changes if milestone.exists: milestone.update() # eventually retarget opened tickets associated with the milestone if 'retarget' in req.args and completed: self.env.db_transaction( """ UPDATE ticket SET milestone=%s WHERE milestone=%s and status != 'closed' """, (retarget_to, old_name)) self.log.info("Tickets associated with milestone %s " "retargeted to %s" % (old_name, retarget_to)) else: milestone.insert() add_notice(req, _("Your changes have been saved.")) req.redirect(req.href.milestone(milestone.name))
def _parse_field_value(self, req, field, value): if field['type'] == 'time': return user_time(req, parse_date, value) return value
def process_request(self, req): testmanagersystem = TestManagerSystem(self.env) tc_statuses = testmanagersystem.get_tc_statuses_by_color() if 'testmanager' in self.config: self.default_days_back = self.config.getint('testmanager', 'default_days_back', TESTMANAGER_DEFAULT_DAYS_BACK) self.default_interval = self.config.getint('testmanager', 'default_interval', TESTMANAGER_DEFAULT_INTERVAL) req_content = req.args.get('content') testplan = None catpath = None testplan_contains_all = True self.env.log.debug("Test Stats - process_request: %s" % req_content) grab_testplan = req.args.get('testplan') if grab_testplan and not grab_testplan == "__all": testplan = grab_testplan.partition('|')[0] catpath = grab_testplan.partition('|')[2] tp = TestPlan(self.env, testplan, catpath) testplan_contains_all = tp['contains_all'] today = datetime.today() today = today.replace(tzinfo = req.tz)+timedelta(2) # Stats start from two years back beginning = today - timedelta(720) if (not req_content == None) and (req_content == "piechartdata"): num_successful = 0 for tc_outcome in tc_statuses['green']: num_successful += self._get_num_tcs_by_status(beginning, today, tc_outcome, testplan, req) num_failed = 0 for tc_outcome in tc_statuses['red']: num_failed += self._get_num_tcs_by_status(beginning, today, tc_outcome, testplan, req) num_to_be_tested = 0 if testplan_contains_all: num_to_be_tested = self._get_num_testcases(beginning, today, catpath, req) - num_successful - num_failed else: for tc_outcome in tc_statuses['yellow']: num_to_be_tested += self._get_num_tcs_by_status(beginning, today, tc_outcome, testplan, req) jsdstr = """ [ {"response": "%s", "count": %s}, {"response": "%s", "count": %s}, {"response": "%s", "count": %s} ] """ % (_("Successful"), num_successful, _("Failed"), num_failed, _("To be tested"), num_to_be_tested) jsdstr = jsdstr.strip() if isinstance(jsdstr, unicode): jsdstr = jsdstr.encode('utf-8') req.send_header("Content-Length", len(jsdstr)) req.write(jsdstr) return if not None in [req.args.get('end_date'), req.args.get('start_date'), req.args.get('resolution')]: # form submit grab_at_date = req.args.get('end_date') grab_from_date = req.args.get('start_date') grab_resolution = req.args.get('resolution') self.env.log.debug("Start date: %s", grab_from_date) self.env.log.debug("End date: %s", grab_at_date) # validate inputs if None in [grab_at_date, grab_from_date]: raise TracError('Please specify a valid range.') if None in [grab_resolution]: raise TracError('Please specify the graph interval.') if 0 in [len(grab_at_date), len(grab_from_date), len(grab_resolution)]: raise TracError('Please ensure that all fields have been filled in.') if not grab_resolution.isdigit(): raise TracError('The graph interval field must be an integer, days.') if compatibility: at_date = parse_date(grab_at_date, req.tz)+timedelta(2) from_date = parse_date(grab_from_date, req.tz) else: at_date = user_time(req, parse_date, grab_at_date, hint='date') from_date = user_time(req, parse_date, grab_from_date, hint='date') graph_res = int(grab_resolution) else: # default data todays_date = datetime.today() at_date = todays_date #+ timedelta(1) # datetime.combine(todays_date,time(23,59,59,0,req.tz)) at_date = at_date.replace(tzinfo = req.tz)+timedelta(2) from_date = at_date - timedelta(self.default_days_back) graph_res = self.default_interval count = [] # Calculate 0th point last_date = from_date - timedelta(graph_res) # Calculate remaining points for cur_date in daterange(from_date, at_date, graph_res): datestr = format_date(cur_date) if graph_res != 1: datestr = "%s thru %s" % (format_date(last_date), datestr) if (not req_content == None) and (req_content == "ticketchartdata"): num_total = self._get_num_tickets_total(beginning, cur_date, testplan, req) num_closed = self._get_num_tickets_by_status(beginning, cur_date, 'closed', testplan, req) num_active = num_total - num_closed count.append( {'from_date': format_date(last_date), 'to_date': datestr, 'date' : datestr, 'active_tickets' : num_active, 'closed_tickets': num_closed, 'tot_tickets' : num_total} ) else: # Handling custom test case outcomes here num_new = self._get_num_testcases(last_date, cur_date, catpath, req) num_successful = 0 for tc_outcome in tc_statuses['green']: num_successful += self._get_num_tcs_by_status(last_date, cur_date, tc_outcome, testplan, req) num_failed = 0 for tc_outcome in tc_statuses['red']: num_failed += self._get_num_tcs_by_status(last_date, cur_date, tc_outcome, testplan, req) num_all_successful = 0 for tc_outcome in tc_statuses['green']: num_all_successful += self._get_num_tcs_by_status(from_date, cur_date, tc_outcome, testplan, req) num_all_failed = 0 for tc_outcome in tc_statuses['red']: num_all_failed += self._get_num_tcs_by_status(from_date, cur_date, tc_outcome, testplan, req) num_all = 0 num_all_untested = 0 if testplan_contains_all: num_all = self._get_num_testcases(None, cur_date, catpath, req) num_all_untested = num_all - num_all_successful - num_all_failed else: for tc_outcome in tc_statuses['yellow']: num_all_untested += self._get_num_tcs_by_status(from_date, cur_date, tc_outcome, testplan, req) num_all = num_all_untested + num_all_successful + num_all_failed count.append( {'from_date': format_date(last_date), 'to_date': datestr, 'date' : datestr, 'new_tcs' : num_new, 'successful': num_successful, 'failed': num_failed, 'all_tcs' : num_all, 'all_successful': num_all_successful, 'all_untested': num_all_untested, 'all_failed': num_all_failed }) last_date = cur_date # if chartdata is requested, raw text is returned rather than data object # for templating if (not req_content == None) and (req_content == "chartdata"): jsdstr = '{"chartdata": [\n' for x in count: jsdstr += '{"date": "%s",' % x['date'] jsdstr += ' "new_tcs": %s,' % x['new_tcs'] jsdstr += ' "successful": %s,' % x['successful'] jsdstr += ' "failed": %s,' % x['failed'] jsdstr += ' "all_tcs": %s,' % x['all_tcs'] jsdstr += ' "all_successful": %s,' % x['all_successful'] jsdstr += ' "all_untested": %s,' % x['all_untested'] jsdstr += ' "all_failed": %s},\n' % x['all_failed'] jsdstr = jsdstr[:-2] +'\n]}' if isinstance(jsdstr, unicode): jsdstr = jsdstr.encode('utf-8') req.send_header("Content-Length", len(jsdstr)) req.write(jsdstr) return elif (not req_content == None) and (req_content == "downloadcsv"): csvstr = "Date from;Date to;New Test Cases;Successful;Failed;Total Test Cases;Total Successful;Total Untested;Total Failed\r\n" for x in count: csvstr += '%s;' % x['from_date'] csvstr += '%s;' % x['to_date'] csvstr += '%s;' % x['new_tcs'] csvstr += '%s;' % x['successful'] csvstr += '%s;' % x['failed'] csvstr += '%s;' % x['all_tcs'] csvstr += '%s;' % x['all_successful'] csvstr += '%s;' % x['all_untested'] csvstr += '%s\r\n' % x['all_failed'] if isinstance(csvstr, unicode): csvstr = csvstr.encode('utf-8') req.send_header("Content-Length", len(csvstr)) req.send_header("Content-Disposition", "attachment;filename=Test_stats.csv") req.write(csvstr) return elif (not req_content == None) and (req_content == "ticketchartdata"): jsdstr = '{"ticketchartdata": [\n' for x in count: jsdstr += '{"date": "%s",' % x['date'] jsdstr += ' "tot_tickets": %s,' % x['tot_tickets'] jsdstr += ' "active_tickets": %s,' % x['active_tickets'] jsdstr += ' "closed_tickets": %s},\n' % x['closed_tickets'] jsdstr = jsdstr[:-2] +'\n]}' if isinstance(jsdstr, unicode): jsdstr = jsdstr.encode('utf-8') req.send_header("Content-Length", len(jsdstr)) req.write(jsdstr) return else: # Normal rendering of first chart showall = req.args.get('show') == 'all' testplan_list = [] for planid, catid, catpath, name, author, ts_str in testmanagersystem.list_all_testplans(): testplan_list.append({'planid': planid, 'catpath': catpath, 'name': name}) data = {} data['testcase_data'] = count data['resolution'] = str(graph_res) data['baseurl'] = req.base_url data['testplans'] = testplan_list data['ctestplan'] = testplan if compatibility: data['start_date'] = format_date(from_date) data['end_date'] = format_date(at_date) return 'testmanagerstats_compatible.html', data, None else: data['start_date'] = from_date data['end_date'] = at_date Chrome(self.env).add_jquery_ui(req) data.update({ 'date_hint': get_date_format_hint(req.lc_time), }) is_iso8601 = req.lc_time == 'iso8601' add_script_data(req, jquery_ui={ 'month_names': get_month_names_jquery_ui(req), 'day_names': get_day_names_jquery_ui(req), 'date_format': get_date_format_jquery_ui(req.lc_time), 'time_format': get_time_format_jquery_ui(req.lc_time), 'ampm': not is_24_hours(req.lc_time), 'first_week_day': get_first_week_day_jquery_ui(req), 'timepicker_separator': 'T' if is_iso8601 else ' ', 'show_timezone': is_iso8601, 'timezone_list': get_timezone_list_jquery_ui() \ if is_iso8601 else [], 'timezone_iso8601': is_iso8601, }) return 'testmanagerstats.html', data, None
def process_request(self, req): """Process the request """ base = self.get_mypage_base(req.authname) tzinfo = getattr(req, 'tz', None) now = datetime.now(tzinfo or localtz) today = format_date(now, 'iso8601', tzinfo) today_page_name = base + today today_page = WikiPage(self.env, today_page_name) if today_page.exists: req.redirect(req.href.wiki(today_page_name, action='edit')) # create page of the day for today if 'WIKI_CREATE' not in req.perm(today_page.resource): raise ResourceNotFound(_("Can't create the page of the day.")) ws = WikiSystem(self.env) def get_page_text(pagename): if ws.has_page(pagename): page = WikiPage(self.env, pagename) if 'WIKI_VIEW' in req.perm(page.resource): self.log.debug("get_page_text(%s) -> %s", pagename, page.text) return page.text self.log.debug("get_page_text(%s) -> None", pagename) # retrieve page template template_name = 'PageTemplates/MyPage' mytemplate_name = '/'.join([template_name, req.authname]) template_text = get_page_text(mytemplate_name) if template_text is None: template_text = get_page_text(template_name) text = last_page_text = last_page_quoted = None if template_text is not None: # retrieve previous "page of the day", if any all_mypages = self.get_all_mypages(base) last = bisect(all_mypages, today_page_name) - 1 self.log.debug("Pos of today %s in %r is %d", today_page_name, all_mypages, last) last_page_name = all_mypages[last] if last >= 0 else None last_page_link = '' if last_page_name: last_page_link = '[[%s]]' % last_page_name last_page_text = get_page_text(last_page_name) if last_page_text is not None: last_page_quoted = '\n'.join( ['> ' + line for line in last_page_text.splitlines()]) today_user = user_time(req, format_date, now, tzinfo=tzinfo) author = req.session.get('name') or get_reporter_id(req) text = template_text \ .replace(self.tokens['date'][0], today_user) \ .replace(self.tokens['isodate'][0], today) \ .replace(self.tokens['user'][0], req.authname) \ .replace(self.tokens['author'][0], author) \ .replace(self.tokens['lp_link'][0], last_page_link) \ .replace(self.tokens['lp_name'][0], last_page_name or '') \ .replace(self.tokens['lp_text'][0], last_page_text or '') \ .replace(self.tokens['lp_quoted'][0], last_page_quoted or '') req.redirect(req.href.wiki(today_page_name, action='edit', text=text))
def _get_user_time(cls, req): time = req.args.get('time') return user_time(req, parse_date, time, hint='datetime') \ if time else None
def process_request(self, req): req.perm.assert_permission('TIMELINE_VIEW') format = req.args.get('format') maxrows = int(req.args.get('max', 50 if format == 'rss' else 0)) lastvisit = int(req.session.get('timeline.lastvisit', '0')) # indication of new events is unchanged when form is updated by user revisit = any(a in req.args for a in ['update', 'from', 'daysback', 'author']) if revisit: lastvisit = int(req.session.get('timeline.nextlastvisit', lastvisit)) # Parse the from date and adjust the timestamp to the last second of # the day fromdate = today = datetime.now(req.tz) yesterday = to_datetime(today.replace(tzinfo=None) - timedelta(days=1), req.tz) precisedate = precision = None if 'from' in req.args: # Acquire from date only from non-blank input reqfromdate = req.args['from'].strip() if reqfromdate: precisedate = user_time(req, parse_date, reqfromdate) fromdate = precisedate.astimezone(req.tz) precision = req.args.get('precision', '') if precision.startswith('second'): precision = timedelta(seconds=1) elif precision.startswith('minute'): precision = timedelta(minutes=1) elif precision.startswith('hour'): precision = timedelta(hours=1) else: precision = None fromdate = to_datetime(datetime(fromdate.year, fromdate.month, fromdate.day, 23, 59, 59, 999999), req.tz) daysback = as_int(req.args.get('daysback'), 90 if format == 'rss' else None) if daysback is None: daysback = as_int(req.session.get('timeline.daysback'), None) if daysback is None: daysback = self.default_daysback daysback = max(0, daysback) if self.max_daysback >= 0: daysback = min(self.max_daysback, daysback) authors = req.args.get('authors') if authors is None and format != 'rss': authors = req.session.get('timeline.authors') authors = (authors or '').strip() data = {'fromdate': fromdate, 'daysback': daysback, 'authors': authors, 'today': user_time(req, format_date, today), 'yesterday': user_time(req, format_date, yesterday), 'precisedate': precisedate, 'precision': precision, 'events': [], 'filters': [], 'abbreviated_messages': self.abbreviated_messages, 'lastvisit': lastvisit} available_filters = [] for event_provider in self.event_providers: available_filters += event_provider.get_timeline_filters(req) or [] # check the request or session for enabled filters, or use default filters = [f[0] for f in available_filters if f[0] in req.args] if not filters and format != 'rss': filters = [f[0] for f in available_filters if req.session.get('timeline.filter.' + f[0]) == '1'] if not filters: filters = [f[0] for f in available_filters if len(f) == 2 or f[2]] # save the results of submitting the timeline form to the session if 'update' in req.args: for filter in available_filters: key = 'timeline.filter.%s' % filter[0] if filter[0] in req.args: req.session[key] = '1' elif key in req.session: del req.session[key] stop = fromdate start = to_datetime(stop.replace(tzinfo=None) - \ timedelta(days=daysback + 1), req.tz) # create author include and exclude sets include = set() exclude = set() for match in self._authors_pattern.finditer(authors): name = (match.group(2) or match.group(3) or match.group(4)).lower() if match.group(1): exclude.add(name) else: include.add(name) # gather all events for the given period of time events = [] for provider in self.event_providers: try: for event in provider.get_timeline_events(req, start, stop, filters) or []: # Check for 0.10 events author = (event[2 if len(event) < 6 else 4] or '').lower() if (not include or author in include) \ and not author in exclude: events.append(self._event_data(provider, event)) except Exception, e: # cope with a failure of that provider self._provider_failure(e, req, provider, filters, [f[0] for f in available_filters])
def _do_save(self, req, milestone): if milestone.exists: req.perm(milestone.resource).require('MILESTONE_MODIFY') else: req.perm(milestone.resource).require('MILESTONE_CREATE') old_name = milestone.name new_name = req.args.get('name') milestone.description = req.args.get('description', '') if 'due' in req.args: due = req.args.get('duedate', '') milestone.due = user_time(req, parse_date, due, hint='datetime') \ if due else None else: milestone.due = None completed = req.args.get('completeddate', '') retarget_to = req.args.get('target') # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name # If the name has changed, check that the milestone doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: new_milestone = Milestone(self.env, new_name) if new_milestone.name == old_name: pass # Creation or no name change elif new_milestone.name: warn(_('Milestone "%(name)s" already exists, please ' 'choose another name.', name=new_milestone.name)) else: warn(_('You must provide a name for the milestone.')) except ResourceNotFound: milestone.name = new_name # -- check completed date if 'completed' in req.args: completed = user_time(req, parse_date, completed, hint='datetime') if completed else None if completed and completed > datetime.now(utc): warn(_('Completion date may not be in the future')) else: completed = None milestone.completed = completed if warnings: return self._render_editor(req, milestone) # -- actually save changes if milestone.exists: milestone.update() # eventually retarget opened tickets associated with the milestone if 'retarget' in req.args and completed: self.env.db_transaction(""" UPDATE ticket SET milestone=%s WHERE milestone=%s and status != 'closed' """, (retarget_to, old_name)) self.log.info("Tickets associated with milestone %s " "retargeted to %s" % (old_name, retarget_to)) else: milestone.insert() add_notice(req, _("Your changes have been saved.")) req.redirect(req.href.milestone(milestone.name))
def _render_admin_panel(self, req, cat, page, milestone): req.perm.require('MILESTONE_VIEW') # Detail view? if milestone: mil = model.Milestone(self.env, milestone) if req.method == 'POST': if req.args.get('save'): req.perm.require('MILESTONE_MODIFY') mil.name = name = req.args.get('name') mil.due = mil.completed = None due = req.args.get('duedate', '') if due: mil.due = user_time(req, parse_date, due, hint='datetime') if req.args.get('completed', False): completed = req.args.get('completeddate', '') mil.completed = user_time(req, parse_date, completed, hint='datetime') if mil.completed > datetime.now(utc): raise TracError(_('Completion date may not be in ' 'the future'), _('Invalid Completion Date')) mil.description = req.args.get('description', '') try: mil.update() except self.env.db_exc.IntegrityError: raise TracError(_('The milestone "%(name)s" already ' 'exists.', name=name)) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) Chrome(self.env).add_wiki_toolbars(req) data = {'view': 'detail', 'milestone': mil} else: default = self.config.get('ticket', 'default_milestone') if req.method == 'POST': # Add Milestone if req.args.get('add') and req.args.get('name'): req.perm.require('MILESTONE_CREATE') name = req.args.get('name') try: mil = model.Milestone(self.env, name=name) except ResourceNotFound: mil = model.Milestone(self.env) mil.name = name if req.args.get('duedate'): mil.due = user_time(req, parse_date, req.args.get('duedate'), hint='datetime') mil.insert() add_notice(req, _('The milestone "%(name)s" has been ' 'added.', name=name)) req.redirect(req.href.admin(cat, page)) else: if mil.name is None: raise TracError(_('Invalid milestone name.')) raise TracError(_("Milestone %(name)s already exists.", name=name)) # Remove milestone elif req.args.get('remove'): req.perm.require('MILESTONE_DELETE') sel = req.args.get('sel') if not sel: raise TracError(_('No milestone selected')) if not isinstance(sel, list): sel = [sel] with self.env.db_transaction: for name in sel: mil = model.Milestone(self.env, name) mil.delete(author=req.authname) add_notice(req, _("The selected milestones have been " "removed.")) req.redirect(req.href.admin(cat, page)) # Set default milestone elif req.args.get('apply'): name = req.args.get('default') if name and name != default: self.log.info("Setting default milestone to %s", name) self.config.set('ticket', 'default_milestone', name) _save_config(self.config, req, self.log) req.redirect(req.href.admin(cat, page)) # Get ticket count milestones = [ (milestone, self.env.db_query(""" SELECT COUNT(*) FROM ticket WHERE milestone=%s """, (milestone.name,))[0][0]) for milestone in model.Milestone.select(self.env)] data = {'view': 'list', 'milestones': milestones, 'default': default} Chrome(self.env).add_jquery_ui(req) data.update({ 'datetime_hint': get_datetime_format_hint(req.lc_time), }) return 'admin_milestones.html', data
def _render_admin_panel(self, req, cat, page, version): # Detail view? if version: ver = model.Version(self.env, version) if req.method == 'POST': if req.args.get('save'): ver.name = req.args.get('name') if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') else: ver.time = None # unset ver.description = req.args.get('description') ver.update() add_notice(req, _("Your changes have been saved.")) req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) chrome = Chrome(self.env) chrome.add_wiki_toolbars(req) chrome.add_auto_preview(req) data = {'view': 'detail', 'version': ver} else: default = self.config.get('ticket', 'default_version') if req.method == 'POST': # Add Version if req.args.get('add') and req.args.get('name'): ver = model.Version(self.env) ver.name = req.args.get('name') if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') ver.insert() add_notice(req, _('The version "%(name)s" has been ' 'added.', name=ver.name)) req.redirect(req.href.admin(cat, page)) # Remove versions elif req.args.get('remove'): sel = req.args.getlist('sel') if not sel: raise TracError(_("No version selected")) with self.env.db_transaction: for name in sel: model.Version(self.env, name).delete() if name == default: self.config.set('ticket', 'default_version', '') self._save_config(req) add_notice(req, _("The selected versions have been " "removed.")) req.redirect(req.href.admin(cat, page)) # Set default version elif req.args.get('apply'): name = req.args.get('default') if name and name != default: self.log.info("Setting default version to %s", name) self.config.set('ticket', 'default_version', name) self._save_config(req) req.redirect(req.href.admin(cat, page)) # Clear default version elif req.args.get('clear'): self.log.info("Clearing default version") self.config.set('ticket', 'default_version', '') self._save_config(req) req.redirect(req.href.admin(cat, page)) data = {'view': 'list', 'versions': list(model.Version.select(self.env)), 'default': default} Chrome(self.env).add_jquery_ui(req) data.update({'datetime_hint': get_datetime_format_hint(req.lc_time)}) return 'admin_versions.html', data
def _do_actions(self, context, actions): api = TrackerApi() time_interval = self.env.config.getint('tracker', 'time_interval', 10) time_separate = 1 minutes_interval = 0 screenshotsWithHourse = [] screenshotsWithMinutes = [] template_hourse = [] minute = 0 min_hourse = 0 max_hourse = 0 allScreenshots = [] for action in actions: if action == 'view': date = datetime.datetime.now(context.req.tz) if 'date' in context.req.args: date_from_calendar = context.req.args['date'].strip() if date_from_calendar: precisedate = user_time(context.req, parse_date, date_from_calendar) date = precisedate.astimezone(context.req.tz) to_date = to_datetime( datetime.datetime(date.year, date.month, date.day, 23, 59, 59, 999999), context.req.tz) to_date_timestamp = to_timestamp(to_date) full_date = { 'from_date': to_date_timestamp - 86400, 'to_date': to_date_timestamp } context.req.data['fromdate'] = to_date context.req.data['username'] = context.req.args.get('username') screenshot_id = int(context.req.args.get('id') or 0) screenshots = api.get_screenshots( context, context.req.args.get('username'), full_date) context.req.data['id'] = screenshot_id for hourse in range(0, 24): for screenshot in screenshots: screenshot["hourse"] = datetime.datetime.fromtimestamp( screenshot["time"]).strftime('%H') if (int(screenshot["hourse"]) == hourse): if min_hourse == 0: min_hourse = hourse elif min_hourse > hourse: min_hourse = hourse if max_hourse < hourse: max_hourse = hourse screenshotsWithHourse.append({hourse: screenshot}) while (minute <= 59): for screenshotsAll in screenshotsWithHourse: for index in screenshotsAll: screenshotMinute = datetime.datetime.fromtimestamp( float(screenshotsAll[index]["time"])).strftime( '%M') if int(screenshotMinute) == minute: screenshotHourse = datetime.datetime.fromtimestamp( screenshotsAll[index]["time"]).strftime( '%H') if int(screenshotHourse ) not in template_hourse: template_hourse.append( int(screenshotHourse)) screenshotsAll[index]['hourse'] = int( screenshotHourse) screenshotsAll[index]['minute'] = int( screenshotMinute) if len(screenshotsWithMinutes ) > 0 and screenshotsWithMinutes[0][ 'minute'] == screenshotsAll[index][ 'minute']: screenshotsWithMinutes.pop() screenshotsWithMinutes.append( screenshotsAll[index]) minute += 10 for hourse in template_hourse: for screenshot in screenshotsWithMinutes: if screenshot['hourse'] == hourse: while screenshot['minute'] != minutes_interval: allScreenshots.append({ "hourse": hourse, "screen": None, "minute": minutes_interval }) minutes_interval += 10 screenshot["screen"] = 1 allScreenshots.append(screenshot) minutes_interval += 10 while (minutes_interval != 60): allScreenshots.append({ "hourse": hourse, "screen": None, "minute": minutes_interval }) minutes_interval += 10 minutes_interval = 0 context.req.data['allScreenshots'] = allScreenshots context.req.data['template_hourse'] = range( int(min_hourse), int(max_hourse) + time_separate) context.req.data['time_interval'] = time_interval context.req.data['time_separate'] = time_separate context.req.data['template'] = 'user_worklog_view.html' add_stylesheet(context.req, 'trac/css/tracker.css') chrome = Chrome(self.env) chrome.add_jquery_ui(context.req) return 'screenshots', None if action == 'get-file': screenshot_id = int(context.req.args.get('id') or 0) format = context.req.args.get('format') or self.default_format screenshot = api.get_screenshot(context, screenshot_id) if format == 'html': context.req.data['screenshot'] = screenshot return 'screenshot', None else: screenshot_path = screenshot[0]['path'] filename = self.path + '/' + screenshot_path file = open(filename.encode('utf-8'), "r") file_data = file.read(1000) file.close() mimeview = Mimeview(self.env) mime_type = mimeview.get_mimetype(filename, file_data) if not mime_type: mime_type = 'application/octet-stream' if 'charset=' not in mime_type: charset = mimeview.get_charset(file_data, mime_type) mime_type = mime_type + '; charset=' + charset context.req.send_file(filename.encode('utf-8'), mime_type) elif action == 'get-users': context.req.data['users'] = api.get_users(context) context.req.data['template'] = 'user_list.html' context.req.data['client'] = { 'download_href': 'jar-tracker/' + calculate_client_package_name() } return 'screenshots', None else: return 'screenshots', None
def _render_admin_panel(self, req, cat, page, version): # Detail view? if version: ver = model.Version(self.env, version) if req.method == 'POST': if req.args.get('save'): ver.name = name = req.args.get('name') if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') else: ver.time = None # unset ver.description = req.args.get('description') try: ver.update() except self.env.db_exc.IntegrityError: raise TracError(_('The version "%(name)s" already ' 'exists.', name=name)) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) Chrome(self.env).add_wiki_toolbars(req) data = {'view': 'detail', 'version': ver} else: default = self.config.get('ticket', 'default_version') if req.method == 'POST': # Add Version if req.args.get('add') and req.args.get('name'): name = req.args.get('name') try: ver = model.Version(self.env, name=name) except ResourceNotFound: ver = model.Version(self.env) ver.name = name if req.args.get('time'): ver.time = user_time(req, parse_date, req.args.get('time'), hint='datetime') ver.insert() add_notice(req, _('The version "%(name)s" has been ' 'added.', name=name)) req.redirect(req.href.admin(cat, page)) else: if ver.name is None: raise TracError(_("Invalid version name.")) raise TracError(_("Version %(name)s already exists.", name=name)) # Remove versions elif req.args.get('remove'): sel = req.args.get('sel') if not sel: raise TracError(_("No version selected")) if not isinstance(sel, list): sel = [sel] with self.env.db_transaction: for name in sel: ver = model.Version(self.env, name) ver.delete() add_notice(req, _("The selected versions have been " "removed.")) req.redirect(req.href.admin(cat, page)) # Set default version elif req.args.get('apply'): name = req.args.get('default') if name and name != default: self.log.info("Setting default version to %s", name) self.config.set('ticket', 'default_version', name) _save_config(self.config, req, self.log) req.redirect(req.href.admin(cat, page)) data = {'view': 'list', 'versions': model.Version.select(self.env), 'default': default} Chrome(self.env).add_jquery_ui(req) data.update({ 'datetime_hint': get_datetime_format_hint(req.lc_time), }) return 'admin_versions.html', data
def _do_save(self, req, db, version): version_name = req.args.get('name') version_project = req.args.get('project') old_version_project = self.__SmpModel.get_id_project_version( version.name) if version.exists: req.perm.require('MILESTONE_MODIFY') else: req.perm.require('MILESTONE_CREATE') old_name = version.name new_name = version_name version.description = req.args.get('description', '') time = req.args.get('time', '') if time: version.time = user_time(req, parse_date, time, hint='datetime') else: version.time = None # Instead of raising one single error, check all the constraints and # let the user fix them by going back to edit mode showing the warnings warnings = [] def warn(msg): add_warning(req, msg) warnings.append(msg) # -- check the name # If the name has changed, check that the version doesn't already # exist # FIXME: the whole .exists business needs to be clarified # (#4130) and should behave like a WikiPage does in # this respect. try: new_version = Version(self.env, new_name, db) if new_version.name == old_name: pass # Creation or no name change elif new_version.name: warn( _( 'Version "%(name)s" already exists, please ' 'choose another name.', name=new_version.name)) else: warn(_('You must provide a name for the version.')) except: version.name = new_name if warnings: return self._render_editor(req, db, version) # -- actually save changes if version.exists: version.update() if old_name != version.name: self.__SmpModel.rename_version_project(old_name, version.name) if not version_project: self.__SmpModel.delete_version_project(version.name) elif not old_version_project: self.__SmpModel.insert_version_project(version.name, version_project) else: self.__SmpModel.update_version_project(version.name, version_project) else: version.insert() if version_project: self.__SmpModel.insert_version_project(version.name, version_project) add_notice(req, _('Your changes have been saved.')) req.redirect(req.href.version(version.name))