def _dump_docs(self, req): self.log.debug("Rendering docs") # Dump RPC documentation req.perm.require('XML_RPC') # Need at least XML_RPC namespaces = {} context = web_context(req) for method in XMLRPCSystem(self.env).all_methods(req): namespace = method.namespace.replace('.', '_') if namespace not in namespaces: namespaces[namespace] = { 'description': format_to_oneliner(self.env, context, method.namespace_description), 'methods': [], 'namespace': method.namespace, } try: namespaces[namespace]['methods'].append( (method.signature, format_to_oneliner(self.env, context, method.description), method.permission)) except Exception, e: from tracrpc.util import StringIO import traceback out = StringIO() traceback.print_exc(file=out) raise Exception('%s: %s\n%s' % (method.name, str(e), out.getvalue()))
def format(self): if not self.changesets: message = _("No changesets for #%s" % self.tkt_id) yield tag.span(format_to_oneliner(self.env, self.context, message, shorten=False), class_='ticketchangesets hint') return n = len(self.changesets) ix = 0 # current index for adding separation markers between repos for (reponame, changesets) in self.changesets: if n > 1: if self.hint == 'ticket': if reponame and reponame != '(default)': yield tag.h3(reponame, class_='change') else: yield tag.h3(_("Default Repository"), class_='change') elif ix > 0: yield ', ' revs = changesets.wiki_revs(reponame, self.compact) log = changesets.wiki_log(reponame) message = revs + ' (' + log + ')' yield tag.span(format_to_oneliner(self.env, self.context, message, shorten=False), class_='ticketchangesets') ix += 1
def expand_macro(self, formatter, name, args): args = tuple(args.split(',')) if len(args) == 2 : return tag.span(format_to_oneliner(self.env, formatter.context, args[1]), style='background-color: %s' % args[0]) else: return tag.span(format_to_oneliner(self.env, formatter.context, args[2]), style='background-color: %s; color: %s' % args[0:2])
def expand_macro(self, formatter, name, args): args = tuple(args.split(',')) if len(args) == 2: return tag.span(format_to_oneliner(self.env, formatter.context, args[1]), style='background-color: %s' % args[0]) else: return tag.span( format_to_oneliner(self.env, formatter.context, args[2]), style='background-color: %s; color: %s' % args[0:2])
def _format_screenshot(self, context, screenshot): screenshot['author'] = format_to_oneliner(self.env, context, screenshot['author']) screenshot['name'] = format_to_oneliner(self.env, context, screenshot['name']) screenshot['description'] = format_to_oneliner( self.env, context, screenshot['description']) screenshot['width'] = int(screenshot['width']) screenshot['height'] = int(screenshot['height']) screenshot['time'] = pretty_timedelta( to_datetime(screenshot['time'], utc)) return screenshot
def render_inline_content(self, _env, _context, _content,mode): #Sceneheaders must start with INT, EXT, or EST sceneheader_re = re.compile('\n(INT|EXT|[^a-zA-Z0-9]EST)([\.\-\s]+?)(.+?)([A-Za-z0-9\)\s\.])\n') #Transitions transitions_re = re.compile('\n([^<>\na-z]*?:|FADE TO BLACK\.|FADE OUT\.|CUT TO BLACK\.)[\s]??\n') #action blocks actions_re = re.compile('\n{2}(([^a-z\n\:]+?[\.\?\,\s\!]*?)\n{2}){1,2}') #character cues characters_re = re.compile('\n{1}(\w+[\.-]*[\s]*\w+?[^\!\)\?\.\s])\n{1}') # characters_re = re.compile('\n([^<>a-z\s][^a-z:\!\?]*?[^a-z\(\!\?:,][\s]??)\n{1}') #parentheticals parentheticals_re = re.compile('(\([^<>]*?\)[\s]??)\n') #dialog dialog_re = re.compile('(<p class="character">.*<\/p>|<p class="parenthetical">.*<\/p>)\n{0,1}(.+?)\n') #default default_re = re.compile('([^<>]*?)\n') #clean up cleanup_re = re.compile('<p class="action">[\n\s]*?<\/p>') #styling # bold_re = re.compile('(\*{2}|\[b\])(.*?)(\*{2}|\[\/b\])') # italic_re = re.compile('(\*{1}|\[i\])(.*?)(\*{1}|\[\/i\])') # underline_re = re.compile('(_|\[u\])(.*?)(_|\[\/u\])') theoutput = tag.div(class_="scrippet"+mode) # self.log.debug("BEFORE SCENE: %s" % _content) _content = sceneheader_re.sub(r'<p class="sceneheader">\1\2\3\4</p>' + "\n",_content) # self.log.debug("BEFORE TRANSITIONS: %s" % _content) _content = transitions_re.sub(r'<p class="transition">\1</p>' + "\n",_content) # self.log.debug("BEFORE ACTIONS: %s" % _content) _content = actions_re.sub("\n" + r'<p class="action">\2</p>' + "\n",_content) # self.log.debug("BEFORE CHARACTERS: %s" % _content) # self.log.debug(_content); _content = characters_re.sub(r'<p class="character">\1</p>',_content) # self.log.debug(characters_re.sub(r'<p class="character">\1</p>',_content)); _content = parentheticals_re.sub(r'<p class="parenthetical">\1</p>',_content); #format_to_oneliner(_env, _context, _content)) _content = dialog_re.sub(r'\1' + "\n" + r'<p class="dialogue">\2</p>' + "\n",_content); #format_to_oneliner(_env, _context, _content)) _content = default_re.sub(r'<p class="action">\1</p>' + "\n",_content) _content = cleanup_re.sub("",_content) # _content = bold_re.sub(r'<b>\2</b>',_content) # _content = italic_re.sub(r'<i>\2</i>',_content) # _content = underline_re.sub(r'<u>\2</u>',_content) para_re = re.compile(r'<p class="(?P<_class>.*?)">(?P<_body>.*?)</p>') for line in _content.splitlines(): # self.log.debug("LINE: %s" % line) m = para_re.search(line) if m != None: # self.log.debug("BODY: %s" % m.group('_body')) # self.log.debug("CLASS: %s" % m.group('_class')) if "FADE IN" in m.group('_body') and m.group('_class') == "transition": theoutput.append(tag.p(format_to_oneliner(_env, _context,m.group('_body')),class_="action"+mode)) else: theoutput.append(tag.p(format_to_oneliner(_env, _context,m.group('_body')),class_=m.group('_class')+mode)) return theoutput
def get_timeline_events(self, req, start, stop, filters): self.log.debug("start: %s, stop: %s, filters: %s" % (start, stop, filters)) if ('discussion' in filters) and 'DISCUSSION_VIEW' in req.perm: # Create request context. context = Context.from_request(req) context.realm = 'discussion-core' # Get database access. db = self.env.get_db_cnx() context.cursor = db.cursor() # Get API component. api = self.env[DiscussionApi] # Add CSS styles and scripts. add_stylesheet(context.req, 'discussion/css/discussion.css') # Get forum events. for forum in api.get_changed_forums(context, start, stop): # Return event. title = 'New forum %s created' % (forum['name'],) description = tag(format_to_oneliner(self.env, context, forum['subject']), ' - ', format_to_oneliner(self.env, context, forum['description'])) ids = ('forum', forum['id']) yield ('discussion unsolved', to_datetime(forum['time'], utc), forum['author'], (title, description, ids)) # Get topic events. for topic in api.get_changed_topics(context, start, stop): title = 'New topic on %s created' % (topic['forum_name'],) description = format_to_oneliner(self.env, context, topic['subject']) ids = ('topic', topic['id']) yield ('discussion solved' if 'solved' in topic['status'] else 'discussion unsolved', to_datetime(topic['time'], utc), topic['author'], (title, description, ids)) # Get message events. for message in api.get_changed_messages(context, start, stop): title = 'New reply on %s created' % (message['forum_name'],) description = format_to_oneliner(self.env, context, message['topic_subject']) ids = (('topic',message['topic']),'message', message['id']) yield ('discussion unsolved', to_datetime(message['time'], utc), message['author'], (title, description, ids))
def _info_formatter(self, formatter, match, fullmatch): infotype = fullmatch.group('infotype').lower() body = format_to_oneliner(formatter.env, formatter.context, fullmatch.group('notes'), False) return tag.div(tag.blockquote(tag.b(infotype.capitalize() + ': ') + body,class_=infotype.upper()), class_=infotype.upper())
def _gather_option_data(self, req, section_name, option_name, section_default_values): option = None if (section_name, option_name) in Option.registry: # Allow wiki formatting in descriptions option = Option.registry[(section_name, option_name)] option_desc = format_to_oneliner(self.env, Context.from_request(req), option.__doc__) option_type = option.__class__.__name__.lower()[:-6] or 'text' else: option_desc = None option_type = 'text' # See "IniEditorBasicSecurityManager" for why we use a pipe char here. if ('%s|%s' % (section_name, option_name)) in self.password_options_set: option_type = 'password' if section_default_values: default_value = (self._convert_value( section_default_values.get(option_name), option) or '') else: default_value = '' return { 'default_value': default_value, 'desc': option_desc, 'type': option_type, 'option_info': option, 'access': self._check_option_access(section_name, option_name) }
def expand_macro(self, formatter, name, args): from trac.config import Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() registry = Option.get_registry(self.compmgr) sections = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): sections.setdefault(section, {})[key] = option return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), tag.table(class_='wiki')( tag.tbody(tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, to_unicode(option.__doc__)))) for option in sorted(sections[section].itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section in sorted(sections))
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], 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]
def expand_macro(self, formatter, name, content): if not content: return '' args, kwargs = parse_args(content) if len(args) > 1: return system_message("Number of args can't be greater than 1") if args[0] == 'author': page = WikiPage(self.env, formatter.context.resource, 1) text = page.author elif args[0] == 'version': page = WikiPage(self.env, formatter.context.resource) text = str(page.version) elif args[0] == 'changed_by': page = WikiPage(self.env, formatter.context.resource) text = page.author elif args[0] == 'comment': page = WikiPage(self.env, formatter.context.resource) text = page.comment elif args[0] == 'changed_ts': page = WikiPage(self.env, formatter.context.resource) text = format_datetime(page.time) else: return system_message("Unkwown argument %s" % args[0]) return format_to_oneliner(self.env, formatter.context, text)
def _do_ticket(self, req, template, data, content_type): if 'ticket' in data and 'linked_tickets' in data: ticket = data['ticket'] context = Context.from_request(req, ticket.resource) # Add name:#n links to link fields of Ticket instance when # flowing from storage to browser if req.method == 'GET': RemoteLinksProvider(self.env).augment_ticket(ticket) # Rerender link fields for field in data['fields']: if field['type'] == 'link': name = field['name'] field['rendered'] = format_to_oneliner(self.env, context, ticket[name]) # Add RemoteTicket objects for linked issues table, and pass list # of rejects that could not be retrieved linked_tickets, linked_rejects = self._remote_tickets(ticket, context) data['linked_tickets'].extend(linked_tickets) data['linked_rejects'].extend(linked_rejects) # Provide list of remote sites if newlinked form options are present if 'newlinked_options' in data: remote_sites = RemoteTicketSystem(self.env).get_remote_tracs() data['remote_sites'] = remote_sites return (template, data, content_type)
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]
def _get_changed_forums(self, context, start, stop): columns = ('id', 'name', 'author', 'subject', 'description', 'time') sql_values = {'start' : to_timestamp(start), 'stop' : to_timestamp(stop)} sql = ("SELECT f.id, f.name, f.author, f.subject, f.description, f.time " "FROM forum f " "WHERE f.time BETWEEN %(start)s AND %(stop)s" % (sql_values)) self.log.debug(sql) context.cursor.execute(sql) for row in context.cursor: row = dict(zip(columns, row)) row['time'] = to_datetime(row['time'], utc) row['subject'] = format_to_oneliner(self.env, context, row['subject']) row['description'] = format_to_oneliner(self.env, context, row['description']) yield row
def test_log_link_checking_repository_resource(self): self.env.config.set( 'trac', 'permission_policies', 'TestLogModulePermissionPolicy, DefaultPermissionPolicy') resource = Resource('wiki', 'WikiStart') req = MockRequest(self.env, authname='anonymous') rendered = unicode( format_to_oneliner(self.env, web_context(req, resource), 'log:mock@42-43')) self.assertIn(' title="No permission to view change log"', rendered) req = MockRequest(self.env, authname='blah') rendered = unicode( format_to_oneliner(self.env, web_context(req, resource), 'log:mock@42-43')) self.assertIn(' href="/trac.cgi/log/mock/?revs=42-43"', rendered)
def render_timeline_event(self, context, field, event): builder_name, num, end, branch, rev, results, text = event[3] if field == 'url': return None elif field == 'title': return tag('Build ', tag.a('#%s' % num, href=context.href.buildbot('builder/%s/%s' % (builder_name, num))), ' of ', builder_name, ' ', results == 'success' and tag.span('passed', style="color: #080") or tag.span('failed', style="color: #f00")) elif field == 'description': return format_to_oneliner(self.env, context, 'Built from %s' % (rev and 'r%s sources' % rev or 'local changes (see TryBuildUsage)'))
def render_timeline_event(self, context, field, event): builder_name, num, end, branch, rev, results, text = event[3] if field == 'url': return None elif field == 'title': return tag('Build ', tag.a('#%s'%num, href=context.href.buildbot('builder/%s/%s'%(builder_name, num))), ' of ', builder_name, ' ', results == 'success' and tag.span('passed', style="color: #080") or tag.span('failed', style="color: #f00")) elif field == 'description': return format_to_oneliner(self.env, context, 'Built from %s'%(rev and 'r%s sources'%rev or 'local changes (see TryBuildUsage)'))
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is True: default = 'true' elif default is False: default = 'false' elif default == 0: default = '0.0' if isinstance(default, float) else '0' elif default: default = ', '.join(to_unicode(val) for val in default) \ if isinstance(default, (list, tuple)) \ else to_unicode(default) else: return tag.td(_("(no default)"), class_='nodefault') return tag.td(tag.code(default), class_='default') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr( tag.td(tag.tt(option.name)), tag.td( format_to_oneliner(self.env, formatter.context, getdoc(option))), default_cell(option)) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def _replaces_formatter(self, formatter, ns, match): replaces = match.group('replaces') if replaces not in self.replace: return match.group(0) title = self.replace[replaces] context = Context.from_request(formatter.req, formatter.resource) return Markup('<span>%s</span>' % (format_to_oneliner(self.env,context,title)))
def expand_macro(self, formatter, name, content, args): self.log.debug("SpoilerMacro: expand_macro") add_stylesheet(formatter.req, 'spoiler/css/spoiler.css') add_javascript(formatter.req, 'spoiler/js/spoiler.js') if '\n' in content: output = tag.div(class_="spoiler")(format_to_html(self.env, formatter.context,content)) else: output = tag.span(class_="spoiler")(format_to_oneliner(self.env, formatter.context,content)) self.log.debug("SpoilerMacro: expand_macro output") return output
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is True: default = 'true' elif default is False: default = 'false' elif default == 0: default = '0.0' if isinstance(default, float) else '0' elif default: default = ', '.join(to_unicode(val) for val in default) \ if isinstance(default, (list, tuple)) \ else to_unicode(default) else: return tag.td(_("(no default)"), class_='nodefault') return tag.td(tag.code(default), class_='default') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, getdoc(option))), default_cell(option)) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def render_timeline_event(self, context, field, event): bp_resource, bp, bc = event[3] 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': return format_to_oneliner( self.env, context(resource=bp_resource), bc.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': return format_to_oneliner( self.env, context(resource=bp_resource), bp.version_comment)
def _replaces_formatter(self, formatter, ns, match): replaces = match.group('replaces') if replaces not in self.replace: return match.group(0) title = self.replace[replaces] context = Context.from_request(formatter.req, formatter.resource) return Markup('<span>%s</span>' % (format_to_oneliner(self.env, context, title)))
def expand_macro(self, formatter, name, content, args): self.log.debug("SpoilerMacro: expand_macro") add_stylesheet(formatter.req, 'spoiler/css/spoiler.css') add_javascript(formatter.req, 'spoiler/js/spoiler.js') if '\n' in content: output = tag.div(class_="spoiler")(format_to_html( self.env, formatter.context, content)) else: output = tag.span(class_="spoiler")(format_to_oneliner( self.env, formatter.context, content)) self.log.debug("SpoilerMacro: expand_macro output") return output
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 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 expand_macro(self, formatter, name, content): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(content) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is not None and default != '': return tag.td(tag.code(option.dumps(default)), class_='default') else: return tag.td(_("(no default)"), class_='nodefault') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.code(option.name)), tag.td( format_to_oneliner(self.env, formatter.context, getdoc(option))), default_cell(option), class_='odd' if idx % 2 else 'even') for idx, option in enumerate( sorted(options.get(section, {}).itervalues(), key=lambda o: o.name)) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def expand_macro(self, formatter, name, content): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(content) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is not None and default != '': return tag.td(tag.code(option.dumps(default)), class_='default') else: return tag.td(_("(no default)"), class_='nodefault') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, getdoc(option))), default_cell(option), class_='odd' if idx % 2 else 'even') for idx, option in enumerate(sorted(options.get(section, {}).itervalues(), key=lambda o: o.name)) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def render_timeline_event(self, context, field, event): ticket,summary,status,resolution,type, started, comment = event[4] if field == 'url': return context.href.ticket(ticket.id) elif field == 'title': title = TicketSystem(self.env).format_summary(summary, status, resolution, type) return tag('Work ', started and 'stopped' or 'started', ' on Ticket ', tag.em('#', ticket.id, title=title), ' (', shorten_line(summary), ') ') elif field == 'description': if self.config['timeline'].getbool('abbreviated_messages'): comment = shorten_line(comment) markup = format_to_oneliner(self.env, context(resource=ticket), comment) return markup
def _remote_tickets(self, ticket, context): link_fields = [f for f in ticket.fields if f['type'] == 'link'] rts = RemoteTicketSystem(self.env) linked_tickets = [] linked_rejects = [] for field in link_fields: for link_name, link in rts.parse_links(ticket[field['name']]): tkt_fmt = format_to_oneliner(self.env, context, '%s:#%s' % (link_name, link)) try: tkt = RemoteTicket(self.env, link_name, link) linked_tickets.append((field['label'], tkt_fmt, tkt)) except ResourceNotFound: linked_rejects.append((field['label'], tkt_fmt)) return linked_tickets, linked_rejects
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() registry = ConfigSection.get_registry(self.compmgr) sections = dict( (name, dgettext(section.doc_domain, to_unicode(section.__doc__))) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr( tag.td(tag.tt(option.name)), tag.td( format_to_oneliner( self.env, formatter.context, dgettext(option.doc_domain, to_unicode(option.__doc__)))), tag.td( tag.code(option.default or 'false') if option.default or option.default is False else _("(no default)"), class_='default' if option.default or option.default is False else 'nodefault')) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, dgettext(section.doc_domain, to_unicode(section.__doc__))) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, dgettext(option.doc_domain, to_unicode(option.__doc__)))), tag.td(tag.code(option.default or 'false') if option.default or option.default is False else _("(no default)"), class_='default' if option.default or option.default is False else 'nodefault')) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def _get_changed_topics(self, context, start, stop): columns = ('id', 'subject', 'body', 'author', 'time', 'forum', 'forum_name') sql_values = {'start' : to_timestamp(start), 'stop' : to_timestamp(stop)} sql = ("SELECT t.id, t.subject, t.body, t.author, t.time, t.forum, " "f.name " "FROM topic t " "LEFT JOIN " "(SELECT id, name " "FROM forum) f " "ON t.forum = f.id " "WHERE t.time BETWEEN %(start)s AND %(stop)s" % (sql_values)) self.log.debug(sql) context.cursor.execute(sql) for row in context.cursor: row = dict(zip(columns, row)) row['time'] = to_datetime(row['time'], utc) row['subject'] = format_to_oneliner(self.env, context, row['subject']) yield row
def _format_description(self, context, template, screenshot): description = template.replace('$id', to_unicode(screenshot['id'])) description = description.replace('$name', screenshot['name']) description = description.replace('$file', to_unicode(screenshot['file'])) description = description.replace('$time', format_datetime(to_datetime( screenshot['time'], utc))) description = description.replace('$author', screenshot['author']) description = description.replace('$description', screenshot['description']) description = description.replace('$width', to_unicode( screenshot['width'])) description = description.replace('$height', to_unicode( screenshot['height'])) description = description.replace('$tags', to_unicode( screenshot['tags'])) description = description.replace('$components', ', '.join(screenshot['components'])) description = description.replace('$versions', ', '.join(screenshot['versions'])) return format_to_oneliner(self.env, context, description)
def _format_description(self, context, template, screenshot): description = template.replace('$id', to_unicode(screenshot['id'])) description = description.replace('$name', screenshot['name']) description = description.replace('$file', to_unicode(screenshot['file'])) description = description.replace( '$time', format_datetime(to_datetime(screenshot['time'], utc))) description = description.replace('$author', screenshot['author']) description = description.replace('$description', screenshot['description']) description = description.replace('$width', to_unicode(screenshot['width'])) description = description.replace('$height', to_unicode(screenshot['height'])) description = description.replace('$tags', to_unicode(screenshot['tags'])) description = description.replace('$components', ', '.join(screenshot['components'])) description = description.replace('$versions', ', '.join(screenshot['versions'])) return format_to_oneliner(self.env, context, description)
def _gather_option_data(self, req, section_name, option_name, section_default_values): option = None if (section_name, option_name) in Option.registry: # Allow wiki formatting in descriptions option = Option.registry[(section_name, option_name)] option_desc = format_to_oneliner(self.env, Context.from_request(req), option.__doc__) option_type = option.__class__.__name__.lower()[:-6] or 'text' else: option_desc = None option_type = 'text' # See "IniEditorBasicSecurityManager" for why we use a pipe char here. if ('%s|%s' % (section_name, option_name)) in self.password_options_set: option_type = 'password' if section_default_values: default_value = (self._convert_value(section_default_values.get(option_name), option) or '') else: default_value = '' return { 'default_value': default_value, 'desc': option_desc, 'type': option_type, 'option_info': option, 'access': self._check_option_access(section_name, option_name) }
def _get_changed_messages(self, context, start, stop): columns = ('id', 'author', 'time', 'forum', 'topic', 'body', 'forum_name', 'topic_subject') sql_values = {'start' : to_timestamp(start), 'stop' : to_timestamp(stop)} sql = ("SELECT m.id, m.author, m.time, m.forum, m.topic, m.body, " "f.name, t.subject " "FROM message m, " "(SELECT id, name " "FROM forum) f, " "(SELECT id, subject " "FROM topic) t " "WHERE t.id = m.topic AND f.id = m.forum AND time BETWEEN " "%(start)s AND %(stop)s" % (sql_values)) self.log.debug(sql) context.cursor.execute(sql) for row in context.cursor: row = dict(zip(columns, row)) row['time'] = to_datetime(row['time'], utc) row['topic_subject'] = format_to_oneliner(self.env, context, row['topic_subject']) yield row
def expand_macro(self, formatter, name, content): largs, kwargs = parse_args(content) try: num = int(largs[0]) - 1 if num < 0: raise Exception except: raise TracError("Argument must be a positive integer!") option = self.env.config.get if 'raw' in kwargs: vraw = kwargs['raw'].lower() if vraw in ('yes', 'true', '1', 'on'): raw = True elif vraw in ('no', 'false', '0', 'off'): raw = False else: raw = self.raw res = formatter.resource id = res.id type = res.realm db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "SELECT filename FROM attachment WHERE type=%s " \ "AND id=%s ORDER BY time", (type,id) ) attmnts = cursor.fetchall() if len(attmnts) < num + 1 or not attmnts[num] or not attmnts[num][0]: raise TracError("Attachment #%i doesn't exists!" % (num + 1)) filename = attmnts[num][0] wikilink = "attachment:'" + filename + "'" if raw: wikilink = "raw-" + wikilink if kwargs.get('format', self.format) == 'short': wikilink = "[%s %s]" % (wikilink, filename) return format_to_oneliner(self.env, formatter.context, wikilink)
def expand_macro(self, formatter, name, content): largs, kwargs = parse_args(content) try: num = int(largs[0]) - 1 if num < 0: raise Exception except: raise TracError("Argument must be a positive integer!") option = self.env.config.get if 'raw' in kwargs: vraw = kwargs['raw'].lower() if vraw in ('yes','true','1','on'): raw = True elif vraw in ('no','false','0','off'): raw = False else: raw = self.raw res = formatter.resource id = res.id type = res.realm db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "SELECT filename FROM attachment WHERE type=%s " \ "AND id=%s ORDER BY time", (type,id) ) attmnts = cursor.fetchall() if len(attmnts) < num + 1 or not attmnts[num] or not attmnts[num][0]: raise TracError("Attachment #%i doesn't exists!" % (num+1)) filename = attmnts[num][0] wikilink = "attachment:'" + filename + "'" if raw: wikilink = "raw-" + wikilink if kwargs.get('format', self.format) == 'short': wikilink = "[%s %s]" % (wikilink,filename) return format_to_oneliner(self.env, formatter.context, wikilink)
def expand_macro(self, formatter, name, args): from trac.config import Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() sections = set([section for section, option in Option.registry.keys() if section.startswith(section_filter)]) return tag.div(class_='tracini')( [(tag.h2('[%s]' % section, id='%s-section' % section), tag.table(class_='wiki')( tag.tbody([tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, to_unicode(option.__doc__)))) for option in sorted(Option.registry.values(), key=lambda o: o.name) if option.section == section and option.name.startswith(key_filter)]))) for section in sorted(sections)])
def expand_macro(self, formatter, name, content): # Make sure data capsule is in place if not hasattr(formatter, '_footnotes'): formatter._footnotes = [] # Chrome add_stylesheet(formatter.req, 'footnote/footnote.css') add_script(formatter.req, 'footnote/footnote.js') if content: # Add a new footnote try: # Reference to an existing footnote output_id = int(content) try: content = formatter._footnotes[output_id-1][0] except IndexError: content = 'Unknown footnote' except ValueError: output_id = None # Try to collate with an existing footnote for i in xrange(len(formatter._footnotes)): if formatter._footnotes[i][0] == content: output_id = i + 1 break # Format markup markup = format_to_oneliner(self.env, formatter.context, content) # Adding a new footnote if not output_id: formatter._footnotes.append((content, markup)) output_id = len(formatter._footnotes) return tag.sup( tag.a( output_id, title=shorten_line(content, 50), id='FootNoteRef%s'%output_id, href='#FootNote%s'%output_id, ), class_='footnote', ) else: # Dump all accumulated notes footnotes = formatter._footnotes[:] formatter._footnotes = [(content, None) for content, markup in footnotes] if formatter._footnotes: return tag.div( tag.hr(), tag.ol( [tag.li( tag.a( '%s.'%(i+1), href='#FootNoteRef%s'%(i+1), class_='sigil', ), ' ', markup, id='FootNote%s'%(i+1), ) for i, (content, markup) in enumerate(footnotes) if markup], ), class_='footnotes', ) else: return []
def _parse_heading(self, formatter, match, fullmatch): shorten = False match = match.strip() depth = min(len(fullmatch.group('nhdepth')), 6) try: formatter.close_table() formatter.close_paragraph() formatter.close_indentation() formatter.close_list() formatter.close_def_list() except: pass ## BEGIN of code provided by Joshua Hoke, see th:#4521. # moved and modified by Martin # Figure out headline numbering for outline counters = self.outline_counters.get(formatter, []) if formatter not in self.outline_counters: self.outline_counters[formatter] = counters if len(counters) < depth: delta = depth - len(counters) counters.extend([0] * (delta - 1)) counters.append(1) else: del counters[depth:] counters[-1] += 1 ## END num = fullmatch.group('nheadnum') or '' anchor = fullmatch.group('nhanchor') or '' heading_text = match[depth + 1 + len(num):-depth - 1 - len(anchor)].strip() num = num.strip() if num and num[-1] == '.': num = num[:-1] if num: numbers = [self._int(n) for n in num.split('.')] if len(numbers) == 1: counters[depth - 1] = numbers[0] else: if len(numbers) > depth: del numbers[depth:] n = 0 while numbers[n] == -1: n = n + 1 counters[depth - len(numbers[n:]):] = numbers[n:] if not heading_text: return tag() heading = format_to_oneliner(formatter.env, formatter.context, heading_text, False) if anchor: anchor = anchor[1:] else: sans_markup = plaintext(heading, keeplinebreaks=False) anchor = WikiParser._anchor_re.sub('', sans_markup) if not anchor or anchor[0].isdigit() or anchor[0] in '.-': # an ID must start with a Name-start character in XHTML anchor = 'a' + anchor # keeping 'a' for backward compat i = 1 anchor_base = anchor while anchor in formatter._anchors: anchor = anchor_base + str(i) i += 1 formatter._anchors[anchor] = True # Add number directly if CSS is not used s = self.startatleveltwo and 1 or 0 #self.env.log.debug('NHL:' + str(counters)) while s < len(counters) and counters[s] == 0: s = s + 1 oheading_text = heading_text heading_text = '.'.join(map(str, counters[s:]) + [" "]) + heading_text if self.number_outline: oheading_text = heading_text heading = format_to_oneliner(formatter.env, formatter.context, heading_text, False) oheading = format_to_oneliner(formatter.env, formatter.context, oheading_text, False) ## BEGIN of code provided by Joshua Hoke, see th:#4521. # modified by Martin # Strip out link tags oheading = re.sub(r'</?a(?: .*?)?>', '', oheading) try: # Add heading to outline formatter.outline.append((depth, anchor, oheading)) except AttributeError: # Probably a type of formatter that doesn't build an # outline. pass ## END of provided code html = tag.__getattr__('h' + str(depth))(heading, id=anchor) if self.fix_paragraph: return '</p>' + to_unicode(html) + '<p>' else: return html
def _wiki_to_oneliner(self, context, wiki, shorten=None): if isinstance(wiki, Fragment): return wiki return format_to_oneliner(self.env, context, wiki, shorten=shorten)
def format_to_oneliner(self, wikidom): return format_to_oneliner(self.env, self.context, wikidom)
def get_list(self, realm, wl, req, fields=None): db = self.env.get_db_cnx() cursor = db.cursor() context = Context.from_request(req) locale = getattr(req, 'locale', LC_TIME) ticketlist = [] extradict = {} if not fields: fields = set(self.default_fields['ticket']) else: fields = set(fields) if 'changetime' in fields: max_changetime = datetime(1970, 1, 1, tzinfo=utc) min_changetime = datetime.now(utc) if 'time' in fields: max_time = datetime(1970, 1, 1, tzinfo=utc) min_time = datetime.now(utc) for sid, last_visit in wl.get_watched_resources( 'ticket', req.authname): ticketdict = {} try: ticket = Ticket(self.env, sid, db) exists = ticket.exists except: exists = False if not exists: ticketdict['deleted'] = True if 'id' in fields: ticketdict['id'] = sid ticketdict['ID'] = '#' + sid if 'author' in fields: ticketdict['author'] = '?' if 'changetime' in fields: ticketdict['changedsincelastvisit'] = 1 ticketdict['changetime'] = '?' ticketdict['ichangetime'] = 0 if 'time' in fields: ticketdict['time'] = '?' ticketdict['itime'] = 0 if 'comment' in fields: ticketdict['comment'] = tag.strong(t_("deleted"), class_='deleted') if 'notify' in fields: ticketdict['notify'] = wl.is_notify(req, 'ticket', sid) if 'description' in fields: ticketdict['description'] = '' if 'owner' in fields: ticketdict['owner'] = '' if 'reporter' in fields: ticketdict['reporter'] = '' ticketlist.append(ticketdict) continue render_elt = lambda x: x if not (Chrome(self.env).show_email_addresses or \ 'EMAIL_VIEW' in req.perm(ticket.resource)): render_elt = obfuscate_email_address # Copy all requested fields from ticket if fields: for f in fields: ticketdict[f] = ticket.values.get(f, u'') else: ticketdict = ticket.values.copy() changetime = ticket.time_changed if wl.options['attachment_changes']: for attachment in Attachment.select(self.env, 'ticket', sid, db): if attachment.date > changetime: changetime = attachment.date if 'attachment' in fields: attachments = [] for attachment in Attachment.select(self.env, 'ticket', sid, db): wikitext = u'[attachment:"' + u':'.join([ attachment.filename, 'ticket', sid ]) + u'" ' + attachment.filename + u']' attachments.extend([ tag(', '), format_to_oneliner(self.env, context, wikitext, shorten=False) ]) if attachments: attachments.reverse() attachments.pop() ticketdict['attachment'] = moreless(attachments, 5) # Changes are special. Comment, commentnum and last author are included in them. if 'changes' in fields or 'author' in fields or 'comment' in fields or 'commentnum' in fields: changes = [] # If there are now changes the reporter is the last author author = ticket.values['reporter'] commentnum = u"0" comment = u"" want_changes = 'changes' in fields for date, cauthor, field, oldvalue, newvalue, permanent in ticket.get_changelog( changetime, db): author = cauthor if field == 'comment': if 'commentnum' in fields: ticketdict['commentnum'] = to_unicode(oldvalue) if 'comment' in fields: comment = to_unicode(newvalue) comment = moreless(comment, 200) ticketdict['comment'] = comment if not want_changes: break else: if want_changes: label = self.fields['ticket'].get(field, u'') if label: changes.extend([ tag( tag.strong(label), ' ', render_property_diff( self.env, req, ticket, field, oldvalue, newvalue)), tag('; ') ]) if want_changes: # Remove the last tag('; '): if changes: changes.pop() changes = moreless(changes, 5) ticketdict['changes'] = tag(changes) if 'id' in fields: ticketdict['id'] = sid ticketdict['ID'] = format_to_oneliner(self.env, context, '#' + sid, shorten=True) if 'cc' in fields: if render_elt == obfuscate_email_address: ticketdict['cc'] = ', '.join( [render_elt(c) for c in ticketdict['cc'].split(', ')]) if 'author' in fields: ticketdict['author'] = render_elt(author) if 'changetime' in fields: ichangetime = to_timestamp(changetime) ticketdict.update( changetime=format_datetime(changetime, locale=locale, tzinfo=req.tz), ichangetime=ichangetime, changedsincelastvisit=(last_visit < ichangetime and 1 or 0), changetime_delta=pretty_timedelta(changetime), changetime_link=req.href.timeline( precision='seconds', from_=trac_format_datetime(changetime, 'iso8601', tzinfo=req.tz))) if changetime > max_changetime: max_changetime = changetime if changetime < min_changetime: min_changetime = changetime if 'time' in fields: time = ticket.time_created ticketdict.update(time=format_datetime(time, locale=locale, tzinfo=req.tz), itime=to_timestamp(time), time_delta=pretty_timedelta(time), time_link=req.href.timeline( precision='seconds', from_=trac_format_datetime( time, 'iso8601', tzinfo=req.tz))) if time > max_time: max_time = time if time < min_time: min_time = time if 'description' in fields: description = ticket.values['description'] description = moreless(description, 200) ticketdict['description'] = description if 'notify' in fields: ticketdict['notify'] = wl.is_notify(req, 'ticket', sid) if 'owner' in fields: ticketdict['owner'] = render_elt(ticket.values['owner']) if 'reporter' in fields: ticketdict['reporter'] = render_elt(ticket.values['reporter']) if 'tags' in fields and self.tagsystem: tags = [] for t in self.tagsystem.get_tags(req, Resource('ticket', sid)): tags.extend( [tag.a(t, href=req.href('tags', q=t)), tag(', ')]) if tags: tags.pop() ticketdict['tags'] = moreless(tags, 10) ticketlist.append(ticketdict) if 'changetime' in fields: extradict['max_changetime'] = format_datetime(max_changetime, locale=locale, tzinfo=req.tz) extradict['min_changetime'] = format_datetime(min_changetime, locale=locale, tzinfo=req.tz) if 'time' in fields: extradict['max_time'] = format_datetime(max_time, locale=locale, tzinfo=req.tz) extradict['min_time'] = format_datetime(min_time, locale=locale, tzinfo=req.tz) return ticketlist, extradict
def expand_macro(self, formatter, name, content, realms=[]): """Evaluate macro call and render results. Calls from web-UI come with pre-processed realm selection. """ env = self.env req = formatter.req tag_system = TagSystem(env) all_realms = tag_system.get_taggable_realms() if not all_realms: # Tag providers are required, no result without at least one. return '' args, kw = parse_args(content) query = args and args[0].strip() or None if not realms: # Check macro arguments for realms (typical wiki macro call). realms = 'realm' in kw and kw['realm'].split('|') or [] if query: # Add realms from query expression. realms.extend(query_realms(query, all_realms)) # Remove redundant realm selection for performance. if set(realms) == all_realms: query = re.sub('(^|\W)realm:\S+(\W|$)', ' ', query).strip() if name == 'TagCloud': # Set implicit 'all tagged realms' as default. if not realms: realms = all_realms if query: all_tags = Counter() # Require per resource query including view permission checks. for resource, tags in tag_system.query(req, query): all_tags.update(tags) else: # Allow faster per tag query, side steps permission checks. all_tags = tag_system.get_all_tags(req, realms=realms) mincount = 'mincount' in kw and kw['mincount'] or None return self.render_cloud(req, all_tags, caseless_sort=self.caseless_sort, mincount=mincount, realms=realms) elif name == 'ListTagged': if content and _OBSOLETE_ARGS_RE.search(content): data = {'warning': 'obsolete_args'} else: data = {'warning': None} context = formatter.context # Use TagsQuery arguments (most likely wiki macro calls). cols = 'cols' in kw and kw['cols'] or self.default_cols format = 'format' in kw and kw['format'] or self.default_format if not realms: # Apply ListTagged defaults to macro call w/o realm. realms = list(set(all_realms)-set(self.exclude_realms)) if not realms: return '' query = '(%s) (%s)' % (query or '', ' or '.join(['realm:%s' % (r) for r in realms])) query_result = tag_system.query(req, query) excludes = [exc.strip() for exc in kw.get('exclude', '' ).split(':') if exc.strip()] if excludes and query_result: filtered_result = [(resource, tags) for resource, tags in query_result if not any(fnmatchcase(resource.id, exc) for exc in excludes)] query_result = filtered_result if not query_result: return '' def _link(resource): if resource.realm == 'tag': # Keep realm selection in tag links. return builder.a(resource.id, href=self.get_href(req, realms, tag=resource)) elif resource.realm == 'ticket': # Return resource link including ticket status dependend # class to allow for common Trac ticket link style. ticket = Ticket(env, resource.id) return builder.a('#%s' % ticket.id, class_=ticket['status'], href=formatter.href.ticket(ticket.id), title=shorten_line(ticket['summary'])) return render_resource_link(env, context, resource, 'compact') if format == 'table': cols = [col for col in cols.split('|') if col in self.supported_cols] # Use available translations from Trac core. try: labels = TicketSystem(env).get_ticket_field_labels() labels['id'] = _('Id') except AttributeError: # Trac 0.11 neither has the attribute nor uses i18n. labels = {'id': 'Id', 'description': 'Description'} labels['realm'] = _('Realm') labels['tags'] = _('Tags') headers = [{'label': labels.get(col)} for col in cols] data.update({'cols': cols, 'headers': headers}) results = sorted(query_result, key=lambda r: \ embedded_numbers(to_unicode(r[0].id))) results = self._paginate(req, results, realms) rows = [] for resource, tags in results: desc = tag_system.describe_tagged_resource(req, resource) tags = sorted(tags) wiki_desc = format_to_oneliner(env, context, desc) if tags: rendered_tags = [_link(Resource('tag', tag)) for tag in tags] if 'oldlist' == format: resource_link = _link(resource) else: resource_link = builder.a(wiki_desc, href=get_resource_url( env, resource, context.href)) if 'table' == format: cells = [] for col in cols: if col == 'id': cells.append(_link(resource)) # Don't duplicate links to resource in both. elif col == 'description' and 'id' in cols: cells.append(wiki_desc) elif col == 'description': cells.append(resource_link) elif col == 'realm': cells.append(resource.realm) elif col == 'tags': cells.append( builder([(tag, ' ') for tag in rendered_tags])) rows.append({'cells': cells}) continue rows.append({'desc': wiki_desc, 'rendered_tags': None, 'resource_link': _link(resource)}) data.update({'format': format, 'paginator': results, 'results': rows, 'tags_url': req.href('tags')}) # Work around a bug in trac/templates/layout.html, that causes a # TypeError for the wiki macro call, if we use add_link() alone. add_stylesheet(req, 'common/css/search.css') return Chrome(env).render_template( req, 'listtagged_results.html', data, 'text/html', True)
def wikify(text): return format_to_oneliner(self.env, formatter.context, text)
def render_property(self, name, mode, context, props): if name in self.wiki_properties: return format_to_html(self.env, context, props[name]) else: return format_to_oneliner(self.env, context, props[name])