Exemple #1
0
    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)])
Exemple #2
0
    def getbool(self, name, default=None):
        """Return the value as a boolean. Raise an `HTTPBadRequest`
        exception if an exception occurs while converting the value to
        a boolean.

        :param name: the name of the request parameter
        :keyword default: the value to return if the parameter is not
                          specified.

        :since: 1.2
        """
        if name not in self:
            return default
        value = self[name]
        if isinstance(value, list):
            raise HTTPBadRequest(
                tag_("Invalid value for request argument "
                     "%(name)s.",
                     name=tag.em(name)))
        value = as_bool(value, None)
        if value is None:
            raise HTTPBadRequest(
                tag_("Invalid value for request argument "
                     "%(name)s.",
                     name=tag.em(name)))
        return value
Exemple #3
0
 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)
Exemple #4
0
    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")
Exemple #5
0
 def _check_quickjump(self, req, noquickjump, kwd):
     """Look for search shortcuts"""
     # 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:
             help_url = req.href.wiki('TracSearch') + '#Quicksearches'
             search_url = req.href.search(q=kwd, noquickjump=1)
             # FIXME: use tag_
             add_notice(req, Markup(_(
                 'You arrived here through the <a href="%(help_url)s">'
                 'quick-jump</a> search feature. To instead search for the '
                 'term <strong>%(term)s</strong>, click <a '
                 'href="%(search_url)s">here</a>.',
                 help_url=escape(help_url), term=escape(kwd),
                 search_url=escape(search_url))))
             req.redirect(quickjump_href)
Exemple #6
0
 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':
         child_resource = context.child(resource=milestone)
         return format_to(self.env, None, child_resource, description)
Exemple #7
0
 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)
Exemple #8
0
    def require(self, name):
        """Raise an `HTTPBadRequest` exception if the parameter is
        not in the request.

        :param name: the name of the request parameter

        :since: 1.2
        """
        if name not in self:
            raise HTTPBadRequest(
                tag_("Missing request argument. The %(name)s argument "
                     "must be included in the request.", name=tag.em(name)))
Exemple #9
0
    def _render_source(self, context, lines, 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(lines, unicode):
            lines = lines.splitlines(True)
        # elif isinstance(lines, list):
        #    pass # assume these are lines already

        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)
                add_warning(
                    context.req,
                    tag.strong(
                        tag_("Can't use %(annotator)s annotator: %(error)s",
                             annotator=tag.em(a),
                             error=tag.pre(e))))
                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(lines):
                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()))
Exemple #10
0
    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]))
Exemple #11
0
 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
Exemple #12
0
    def getint(self, name, default=None, min=None, max=None):
        """Return the value as an integer. Raise an `HTTPBadRequest`
        exception if an exception occurs while converting the value
        to an integer.

        :param name: the name of the request parameter
        :keyword default: the value to return if the parameter is not
                          specified
        :keyword min: lower bound to which the value is limited
        :keyword max: upper bound to which the value is limited

        :since: 1.2
        """
        if name not in self:
            return default
        value = as_int(self[name], None, min, max)
        if value is None:
            raise HTTPBadRequest(tag_("Invalid value for request argument "
                                      "%(name)s.", name=tag.em(name)))
        return value
Exemple #13
0
    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)
Exemple #14
0
 def test_str(self):
     self.assertEqual(b'<b>M<em>ess\xc3\xa4ge</em></b>',
                      str(tag.b('M', tag.em('essäge'))))
Exemple #15
0
 def test_unicode(self):
     self.assertEqual('<b>M<em>essäge</em></b>',
                      unicode(tag.b('M', tag.em('essäge'))))