def render_timeline_event(self, context, field, event): bp_resource, bp, bc = event[3] compat_format_0_11_2 = 'oneliner' if hasattr(context, '_hints'): compat_format_0_11_2 = None if bc: # A blog comment if field == 'url': return context.href.blog(bp.name) + '#comment-%d' % bc.number elif field == 'title': return tag('Blog: ', tag.em(bp.title), ' comment added') elif field == 'description': comment = compat_format_0_11_2 and shorten_line(bc.comment) \ or bc.comment return format_to(self.env, compat_format_0_11_2, context(resource=bp_resource), comment) else: # A blog post if field == 'url': return context.href.blog(bp.name) elif field == 'title': return tag('Blog: ', tag.em(bp.title), bp.version > 1 and ' edited' or ' created') elif field == 'description': comment = compat_format_0_11_2 and shorten_line(bp.version_comment) \ or bp.version_comment return format_to(self.env, compat_format_0_11_2, context(resource=bp_resource), comment)
def expand_macro(self, formatter, name, content): intertracs = {} for key, value in self.config.options("intertrac"): idx = key.rfind(".") # rsplit only in 2.4 if idx > 0: # 0 itself doesn't help much: .xxx = ... prefix, attribute = key[:idx], key[idx + 1 :] intertrac = intertracs.setdefault(prefix, {}) intertrac[attribute] = value else: intertracs[key] = value # alias if "trac" not in intertracs: intertracs["trac"] = {"title": _("The Trac Project"), "url": "http://trac.edgewall.org"} def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr(tag.td(tag.b(prefix)), tag.td("Alias for ", tag.b(intertrac))) else: url = intertrac.get("url", "") if url: title = intertrac.get("title", url) yield tag.tr(tag.td(tag.a(tag.b(prefix), href=url + "/timeline")), tag.td(tag.a(title, href=url))) return tag.table(class_="wiki intertrac")( tag.tr(tag.th(tag.em("Prefix")), tag.th(tag.em("Trac Site"))), [generate_prefix(p) for p in sorted(intertracs.keys())], )
def format_change(field, oldvalue, newvalue): """Formats tickets changes.""" fieldtag = tag.strong(field) if field == "cc": oldvalues = set(oldvalue and oldvalue.split(", ") or []) newvalues = set(newvalue and newvalue.split(", ") or []) added = newvalues.difference(oldvalues) removed = oldvalues.difference(newvalues) strng = fieldtag if added: strng += tag(" ", tag.em(", ".join(added)), " added") if removed: if added: strng += tag(", ") strng += tag(" ", tag.em(", ".join(removed)), " removed") return strng elif field == "description": return fieldtag + tag( " modified (", tag.a("diff", href=href("ticket", id, action="diff", version=self.commentnum)), ")", ) elif field == "comment": self.commentnum = oldvalue self.comment = newvalue return tag("") elif not oldvalue: return fieldtag + tag(" ", tag.em(newvalue), " added") elif not newvalue: return fieldtag + tag(" ", tag.em(oldvalue), " deleted") else: return fieldtag + tag(" changed from ", tag.em(oldvalue), " to ", tag.em(newvalue))
def expand_macro(self, formatter, name, content): intertracs = {} for key, value in self.intertrac_section.options(): idx = key.rfind('.') if idx > 0: # 0 itself doesn't help much: .xxx = ... prefix, attribute = key[:idx], key[idx+1:] intertrac = intertracs.setdefault(prefix, {}) intertrac[attribute] = value else: intertracs[key] = value # alias if 'trac' not in intertracs: intertracs['trac'] = {'title': _('The Trac Project'), 'url': 'http://trac.edgewall.org'} def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr(tag.td(tag.b(prefix)), tag.td('Alias for ', tag.b(intertrac))) else: url = intertrac.get('url', '') if url: title = intertrac.get('title', url) yield tag.tr(tag.td(tag.a(tag.b(prefix), href=url + '/timeline')), tag.td(tag.a(title, href=url))) return tag.table(class_="wiki intertrac")( tag.tr(tag.th(tag.em('Prefix')), tag.th(tag.em('Trac Site'))), [generate_prefix(p) for p in sorted(intertracs.keys())])
def expand_macro(self, formatter, name, content): intertracs = {} for key, value in self.config.options('intertrac'): idx = key.rfind('.') # rsplit only in 2.4 if idx > 0: # 0 itself doesn't help much: .xxx = ... prefix, attribute = key[:idx], key[idx+1:] intertrac = intertracs.setdefault(prefix, {}) intertrac[attribute] = value else: intertracs[key] = value # alias def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr(tag.td(tag.b(prefix)), tag.td('Alias for ', tag.b(intertrac))) else: url = intertrac.get('url', '') if url: title = intertrac.get('title', url) yield tag.tr(tag.td(tag.a(tag.b(prefix), href=url + '/timeline')), tag.td(tag.a(title, href=url))) return tag.table(class_="wiki intertrac")( tag.tr(tag.th(tag.em('Prefix')), tag.th(tag.em('Trac Site'))), [generate_prefix(p) for p in sorted(intertracs.keys())])
def render_timeline_event(self, context, field, event): #self.log.debug("Monit: render_timeline_event() called") evt, srv, monit = event[3] if field == 'url': return context.href.monit('event', evt['id']) elif field == 'title': return tag(tag.em('New ', srv_types.get(evt['type'], ''), ' event')) elif field == 'description': if srv and monit: markup = tag.div('Event on ', tag.b(monit['localhostname']), ' for service ', tag.b(srv['name']), '(type %s) ' % srv_types.get(evt['type'], ''), tag.em(evt['message'])) self.log.debug("Monit markup for Timeline -> %s" % str(markup)) elif srv: markup = tag.div('Event on ', tag.b('unknown'), ' for service ', tag.b(srv['name']), '(type %s) ' % srv_types.get(evt['type'], ''), tag.em(evt['message'])) else: markup = tag.div('Event on ', tag.b('unknown'), ' for service ', tag.b('unknown'), '(type unknown)', tag.em(evt['message'])) self.log.debug("Monit markup for Timeline -> %s" % str(markup)) return markup
def expand_macro(self, formatter, name, content): interwikis = [] for k in sorted(self.keys()): prefix, url, title = self[k] interwikis.append({ 'prefix': prefix, 'url': url, 'title': title, 'rc_url': self._expand_or_append(url, ['RecentChanges']), 'description': url if title == prefix else title }) return tag.table( tag.tr(tag.th(tag.em(_("Prefix"))), tag.th(tag.em(_("Site")))), [ tag.tr( tag.td(tag.a(w['prefix'], href=w['rc_url'])), tag.td(tag.a(w['description'], href=w['url']))) for w in interwikis ], class_="wiki interwiki")
def post_process_request(self, req, template, data, content_type): if req.path_info.startswith('/ticket/'): # In case of an invalid ticket, the data is invalid if not data: return template, data, content_type tkt = data['ticket'] links = TicketLinks(self.env, tkt) for i in links.blocked_by: if Ticket(self.env, i)['status'] != 'closed': add_script(req, 'mastertickets/disable_resolve.js') break # Add link to depgraph if needed if links: add_ctxtnav(req, 'Depgraph', req.href.depgraph(tkt.id)) for change in data.get('changes', {}): if not change.has_key('fields'): continue for field, field_data in change['fields'].iteritems(): if field in self.fields: if field_data['new'].strip(): new = set([int(n) for n in field_data['new'].split(',')]) else: new = set() if field_data['old'].strip(): old = set([int(n) for n in field_data['old'].split(',')]) else: old = set() add = new - old sub = old - new elms = tag() if add: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(add)])) ) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(sub)])) ) elms.append(u' removed') field_data['rendered'] = elms #add a link to generate a dependency graph for all the tickets in the milestone if req.path_info.startswith('/milestone/'): if not data: return template, data, content_type milestone=data['milestone'] add_ctxtnav(req, 'Depgraph', req.href.depgraph('milestone', milestone.name)) return template, data, content_type
def expand_macro(self, formatter, names, content): if not content: edit = '' text = "''Gringlet Name Missing''" acl = '' elif not re.match(r'^[a-zA-Z0-9]+$', content): edit = '' text = tag.em("Invalid Gringlet Name - only letters and numbers allowed") acl = '' else: db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute('SELECT text,acl FROM gringotts WHERE name=%s AND version=' '(SELECT MAX(version) FROM gringotts WHERE name=%s)', (content, content)) try: text,acl = cursor.fetchone() key = str(self.config.get('gringotts', 'key')) k = ezPyCrypto.key(key) text = wiki_to_html(k.decStringFromAscii(text), self.env, formatter.req) edit = 'Edit' except: edit = 'Create' text = tag.em("No Gringlet called \"%s\" found" % content) acl = '' if acl: if not validate_acl(formatter.req, acl): text = tag.em("You do not have permission to view the \"%s\" Gringlet." % content) edit = '' control = None if edit: control = tag.div(tag.a(edit, href=(formatter.href.gringotts() + "/" + content + "?action=edit")), class_="gringottcontrol") # Use eight divs for flexible frame styling return tag.div( tag.div( tag.div( tag.div( tag.div( tag.div( tag.div( tag.div( tag.div(text, class_="gringottcontent") + control, class_="gringott"), class_="gringott"), class_="gringott"), class_="gringott"), class_="gringott"), class_="gringott"), class_="gringott"), class_="gringottframe")
def post_process_request(self, req, template, data, content_type): if req.path_info.startswith('/ticket/'): # In case of an invalid ticket, the data is invalid if not data: return template, data, content_type tkt = data['ticket'] self.pm.check_component_enabled(self, pid=tkt.pid) links = TicketLinks(self.env, tkt) # Add link to depgraph if needed if links: add_ctxtnav(req, _('Depgraph'), req.href.depgraph(get_resource_url(self.env, tkt.resource))) for change in data.get('changes', {}): if not change.has_key('fields'): continue for field, field_data in change['fields'].iteritems(): if field in self.fields: vals = {} for i in ('new', 'old'): if isinstance(field_data[i], basestring): val = field_data[i].strip() else: val = '' if val: vals[i] = set([int(n) for n in val.split(',')]) else: vals[i] = set() add = vals['new'] - vals['old'] sub = vals['old'] - vals['new'] elms = tag() if add: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(add)])) ) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(sub)])) ) elms.append(u' removed') field_data['rendered'] = elms #add a link to generate a dependency graph for all the tickets in the milestone if req.path_info.startswith('/milestone/'): if not data or not 'milestone' in data: return template, data, content_type milestone=data['milestone'] self.pm.check_component_enabled(self, pid=milestone.pid) add_ctxtnav(req, _('Depgraph'), req.href.depgraph(get_resource_url(self.env, milestone.resource))) return template, data, content_type
def render_timeline_event(self, context, field, event): (start, sprint) = event[3] if field == 'url': return context.href.sprint(sprint.name) elif field == 'title': if start: return tag('Sprint ', tag.em(sprint.name), ' started') return tag('Sprint ', tag.em(sprint.name), ' finished') elif field == 'description': return format_to(self.env, None, context(resource=sprint), sprint.description)
def render_timeline_event(self, context, field, event): attachment, descr = event[3] if field == 'url': return self.get_resource_url(attachment, context.href) elif field == 'title': name = get_resource_name(self.env, attachment.parent) title = get_resource_summary(self.env, attachment.parent) return tag(tag.em(os.path.basename(attachment.id)), _(" attached to "), tag.em(name, title=title)) elif field == 'description': return format_to(self.env, None, context(attachment.parent), descr)
def render_timeline_event(self, context, field, event): attachment, descr = event[3] if field == 'url': return self.get_resource_url(attachment, context.href) elif field == 'title': name = get_resource_name(self.env, attachment.parent) title = get_resource_summary(self.env, attachment.parent) return tag_("%(attachment)s attached to %(resource)s", attachment=tag.em(os.path.basename(attachment.id)), resource=tag.em(name, title=title)) elif field == 'description': return format_to(self.env, None, context.child(attachment.parent), descr)
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) page = kw.get('page', '') sort = kw.get('sort', 'DESC') order = kw.get('order', 'time') self.env.log.error('sort %s, order %s' % (sort, order)) attachment_type = "" wiki_path = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] db = self.env.get_db_cnx() if db == None: return "No DB connection" attachmentFormattedList="" cursor = db.cursor() if attachment_type == None or attachment_type == "": cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment") elif page == None or page == "": cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s ORDER " "BY " + order + " " + sort, (attachment_type,)) else: cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s and " "id=%s ORDER BY " + order + " " + sort, (attachment_type, page)) formatters={"wiki": formatter.href.wiki, "ticket": formatter.href.ticket} types={"wiki": "", "ticket": "ticket "} return tag.ul( [tag.li( tag.a(filename, href=formatter.href.attachment(type + "/" + id + "/" + filename)), " (", tag.span(pretty_size(size), title=size), ") - ", tag.em(format_datetime(time)), " - added by ", tag.em(author), " to ", tag.a(types[type] + " " + id, href=formatters[type](id)), " ") for type,id,filename,size,time,description,author,ipnr in cursor]) return attachmentFormattedList
def render_tag_changes(old_tags, new_tags): old_tags = split_into_tags(old_tags or '') new_tags = split_into_tags(new_tags or '') added = sorted(new_tags - old_tags) added = added and \ tagn_("%(tags)s added", "%(tags)s added", len(added), tags=builder.em(', '.join(added))) removed = sorted(old_tags - new_tags) removed = removed and \ tagn_("%(tags)s removed", "%(tags)s removed", len(removed), tags=builder.em(', '.join(removed))) # TRANSLATOR: How to delimit added and removed tags. delim = added and removed and _("; ") return builder(builder.strong(_("Tags")), ' ', added, delim, removed)
def post_process_request(self, req, template, data, content_type): if req.path_info.startswith('/ticket/'): tkt = data['ticket'] links = TicketLinks(self.env, tkt) for i in links.blocked_by: if Ticket(self.env, i)['status'] != 'closed': add_script(req, 'mastertickets/disable_resolve.js') break data['mastertickets'] = { 'field_values': { 'blocking': linkify_ids(self.env, req, links.blocking), 'blockedby': linkify_ids(self.env, req, links.blocked_by), }, } # Add link to depgraph if needed if links: add_ctxtnav(req, 'Depgraph', req.href.depgraph(tkt.id)) for change in data.get('changes', []): for field, field_data in change['fields'].iteritems(): if field in self.fields: if field_data['new'].strip(): new = set([int(n) for n in field_data['new'].split(',')]) else: new = set() if field_data['old'].strip(): old = set([int(n) for n in field_data['old'].split(',')]) else: old = set() add = new - old sub = old - new elms = tag() if add: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(add)])) ) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(sub)])) ) elms.append(u' removed') field_data['rendered'] = elms return template, data, content_type
def _format_reminder(self, req, ticket, id, time, author, origin, description, delete_button=True): now = to_datetime(None) time = to_datetime(time) if now >= time: when = tag(tag.strong("Right now"), " (pending)") else: when = tag("In ", tag.strong(pretty_timedelta(time)), " (", format_date(time), ")") if description: context = Context.from_request(req, ticket.resource) desc = tag.div(format_to_oneliner(self.env, context, description), class_="description") else: desc = tag() return tag( self._reminder_delete_form(req, id) if delete_button else None, when, " - added by ", tag.em(Chrome(self.env).authorinfo(req, author)), " ", tag.span(pretty_timedelta(origin), title=format_datetime( origin, req.session.get('datefmt', 'iso8601'), req.tz)), " ago.", desc)
def _check_quickjump(self, req, kwd): """Look for search shortcuts""" noquickjump = as_int(req.args.get('noquickjump'), 0) # Source quickjump FIXME: delegate to ISearchSource.search_quickjump quickjump_href = None if kwd[0] == '/': quickjump_href = req.href.browser(kwd) name = kwd description = _('Browse repository path %(path)s', path=kwd) else: context = web_context(req, 'search') link = find_element(extract_link(self.env, context, kwd), 'href') if link is not None: quickjump_href = link.attrib.get('href') name = link.children description = link.attrib.get('title', '') if quickjump_href: # Only automatically redirect to local quickjump links if not quickjump_href.startswith(req.base_path or '/'): noquickjump = True if noquickjump: return { 'href': quickjump_href, 'name': tag.em(name), 'description': description } else: req.redirect(quickjump_href)
def _render_source(self, context, stream, annotations, marks=None): from trac.web.chrome import add_warning annotators, labels, titles = {}, {}, {} for annotator in self.annotators: atype, alabel, atitle = annotator.get_annotation_type() if atype in annotations: labels[atype] = alabel titles[atype] = atitle annotators[atype] = annotator annotations = [a for a in annotations if a in annotators] if isinstance(stream, list): stream = HTMLParser(StringIO(u'\n'.join(stream))) elif isinstance(stream, unicode): text = stream def linesplitter(): for line in text.splitlines(True): yield TEXT, line, (None, -1, -1) stream = linesplitter() annotator_datas = [] for a in annotations: annotator = annotators[a] try: data = (annotator, annotator.get_annotation_data(context)) except TracError, e: self.log.warning("Can't use annotator '%s': %s", a, e.message) add_warning(context.req, tag.strong( tag_("Can't use %(annotator)s annotator: %(error)s", annotator=tag.em(a), error=tag.pre(e.message)))) data = (None, None) annotator_datas.append(data)
def _render_ticket_event(self, field, context): if (field == 'url'): self._read_idx += 1 #next index now #call the original render function output = self._old_render_fn[self._read_idx](field, context) if field == 'title': #now it's time to insert the project name #split the whole string until we can insert splitted_output = to_unicode(output).split("</em>") tooltip = splitted_output[0].split('\"') ticket_no = splitted_output[0].split('>') if len(tooltip) == 3: #it's a ticket #now rebuild the puzzle by inserting the name output = tag( 'Ticket' + ' ', tag.em(ticket_no[1], title=tooltip[1]), ' ', tag.span(self._current_project[self._read_idx], style="background-color: #ffffd0;"), splitted_output[1]) elif len(tooltip) == 1 and len( splitted_output) == 3: #it's an attachment output += tag( ' ', tag.span(self._current_project[self._read_idx], style="background-color: #ffffd0;")) return output
def render_timeline_event(self, context, field, event): if field=='url': return None elif field=='title': return tag.em(event[3]) elif field=='description': return event[3]
def expand_macro(self, formatter, name, content): attachment_type = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] db = self.env.get_db_cnx() if db == None: return "No DB connection" attachmentFormattedList="" cursor = db.cursor() if attachment_type == None or attachment_type == "": cursor.execute("SELECT type,id,filename,size,time," "description,author,ipnr FROM attachment") else: cursor.execute("SELECT type,id,filename,size,time," "description,author,ipnr FROM attachment " "WHERE type=%s", (attachment_type, )) formatters={"wiki": formatter.href.wiki, "ticket": formatter.href.ticket} types={"wiki": "", "ticket": "ticket "} return tag.ul( [tag.li( tag.a(filename, href=formatter.href.attachment(type + "/" + id + "/" + filename)), " (", tag.span(pretty_size(size), title=size), ") - added by ", tag.em(author), " to ", tag.a(types[type] + " " + id, href=formatters[type](id)), " ") for type,id,filename,size,time,description,author,ipnr in cursor if self._has_perm(type, id, filename, formatter.context)]) return attachmentFormattedList
def expand_macro(self, formatter, name, content): interwikis = [] for k in sorted(self.keys()): prefix, url, title = self[k] interwikis.append({ 'prefix': prefix, 'url': url, 'title': title, 'rc_url': self._expand_or_append(url, ['RecentChanges']), 'description': url if title == prefix else title}) return tag.table(tag.tr(tag.th(tag.em(_("Prefix"))), tag.th(tag.em(_("Site")))), [tag.tr(tag.td(tag.a(w['prefix'], href=w['rc_url'])), tag.td(tag.a(w['description'], href=w['url']))) for w in interwikis ], class_="wiki interwiki")
def render_timeline_event(self, context, field, event): url, title, desc = event[3] if field == 'url': return url elif field == 'title': return tag_('%(page)s created', page=tag.em(title)) elif field == 'description': return tag(desc)
def mozillate(fmt, match, fullmatch): expr = match[1:-1] if match[0] == '*': return tag.strong(expr) elif match[0] == '/': return tag.em(expr) else: return tag.span(expr, class_='underline')
class MacroListMacro(WikiMacroBase): _domain = 'messages' _description = cleandoc_( """Display a list of all installed Wiki macros, including documentation if available. Optionally, the name of a specific macro can be provided as an argument. In that case, only the documentation for that macro will be rendered. Note that this macro will not be able to display the documentation of macros if the `PythonOptimize` option is enabled for mod_python! """) def expand_macro(self, formatter, name, content): from trac.wiki.formatter import system_message content = content.strip() if content else '' name_filter = content.strip('*') def get_macro_descr(): for macro_provider in formatter.wiki.macro_providers: names = list(macro_provider.get_macros() or []) if name_filter and not any(name.startswith(name_filter) for name in names): continue try: name_descriptions = [ (name, macro_provider.get_macro_description(name)) for name in names] except Exception, e: yield system_message( _("Error: Can't get description for macro %(name)s", name=names[0]), e), names else: for descr, pairs in groupby(name_descriptions, key=lambda p: p[1]): if descr: if isinstance(descr, (tuple, list)): descr = dgettext(descr[0], descr[1]) else: descr = to_unicode(descr) or '' if content == '*': descr = format_to_oneliner( self.env, formatter.context, descr, shorten=True) else: descr = format_to_html( self.env, formatter.context, descr) yield descr, [name for name, descr in pairs] return tag.div(class_='trac-macrolist')( (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]), len(names) > 1 and tag.p(tag.strong(_("Aliases:")), [tag.code(' [[', alias, ']]') for alias in names[1:]]) or None, description or tag.em(_("Sorry, no documentation found"))) for description, names in sorted(get_macro_descr(), key=lambda item: item[1][0]))
def _render_source(self, context, stream, annotations): from trac.web.chrome import add_warning annotators, labels, titles = {}, {}, {} for annotator in self.annotators: atype, alabel, atitle = annotator.get_annotation_type() if atype in annotations: labels[atype] = alabel titles[atype] = atitle annotators[atype] = annotator annotations = [a for a in annotations if a in annotators] if isinstance(stream, list): stream = HTMLParser(StringIO(u'\n'.join(stream))) elif isinstance(stream, unicode): text = stream def linesplitter(): for line in text.splitlines(True): yield TEXT, line, (None, -1, -1) stream = linesplitter() annotator_datas = [] for a in annotations: annotator = annotators[a] try: data = (annotator, annotator.get_annotation_data(context)) except TracError as e: self.log.warning("Can't use annotator '%s': %s", a, e.message) add_warning( context.req, tag.strong( tag_("Can't use %(annotator)s annotator: %(error)s", annotator=tag.em(a), error=tag.pre(e.message)))) data = (None, None) annotator_datas.append(data) def _head_row(): return tag.tr([ tag.th(labels[a], class_=a, title=titles[a]) for a in annotations ] + [tag.th(u'\xa0', class_='content')]) def _body_rows(): for idx, line in enumerate(_group_lines(stream)): row = tag.tr() for annotator, data in annotator_datas: if annotator: annotator.annotate_row(context, row, idx + 1, line, data) else: row.append(tag.td()) row.append(tag.td(line)) yield row return tag.table(class_='code')(tag.thead(_head_row()), tag.tbody(_body_rows()))
def render_property_diff(self, req, ticket, field, old, new, resource_new=None): "Version for Trac 0.11" rendered = None # per type special rendering of diffs type_ = None for f in ticket.fields: if f['name'] == field: type_ = f['type'] break if type_ == 'checkbox': rendered = new == '1' and "set" or "unset" elif type_ == 'textarea': if not resource_new: rendered = _('modified') else: href = get_resource_url(self.env, resource_new, req.href, action='diff') rendered = tag('modified (', tag.a('diff', href=href), ')') # per name special rendering of diffs old_list, new_list = None, None render_elt = lambda x: x sep = ', ' if field == 'cc': chrome = Chrome(self.env) old_list, new_list = chrome.cc_list(old), chrome.cc_list(new) if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource_new or ticket.resource)): render_elt = obfuscate_email_address elif field == 'keywords': old_list, new_list = (old or '').split(), new.split() sep = ' ' if (old_list, new_list) != (None, None): added = [tag.em(render_elt(x)) for x in new_list if x not in old_list] remvd = [tag.em(render_elt(x)) for x in old_list if x not in new_list] added = added and tag(separated(added, sep), " added") remvd = remvd and tag(separated(remvd, sep), " removed") if added or remvd: rendered = tag(added, added and remvd and '; ', remvd) return rendered if field in ('reporter', 'owner'): if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource_new or ticket.resource)): old = obfuscate_email_address(old) new = obfuscate_email_address(new) # Added by MS if field == 'attachment': rendered = tag(tag.em(new), " added") # changed 'if' to 'elif': elif old and not new: rendered = tag(tag.em(old), " deleted") elif new and not old: rendered = tag("set to ", tag.em(new)) elif old and new: rendered = tag("changed from ", tag.em(old), " to ", tag.em(new)) return rendered
def render_timeline_event(self, context, field, event): name, url, result, message, started, completed = event[3] if field == 'title': return tag('Build "', tag.em(name), '" (%s)' % result.lower()) elif field == 'description': return "%s duration %s" % \ (message, pretty_timedelta(started, completed)) elif field == 'url': return url
def render_property(self, name, mode, context, props): repos, value = props[name] try: return unicode(value) except UnicodeDecodeError: if len(value) <= 100: return tag.tt(''.join(("%02x" % ord(c)) for c in value)) else: return tag.em(_("(binary, size greater than 100 bytes)"))
def render_timeline_event(self, context, field, event): codereview_page, name, notes, reviewersList = event[3] if field == 'url': return context.href.peerReviewView(Review=codereview_page.id) if field == 'title': return tag('Code review ', tag.em(name), ' has been raised') if field == 'description': return tag('Assigned to: ', reviewersList, tag.br(), ' Additional notes: ', notes)
def render_timeline_event(self, context, field, event): milestone, verb, status, description, comment = event[3] if field == 'url': return context.href.milestone(milestone.id) elif field == 'title': return tag('Milestone ', tag.em(milestone.id), ' ', verb) elif field == 'description': return format_to(self.env, None, context(resource=milestone), status == 'comment' and comment or description)
def render_timeline_event(self, context, field, event): resource = event[3][0] if field == 'url': return get_resource_url(self.env, resource, context.href) elif field == 'title': name = builder.em(get_resource_name(self.env, resource)) return tag_("Tag change on %(resource)s", resource=name) elif field == 'description': return render_tag_changes(event[3][1], event[3][2])
def render_timeline_event(self, context, field, event): milestone, verb, status, description, comment = event[3] if field == 'url': return context.href.milestone(milestone.id) elif field == 'title': return tag('Milestone ', tag.em(milestone.id), ' ', verb) elif field == 'description': return format_to(self.env, None, context(resource=milestone), status=='comment' and comment or description)
def render_timeline_event(self, context, field, event): milestone, description = event[3] if field == 'url': return context.href.milestone(milestone.id) elif field == 'title': return tag('Milestone ', tag.em(milestone.id), ' completed') elif field == 'description': return format_to(self.env, None, context(resource=milestone), description)
def render_timeline_event(self, context, field, event): ev = event[3] if field=='title': return tag(tag.em(ev[0]), ' found on ', ev[1]) elif field=='description': return format_to_html(self.env, context, ev[3]) elif field=='url': return ev[2]
def post_process_request(self, req, template, data, content_type): if req.path_info.startswith('/ticket/'): # In case of an invalid ticket, the data is invalid if not data: return template, data, content_type tkt = data['ticket'] links = TicketLinks(self.env, tkt) for i in links.blocked_by: if Ticket(self.env, i)['status'] != 'closed': add_script(req, 'ticketrelations/disable_resolve.js') break for change in data.get('changes', {}): if not change.has_key('fields'): continue for field, field_data in change['fields'].iteritems(): if field in self.fields: if field_data['new'].strip(): new = extract_ticket_ids(field_data['new']) else: new = set() if field_data['old'].strip(): old = extract_ticket_ids(field_data['old']) else: old = set() add = new - old sub = old - new elms = tag() if add: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(add)])) ) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( tag.em(u', '.join([unicode(n) for n in sorted(sub)])) ) elms.append(u' removed') field_data['rendered'] = elms return template, data, content_type
def render_timeline_event(self, context, field, event): milestone, description = event[3] if field == 'url': return context.href.milestone(milestone.id) elif field == 'title': return tag_('Milestone %(name)s completed', name=tag.em(milestone.id)) elif field == 'description': return format_to(self.env, None, context.child(resource=milestone), description)
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description = event[3] # Return apropriate content. if field == 'url': return context.href.screenshots(id) elif field == 'title': return tag('New screenshot ', tag.em(name), ' created') elif field == 'description': return tag('%s' % (description, ))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description = event[3] # Return apropriate content. if field == 'url': return context.href.screenshots(id) elif field == 'title': return tag('New screenshot ', tag.em(name), ' created') elif field == 'description': return tag('%s' % (description,))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description, size = event[3] # Return apropriate content. if field == 'url': return context.req.href.downloads(id) elif field == 'title': return tag('New download ', tag.em(name), ' created') elif field == 'description': return tag('(%s) ' % (pretty_size(size), ), format_to_oneliner(self.env, context, description))
def validate(self, relation): rls = RelationsSystem(self.env) existing_relations = \ rls._select_relations(resource_type=relation.type, destination=relation.destination) if existing_relations: raise ValidationError( tag_("Another resource is already related to %(destination)s " "with %(relation)s relation.", destination=tag.em(relation.destination), relation=tag.b(self.render_relation_type(relation.type))) )
def _render_change(old, new): rendered = None if old and not new: rendered = tag( Markup(_("%(value)s reset to default value", value=tag.em(old)))) elif new and not old: rendered = tag( Markup(_("from default value set to %(value)s", value=tag.em(new)))) elif old and new: if len(old) < 20 and len(new) < 20: rendered = tag( Markup( _("changed from %(old)s to %(new)s", old=tag.em(old), new=tag.em(new)))) else: nbsp = tag.br() # TRANSLATOR: same as before, but with additional line breaks rendered = tag( Markup( _("changed from %(old)s to %(new)s", old=tag.em(nbsp, old), new=tag.em(nbsp, new)))) return rendered
def expand_macro(self, formatter, name, content): from trac.wiki.formatter import system_message content = content.strip() if content else '' name_filter = content.strip('*') def get_macro_descr(): for macro_provider in formatter.wiki.macro_providers: names = list(macro_provider.get_macros() or []) if name_filter and not any( name.startswith(name_filter) for name in names): continue try: name_descriptions = [ (name, macro_provider.get_macro_description(name)) for name in names ] except Exception as e: yield system_message( _("Error: Can't get description for macro %(name)s", name=names[0]), e), names else: for descr, pairs in groupby(name_descriptions, key=lambda p: p[1]): if descr: if isinstance(descr, (tuple, list)): descr = dgettext(descr[0], to_unicode(descr[1])) \ if descr[1] else '' else: descr = to_unicode(descr) or '' if content == '*': descr = format_to_oneliner(self.env, formatter.context, descr, shorten=True) else: descr = format_to_html(self.env, formatter.context, descr) yield descr, [name for name, descr in pairs] return tag.div(class_='trac-macrolist')( (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]), len(names) > 1 and tag.p( tag.strong(_("Aliases:")), [tag.code(' [[', alias, ']]') for alias in names[1:]]) or None, description or tag.em(_("Sorry, no documentation found"))) for description, names in sorted(get_macro_descr(), key=lambda item: item[1][0]))
def render_timeline_event(self, context, field, event): # Decompose event data. id = event[3] # Return apropriate content. resource = Resource('downloads', id) if field == 'url': if context.req.perm.has_permission('DOWNLOADS_VIEW', resource): return get_resource_url(self.env, resource, context.req.href) else: return '#' elif field == 'title': return tag('New download ', tag.em(get_resource_name(self.env, resource)), ' created') elif field == 'description': return get_resource_description(self.env, resource, 'summary')
def expand_macro(self, formatter, name, content): intertracs = {} for key, value in self.intertrac_section.options(): idx = key.rfind('.') if idx > 0: # 0 itself doesn't help much: .xxx = ... prefix, attribute = key[:idx], key[idx + 1:] intertrac = intertracs.setdefault(prefix, {}) intertrac[attribute] = value else: intertracs[key] = value # alias if 'trac' not in intertracs: intertracs['trac'] = { 'title': _('The Trac Project'), 'url': 'http://trac.edgewall.org' } def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr( tag.td(tag.strong(prefix)), tag.td( tag_("Alias for %(name)s", name=tag.strong(intertrac)))) else: url = intertrac.get('url', '') if url: title = intertrac.get('title', url) yield tag.tr( tag.td( tag.a(tag.strong(prefix), href=url + '/timeline')), tag.td(tag.a(title, href=url))) return tag.table(class_="wiki intertrac")( tag.tr(tag.th(tag.em(_("Prefix"))), tag.th(tag.em(_("Trac Site")))), [generate_prefix(p) for p in sorted(intertracs.keys())])
def _post_process_request_history(self, req, data): history = [] page_histories = data.get('history', []) resource = data['resource'] tags_histories = tag_changes(self.env, resource) for page_history in page_histories: while tags_histories and \ tags_histories[0][0] >= page_history['date']: tags_history = tags_histories.pop(0) date = tags_history[0] author = tags_history[1] old_tags = split_into_tags(tags_history[2] or '') new_tags = split_into_tags(tags_history[3] or '') added = sorted(new_tags - old_tags) added = added and \ tagn_("%(tags)s added", "%(tags)s added", len(added), tags=tag.em(', '.join(added))) removed = sorted(old_tags - new_tags) removed = removed and \ tagn_("%(tags)s removed", "%(tags)s removed", len(removed), tags=tag.em(', '.join(removed))) # TRANSLATOR: How to delimit added and removed tags. delim = added and removed and _("; ") comment = tag(tag.strong(_("Tags")), ' ', added, delim, removed) url = req.href(resource.realm, resource.id, version=page_history['version'], tags_version=to_utimestamp(date)) history.append({'version': '*', 'url': url, 'date': date, 'author': author, 'comment': comment, 'ipnr': ''}) history.append(page_history) data.update(dict(history=history, wiki_to_oneliner=self._wiki_to_oneliner))
def render_timeline_event(self, context, field, event): wiki_page, comment = event[3] if field == 'url': return context.href.wiki(wiki_page.id, version=wiki_page.version) elif field == 'title': name = tag.em(get_resource_name(self.env, wiki_page)) if wiki_page.version > 1: return tag_('%(page)s edited', page=name) else: return tag_('%(page)s created', page=name) elif field == 'description': markup = format_to(self.env, None, context.child(resource=wiki_page), comment) if wiki_page.version > 1: diff_href = context.href.wiki( wiki_page.id, version=wiki_page.version, action='diff') markup = tag(markup, ' (', tag.a(_('diff'), href=diff_href), ')') return markup
def render_timeline_event(self, context, field, event): id_, config, label, rev, platform, status, errors = event[3] if field == 'url': return context.href.build(config, id_) elif field == 'title': return tag('Build of ', tag.em('%s [%s]' % (label, rev)), ' on %s %s' % (platform, _status_label[status])) elif field == 'description': message = '' if context.req.args.get('format') == 'rss': if errors: buf = StringIO() prev_step = None for step, error in errors: if step != prev_step: if prev_step is not None: buf.write('</ul>') buf.write('<p>Step %s failed:</p><ul>' \ % escape(step)) prev_step = step buf.write('<li>%s</li>' % escape(error)) buf.write('</ul>') message = Markup(buf.getvalue()) else: if errors: steps = [] for step, error in errors: if step not in steps: steps.append(step) steps = [Markup('<em>%s</em>') % step for step in steps] if len(steps) < 2: message = steps[0] elif len(steps) == 2: message = Markup(' and ').join(steps) elif len(steps) > 2: message = Markup(', ').join(steps[:-1]) + ', and ' + \ steps[-1] message = Markup('Step%s %s failed') % ( len(steps) != 1 and 's' or '', message) return message
def _generate_attachmentflags_fieldset(self, readonly=True, current_flags=None, form=False): fields = Fragment() for flag in self.known_flags: flagid = 'flag_' + flag if current_flags and flag in current_flags: date = datetime.datetime.fromtimestamp( current_flags[flag]["updated_on"], utc) text = tag.span( tag.strong(flag), " set by ", tag.em(current_flags[flag]["updated_by"]), ", ", tag.span(pretty_timedelta(date), title=format_datetime(date)), " ago") if readonly == True: fields += tag.input(text, \ type='checkbox', id=flagid, \ name=flagid, checked="checked", disabled="true") + tag.br() else: fields += tag.input(text, \ type='checkbox', id=flagid, \ name=flagid, checked="checked") + tag.br() else: if readonly == True: fields += tag.input(flag, \ type='checkbox', id=flagid, \ name=flagid, disabled="true") + tag.br() else: fields += tag.input(flag, \ type='checkbox', id=flagid, \ name=flagid) + tag.br() if form and not readonly: return tag.form(tag.fieldset( tag.legend("Attachment Flags") + fields, tag.input(type="hidden", name="action", value="update_flags"), tag.input(type="submit", value="Update flags")), method="POST") return tag.fieldset(tag.legend("Attachment Flags") + fields)
def format_change(field, oldvalue, newvalue): """Formats tickets changes.""" fieldtag = tag.strong(field) if field == 'cc': oldvalues = set(oldvalue and oldvalue.split(', ') or []) newvalues = set(newvalue and newvalue.split(', ') or []) added = newvalues.difference(oldvalues) removed = oldvalues.difference(newvalues) strng = fieldtag if added: strng += tag(" ", tag.em(', '.join(added)), " added") if removed: if added: strng += tag(', ') strng += tag(" ", tag.em(', '.join(removed)), " removed") return strng elif field == 'description': return fieldtag + tag( " modified (", tag.a("diff", href=href('ticket', id, action='diff', version=self.commentnum)), ")") elif field == 'comment': self.commentnum = oldvalue self.comment = newvalue return tag("") elif not oldvalue: return fieldtag + tag(" ", tag.em(newvalue), " added") elif not newvalue: return fieldtag + tag(" ", tag.em(oldvalue), " deleted") else: return fieldtag + tag(" changed from ", tag.em(oldvalue), " to ", tag.em(newvalue))
def render_timeline_event(self, context, field, event): p_id, p_title = event[3] if field == 'url': return context.href.pastebin(p_id) elif field == 'title': return tag(_('Pastebin: '), tag.em(p_title), _(' pasted'))
def render_property_diff(self, name, old_context, old_props, new_context, new_props, options): # Build 5 columns table showing modifications on merge sources # || source || added || removed || added (ni) || removed (ni) || # || source || removed || rm = RepositoryManager(self.env) repos = rm.get_repository(old_context.resource.parent.id) def parse_sources(props): sources = {} value = props[name] lines = value.splitlines() if name == 'svn:mergeinfo' \ else value.split() for line in lines: path, revs = line.split(':', 1) spath = _path_within_scope(repos.scope, path) if spath is not None: inheritable, non_inheritable = _partition_inheritable(revs) sources[spath] = (set(Ranges(inheritable)), set(Ranges(non_inheritable))) return sources old_sources = parse_sources(old_props) new_sources = parse_sources(new_props) # Go through new sources, detect modified ones or added ones blocked = name.endswith('blocked') added_label = [_("merged: "), _("blocked: ")][blocked] removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked] added_ni_label = _("marked as non-inheritable: ") removed_ni_label = _("unmarked as non-inheritable: ") sources = [] changed_revs = {} changed_nodes = [] for spath, (new_revs, new_revs_ni) in new_sources.iteritems(): new_spath = spath not in old_sources if new_spath: old_revs = old_revs_ni = set() else: old_revs, old_revs_ni = old_sources.pop(spath) added = new_revs - old_revs removed = old_revs - new_revs # unless new revisions differ from old revisions if not added and not removed: continue added_ni = new_revs_ni - old_revs_ni removed_ni = old_revs_ni - new_revs_ni revs = sorted(added | removed | added_ni | removed_ni) try: node = repos.get_node(spath, revs[-1]) changed_nodes.append((node, revs[0])) except NoSuchNode: pass sources.append( (spath, new_spath, added, removed, added_ni, removed_ni)) if changed_nodes: changed_revs = repos._get_changed_revs(changed_nodes) def revs_link(revs, context): if revs: revs = to_ranges(revs) return _get_revs_link(revs.replace(',', u',\u200b'), context, spath, revs) modified_sources = [] for spath, new_spath, added, removed, added_ni, removed_ni in sources: if spath in changed_revs: revs = set(changed_revs[spath]) added &= revs removed &= revs added_ni &= revs removed_ni &= revs if added or removed: if new_spath: status = _(" (added)") else: status = None modified_sources.append( (spath, [_get_source_link(spath, new_context), status], added and tag(added_label, revs_link(added, new_context)), removed and tag(removed_label, revs_link(removed, old_context)), added_ni and tag(added_ni_label, revs_link(added_ni, new_context)), removed_ni and tag(removed_ni_label, revs_link(removed_ni, old_context)))) # Go through remaining old sources, those were deleted removed_sources = [] for spath, old_revs in old_sources.iteritems(): removed_sources.append( (spath, _get_source_link(spath, old_context))) if modified_sources or removed_sources: modified_sources.sort() removed_sources.sort() changes = tag.table(tag.tbody([ tag.tr(tag.td(c) for c in cols[1:]) for cols in modified_sources ], [ tag.tr(tag.td(src), tag.td(_('removed'), colspan=4)) for spath, src in removed_sources ]), class_='props') else: changes = tag.em(_(' (with no actual effect on merging)')) return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)), changes)