def get_timeline_events(self, req, start, stop, filters): # timeline动作的输入 if 'wiki' in filters: wiki = WikiSystem(self.env) format = req.args.get('format') href = format == 'rss' and req.abs_href or req.href db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("SELECT time,name,comment,author,version " "FROM wiki WHERE time>=%s AND time<=%s", (start, stop)) for t,name,comment,author,version in cursor: title = Markup('<em>%s</em> '+ u"编辑者 %s", wiki.format_page_name(name), author) diff_link = html.A(u'变化', href=href.wiki(name, action='diff', version=version)) if format == 'rss': comment = wiki_to_html(comment or '--', self.env, req, db, absurls=True) else: comment = wiki_to_oneliner(comment, self.env, db, shorten=True) if version > 1: comment = Markup('%s (%s)', comment, diff_link) yield 'wiki', href.wiki(name), title, t, author, comment # Attachments att = AttachmentModule(self.env) for event in att.get_timeline_events(req, db, 'wiki', format, start, stop, lambda id: html.EM(id)): yield event
def _create_html_body(self, chrome, req, ticket, cnum, link): tktmod = TicketModule(self.env) attmod = AttachmentModule(self.env) data = tktmod._prepare_data(req, ticket) tktmod._insert_ticket_data(req, ticket, data, req.authname, {}) data['ticket']['link'] = link changes = data.get('changes') if cnum is None: changes = [] else: changes = [ change for change in (changes or []) if change.get('cnum') == cnum ] data['changes'] = changes context = Context.from_request(req, ticket.resource, absurls=True) data.update({ 'can_append': False, 'show_editor': False, 'start_time': ticket['changetime'], 'context': context, 'alist': attmod.attachment_data(context), 'styles': self._get_styles(chrome), 'link': tag.a(link, href=link), 'tag_': tag_, }) rendered = chrome.render_template(req, 'htmlnotification_ticket.html', data, fragment=True) return unicode(rendered)
def test_download_zip(self): att = Attachment(self.env, 'parent_realm', 'parent_id') att.description = 'Blah blah' att.insert('foo.txt', StringIO('foo'), 3, datetime(2016, 9, 23, 12, 34, 56, tzinfo=utc)) att = Attachment(self.env, 'parent_realm', 'parent_id') att.insert('bar.jpg', StringIO('bar'), 3, datetime(2016, 12, 14, 23, 56, 30, tzinfo=utc)) module = AttachmentModule(self.env) req = MockRequest(self.env, args={'format': 'zip'}, path_info='/attachment/parent_realm/parent_id/') self.assertTrue(module.match_request(req)) self.assertRaises(RequestDone, module.process_request, req) z = zipfile.ZipFile(req.response_sent, 'r') self.assertEqual(['bar.jpg', 'foo.txt'], sorted(i.filename for i in z.infolist())) zinfo = z.getinfo('foo.txt') self.assertEqual('foo', z.read('foo.txt')) self.assertEqual(3, zinfo.file_size) self.assertEqual((2016, 9, 23, 12, 34, 56), zinfo.date_time) self.assertEqual('Blah blah', zinfo.comment) zinfo = z.getinfo('bar.jpg') self.assertEqual('bar', z.read('bar.jpg')) self.assertEqual(3, zinfo.file_size) self.assertEqual((2016, 12, 14, 23, 56, 30), zinfo.date_time) self.assertEqual('', zinfo.comment)
def post_process_request(self, req, template, data, content_type): if not req or not template or not isinstance(data, dict): return template, data, content_type model = None resource = None attachments = None if template in ('wiki_view.html', 'wiki_edit.html'): model = data.get('page') elif template == 'ticket.html': model = data.get('ticket') elif template in ('milestone_view.html', 'milestone_edit.html'): model = data.get('milestone') elif template == 'attachment.html': attachments = data.get('attachments') if attachments: resource = attachments['parent'] if not resource and model and model.exists: resource = model.resource if not resource: return template, data, content_type if not attachments: attachments = data.get('attachments') if not attachments and model and resource: context = web_context(req, resource) attachments = AttachmentModule(self.env).attachment_data(context) data['attachments'] = attachments if template in ('wiki_edit.html', 'milestone_edit.html'): self._add_overlayview(req) add_stylesheet(req, 'tracdragdrop/tracdragdrop.css') if hasattr(req, 'locale'): locale = str(req.locale) if locale in self.messages_files: add_script(req, 'tracdragdrop/messages/%s.js' % locale) add_script(req, 'common/js/folding.js') add_script(req, 'tracdragdrop/tracdragdrop.js') script_data = { '_tracdragdrop': { 'base_url': req.href().rstrip('/') + '/', 'new_url': req.href('tracdragdrop', 'new', resource.realm, resource.id), 'can_create': attachments.get('can_create') or False, 'max_size': AttachmentModule(self.env).max_size, }, 'form_token': req.form_token, } if add_script_data: add_script_data(req, script_data) else: setattr(req, '_tracdragdrop_data', script_data) return template, data, content_type
def test_attachment_parent_realm_raises_exception(self): """TracError is raised when 'attachment' is the resource parent realm. """ path_info = '/attachment/attachment/parent_id/attachment_id' req = MockRequest(self.env, path_info=path_info) module = AttachmentModule(self.env) self.assertTrue(module.match_request(req)) self.assertRaises(TracError, module.process_request, req)
def test_post_request_without_attachment_raises_exception(self): """TracError is raised for POST request with no file.""" path_info = '/attachment/parent_realm/parent_id' req = MockRequest(self.env, path_info=path_info, method='POST', args={'action': 'new'}) module = AttachmentModule(self.env) self.assertTrue(module.match_request(req)) with self.assertRaises(TracError) as cm: module.process_request(req) self.assertEqual("No file uploaded", unicode(cm.exception))
def test_invalid_post_request_raises_exception(self): path_info = '/attachment/parent_realm/parent_id/attachment_id' attachment = Attachment(self.env, 'parent_realm', 'parent_id') attachment.insert('attachment_id', io.BytesIO(), 0, 1) req = MockRequest(self.env, method='POST', action=None, path_info=path_info) module = AttachmentModule(self.env) self.assertTrue(module.match_request(req)) self.assertRaises(HTTPBadRequest, module.process_request, req)
def test_post_request_without_attachment_raises_exception(self): """TracError is raised when a POST request is submitted without an attachment. """ path_info = '/attachment/parent_realm/parent_id' req = MockRequest(self.env, path_info=path_info, method='POST', args={'action': 'new'}) module = AttachmentModule(self.env) self.assertTrue(module.match_request(req)) self.assertRaises(TracError, module.process_request, req)
def test_post_request_with_empty_attachment_raises_exception(self): """TracError is raised for POST request with empty file.""" module = AttachmentModule(self.env) path_info = '/attachment/parent_realm/parent_id' with tempfile.NamedTemporaryFile('rb', dir=self.env.path) as file_: upload = Mock(filename=file_.name, file=file_) req = MockRequest(self.env, path_info=path_info, method='POST', args={'action': 'new', 'attachment': upload}) self.assertTrue(module.match_request(req)) with self.assertRaises(TracError) as cm: module.process_request(req) self.assertEqual("Can't upload empty file", unicode(cm.exception))
def attachment_to_hdf(env, req, db, attachment): """ This function have been removed from 0.11, this is copied from 0.10, then modified to work with 0.11 """ if not db: db = env.get_db_cnx() hdf = { 'filename': attachment.filename, 'description': wiki_to_oneliner(attachment.description, env, db, req=req), 'author': attachment.author, 'ipnr': attachment.ipnr, 'size': pretty_size(attachment.size), 'time': format_datetime(attachment.date), 'age': pretty_timedelta(attachment.date), 'href': AttachmentModule(env).get_resource_url(attachment.resource, req.href) } return hdf
def test_preview_valid_xhtml(self): chrome = Chrome(self.env) module = AttachmentModule(self.env) def render(attachment): path_info = '/attachment/%s/%s/%s' % (attachment.parent_realm, attachment.parent_id, attachment.filename) req = MockRequest(self.env, path_info=path_info) self.assertTrue(module.match_request(req)) template, data = module.process_request(req) return chrome.render_template(req, template, data, {'fragment': True}) # empty file attachment = Attachment(self.env, 'parent_realm', 'parent_id') attachment.insert('empty', io.BytesIO(), 0, 1) result = render(attachment) self.assertIn('<strong>(The file is empty)</strong>', result) xml = minidom.parseString(result) # text file attachment = Attachment(self.env, 'parent_realm', 'parent_id') attachment.insert('foo.txt', io.BytesIO(b'text'), 4, 1) result = render(attachment) self.assertIn('<tr><th id="L1"><a href="#L1">1</a></th>' '<td>text</td></tr>', result) xml = minidom.parseString(result) # preview unavailable attachment = Attachment(self.env, 'parent_realm', 'parent_id') attachment.insert('foo.dat', io.BytesIO(b'\x00\x00\x01\xb3'), 4, 1) result = render(attachment) self.assertIn('<strong>HTML preview not available</strong>', result) xml = minidom.parseString(result)
def get_search_results(self, req, terms, filters): if not 'wiki' in filters: return with self.env.db_query as db: sql_query, args = search_to_sql( db, ['w1.name', 'w1.author', 'w1.text'], terms) wiki_realm = Resource('wiki') for name, ts, author, text in db( """ SELECT w1.name, w1.time, w1.author, w1.text FROM wiki w1,(SELECT name, max(version) AS ver FROM wiki GROUP BY name) w2 WHERE w1.version = w2.ver AND w1.name = w2.name AND """ + sql_query, args): page = wiki_realm(id=name) if 'WIKI_VIEW' in req.perm(page): yield (get_resource_url(self.env, page, req.href), '%s: %s' % (name, shorten_line(text)), from_utimestamp(ts), author, shorten_result(text, terms)) # Attachments for result in AttachmentModule(self.env).get_search_results( req, wiki_realm, terms): yield result
def filter_stream(self, req, method, filename, stream, data): """Return a filtered Genshi event stream, or the original unfiltered stream if no match. """ if filename == "ticket.html" and \ ('TICKET_REMINDER_VIEW' in req.perm or 'TICKET_REMINDER_MODIFY' in req.perm or 'TICKET_ADMIN' in req.perm): tags = self._reminder_tags(req, data) if tags: ticket_resource = data['ticket'].resource context = Context.from_request(req, ticket_resource) attachments_data = AttachmentModule( self.env).attachment_data(context) add_stylesheet(req, 'ticketreminder/css/ticketreminder.css') # Will attachments section be displayed? attachments_or_ticket = Transformer( '//div[@id="attachments"]' ) if attachments_data['can_create'] or attachments_data[ 'attachments'] else Transformer('//div[@id="ticket"]') trac_nav = Transformer( '//form[@id="propertyform"]/div[@class="trac-nav"]') return stream | attachments_or_ticket.after( tags) | trac_nav.append(self._reminder_trac_nav(req, data)) return stream
def _render_editor(self, req, db, milestone): data = { 'milestone': milestone, 'ticket': milestone.ticket, 'datefields': self.date_fields, 'date_hint': get_date_format_hint(), 'datetime_hint': get_datetime_format_hint(), 'milestone_groups': [], 'jump_to': req.args.get('jump_to') or referer_module(req) } if milestone.exists: req.perm(milestone.resource).require('MILESTONE_VIEW') milestones = [ m for m in StructuredMilestone.select(self.env, db=db) if m.name != milestone.name and 'MILESTONE_VIEW' in req.perm(m.resource) ] data['milestone_groups'] = group_milestones( milestones, 'TICKET_ADMIN' in req.perm) else: req.perm(milestone.resource).require('MILESTONE_CREATE') TicketModule(self.env)._insert_ticket_data( req, milestone.ticket, data, get_reporter_id(req, 'author'), {}) self._add_tickets_report_data(milestone, req, data) context = Context.from_request(req, milestone.resource) data['attachments'] = AttachmentModule( self.env).attachment_data(context) return 'itteco_milestone_edit.html', data, None
def get_timeline_events(self, req, start, stop, filters): if 'blog' in filters: blog_realm = Resource('blog') if not 'BLOG_VIEW' in req.perm(blog_realm): return add_stylesheet(req, 'tracfullblog/css/fullblog.css') # Blog posts blog_posts = get_blog_posts(self.env, from_dt=start, to_dt=stop, all_versions=True) for name, version, time, author, title, body, category_list \ in blog_posts: bp_resource = blog_realm(id=name, version=version) if 'BLOG_VIEW' not in req.perm(bp_resource): continue bp = BlogPost(self.env, name, version=version) yield ('blog', bp.version_time, bp.version_author, (bp_resource, bp, None)) # Attachments (will be rendered by attachment module) for event in AttachmentModule(self.env).get_timeline_events( req, blog_realm, start, stop): yield event # Blog comments blog_comments = get_blog_comments(self.env, from_dt=start, to_dt=stop) blog_comments = sorted(blog_comments, key=operator.itemgetter(4), reverse=True) for post_name, number, comment, author, time in blog_comments: bp_resource = blog_realm(id=post_name) if 'BLOG_VIEW' not in req.perm(bp_resource): continue bp = BlogPost(self.env, post_name) bc = BlogComment(self.env, post_name, number=number) yield 'blog', time, author, (bp_resource, bp, bc)
def get_search_results(self, req, terms, filters): if not 'milestone' in filters: return db = self.env.get_db_cnx() sql_query, args = search_to_sql(db, ['name', 'description'], terms) cursor = db.cursor() cursor.execute( "SELECT name,due,completed,description " "FROM milestone " "WHERE " + sql_query, args) milestone_realm = Resource('milestone') for name, due, completed, description in cursor: milestone = milestone_realm(id=name) if 'MILESTONE_VIEW' in req.perm(milestone): dt = (completed and from_utimestamp(completed) or due and from_utimestamp(due) or datetime.now(utc)) yield (get_resource_url(self.env, milestone, req.href), get_resource_name(self.env, milestone), dt, '', shorten_result(description, terms)) # Attachments for result in AttachmentModule(self.env).get_search_results( req, milestone_realm, terms): yield result
def test_post_request_exceeding_max_size_raises_exception(self): """TracError is raised for file exceeding max size""" self.env.config.set('attachment', 'max_size', 10) module = AttachmentModule(self.env) path_info = '/attachment/parent_realm/parent_id' with tempfile.NamedTemporaryFile('w+b', dir=self.env.path) as file_: file_.write(b' ' * (module.max_size + 1)) file_.flush() upload = Mock(filename=file_.name, file=file_) req = MockRequest(self.env, path_info=path_info, method='POST', args={'action': 'new', 'attachment': upload}) self.assertTrue(module.match_request(req)) with self.assertRaises(TracError) as cm: module.process_request(req) self.assertEqual("Maximum attachment size: 10 bytes", unicode(cm.exception))
def _delegate_new_request(self, req): attachments = req.args.get('attachment') if not isinstance(attachments, list): attachments = [attachments] mod = AttachmentModule(self.env) for val in attachments: req.args['attachment'] = val try: mod.process_request(req) except OSError, e: if e.args[0] == errno.ENAMETOOLONG: raise TracError(_("File name too long")) if os.name == 'nt' and e.args[0] == errno.ENOENT: raise TracError(_("File name too long")) raise TracError(os.strerror(e.args[0])) except RedirectListened: pass
def test_wiki_link_foreign(self): attachment = Attachment(self.env, 'ticket', 123) attachment.insert('foo.txt', tempfile.TemporaryFile(), 0) ns, func = AttachmentModule(self.env).get_link_resolvers().next() self.assertEqual('attachment', ns) req = Mock(path_info='/wiki') formatter = Formatter(self.env, req) self.assertEqual('<a class="attachment" title="Attachment #123: ' 'foo.txt" href="/trac.cgi/attachment/ticket/123/' 'foo.txt">Foo</a>', func(formatter, ns, 'ticket:123:foo.txt', 'Foo'))
def __init__(self, env, req): max_size = AttachmentModule(env).max_size size = self.__get_content_length(req) self.__verify_size(size, max_size) tempfile = TemporaryFile() try: self.__read_content(req, tempfile, size, max_size) except: tempfile.close() raise self.file = tempfile filename = req.get_header('X-TracDragDrop-Filename') self.filename = unicode_unquote(filename or '').encode('utf-8')
def get_timeline_events(self, req, start, stop, filters): # timeline动作的输入 if 'wiki' in filters: wiki = WikiSystem(self.env) format = req.args.get('format') href = format == 'rss' and req.abs_href or req.href db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "SELECT time,name,comment,author,version " "FROM wiki WHERE time>=%s AND time<=%s", (start, stop)) for t, name, comment, author, version in cursor: title = Markup('<em>%s</em> ' + u"编辑者 %s", wiki.format_page_name(name), author) diff_link = html.A(u'变化', href=href.wiki(name, action='diff', version=version)) if format == 'rss': comment = wiki_to_html(comment or '--', self.env, req, db, absurls=True) else: comment = wiki_to_oneliner(comment, self.env, db, shorten=True) if version > 1: comment = Markup('%s (%s)', comment, diff_link) yield 'wiki', href.wiki(name), title, t, author, comment # Attachments att = AttachmentModule(self.env) for event in att.get_timeline_events(req, db, 'wiki', format, start, stop, lambda id: html.EM(id)): yield event
def test_wiki_link_subpage(self): attachment = Attachment(self.env, 'wiki', 'SomePage/SubPage') attachment.insert('foo.txt', tempfile.TemporaryFile(), 0) ns, func = AttachmentModule(self.env).get_link_resolvers().next() self.assertEqual('attachment', ns) req = Mock(path_info='/wiki/SomePage/SubPage') formatter = Formatter(self.env, req) self.assertEqual( '<a class="attachment" ' 'title="Attachment SomePage/SubPage: foo.txt" ' 'href="/trac.cgi/attachment/wiki/SomePage/SubPage/' 'foo.txt">Foo</a>', func(formatter, ns, 'foo.txt', 'Foo'))
def _render_view(self, req, db, version): db = self.env.get_db_cnx() sql = "SELECT name FROM milestone " \ "INNER JOIN milestone_version ON (name = milestone) " \ "WHERE version = %s " \ "ORDER BY due" cursor = db.cursor() cursor.execute(sql, (version.name,)) milestones = [] tickets = [] milestone_stats = [] for row in cursor: milestone = Milestone(self.env, row[0]) milestones.append(milestone) mtickets = get_tickets_for_milestone(self.env, db, milestone.name, 'owner') mtickets = apply_ticket_permissions(self.env, req, mtickets) tickets += mtickets stat = get_ticket_stats(self.milestone_stats_provider, mtickets) milestone_stats.append(milestone_stats_data(self.env, req, stat, milestone.name)) stats = get_ticket_stats(self.version_stats_provider, tickets) interval_hrefs = version_interval_hrefs(self.env, req, stats, [milestone.name for milestone in milestones]) version.resource = Resource('version', version.name) context = Context.from_request(req, version.resource) version.is_released = version.time and version.time.date() < date.today() version.stats = stats version.interval_hrefs = interval_hrefs version.stats_href = [] # Not implemented yet, see th:#10349 data = { 'context': context, 'version': version, 'attachments': AttachmentModule(self.env).attachment_data(context), 'milestones': milestones, 'milestone_stats': milestone_stats, 'show_milestone_description': self.show_milestone_description # Not implemented yet } add_stylesheet(req, 'extendedversion/css/version.css') add_script(req, 'common/js/folding.js') add_ctxtnav(req, _("Back to Versions"), req.href.versions()) return 'version_view.html', data, None
def _alter_req(self, req): alter = False if req.path_info.startswith('/wiki/'): if not req.perm.has_permission('WIKI_DELETE_SELF') or \ req.perm.has_permission('WIKI_DELETE'): return # Not allowed pagename = req.path_info[6:] or 'WikiStart' page = WikiPage(self.env, pagename, version=1) if not page.exists: return # Sanity check if req.authname == page.author: alter = 'WIKI_DELETE' elif AttachmentModule(self.env).match_request(req): parent_type = req.args.get('type') path = req.args.get('path') if req.args.get('action') == 'new': return # Delete permissions don't matter for this anyway needed_perm = { 'ticket': 'TICKET_DELETE', 'wiki': 'WIKI_DELETE' }[parent_type] if not req.perm.has_permission(needed_perm+'_SELF') or \ req.perm.has_permission(needed_perm): return # Not allowed segments = path.split('/') parent_id = '/'.join(segments[:-1]) last_segment = segments[-1] if len(segments) == 1: return # List view, don't care about this try: attachment = Attachment(self.env, parent_type, parent_id, last_segment) except TracError: return # Sanity check if req.authname == attachment.author: alter = needed_perm if alter: self.log.info( 'SelfDeleteModule: Allowing user %s to delete the resource at %s.', req.authname, req.path_info) req.perm.perms[alter] = True req.hdf['trac.acl.%s' % alter] = '1'
def _render_view(self, req, version): milestones = [] tickets = [] milestone_stats = [] for name, in self.env.db_query( """ SELECT name FROM milestone INNER JOIN milestone_version ON (name = milestone) WHERE version = %s ORDER BY due """, (version.name, )): milestone = Milestone(self.env, name) milestones.append(milestone) mtickets = get_tickets_for_milestone(self.env, milestone.name, 'owner') mtickets = apply_ticket_permissions(self.env, req, mtickets) tickets += mtickets stat = get_ticket_stats(self.milestone_stats_provider, mtickets) milestone_stats.append( milestone_stats_data(self.env, req, stat, milestone.name)) stats = get_ticket_stats(self.version_stats_provider, tickets) interval_hrefs = version_interval_hrefs( self.env, req, stats, [milestone.name for milestone in milestones]) version.resource = Resource('version', version.name) context = web_context(req, version.resource) version.is_released = version.time \ and version.time < datetime.now(utc) version.stats = stats version.interval_hrefs = interval_hrefs names = [milestone.name for milestone in milestones] version.stats_href = version_stats_href(self.env, req, names) data = { 'version': version, 'attachments': AttachmentModule(self.env).attachment_data(context), 'milestones': milestones, 'milestone_stats': milestone_stats, 'show_milestone_description': self.show_milestone_description # Not implemented yet } add_stylesheet(req, 'extendedversion/css/version.css') add_script(req, 'common/js/folding.js') add_ctxtnav(req, _("Back to Versions"), req.href.versions()) return 'version_view.html', data, None
def get_search_results(self, req, terms, filters): """Overriding search results for Tickets""" if not 'ticket' in filters: return ticket_realm = Resource('ticket') with self.env.db_query as db: sql, args = search_to_sql(db, [ 'summary', 'keywords', 'description', 'reporter', 'cc', db.cast('id', 'text') ], terms) sql2, args2 = search_to_sql(db, ['newvalue'], terms) sql3, args3 = search_to_sql(db, ['value'], terms) ticketsystem = TicketSystem(self.env) if req.args.get('product'): productsql = "product='%s' AND" % req.args.get('product') else: productsql = "" for summary, desc, author, type, tid, ts, status, resolution in \ db("""SELECT summary, description, reporter, type, id, time, status, resolution FROM ticket WHERE (%s id IN ( SELECT id FROM ticket WHERE %s UNION SELECT ticket FROM ticket_change WHERE field='comment' AND %s UNION SELECT ticket FROM ticket_custom WHERE %s )) """ % (productsql, sql, sql2, sql3), args + args2 + args3): t = ticket_realm(id=tid) if 'TICKET_VIEW' in req.perm(t): yield (req.href.ticket(tid), tag_("%(title)s: %(message)s", title=tag.span(get_resource_shortname( self.env, t), class_=status), message=ticketsystem.format_summary( summary, status, resolution, type)), from_utimestamp(ts), author, shorten_result(desc, terms)) # Attachments for result in AttachmentModule(self.env) \ .get_search_results(req, ticket_realm, terms): yield result
def process_request(self, req): if req.get_header('X-Requested-With') != 'XMLHttpRequest': req.send('', status=204) cmd = req.args.get('cmd') try: if cmd == 'attachment': req.environ['PATH_INFO'] = req.path_info[len('/overlayview'):] \ .encode('utf-8') template, data, content_type = \ AttachmentModule(self.env).process_request(req) return 'overlayview_attachment.html', data, content_type except RequestDone: raise except (PermissionError, HTTPForbidden), e: self._send_exception(req, e, 403)
def get_timeline_events(self, req, start, stop, filters): if 'build' not in filters: return # Attachments (will be rendered by attachment module) for event in AttachmentModule(self.env).get_timeline_events( req, Resource('build'), start, stop): yield event start = to_timestamp(start) stop = to_timestamp(stop) add_stylesheet(req, 'bitten/bitten.css') db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "SELECT b.id,b.config,c.label,c.path, b.rev,p.name," "b.stopped,b.status FROM bitten_build AS b" " INNER JOIN bitten_config AS c ON (c.name=b.config) " " INNER JOIN bitten_platform AS p ON (p.id=b.platform) " "WHERE b.stopped>=%s AND b.stopped<=%s " "AND b.status IN (%s, %s) ORDER BY b.stopped", (start, stop, Build.SUCCESS, Build.FAILURE)) repos = self.env.get_repository(authname=req.authname) assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 'named "(default)" to Trac.' event_kinds = { Build.SUCCESS: 'successbuild', Build.FAILURE: 'failedbuild' } for id_, config, label, path, rev, platform, stopped, status in cursor: if not _has_permission(req.perm, repos, path, rev=rev): continue errors = [] if status == Build.FAILURE: for step in BuildStep.select(self.env, build=id_, status=BuildStep.FAILURE, db=db): errors += [(step.name, error) for error in step.errors] display_rev = repos.normalize_rev(rev) yield (event_kinds[status], to_datetime(stopped, utc), None, (id_, config, label, display_rev, platform, status, errors))
def get_timeline_events(self, req, start, stop, filters): if 'wiki' in filters: wiki_realm = Resource(self.realm) for ts, name, comment, author, version in self.env.db_query(""" SELECT time, name, comment, author, version FROM wiki WHERE time>=%s AND time<=%s """, (to_utimestamp(start), to_utimestamp(stop))): wiki_page = wiki_realm(id=name, version=version) if 'WIKI_VIEW' not in req.perm(wiki_page): continue yield ('wiki', from_utimestamp(ts), author, (wiki_page, comment)) # Attachments for event in AttachmentModule(self.env).get_timeline_events( req, wiki_realm, start, stop): yield event
def get_timeline_events(self, req, start, stop, filters): if 'milestone' in filters: milestone_realm = Resource(self.realm) for name, due, completed, description \ in MilestoneCache(self.env).milestones.itervalues(): if completed and start <= completed <= stop: # TODO: creation and (later) modifications should also be # reported milestone = milestone_realm(id=name) if 'MILESTONE_VIEW' in req.perm(milestone): yield ('milestone', completed, '', # FIXME: author? (milestone, description)) # Attachments for event in AttachmentModule(self.env).get_timeline_events( req, milestone_realm, start, stop): yield event
def get_timeline_events(self, req, start, stop, filters): if 'milestone' in filters: milestone_realm = Resource('milestone') for completed, name, description in self.env.db_query(""" SELECT completed, name, description FROM milestone WHERE completed>=%s AND completed<=%s """, (to_utimestamp(start), to_utimestamp(stop))): # TODO: creation and (later) modifications should also be # reported milestone = milestone_realm(id=name) if 'MILESTONE_VIEW' in req.perm(milestone): yield ('milestone', from_utimestamp(completed), '', (milestone, description)) # FIXME: author? # Attachments for event in AttachmentModule(self.env).get_timeline_events( req, milestone_realm, start, stop): yield event