Пример #1
0
 def _launch(self, encoded_input, *args):
     """Launch a process (cmd), and returns exitcode, stdout + stderr"""
     # Note: subprocess.Popen doesn't support unicode options arguments
     # (http://bugs.python.org/issue1759845) so we have to encode them.
     # Anyway, dot expects utf-8 or the encoding specified with -Gcharset.
     encoded_cmd = []
     for arg in args:
         if isinstance(arg, unicode):
             arg = arg.encode(self.encoding, 'replace')
         encoded_cmd.append(arg)
     p = subprocess.Popen(encoded_cmd, stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     if input:
         p.stdin.write(encoded_input)
     p.stdin.close()
     out = p.stdout.read()
     err = p.stderr.read()
     reason = None
     if p.wait() != 0:
         reason = _("failed with the following output:")
     if err or out:
         reason = _("succeeded but emitted the following output:")
     if reason:
         return tag.p(tag.br(), _("The command:"), 
                      tag.pre(repr(' '.join(encoded_cmd))), reason, 
                      out and tag.pre(repr(out)), err and tag.pre(repr(err)))
Пример #2
0
 def launch(self, proc_cmd, encoded_input, *args):
     """Launch a process (cmd), and returns exitcode, stdout + stderr"""
     # Note: subprocess.Popen doesn't support unicode options arguments
     # (http://bugs.python.org/issue1759845) so we have to encode them.
     # Anyway, dot expects utf-8 or the encoding specified with -Gcharset.
     encoded_cmd = proc_cmd
     proc = subprocess.Popen(encoded_cmd,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
     if encoded_input:
         proc.stdin.write(encoded_input)
     proc.stdin.close()
     out = proc.stdout.read()
     err = proc.stderr.read()
     failure = proc.wait() != 0
     if failure or err or out:
         return (failure,
                 tag.div(tag.br(),
                         _("The command:"),
                         tag.pre(repr(' '.join(encoded_cmd))),
                         (_("succeeded but emitted the following output:"),
                          _("failed with the following output:"))[failure],
                         out and tag.pre(out),
                         err and tag.pre(err),
                         class_="system-message"))
     else:
         return (False, None)
Пример #3
0
 def _launch(self, encoded_input, *args):
     """Launch a process (cmd), and returns exitcode, stdout + stderr"""
     # Note: subprocess.Popen doesn't support unicode options arguments
     # (http://bugs.python.org/issue1759845) so we have to encode them.
     # Anyway, dot expects utf-8 or the encoding specified with -Gcharset.
     encoded_cmd = []
     for arg in args:
         if isinstance(arg, unicode):
             arg = arg.encode(self.encoding, 'replace')
         encoded_cmd.append(arg)
     p = subprocess.Popen(encoded_cmd, stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     if encoded_input:
         p.stdin.write(encoded_input)
     p.stdin.close()
     out = p.stdout.read()
     err = p.stderr.read()
     failure = p.wait() != 0
     if failure or err or out:
         return (failure, tag.p(tag.br(), _("The command:"), 
                      tag.pre(repr(' '.join(encoded_cmd))), 
                      (_("succeeded but emitted the following output:"),
                       _("failed with the following output:"))[failure],
                      out and tag.pre(repr(out)), 
                      err and tag.pre(repr(err))))
     else:
         return (False, None)
Пример #4
0
def pygmentize_to_tag(code, language, linenos=False, **kwargs):
    """
    Rebuild a raw pygmentize highlighting as tag elements, avoiding Genshi to delete blank lines.

    See http://genshi.edgewall.org/wiki/GenshiFaq#WhatisGenshidoingwiththewhitespaceinmymarkuptemplate
    """

    codeblock = pygmentize(code, language, linenos, **kwargs)
    pre = re.findall("<pre>(.*?)\n*</pre>", codeblock, re.DOTALL)
    if len(pre) == 1:
        return tag.pre(Markup(pre[0]), data_language=language)
    return tag.table(
        tag.tr(tag.td(tag.pre(pre[0])), tag.td(tag.pre(Markup(pre[1])))), data_language=language  # line numbers  # code
    )
Пример #5
0
    def process_request(self, req):
        if req.path_info == '/mindmap/status':
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            try:
                cursor.execute('SELECT hash,content FROM mindmapcache')
                content = tag.html(
                    tag.body(
                        tag.dd([[
                            tag.dt(tag.a(k, href=req.href.mindmap(k + '.mm'))),
                            tag.dd(tag.pre(v))
                        ] for k, v in cursor.fetchall()])))
            except Exception, e:
                content = tag.html(
                    tag.body(tag.strong("DB Error: " + unicode(e))))
            html = content.generate().render("xhtml")
            req.send_response(200)
            req.send_header('Cache-control', 'must-revalidate')
            req.send_header('Content-Type', 'text/html;charset=utf-8')
            req.send_header('Content-Length', len(html))
            req.end_headers()

            if req.method != 'HEAD':
                req.write(html)
            raise RequestDone
Пример #6
0
 def expand_macro(self, formatter, name, content, args=None):
     # pylint: disable=too-many-function-args
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     # pylint: disable=no-member
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:  # pylint: disable=broad-except
         message = content
         resource = Resource('repository', reponame)
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
 def expand_macro(self, formatter, name, content, args=None):
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource('repository', reponame)
     if formatter.context.resource.realm == 'ticket':
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(int(tkt_id) == int(formatter.context.resource.id)
                    for tkt_id in ticket_re.findall(message)):
             return tag.p(_("(The changeset message doesn't reference this "
                            "ticket)"), class_='hint')
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
             formatter.context.child('changeset', rev, parent=resource),
             message, escape_newlines=True), class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
 def safe_wiki_to_html(context, text):
     try:
         return format_to_html(self.env, context, text)
     except Exception, e:
         self.log.error('Unable to render component documentation: %s',
                        exception_to_unicode(e, traceback=True))
         return tag.pre(text)
Пример #11
0
 def expand_macro(self, formatter, name, content, args={}):
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource('repository', reponame)
     if formatter.context.resource.realm == 'ticket':
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(
                 int(tkt_id) == int(formatter.context.resource.id)
                 for tkt_id in ticket_re.findall(message)):
             return tag.p(
                 "(The changeset message doesn't reference this "
                 "ticket)",
                 class_='hint')
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #12
0
 def expand_macro(self, formatter, name, content, args={}):
     reponame = args.get("repository") or ""
     rev = args.get("revision")
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource("repository", reponame)
     if formatter.context.resource.realm == "ticket":
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(int(tkt_id) == int(formatter.context.resource.id) for tkt_id in ticket_re.findall(message)):
             return tag.p("(The changeset message doesn't reference this " "ticket)", class_="hint")
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(
             format_to_html(
                 self.env, formatter.context.child("changeset", rev, parent=resource), message, escape_newlines=True
             ),
             class_="message",
         )
     else:
         return tag.pre(message, class_="message")
Пример #13
0
 def safe_wiki_to_html(context, text):
     try:
         return format_to_html(self.env, context, text)
     except Exception as e:
         self.log.error("Unable to render component documentation: %s",
                        exception_to_unicode(e, traceback=True))
         return tag.pre(text)
Пример #14
0
 def expand_macro(self, formatter, name, content, args):
     add_stylesheet(formatter.req, 'text_boxes/css/text_boxes.css')
     # TODO(holtgrew): Actually, we would like to add a style sheet but this does not work. Thus we use a style tag below.
     #add_stylesheet(formatter.req, 'text_boxes/css/text_boxes.css')
     className = CLASSES.get(name, 'ShellBox')
     if name in ['TextIcon']:
         args = trac.wiki.parse_args(content)
         if not args or not args[0]:  # Handle case of empty entry.
             return None
         DEFAULT = 'gray'
         COLOR_CLASSES = ['green', 'red', 'yellow', 'black', 'gray', 'blue']
         color_class_name = args[1].get('color', DEFAULT)
         if not color_class_name in COLOR_CLASSES:
             color_class_name = DEFAULT
         return tag.span(args[0], class_=('text_icon %s' % color_class_name))
     elif name in ['MenuTrace']:
         args = trac.wiki.parse_args(content)
         if not args[0]:
             return None
         result = tag.span(args[0][0], class_='menu_item')
         for text in args[0][1:]:
             result += tag.span(u' \u25B8 ', class_='arrow')
             result += tag.span(text, class_='menu_item')
         return tag.span(result, class_='menu_trace')
     elif name in ['WarningBox', 'InfoBox', 'ImportantBox', 'AssignmentBox']:
         content_html = self.format_wiki(formatter, content)
         return tag.div(genshi.core.Markup(content_html), class_=className)
     else:
         return tag.pre(content, class_='wiki ' + className)
Пример #15
0
 def expand_macro(self, formatter, name, content, args):
     add_stylesheet(formatter.req, 'text_boxes/css/text_boxes.css')
     # TODO(holtgrew): Actually, we would like to add a style sheet but this does not work. Thus we use a style tag below.
     #add_stylesheet(formatter.req, 'text_boxes/css/text_boxes.css')
     className = CLASSES.get(name, 'ShellBox')
     if name in ['TextIcon']:
         args = trac.wiki.parse_args(content)
         if not args or not args[0]:  # Handle case of empty entry.
             return None
         DEFAULT = 'gray'
         COLOR_CLASSES = ['green', 'red', 'yellow', 'black', 'gray', 'blue']
         color_class_name = args[1].get('color', DEFAULT)
         if not color_class_name in COLOR_CLASSES:
             color_class_name = DEFAULT
         return tag.span(args[0],
                         class_=('text_icon %s' % color_class_name))
     elif name in ['MenuTrace']:
         args = trac.wiki.parse_args(content)
         if not args[0]:
             return None
         result = tag.span(args[0][0], class_='menu_item')
         for text in args[0][1:]:
             result += tag.span(u' \u25B8 ', class_='arrow')
             result += tag.span(text, class_='menu_item')
         return tag.span(result, class_='menu_trace')
     elif name in [
             'WarningBox', 'InfoBox', 'ImportantBox', 'AssignmentBox'
     ]:
         content_html = self.format_wiki(formatter, content)
         return tag.div(genshi.core.Markup(content_html), class_=className)
     else:
         return tag.pre(content, class_='wiki ' + className)
Пример #16
0
	def render(self, context, mimetype, content, filename=None, url=None):
		self.log.debug("Using Markdown Mimeviewer")
		req = context.req
		add_stylesheet(req, 'readme/readme.css')
		add_script(req, 'readme/marked.js')
		content = content_to_unicode(self.env, content, mimetype)
		# for some insane reason genshi will only preserve whitespace of <pre> elements, trac calls Stream.render() inappropriately.
		return tag.pre(content.encode('utf-8'))
Пример #17
0
 def render(self, context, mimetype, content, filename=None, url=None):
     self.log.debug("Using Markdown Mimeviewer")
     req = context.req
     add_stylesheet(req, 'readme/readme.css')
     add_script(req, 'readme/marked.js')
     content = content_to_unicode(self.env, content, mimetype)
     # for some insane reason genshi will only preserve whitespace of <pre> elements, trac calls Stream.render() inappropriately.
     return tag.pre(content.encode('utf-8'))
Пример #18
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()))
Пример #19
0
 def _error_div(self, msg):
     """Display msg in an error box, using Trac style."""
     if isinstance(msg, str):
         msg = to_unicode(msg)
     self.log.error(msg)
     if isinstance(msg, unicode):
         msg = tag.pre(escape(msg))
     return tag.div(
             tag.strong(_("Graphviz macro processor has detected an error. "
                          "Please fix the problem before continuing.")),
             msg, class_="system-message")
Пример #20
0
 def _error_div(self, msg):
     """Display msg in an error box, using Trac style."""
     if isinstance(msg, str):
         msg = to_unicode(msg)
     self.log.error(msg)
     if isinstance(msg, unicode):
         msg = tag.pre(escape(msg))
     return tag.div(
             tag.strong(_("Canviz macro processor has detected an error. "
                          "Please fix the problem before continuing.")),
             msg, class_="system-message")
Пример #21
0
class CommitTicketReferenceMacro(WikiMacroBase):
    """This is intended to replace the builtin macro by providing additional
    code review status info for the changeset.  To use, disable the builtin
    macro as follows:
    
    [components]
    tracopt.ticket.commit_updater.committicketreferencemacro = disabled
    """
    def expand_macro(self, formatter, name, content, args={}):
        reponame = args.get('repository') or ''
        rev = args.get('revision')
        repos = RepositoryManager(self.env).get_repository(reponame)
        try:
            changeset = repos.get_changeset(rev)
            message = changeset.message

            # add review status to commit message (
            review = CodeReview(self.env, reponame, rev)
            status = review.encode(review.status)
            message += '\n\n{{{#!html \n'
            message += '<div class="codereviewstatus">'
            message += '  <div class="system-message %s">' % status.lower()
            message += '    <p>Code review status: '
            message += '      <span>%s</span>' % review.status
            message += '    </p>'
            message += '  </div>'
            message += '</div>'
            message += '\n}}}'

            rev = changeset.rev
            resource = repos.resource
        except Exception, e:
            message = content
            resource = Resource('repository', reponame)
        if formatter.context.resource.realm == 'ticket':
            ticket_re = CommitTicketUpdater.ticket_re
            if not any(
                    int(tkt_id) == int(formatter.context.resource.id)
                    for tkt_id in ticket_re.findall(message)):
                return tag.p(
                    "(The changeset message doesn't reference this "
                    "ticket)",
                    class_='hint')
        if ChangesetModule(self.env).wiki_format_messages:
            return tag.div(format_to_html(self.env,
                                          formatter.context('changeset',
                                                            rev,
                                                            parent=resource),
                                          message,
                                          escape_newlines=True),
                           class_='message')
        else:
            return tag.pre(message, class_='message')
Пример #22
0
 def include(self, name, parse=True, raw=False, context="block", data=None):
     if name in self.storage:
         text = self.storage.page_text(name)
         if parse:
             return self.parser.generate(text, context=context,
                     environ=(self, data))
         else:
             if raw:
                 return Markup(text)
             else:
                 return tag.pre(text)
     else:
         return tag.div(tag.p(u"Page %s Not Found" % name), class_="error")
Пример #23
0
	def launch(self, proc_cmd, encoded_input, *args):
		"""Launch a process (cmd), and returns exitcode, stdout + stderr"""
		# Note: subprocess.Popen doesn't support unicode options arguments
		# (http://bugs.python.org/issue1759845) so we have to encode them.
		# Anyway, dot expects utf-8 or the encoding specified with -Gcharset.
		encoded_cmd = proc_cmd
		proc = subprocess.Popen(encoded_cmd, stdin=subprocess.PIPE,
			stdout=subprocess.PIPE, stderr=subprocess.PIPE)
		if encoded_input:
			proc.stdin.write(encoded_input)
		proc.stdin.close()
		out = proc.stdout.read()
		err = proc.stderr.read()
		failure = proc.wait() != 0
		if failure or err or out:
			return (failure, tag.div(tag.br(), _("The command:"), 
				tag.pre(repr(' '.join(encoded_cmd))), 
					       (_("succeeded but emitted the following output:"),
						_("failed with the following output:"))[failure],
					       out and tag.pre(out), 
					       err and tag.pre(err), class_="system-message"))
		else:
			return (False, None)
Пример #24
0
 def include(self, name, parse=True, raw=False, context="block", data=None):
     if name in self.storage:
         text = self.storage.page_text(name)
         if parse:
             return self.parser.generate(text,
                                         context=context,
                                         environ=(self, data))
         else:
             if raw:
                 return Markup(text)
             else:
                 return tag.pre(text)
     else:
         return tag.div(tag.p(u"Page %s Not Found" % name), class_="error")
Пример #25
0
 def expand_macro(self, formatter, name, content, args=None):
     # pylint: disable=too-many-function-args
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     # pylint: disable=no-member
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:  # pylint: disable=broad-except
         message = content
         resource = Resource('repository', reponame)
     config = self.ticket_replace_section
     fields = {}
     for key, value in config.options():
         idx = key.rfind('.')
         if idx >= 0:
             prefix, attribute = key[:idx], key[idx + 1:]
             field = fields.setdefault(prefix, {})
             field[attribute] = config.get(key)
         else:
             fields[key] = {'': value}
     for prefix, field in fields.iteritems():
         if not all(k in field for k in ['pattern', 'replace']):
             self.log.warn(
                 "Ignoring [%s] %s, missing .pattern or .replace" %
                 (self.ticket_replace_section_name, key))
             continue
         subst = {'repository': reponame, 'revision': rev}
         pattern = field['pattern'].replace('$(', '%(') % subst
         replace = field['replace'].replace('$(', '%(') % subst
         message = re.sub(pattern, replace, message)
     if ChangesetModule(self.env).wiki_format_messages:
         message = '\n'.join(
             map(lambda line: "> " + line, message.split('\n')))
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #26
0
def highlight(text, mime=None, lang=None, linenos=False, title=""):
    formatter = HTMLFormatter(cssclass="code",
                              linenos=linenos,
                              full=True,
                              title=title)

    try:
        if mime:
            lexer = pygments.lexers.get_lexer_for_mimetype(mime)
        elif lang:
            lexer = pygments.lexers.get_lexer_by_name(lang)
        else:
            lexer = pygments.lexers.guess_lexer(text)
    except pygments.util.ClassNotFound:
        return tag.pre(text)

    return Markup(pygments.highlight(text, lexer, formatter))
Пример #27
0
def include(macro, environ, data, *args, **kwargs):
    """Include the contents of another wiki page.
    
    This macro allows you to include the contents of another wiki page,
    optinoally allowing you to include it parsed (//the default//) or
    unparsed (//parse=False//). If the specified page does not exist,
    then "Page Not Found" will be displayed.

    **Arguments:**
    * name=None (//the name of the page to include//)
    * parse=True (//whether to parse the page//)
    * raw=False (//whether to include this raw//)
    * source=False (//whether to display the genereated HTML / source//)

    **Example(s):**
    {{{
    <<include "SandBox">>
    }}}

    <<include "SandBox">>

    {{{
    <<include "SandBox", parse=False>>
    }}}

    <<include "SandBox", parse=False>>
    """

    name = kwargs.get("name", (args and args[0]) or None)

    if name is None:
        return None

    parse = kwargs.get("parse", True)
    raw = kwargs.get("raw", False)
    source = kwargs.get("source", False)

    contents = environ.include(name, parse, raw, data=data)

    if source:
        return tag.pre("".join(serializer(contents)))
    else:
        return contents
Пример #28
0
def include(macro, environ, data, *args, **kwargs):
    """Include the contents of another wiki page.
    
    This macro allows you to include the contents of another wiki page,
    optinoally allowing you to include it parsed (//the default//) or
    unparsed (//parse=False//). If the specified page does not exist,
    then "Page Not Found" will be displayed.

    **Arguments:**
    * name=None (//the name of the page to include//)
    * parse=True (//whether to parse the page//)
    * raw=False (//whether to include this raw//)
    * source=False (//whether to display the genereated HTML / source//)

    **Example(s):**
    {{{
    <<include "SandBox">>
    }}}

    <<include "SandBox">>

    {{{
    <<include "SandBox", parse=False>>
    }}}

    <<include "SandBox", parse=False>>
    """
    
    name = kwargs.get("name", (args and args[0]) or None)

    if name is None:
        return None

    parse = kwargs.get("parse", True)
    raw = kwargs.get("raw", False)
    source = kwargs.get("source", False)

    contents = environ.include(name, parse, raw, data=data)

    if source:
        return tag.pre("".join(serializer(contents)))
    else:
        return contents
Пример #29
0
def highlight(text, mime=None, lang=None, linenos=False, title=""):
    formatter = HTMLFormatter(
        cssclass="code",
        linenos=linenos,
        full=True,
        title=title
    )

    try:
        if mime:
            lexer = pygments.lexers.get_lexer_for_mimetype(mime)
        elif lang:
            lexer = pygments.lexers.get_lexer_by_name(lang)
        else:
            lexer = pygments.lexers.guess_lexer(text)
    except pygments.util.ClassNotFound:
        return tag.pre(text)

    return Markup(pygments.highlight(text, lexer, formatter))
Пример #30
0
    def process_request(self, req):
        if req.path_info == '/mindmap/status':
          db = self.env.get_db_cnx()
          cursor = db.cursor()
          try:
              cursor.execute('SELECT hash,content FROM mindmapcache')
              content = tag.html(tag.body(tag.dd(
                  [ [tag.dt(tag.a(k,href=req.href.mindmap(k + '.mm'))),tag.dd(tag.pre(v))] for k,v in cursor.fetchall()]
                )))
          except Exception, e:
              content = tag.html(tag.body(tag.strong("DB Error: " + unicode(e))))
          html = content.generate().render("xhtml")
          req.send_response(200)
          req.send_header('Cache-control', 'must-revalidate')
          req.send_header('Content-Type', 'text/html;charset=utf-8')
          req.send_header('Content-Length', len(html))
          req.end_headers()

          if req.method != 'HEAD':
             req.write(html)
          raise RequestDone
Пример #31
0
def source(macro, environ, data, *args, **kwargs):
    """Display the HTML source of some parsed wiki text
    
    This macro allows you to display the genereated HTML source of some
    parsed wiki text. (//Useful mostly for debugging//).

    **Arguments:** //No Arguments//

    **Example(s):**
    {{{
    <<source>>**Hello World!**<</source>>
    }}}

    <<source>>**Hello World!**<</source>>
    """

    if not macro.body:
        return None

    contents = environ.parser.generate(macro.body, context="inline",
            environ=(environ, data))
    
    return tag.pre("".join(serializer(contents)))
Пример #32
0
 def expand_macro(self, formatter, name, content, args={}):
     if args:
         reponame = args.get('repository', '')
         rev = args.get('revision')
     else:
         if ',' in content:
             reponame = ''
             rev = 0
             for c in [x.strip() for x in content.split(',')]:
                 if c.isnumeric():
                     rev = c
                 else:
                     reponame = c
         else:
             rev = content.strip()
             reponame = ''
     repos = RepositoryManager(self.env).get_repository(reponame)
     if repos:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
     else:
         message = content
     if formatter.context.resource.realm == 'ticket':
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(int(tkt_id) == formatter.context.resource.id
                    for tkt_id in ticket_re.findall(message)):
             return tag.div(tag.p(_("(The changeset message doesn't "
                 "reference this ticket)"), class_='hint'),
                 class_='commitmessage')
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
             formatter.context('changeset', rev, parent=repos.resource),
             message, escape_newlines=True), class_='commitmessage')
     else:
         return tag.pre(message, class_='commitmessage')
Пример #33
0
def source(macro, environ, data, *args, **kwargs):
    """Display the HTML source of some parsed wiki text
    
    This macro allows you to display the genereated HTML source of some
    parsed wiki text. (//Useful mostly for debugging//).

    **Arguments:** //No Arguments//

    **Example(s):**
    {{{
    <<source>>**Hello World!**<</source>>
    }}}

    <<source>>**Hello World!**<</source>>
    """

    if not macro.body:
        return None

    contents = environ.parser.generate(macro.body,
                                       context="inline",
                                       environ=(environ, data))

    return tag.pre("".join(serializer(contents)))
Пример #34
0
    def _render_view(self, req, id):
        """Retrieve the report results and pre-process them for rendering."""
        title, description, sql = self.get_report(id)
        try:
            args = self.get_var_args(req)
        except ValueError as e:
            raise TracError(_("Report failed: %(error)s", error=e))

        # If this is a saved custom query, redirect to the query module
        #
        # A saved query is either an URL query (?... or query:?...),
        # or a query language expression (query:...).
        #
        # It may eventually contain newlines, for increased clarity.
        #
        query = ''.join([line.strip() for line in sql.splitlines()])
        if query and (query[0] == '?' or query.startswith('query:?')):
            query = query if query[0] == '?' else query[6:]
            report_id = 'report=%s' % id
            if 'report=' in query:
                if not report_id in query:
                    err = _('When specified, the report number should be '
                            '"%(num)s".', num=id)
                    req.redirect(req.href.report(id, action='edit', error=err))
            else:
                if query[-1] != '?':
                    query += '&'
                query += report_id
            req.redirect(req.href.query() + quote_query_string(query))
        elif query.startswith('query:'):
            try:
                from trac.ticket.query import Query, QuerySyntaxError
                query = Query.from_string(self.env, query[6:], report=id)
                req.redirect(query.get_href(req.href))
            except QuerySyntaxError as e:
                req.redirect(req.href.report(id, action='edit',
                                             error=to_unicode(e)))

        format = req.args.get('format')
        if format == 'sql':
            self._send_sql(req, id, title, description, sql)

        title = '{%i} %s' % (id, title)

        report_resource = Resource('report', id)
        req.perm(report_resource).require('REPORT_VIEW')
        context = web_context(req, report_resource)

        page = int(req.args.get('page', '1'))
        default_max = {'rss': self.items_per_page_rss,
                       'csv': 0, 'tab': 0}.get(format, self.items_per_page)
        max = req.args.get('max')
        limit = as_int(max, default_max, min=0) # explict max takes precedence
        offset = (page - 1) * limit

        sort_col = req.args.get('sort', '')
        asc = req.args.get('asc', 1)
        asc = bool(int(asc)) # string '0' or '1' to int/boolean

        def report_href(**kwargs):
            """Generate links to this report preserving user variables,
            and sorting and paging variables.
            """
            params = args.copy()
            if sort_col:
                params['sort'] = sort_col
            params['page'] = page
            if max:
                params['max'] = max
            params.update(kwargs)
            params['asc'] = '1' if params.get('asc', asc) else '0'
            return req.href.report(id, params)

        data = {'action': 'view',
                'report': {'id': id, 'resource': report_resource},
                'context': context,
                'title': sub_vars(title, args),
                'description': sub_vars(description or '', args),
                'max': limit, 'args': args, 'show_args_form': False,
                'message': None, 'paginator': None,
                'report_href': report_href,
                }

        res = self.execute_paginated_report(req, id, sql, args, limit, offset)

        if len(res) == 2:
            e, sql = res
            data['message'] = \
                tag_("Report execution failed: %(error)s %(sql)s",
                     error=tag.pre(exception_to_unicode(e)),
                     sql=tag(tag.hr(),
                             tag.pre(sql, style="white-space: pre")))
            return 'report_view.html', data, None

        cols, results, num_items, missing_args, limit_offset = res
        need_paginator = limit > 0 and limit_offset
        need_reorder = limit_offset is None
        results = [list(row) for row in results]
        numrows = len(results)

        paginator = None
        if need_paginator:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
            for p in shown_pages:
                pagedata.append([report_href(page=p), None, str(p),
                                 _('Page %(num)d', num=p)])
            fields = ['href', 'class', 'string', 'title']
            paginator.shown_pages = [dict(zip(fields, p)) for p in pagedata]
            paginator.current_page = {'href': None, 'class': 'current',
                                      'string': str(paginator.page + 1),
                                      'title': None}
            numrows = paginator.num_items

        # Place retrieved columns in groups, according to naming conventions
        #  * _col_ means fullrow, i.e. a group with one header
        #  * col_ means finish the current group and start a new one

        field_labels = TicketSystem(self.env).get_ticket_field_labels()

        header_groups = [[]]
        for idx, col in enumerate(cols):
            if col in field_labels:
                title = field_labels[col]
            else:
                title = col.strip('_').capitalize()
            header = {
                'col': col,
                'title': title,
                'hidden': False,
                'asc': None,
            }

            if col == sort_col:
                header['asc'] = asc
                if not paginator and need_reorder:
                    # this dict will have enum values for sorting
                    # and will be used in sortkey(), if non-empty:
                    sort_values = {}
                    if sort_col in ('status', 'resolution', 'priority',
                                    'severity'):
                        # must fetch sort values for that columns
                        # instead of comparing them as strings
                        with self.env.db_query as db:
                            for name, value in db(
                                    "SELECT name, %s FROM enum WHERE type=%%s"
                                    % db.cast('value', 'int'),
                                    (sort_col,)):
                                sort_values[name] = value

                    def sortkey(row):
                        val = row[idx]
                        # check if we have sort_values, then use them as keys.
                        if sort_values:
                            return sort_values.get(val)
                        # otherwise, continue with string comparison:
                        if isinstance(val, basestring):
                            val = val.lower()
                        return val
                    results = sorted(results, key=sortkey, reverse=(not asc))

            header_group = header_groups[-1]

            if col.startswith('__') and col.endswith('__'): # __col__
                header['hidden'] = True
            elif col[0] == '_' and col[-1] == '_':          # _col_
                header_group = []
                header_groups.append(header_group)
                header_groups.append([])
            elif col[0] == '_':                             # _col
                header['hidden'] = True
            elif col[-1] == '_':                            # col_
                header_groups.append([])
            header_group.append(header)

        # Structure the rows and cells:
        #  - group rows according to __group__ value, if defined
        #  - group cells the same way headers are grouped
        chrome = Chrome(self.env)
        row_groups = []
        authorized_results = []
        prev_group_value = None
        for row_idx, result in enumerate(results):
            col_idx = 0
            cell_groups = []
            row = {'cell_groups': cell_groups}
            realm = self.realm
            parent_realm = ''
            parent_id = ''
            email_cells = []
            for header_group in header_groups:
                cell_group = []
                for header in header_group:
                    value = cell_value(result[col_idx])
                    cell = {'value': value, 'header': header, 'index': col_idx}
                    col = header['col']
                    col_idx += 1
                    # Detect and create new group
                    if col == '__group__' and value != prev_group_value:
                        prev_group_value = value
                        # Brute force handling of email in group by header
                        row_groups.append(
                            (value and chrome.format_author(req, value), []))
                    # Other row properties
                    row['__idx__'] = row_idx
                    if col in self._html_cols:
                        row[col] = value
                    if col in ('report', 'ticket', 'id', '_id'):
                        row['id'] = value
                    # Special casing based on column name
                    col = col.strip('_')
                    if col in ('reporter', 'cc', 'owner'):
                        email_cells.append(cell)
                    elif col == 'realm':
                        realm = value
                    elif col == 'parent_realm':
                        parent_realm = value
                    elif col == 'parent_id':
                        parent_id = value
                    cell_group.append(cell)
                cell_groups.append(cell_group)
            if parent_realm:
                resource = Resource(realm, row.get('id'),
                                    parent=Resource(parent_realm, parent_id))
            else:
                resource = Resource(realm, row.get('id'))
            # FIXME: for now, we still need to hardcode the realm in the action
            if resource.realm.upper()+'_VIEW' not in req.perm(resource):
                continue
            authorized_results.append(result)
            if email_cells:
                for cell in email_cells:
                    emails = chrome.format_emails(context.child(resource),
                                                  cell['value'])
                    result[cell['index']] = cell['value'] = emails
            row['resource'] = resource
            if row_groups:
                row_group = row_groups[-1][1]
            else:
                row_group = []
                row_groups = [(None, row_group)]
            row_group.append(row)

        data.update({'header_groups': header_groups,
                     'row_groups': row_groups,
                     'numrows': numrows})

        if format == 'rss':
            data['context'] = web_context(req, report_resource,
                                          absurls=True)
            return 'report.rss', data, 'application/rss+xml'
        elif format == 'csv':
            filename = 'report_%s.csv' % id if id else 'report.csv'
            self._send_csv(req, cols, authorized_results, mimetype='text/csv',
                           filename=filename)
        elif format == 'tab':
            filename = 'report_%s.tsv' % id if id else 'report.tsv'
            self._send_csv(req, cols, authorized_results, '\t',
                           mimetype='text/tab-separated-values',
                           filename=filename)
        else:
            p = page if max is not None else None
            add_link(req, 'alternate',
                     auth_link(req, report_href(format='rss', page=None)),
                     _('RSS Feed'), 'application/rss+xml', 'rss')
            add_link(req, 'alternate', report_href(format='csv', page=p),
                     _('Comma-delimited Text'), 'text/plain')
            add_link(req, 'alternate', report_href(format='tab', page=p),
                     _('Tab-delimited Text'), 'text/plain')
            if 'REPORT_SQL_VIEW' in req.perm('report', id):
                add_link(req, 'alternate',
                         req.href.report(id=id, format='sql'),
                         _('SQL Query'), 'text/plain')

            # reuse the session vars of the query module so that
            # the query navigation links on the ticket can be used to
            # navigate report results as well
            try:
                req.session['query_tickets'] = \
                    ' '.join([str(int(row['id']))
                              for rg in row_groups for row in rg[1]])
                req.session['query_href'] = \
                    req.session['query_href'] = report_href()
                # Kludge: we have to clear the other query session
                # variables, but only if the above succeeded
                for var in ('query_constraints', 'query_time'):
                    if var in req.session:
                        del req.session[var]
            except (ValueError, KeyError):
                pass
            if set(data['args']) - set(['USER']):
                data['show_args_form'] = True
                add_script(req, 'common/js/folding.js')
            if missing_args:
                add_warning(req, _(
                    'The following arguments are missing: %(args)s',
                    args=", ".join(missing_args)))
            return 'report_view.html', data, None
Пример #35
0
                'max': limit, 'args': args, 'show_args_form': False,
                'message': None, 'paginator': None,
                'report_href': report_href, 
                }

        try:
            cols, results, num_items, missing_args = \
                self.execute_paginated_report(req, db, id, sql, args, limit,
                                              offset)
            results = [list(row) for row in results]
            numrows = len(results)

        except Exception, e:
            db.rollback()
            data['message'] = tag_('Report execution failed: %(error)s',
                                   error=tag.pre(to_unicode(e)))
            return 'report_view.html', data, None

        paginator = None
        if limit > 0:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
Пример #36
0
    def _do_save(self, req, db, milestone):
        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')
        
        ticket_module = TicketModule(self.env)
        ticket_module._populate(req, milestone.ticket, False)
        if not milestone.exists:
            reporter_id = get_reporter_id(req, 'author')
            milestone.ticket.values['reporter'] = reporter_id

        action = req.args.get('action', 'leave')

        field_changes, problems = ticket_module.get_ticket_changes(req, milestone.ticket,
                                    action)
        if problems:
            for problem in problems:
                add_warning(req, problem)
                add_warning(req,
                            tag(tag.p('Please review your configuration, '
                                      'probably starting with'),
                                tag.pre('[trac]\nworkflow = ...\n'),
                                tag.p('in your ', tag.tt('trac.ini'), '.'))
                            )

        ticket_module._apply_ticket_changes(milestone.ticket, field_changes)

        old_name = milestone.name
        new_name = milestone.ticket['summary']
        
        milestone.name = new_name
        milestone.description = milestone.ticket['description']

        due = req.args.get('duedate', '')
        milestone.due = due and parse_date(due, tzinfo=req.tz) or None
        milestone.ticket['duedate']=milestone.due and str(to_timestamp(milestone.due)) or None

        completed = req.args.get('completedate', '')
        retarget_to = req.args.get('target')

        # Instead of raising one single error, check all the constraints and
        # let the user fix them by going back to edit mode showing the warnings
        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        # -- check the name
        if new_name:
            if new_name != old_name:
                # check that the milestone doesn't already exists
                # FIXME: the whole .exists business needs to be clarified
                #        (#4130) and should behave like a WikiPage does in
                #        this respect.
                try:
                    other_milestone = StructuredMilestone(self.env, new_name, db)
                    warn(_('Milestone "%(name)s" already exists, please '
                           'choose another name', name=new_name))
                except ResourceNotFound:
                    pass
        else:
            warn(_('You must provide a name for the milestone.'))

        # -- check completed date
        if action in MilestoneSystem(self.env).starting_action:
            milestone.ticket['started'] = str(to_timestamp(datetime.now(utc)))
        if action in MilestoneSystem(self.env).completing_action:
            milestone.completed = datetime.now(utc)
            
        if warnings:
            return self._render_editor(req, db, milestone)
        
        # -- actually save changes
        if milestone.exists:
            cnum = req.args.get('cnum')
            replyto = req.args.get('replyto')
            internal_cnum = cnum
            if cnum and replyto: # record parent.child relationship
                internal_cnum = '%s.%s' % (replyto, cnum)

            now = datetime.now(utc)
            milestone.save_changes(get_reporter_id(req, 'author'),
                                         req.args.get('comment'), when=now,
                                         cnum=internal_cnum)
            # eventually retarget opened tickets associated with the milestone
            if 'retarget' in req.args and completed:
                cursor = db.cursor()
                cursor.execute("UPDATE ticket SET milestone=%s WHERE "
                               "milestone=%s and status != 'closed'",
                                (retarget_to, old_name))
                self.env.log.info('Tickets associated with milestone %s '
                                  'retargeted to %s' % (old_name, retarget_to))
        else:
            milestone.insert()
        db.commit()

        add_notice(req, _('Your changes have been saved.'))
        jump_to = req.args.get('jump_to', 'roadmap')
        if jump_to=='roadmap':
            req.redirect(req.href.roadmap())
        elif jump_to =='whiteboard':
            req.redirect(req.href.whiteboard('team_tasks')+'#'+milestone.name)
        else:
            req.redirect(req.href.milestone(milestone.name))
Пример #37
0
    def render(self,
               context,
               mimetype,
               content,
               filename=None,
               url=None,
               annotations=None,
               force_source=False):
        """Render an XHTML preview of the given `content`.

        `content` is the same as an `IHTMLPreviewRenderer.render`'s
        `content` argument.

        The specified `mimetype` will be used to select the most appropriate
        `IHTMLPreviewRenderer` implementation available for this MIME type.
        If not given, the MIME type will be infered from the filename or the
        content.

        Return a string containing the XHTML text.

        When rendering with an `IHTMLPreviewRenderer` fails, a warning is added
        to the request associated with the context (if any), unless the
        `disable_warnings` hint is set to `True`.
        """
        if not content:
            return ''
        if not isinstance(context, RenderingContext):
            raise TypeError("RenderingContext expected (since 0.11)")

        # Ensure we have a MIME type for this content
        full_mimetype = mimetype
        if not full_mimetype:
            if hasattr(content, 'read'):
                content = content.read(self.max_preview_size)
            full_mimetype = self.get_mimetype(filename, content)
        if full_mimetype:
            mimetype = ct_mimetype(full_mimetype)  # split off charset
        else:
            mimetype = full_mimetype = 'text/plain'  # fallback if not binary

        # Determine candidate `IHTMLPreviewRenderer`s
        candidates = []
        for renderer in self.renderers:
            qr = renderer.get_quality_ratio(mimetype)
            if qr > 0:
                candidates.append((qr, renderer))
        candidates.sort(lambda x, y: cmp(y[0], x[0]))

        # Wrap file-like object so that it can be read multiple times
        if hasattr(content, 'read'):
            content = Content(content, self.max_preview_size)

        # First candidate which renders successfully wins.
        # Also, we don't want to expand tabs more than once.
        expanded_content = None
        for qr, renderer in candidates:
            if force_source and not getattr(renderer, 'returns_source', False):
                continue  # skip non-source renderers in force_source mode
            if isinstance(content, Content):
                content.reset()
            try:
                ann_names = ', '.join(annotations) if annotations else \
                           'no annotations'
                self.log.debug('Trying to render HTML preview using %s [%s]',
                               renderer.__class__.__name__, ann_names)

                # check if we need to perform a tab expansion
                rendered_content = content
                if getattr(renderer, 'expand_tabs', False):
                    if expanded_content is None:
                        content = content_to_unicode(self.env, content,
                                                     full_mimetype)
                        expanded_content = content.expandtabs(self.tab_width)
                    rendered_content = expanded_content

                result = renderer.render(context, full_mimetype,
                                         rendered_content, filename, url)
                if not result:
                    continue

                if not (force_source
                        or getattr(renderer, 'returns_source', False)):
                    # Direct rendering of content
                    if isinstance(result, basestring):
                        if not isinstance(result, unicode):
                            result = to_unicode(result)
                        return Markup(to_unicode(result))
                    elif isinstance(result, Fragment):
                        return result.generate()
                    else:
                        return result

                # Render content as source code
                if annotations:
                    marks = context.req.args.get('marks') if context.req \
                            else None
                    if marks:
                        context.set_hints(marks=marks)
                    return self._render_source(context, result, annotations)
                else:
                    if isinstance(result, list):
                        result = Markup('\n').join(result)
                    return tag.div(class_='code')(tag.pre(result)).generate()

            except Exception as e:
                self.log.warning('HTML preview using %s failed: %s',
                                 renderer.__class__.__name__,
                                 exception_to_unicode(e, traceback=True))
                if context.req and not context.get_hint('disable_warnings'):
                    from trac.web.chrome import add_warning
                    add_warning(
                        context.req,
                        _("HTML preview using %(renderer)s failed (%(err)s)",
                          renderer=renderer.__class__.__name__,
                          err=exception_to_unicode(e)))
Пример #38
0
            'paginator': None,
            'report_href': report_href,
        }

        with self.env.db_query as db:
            try:
                cols, results, num_items, missing_args = \
                    self.execute_paginated_report(req, db, id, sql, args, limit,
                                                  offset)
                results = [list(row) for row in results]
                numrows = len(results)

            except Exception, e:
                data['message'] = tag_(
                    'Report execution failed: %(error)s',
                    error=tag.pre(exception_to_unicode(e, traceback=True)))
                return 'report_view.html', data, None

        paginator = None
        if limit > 0:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
Пример #39
0
    def _do_save(self, req, db, milestone):
        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        ticket_module = TicketModule(self.env)
        ticket_module._populate(req, milestone.ticket, False)
        if not milestone.exists:
            reporter_id = get_reporter_id(req, 'author')
            milestone.ticket.values['reporter'] = reporter_id

        action = req.args.get('action', 'leave')

        field_changes, problems = ticket_module.get_ticket_changes(
            req, milestone.ticket, action)
        if problems:
            for problem in problems:
                add_warning(req, problem)
                add_warning(
                    req,
                    tag(
                        tag.p('Please review your configuration, '
                              'probably starting with'),
                        tag.pre('[trac]\nworkflow = ...\n'),
                        tag.p('in your ', tag.tt('trac.ini'), '.')))

        ticket_module._apply_ticket_changes(milestone.ticket, field_changes)

        old_name = milestone.name
        new_name = milestone.ticket['summary']

        milestone.name = new_name
        milestone.description = milestone.ticket['description']

        due = req.args.get('duedate', '')
        milestone.due = due and parse_date(due, tzinfo=req.tz) or None
        milestone.ticket['duedate'] = milestone.due and str(
            to_timestamp(milestone.due)) or None

        completed = req.args.get('completedate', '')
        retarget_to = req.args.get('target')

        # Instead of raising one single error, check all the constraints and
        # let the user fix them by going back to edit mode showing the warnings
        warnings = []

        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        # -- check the name
        if new_name:
            if new_name != old_name:
                # check that the milestone doesn't already exists
                # FIXME: the whole .exists business needs to be clarified
                #        (#4130) and should behave like a WikiPage does in
                #        this respect.
                try:
                    other_milestone = StructuredMilestone(
                        self.env, new_name, db)
                    warn(
                        _(
                            'Milestone "%(name)s" already exists, please '
                            'choose another name',
                            name=new_name))
                except ResourceNotFound:
                    pass
        else:
            warn(_('You must provide a name for the milestone.'))

        # -- check completed date
        if action in MilestoneSystem(self.env).starting_action:
            milestone.ticket['started'] = str(to_timestamp(datetime.now(utc)))
        if action in MilestoneSystem(self.env).completing_action:
            milestone.completed = datetime.now(utc)

        if warnings:
            return self._render_editor(req, db, milestone)

        # -- actually save changes
        if milestone.exists:
            cnum = req.args.get('cnum')
            replyto = req.args.get('replyto')
            internal_cnum = cnum
            if cnum and replyto:  # record parent.child relationship
                internal_cnum = '%s.%s' % (replyto, cnum)

            now = datetime.now(utc)
            milestone.save_changes(get_reporter_id(req, 'author'),
                                   req.args.get('comment'),
                                   when=now,
                                   cnum=internal_cnum)
            # eventually retarget opened tickets associated with the milestone
            if 'retarget' in req.args and completed:
                cursor = db.cursor()
                cursor.execute(
                    "UPDATE ticket SET milestone=%s WHERE "
                    "milestone=%s and status != 'closed'",
                    (retarget_to, old_name))
                self.env.log.info('Tickets associated with milestone %s '
                                  'retargeted to %s' % (old_name, retarget_to))
        else:
            milestone.insert()
        db.commit()

        add_notice(req, _('Your changes have been saved.'))
        jump_to = req.args.get('jump_to', 'roadmap')
        if jump_to == 'roadmap':
            req.redirect(req.href.roadmap())
        elif jump_to == 'whiteboard':
            req.redirect(
                req.href.whiteboard('team_tasks') + '#' + milestone.name)
        else:
            req.redirect(req.href.milestone(milestone.name))
Пример #40
0
                'title': title, 'description': description,
                'max': limit, 'args': args, 'show_args_form': False,
                'message': None, 'paginator': None,
                'report_href': report_href,
                }

        res = None
        with self.env.db_query as db:
            res = self.execute_paginated_report(req, db, id, sql, args, limit,
                                                offset)

        if len(res) == 2:
             e, sql = res
             data['message'] = \
                 tag_("Report execution failed: %(error)s %(sql)s",
                      error=tag.pre(exception_to_unicode(e)),
                      sql=tag(tag.hr(),
                              tag.pre(sql, style="white-space: pre")))
             return 'report_view.html', data, None

        cols, results, num_items, missing_args, limit_offset = res
        need_paginator = limit > 0 and limit_offset
        need_reorder = limit_offset is None
        results = [list(row) for row in results]
        numrows = len(results)

        paginator = None
        if need_paginator:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
Пример #41
0
Файл: report.py Проект: t2y/trac
    def _render_view(self, req, id):
        """Retrieve the report results and pre-process them for rendering."""
        title, description, sql = self.get_report(id)
        try:
            args = self.get_var_args(req)
        except ValueError as e:
            raise TracError(_("Report failed: %(error)s", error=e))

        # If this is a saved custom query, redirect to the query module
        #
        # A saved query is either an URL query (?... or query:?...),
        # or a query language expression (query:...).
        #
        # It may eventually contain newlines, for increased clarity.
        #
        query = ''.join([line.strip() for line in sql.splitlines()])
        if query and (query[0] == '?' or query.startswith('query:?')):
            query = query if query[0] == '?' else query[6:]
            report_id = 'report=%s' % id
            if 'report=' in query:
                if not report_id in query:
                    err = _(
                        'When specified, the report number should be '
                        '"%(num)s".',
                        num=id)
                    req.redirect(req.href.report(id, action='edit', error=err))
            else:
                if query[-1] != '?':
                    query += '&'
                query += report_id
            req.redirect(req.href.query() + quote_query_string(query))
        elif query.startswith('query:'):
            try:
                from trac.ticket.query import Query, QuerySyntaxError
                query = Query.from_string(self.env, query[6:], report=id)
                req.redirect(query.get_href(req))
            except QuerySyntaxError as e:
                req.redirect(
                    req.href.report(id, action='edit', error=to_unicode(e)))

        format = req.args.get('format')
        if format == 'sql':
            self._send_sql(req, id, title, description, sql)

        title = '{%i} %s' % (id, title)

        report_resource = Resource('report', id)
        req.perm(report_resource).require('REPORT_VIEW')
        context = web_context(req, report_resource)

        page = int(req.args.get('page', '1'))
        default_max = {
            'rss': self.items_per_page_rss,
            'csv': 0,
            'tab': 0
        }.get(format, self.items_per_page)
        max = req.args.get('max')
        limit = as_int(max, default_max, min=0)  # explict max takes precedence
        offset = (page - 1) * limit

        sort_col = req.args.get('sort', '')
        asc = req.args.get('asc', 1)
        asc = bool(int(asc))  # string '0' or '1' to int/boolean

        def report_href(**kwargs):
            """Generate links to this report preserving user variables,
            and sorting and paging variables.
            """
            params = args.copy()
            if sort_col:
                params['sort'] = sort_col
            params['page'] = page
            if max:
                params['max'] = max
            params.update(kwargs)
            params['asc'] = '1' if params.get('asc', asc) else '0'
            return req.href.report(id, params)

        data = {
            'action': 'view',
            'report': {
                'id': id,
                'resource': report_resource
            },
            'context': context,
            'title': sub_vars(title, args),
            'description': sub_vars(description or '', args),
            'max': limit,
            'args': args,
            'show_args_form': False,
            'message': None,
            'paginator': None,
            'report_href': report_href,
        }

        res = self.execute_paginated_report(req, id, sql, args, limit, offset)

        if len(res) == 2:
            e, sql = res
            data['message'] = \
                tag_("Report execution failed: %(error)s %(sql)s",
                     error=tag.pre(exception_to_unicode(e)),
                     sql=tag(tag.hr(),
                             tag.pre(sql, style="white-space: pre")))
            return 'report_view.html', data, None

        cols, results, num_items, missing_args, limit_offset = res
        need_paginator = limit > 0 and limit_offset
        need_reorder = limit_offset is None
        results = [list(row) for row in results]
        numrows = len(results)

        paginator = None
        if need_paginator:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
            for p in shown_pages:
                pagedata.append([
                    report_href(page=p), None,
                    str(p),
                    _('Page %(num)d', num=p)
                ])
            fields = ['href', 'class', 'string', 'title']
            paginator.shown_pages = [dict(zip(fields, p)) for p in pagedata]
            paginator.current_page = {
                'href': None,
                'class': 'current',
                'string': str(paginator.page + 1),
                'title': None
            }
            numrows = paginator.num_items

        # Place retrieved columns in groups, according to naming conventions
        #  * _col_ means fullrow, i.e. a group with one header
        #  * col_ means finish the current group and start a new one

        field_labels = TicketSystem(self.env).get_ticket_field_labels()

        header_groups = [[]]
        for idx, col in enumerate(cols):
            if col in field_labels:
                title = field_labels[col]
            else:
                title = col.strip('_').capitalize()
            header = {
                'col': col,
                'title': title,
                'hidden': False,
                'asc': None,
            }

            if col == sort_col:
                header['asc'] = asc
                if not paginator and need_reorder:
                    # this dict will have enum values for sorting
                    # and will be used in sortkey(), if non-empty:
                    sort_values = {}
                    if sort_col in ('status', 'resolution', 'priority',
                                    'severity'):
                        # must fetch sort values for that columns
                        # instead of comparing them as strings
                        with self.env.db_query as db:
                            for name, value in db(
                                    "SELECT name, %s FROM enum WHERE type=%%s"
                                    % db.cast('value', 'int'), (sort_col, )):
                                sort_values[name] = value

                    def sortkey(row):
                        val = row[idx]
                        # check if we have sort_values, then use them as keys.
                        if sort_values:
                            return sort_values.get(val)
                        # otherwise, continue with string comparison:
                        if isinstance(val, basestring):
                            val = val.lower()
                        return val

                    results = sorted(results, key=sortkey, reverse=(not asc))

            header_group = header_groups[-1]

            if col.startswith('__') and col.endswith('__'):  # __col__
                header['hidden'] = True
            elif col[0] == '_' and col[-1] == '_':  # _col_
                header_group = []
                header_groups.append(header_group)
                header_groups.append([])
            elif col[0] == '_':  # _col
                header['hidden'] = True
            elif col[-1] == '_':  # col_
                header_groups.append([])
            header_group.append(header)

        # Structure the rows and cells:
        #  - group rows according to __group__ value, if defined
        #  - group cells the same way headers are grouped
        chrome = Chrome(self.env)
        row_groups = []
        authorized_results = []
        prev_group_value = None
        for row_idx, result in enumerate(results):
            col_idx = 0
            cell_groups = []
            row = {'cell_groups': cell_groups}
            realm = 'ticket'
            parent_realm = ''
            parent_id = ''
            email_cells = []
            for header_group in header_groups:
                cell_group = []
                for header in header_group:
                    value = cell_value(result[col_idx])
                    cell = {'value': value, 'header': header, 'index': col_idx}
                    col = header['col']
                    col_idx += 1
                    # Detect and create new group
                    if col == '__group__' and value != prev_group_value:
                        prev_group_value = value
                        # Brute force handling of email in group by header
                        row_groups.append(
                            (value and chrome.format_author(req, value), []))
                    # Other row properties
                    row['__idx__'] = row_idx
                    if col in self._html_cols:
                        row[col] = value
                    if col in ('report', 'ticket', 'id', '_id'):
                        row['id'] = value
                    # Special casing based on column name
                    col = col.strip('_')
                    if col in ('reporter', 'cc', 'owner'):
                        email_cells.append(cell)
                    elif col == 'realm':
                        realm = value
                    elif col == 'parent_realm':
                        parent_realm = value
                    elif col == 'parent_id':
                        parent_id = value
                    cell_group.append(cell)
                cell_groups.append(cell_group)
            if parent_realm:
                resource = Resource(realm,
                                    row.get('id'),
                                    parent=Resource(parent_realm, parent_id))
            else:
                resource = Resource(realm, row.get('id'))
            # FIXME: for now, we still need to hardcode the realm in the action
            if resource.realm.upper() + '_VIEW' not in req.perm(resource):
                continue
            authorized_results.append(result)
            if email_cells:
                for cell in email_cells:
                    emails = chrome.format_emails(context.child(resource),
                                                  cell['value'])
                    result[cell['index']] = cell['value'] = emails
            row['resource'] = resource
            if row_groups:
                row_group = row_groups[-1][1]
            else:
                row_group = []
                row_groups = [(None, row_group)]
            row_group.append(row)

        data.update({
            'header_groups': header_groups,
            'row_groups': row_groups,
            'numrows': numrows
        })

        if format == 'rss':
            data['email_map'] = chrome.get_email_map()
            data['context'] = web_context(req, report_resource, absurls=True)
            return 'report.rss', data, 'application/rss+xml'
        elif format == 'csv':
            filename = 'report_%s.csv' % id if id else 'report.csv'
            self._send_csv(req,
                           cols,
                           authorized_results,
                           mimetype='text/csv',
                           filename=filename)
        elif format == 'tab':
            filename = 'report_%s.tsv' % id if id else 'report.tsv'
            self._send_csv(req,
                           cols,
                           authorized_results,
                           '\t',
                           mimetype='text/tab-separated-values',
                           filename=filename)
        else:
            p = page if max is not None else None
            add_link(req, 'alternate',
                     auth_link(req, report_href(format='rss', page=None)),
                     _('RSS Feed'), 'application/rss+xml', 'rss')
            add_link(req, 'alternate', report_href(format='csv', page=p),
                     _('Comma-delimited Text'), 'text/plain')
            add_link(req, 'alternate', report_href(format='tab', page=p),
                     _('Tab-delimited Text'), 'text/plain')
            if 'REPORT_SQL_VIEW' in req.perm('report', id):
                add_link(req, 'alternate', req.href.report(id=id,
                                                           format='sql'),
                         _('SQL Query'), 'text/plain')

            # reuse the session vars of the query module so that
            # the query navigation links on the ticket can be used to
            # navigate report results as well
            try:
                req.session['query_tickets'] = \
                    ' '.join([str(int(row['id']))
                              for rg in row_groups for row in rg[1]])
                req.session['query_href'] = \
                    req.session['query_href'] = report_href()
                # Kludge: we have to clear the other query session
                # variables, but only if the above succeeded
                for var in ('query_constraints', 'query_time'):
                    if var in req.session:
                        del req.session[var]
            except (ValueError, KeyError):
                pass
            if set(data['args']) - set(['USER']):
                data['show_args_form'] = True
                add_script(req, 'common/js/folding.js')
            if missing_args:
                add_warning(
                    req,
                    _('The following arguments are missing: %(args)s',
                      args=", ".join(missing_args)))
            return 'report_view.html', data, None
Пример #42
0
 def expand_macro(self, formatter, name, content):
     """
     """
     args, kwargs = parse_args(content, strict=False)
     kwargs = string_keys(kwargs)
     
     cite_list = getattr(formatter, CITE_LIST, [])
     cite_dict = getattr(formatter, CITE_DICT, {})
     
     if len(args) == 1:
         label = args[0]
         description = ''
     
     if len(args) == 2:
         label = args[0]
         description = args[1]
     
     # Allow for extra parameters, people can use it to store BibTeX data.
     if len(args) == 0:
         raise TracError('At the very least a `label` is required.')
     
     # `makeindex` will not make sense to non-LaTeX users.
     if label == 'references':
         h = kwargs.get('h', '1')
         backref = kwargs.get('backref')
         
         tags = []
         if h == '1':
             root = tag.h1
         elif h == '2':
             root = tag.h2
         elif h == '3':
             root = tag.h3
         elif h == '4':
             root = tag.h4
         else:
             root = tag.h5
         
         tags.append(root(id='References')('References'))
         
         li = []
         for index, label in enumerate(cite_list):
             description, params = cite_dict[label]
             
             if description:
                 line = [description]
             else:
                 line = []
             
             for key in REFERENCE_SEQUENCE:
                 value = params.get(key)
                 if value:
                     reference_formatter = REFERENCE_FORMAT[key]
                     if callable(reference_formatter):
                         value = reference_formatter(value, params)
                     elif reference_formatter.find('%s') >= 0:
                         value = reference_formatter % value
                     else:
                         continue
                     
                     if value:
                         line.append(value)
             
             entry = ', '.join(line)
             
             url = params.get('url')
             
             if entry and url:
                 entry += ','
             
             if entry:
                 if url:
                     if backref:
                         li.append(tag.li(tag.a(name=label), tag.a(href='#cite_%s' % label)('^'), ' ', entry, tag.br(), tag.a(href=url)(url)))
                     else:
                         li.append(tag.li(tag.a(name=label), entry, tag.br(), tag.a(href=url)(url)))
                 else:
                     if backref:
                         li.append(tag.li(tag.a(name=label), tag.a(href='#cite_%s' % label)('^'), ' ', entry))
                     else:
                         li.append(tag.li(tag.a(name=label), entry))
             else:
                 if url:
                     if backref:
                         li.append(tag.li(tag.a(name=label), tag.a(href='#cite_%s' % label)('^'), ' ', tag.a(href=url)(url)))
                     else:
                         li.append(tag.li(tag.a(name=label), tag.a(href=url)(url)))
         
         ol = tag.ol(*li)
         tags.append(ol)
         
         # This is ugly but it is easy.
         return tag.div(id='References')(*tags)
     
     elif label == 'bibtex':
         indent = kwargs.get('indent', 2)
         try:
             indent = int(indent)
             indent = (indent, 0)[indent < 0]
             indent = (indent, 8)[indent > 8]
         except ValueError:
             intent = 2
         
         references = []
         for index, label in enumerate(cite_list):
             description, params = cite_dict[label]
             reftype = params.get('reftype', 'Book')
             
             reference = []
             reference.append('@%s{%s' % (reftype, label))
             for key in BIBTEX_SEQUENCE:
                 value = params.get(key)
                 if value:
                     bibtex_formatter = BIBTEX_FORMAT[key]
                     if callable(bibtex_formatter):
                         value = bibtex_formatter(value, params)
                     elif bibtex_formatter.find('%s') >= 0:
                         value = bibtex_formatter % value
                     else:
                         continue
                     
                     if value:
                         reference.append(',\n%s%s = "%s"' % (' ' * indent, key, value))
             
             if len(reference) == 1:
                 reference.append(',')
             
             reference.append('\n};')
             references.append(''.join(reference))
         
         if 'class' in kwargs:
             kwargs['class_'] = kwargs.pop('class')
         
         return tag.pre('\n\n'.join(references), **kwargs)
     
     else:
         if label not in cite_list:
             cite_list.append(label)
             cite_dict[label] = (description, kwargs)
             
             setattr(formatter, CITE_LIST, cite_list)
             setattr(formatter, CITE_DICT, cite_dict)
             backref = True
         else:
             backref = False
         
         index = cite_list.index(label) + 1
         
         if backref:
             return ''.join(['[', str(tag.a(name='cite_%s' % label)), str(tag.a(href='#%s' % label)('%d' % index)), ']'])
         else:
             return ''.join(['[', str(tag.a(href='#%s' % label)('%d' % index)), ']'])
Пример #43
0
 def expand_macro(self, formatter, name, content):
     args, kwargs = parse_args(content, strict=True)
     try:
         kwargs = string_keys(kwargs)
     except:
         raise TracError('Error #3922, content: %s, args: %s, kwargs: %s', (str(content), str(args), kwargs))
     
     if len(args) >= 1:
         url = args[0]
     elif len(args) == 0:
         raise TracError('URL to the mindmap at least required.')
     
     embed_count = getattr(formatter, EMBED_COUNT, 0)
     embed_count += 1
     setattr(formatter, EMBED_COUNT, embed_count)
     
     if embed_count == 1:
         add_script(formatter.req, 'freemind/js/flashobject.js')
     
     url = get_absolute_url(url, formatter)
     base = url[:url.rfind('/')+1]
     
     #script = '''\
     #    $(document).ready(function() {
     #        $("#flashcontent%(count)02d").mouseover(function() {
     #            document.visorFreeMind%(count)02d.focus();
     #        });
     #        
     #        var fo = new FlashObject("%(visor)s", "visorFreeMind%(count)02d", "100%%", "100%%", 6, "#9999ff");
     #        
     #        fo.addParam("quality","high");
     #        fo.addParam("bgcolor","#a0a0f0");
     #        fo.addVariable("openUrl","_blank");
     #        fo.addVariable("startCollapsedToLevel","3");
     #        fo.addVariable("maxNodeWidth","200");
     #        fo.addVariable("mainNodeShape","elipse");
     #        fo.addVariable("justMap","false");
     #        fo.addVariable("initLoadFile","%(file)s");
     #        fo.addVariable("defaultToolTipWordWrap",200);
     #        fo.addVariable("offsetX","left");
     #        fo.addVariable("offsetY","top");
     #        fo.addVariable("buttonsPos","top");
     #        fo.addVariable("min_alpha_buttons",20);
     #        fo.addVariable("max_alpha_buttons",100);
     #        fo.addVariable("scaleTooltips","false");
     #        fo.addVariable("baseImagePath","%(base)s");
     #        fo.addVariable("CSSFile","%(css)s");
     #        //fo.addVariable("toolTipsBgColor","0xa0a0f0");
     #        //fo.addVariable("genAllShots","true");
     #        //fo.addVariable("unfoldAll","true");
     #        fo.write("flashcontent%(count)02d");
     #    });
     #''' % {
     #    'count': embed_count,
     #    'visor': get_absolute_url('htdocs://freemind/swf/visorFreemind.swf', formatter),
     #    'file': url,
     #    'base': base,
     #    'css': get_absolute_url('htdocs://freemind/css/flashfreemind.css', formatter),
     #}
     
     script = '''\
         $(document).ready(function() {
             $("#flashcontent%(count)02d").mouseover(function() {
                 document.visorFreeMind%(count)02d.focus();
             });
         });
         
         // url: %(url)s
         // base: %(base)s
         
         
     ''' % {'count': embed_count, 'url': url, 'base': base}
     
     flash_dict = {
         'openUrl': '_blank',
         'initLoadFile': url,
         'startCollapsedToLevel': '3',
         'defaultToolTipWordWrap': '200',
         'baseImagePath': base,
         'min_alpha_buttons': '20',
         'max_alpha_buttons': '100'
     }
     
     flash_vars = '&'.join(['%s=%s' % (k, v) for k, v in flash_dict.items()])
     
     embed = tag.embed(type='application/x-shockwave-flash',
                       src=get_absolute_url('htdocs://freemind/swf/visorFreemind.swf', formatter),
                       id='visorFreeMind%02d' % embed_count,
                       bgcolor='#ffffff',
                       quality='high',
                       flashvars=flash_vars,
                       align='middle',
                       height='100%',
                       width='100%')
     
     # Debugging.
     if 'debug' in args:
         import os
         import datetime
         
         output = "FreemindMacro Debug Log\n"\
                  "=======================\n\n"\
                  "time: %(time)s\n"\
                  "version: %(version)s\n"\
                  "content: %(content)s\n"\
                  "args: %(args)s\n"\
                  "kwargs: %(kwargs)s\n"\
                  "formatter.href.base: %(base)s\n"\
                  "script: \n\n"\
                  "%(script)s" % {
             
             'time': datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%SZ'),
             'version': __version__,
             'content': content,
             'args': str(args),
             'kwargs': str(kwargs),
             'base': str(formatter.href.base),
             'script': script
         }
         
         return tag.pre(output, style='border: 2px dashed red; padding: 5px; background: #eee;')
     
     
     style_dict = xform_style(kwargs.get('style', ''))
     
     width = kwargs.pop('width', style_dict.get('width', '800px'))
     height = kwargs.pop('height', style_dict.get('height', '600px'))
     
     style_dict['border'] = style_dict.get('border', '1px solid #cccccc;')
     style_dict['margin'] = style_dict.get('margin', '0 auto')
     style_dict['width'] = width
     style_dict['height'] = height
     
     kwargs['style'] = xform_style(style_dict)
     
     # You can't touch this...
     kwargs.pop('id', None)
     
     if 'class' in kwargs:
         kwargs['class_'] = kwargs.pop('class')
     
     tags = []
     #tags.append(tag.div('Flash plugin or JavaScript are turned off. Activate both and reload to view the mindmap.',
     #                    id='flashcontent%02d' % embed_count, **kwargs))
     
     tags.append(tag.div(embed, id='flashcontent%02d' % embed_count, **kwargs))
     tags.append(tag.script(script))
     
     return ''.join([str(i) for i in tags])
Пример #44
0
    def _render(self, text=None):
        if text is None:
            text = self._get_text()

        return tag.pre(text)
    def render_macro(self, req, name, content):
        args,kwargs = parse_args(content)
        if len(args) == 0:
            ul = tag.ul(class_="mailinglistlist")

            for mailinglist in Mailinglist.select(self.env):
                if "MAILINGLIST_VIEW" in req.perm(mailinglist.resource):         
                    ul.append(tag.li(tag.a(mailinglist.name,
                                           href=get_resource_url(self.env, mailinglist.resource, req.href))))
                        
            return ul
        if kwargs.has_key('limit'):
            limit = int(kwargs['limit'])
        elif len(args) > 1:
            limit = int(args[1])
        else:
            limit = 10
        resource = Resource("mailinglist",args[0])
        instance = MailinglistSystem(self.env).get_instance_for_resource(resource)

        if isinstance(instance, Mailinglist):
            if not req.perm(instance.resource).has_permission('MAILINGLIST_VIEW'):
                return system_message("Permission denied viewing mailinglist: %s" % instance.name)
            ul = tag.ul()
            for message in instance.messages(limit=limit, insubject=kwargs.get('insubject', None),desc=True):
                ul.append(tag.li(
                    tag.a(tag.span(message.subject, class_="messagesubject"),
                          href=get_resource_url(self.env, message.resource, req.href)),
                    " (",
                    dateinfo(message.date),
                    ")",
                    ))
            ul.append(tag.li(tag.a("(%d messages...)" % instance.count_messages(insubject=kwargs.get('insubject', None)),
                                   href=get_resource_url(self.env, instance.resource, req.href))))
            return tag.div("Mailinglist: ",
                           tag.a(instance.name,
                                 href=get_resource_url(self.env, instance.resource, req.href)),
                           ul,
                           class_="mailinglistfeed")
        elif isinstance(instance, MailinglistMessage):
            if not req.perm(instance.resource).has_permission('MAILINGLIST_VIEW'):
                return system_message("Permission denied viewing mail.")


            else:
                limit = None
            text = wrap_and_quote(instance.body, 78)[0]
            if limit:
                text = "\n".join(text.split("\n")[0:limit])
                textelement = tag.pre(text) + tag.a(tag.pre("(More...)"),
                                                    href=get_resource_url(self.env, instance.resource, req.href))
            else:
                textelement = tag.pre(text)                
            return tag.div(
                tag.div("Mailinglist: ",
                        tag.a(instance.conversation.mailinglist.name,
                              href=get_resource_url(self.env, instance.conversation.mailinglist.resource, req.href))),
                tag.div("Subject: ",
                        tag.a(instance.subject, href=get_resource_url(self.env, instance.resource, req.href))),
                tag.div("From: ",
                        tag.a(instance.from_name, href="mailto:%s" % instance.from_email)),
                tag.div("To: ", instance.to_header),
                tag.div("Date: ", dateinfo(instance.date)),
                tag.div(textelement),
                class_="mailinglistmessage")            
            
        return system_message("Unknown Mailinglist: %s" % content)
Пример #46
0
    def expand_macro(self, formatter, name, content, args=None):
        # Utility methods
        def lte_ie8(req):
            user_agent = formatter.req.get_header('user-agent')
            msie = user_agent.find('MSIE ')
            return (msie != -1) and user_agent[msie + 5:msie + 6] in ['6', '7', '8']

        def after_AS(string):
            index = string.find(' AS ')
            return index > 0 and string[index + 4:] or string

        def before_AS(string):
            index = string.find(' AS ')
            return index > 0 and string[:index] or string
        # add scripts
        if lte_ie8(formatter.req):
            add_script(formatter.req, "statushistorychart/js/flot/excanvas.js")
        add_script(formatter.req, "statushistorychart/js/flot/jquery.flot.js")
        add_script(formatter.req, "statushistorychart/js/flot/jquery.flot.time.js")
        add_script(formatter.req, "statushistorychart/js/enabler.js")
        # from macro parameters
        query = None
        query_href = None
        status_list = ['new', 'assigned', 'accepted', 'closed']  # default
        if(content):
            # replace parameters
            for match in reversed([match for match in re_param.finditer(content)]):
                param_name = match.group(0)
                if param_name == '$USER':
                    authname = formatter.req.authname
                    if authname == 'anonymous':
                        authname = 'anonymous||somebody'
                    content = content.replace(param_name, authname)
                else:
                    param_value = formatter.req.args.get(param_name[1:])
                    if param_value:
                        content = content.replace(param_name, param_value)
            # execute query
            query = Query.from_string(formatter.env, content)
        field = query and query.id or 'status'  # stopgap implementation; I use 'report' for y-axis parameter
        field = filter(lambda x: x['name'] == field, TicketSystem(self.env).fields)
        if len(field) <= 0:
            return tag.div(tag.strong('Error: Macro %s failed' % name),
                       tag.pre("%s is not field name" % query.id), class_="system-message")
        field = field[0]
        custom = 'custom' in field and field['custom'] or None
        status_list = query and query.format and query.format.split('/') or \
                      'options' in field and copy.copy(field['options']) or status_list
        if field['name'] == 'status' and not (query and query.format):
            def isprime(item):
                primaries = ['new', 'assigned', 'accepted', 'closed']
                return (item in primaries and [primaries.index(item)] or [len(primaries)])[0]
            status_list.sort(key=isprime)
        if '*' not in status_list:
            status_list.append('*')
        default_status = status_list.index('*')
        # execute query for ids of ticket
        if(query and len(query.constraint_cols) > 0):
            result = query.execute() or [{'id':-1}]  # Sentinel for no result
            cond = "ticket.id in (%s)" % ', '.join([str(t['id']) for t in result])
        elif formatter.resource.realm == 'milestone':
            cond = "ticket.milestone='%s'" % formatter.resource.id
        elif('query_tickets' in formatter.req.session):  # You Feeling Lucky
            query_tickets = formatter.req.session.get('query_tickets', '')
            query_href = formatter.req.session.get('query_href', '')
            tickets = len(query_tickets) and query_tickets.split(' ') or ['-1']  # Sentinel for no result
            cond = "ticket.id in (%s)" % ', '.join(tickets)
        else:
            raise TracError("%sMacro: Empty. There are no content and no context." % name)
        # execute query for value changes of each ticket
        join_clause_dummy = ''
        join_clause = "JOIN ticket_custom ON ticket.id = ticket_custom.ticket and ticket_custom.name = '%s'"
        cursor = formatter.env.get_read_db().cursor()
        cursor.execute("""
                SELECT id, time, null, %s
                    FROM ticket
                    %s
                    WHERE %s
                UNION
                SELECT id, ticket_change.time, oldvalue, newvalue
                    FROM ticket
                    JOIN ticket_change ON ticket.id = ticket_change.ticket
                    WHERE %s AND field='%s'
                ORDER BY id, time
                """ % (custom and "'\uFEFF'" or field['name'],  # ZERO WIDTH NO-BREAK SPACE; uses for mark of invalid data
                       custom and (join_clause % field['name']) or join_clause_dummy,
                       cond, cond, field['name']))
        changes = [row for row in cursor.fetchall()]
        # transform (ticket, time, status)* ==> (ticket <>- status)*
        tid = 0  # position of ticket id
        tickets = {}
        for change in changes:
            ticket = tickets.get(change[tid])  # slot is exist, or
            if ticket is None:
                ticket = tickets[change[tid]] = []  # create new slot and use it
            ticket.append(list(change))
        # generate status_list splitted, {a, b+c, d} => {a:0, b+c:1, b:1, c:1, d:2}
        status_list_splitted = {}
        for index, status in enumerate(map(before_AS, status_list)):
            status_list_splitted[status] = index
            if status.find('+') >= 0:
                for each in status.split('+'):
                    status_list_splitted[each] = index
#        groupstats = self.compmgr[DefaultTicketGroupStatsProvider]
#        ticket_groups = groupstats._get_ticket_groups()
#        for group in ticket_groups:
#            pass
        for tid in tickets:
            if len(tickets[tid]) > 1:
                tickets[tid][0][3] = tickets[tid][1][2]  # override last value with initial value
        # generate data
        data = []
        # points
        too_many_tickets = len(tickets) > 200
        for no, tid in enumerate(sorted(tickets)):
            if not too_many_tickets or tickets[tid][-1][3] != 'closed':
                void, time, void, state = tickets[tid][-1]  # @UnusedVariable
                index = status_list_splitted.get(state, default_status)
                data.append({'points': {'show': True, 'radius': 8, 'color': no},
                             'label': tid,
                             'data': [[time / 1000, index]]})
        # lines
        for no, tid in enumerate(sorted(tickets)):
            data.append({'color': no, 'label': tid,
                         'data': [[time / 1000, status_list_splitted.get(state, default_status)]
                                  for void, time, void, state in tickets[tid]]})  # @UnusedVariable
        from trac import __version__ as VERSION
        if VERSION[0:1] != '0':
        # render for trac 1.0 or later
            add_script_data(formatter.req, {'statushistorychart_yaxis': map(after_AS, status_list)})
            add_script_data(formatter.req, {'statushistorychart_data': data})
            return tag.a(_("Return to Last Query"), href=query_href) \
                 + tag.div(id="statushistorychart", style="width: 800px; height: 400px;")
        else:  # if trac < 1.0 or earlier
            from trac.util.presentation import to_json
            return tag.script("var statushistorychart_yaxis = %s; var statushistorychart_data = %s" \
                              % (to_json(map(after_AS, status_list)), to_json(data)),
                              type="text/javascript") \
                 + tag.a(_("Return to Last Query"), href=query_href) \
                 + tag.div(id="statushistorychart", style="width: 800px; height: 400px;")
Пример #47
0
    def render(self, context, mimetype, content, filename=None, url=None,
               annotations=None, force_source=False):
        """Render an XHTML preview of the given `content`.

        `content` is the same as an `IHTMLPreviewRenderer.render`'s
        `content` argument.

        The specified `mimetype` will be used to select the most appropriate
        `IHTMLPreviewRenderer` implementation available for this MIME type.
        If not given, the MIME type will be infered from the filename or the
        content.

        Return a string containing the XHTML text.

        When rendering with an `IHTMLPreviewRenderer` fails, a warning is added
        to the request associated with the context (if any), unless the
        `disable_warnings` hint is set to `True`.
        """
        if not content:
            return ''
        if not isinstance(context, RenderingContext):
            raise TypeError("RenderingContext expected (since 0.11)")

        # Ensure we have a MIME type for this content
        full_mimetype = mimetype
        if not full_mimetype:
            if hasattr(content, 'read'):
                content = content.read(self.max_preview_size)
            full_mimetype = self.get_mimetype(filename, content)
        if full_mimetype:
            mimetype = ct_mimetype(full_mimetype)   # split off charset
        else:
            mimetype = full_mimetype = 'text/plain' # fallback if not binary

        # Determine candidate `IHTMLPreviewRenderer`s
        candidates = []
        for renderer in self.renderers:
            qr = renderer.get_quality_ratio(mimetype)
            if qr > 0:
                candidates.append((qr, renderer))
        candidates.sort(lambda x, y: cmp(y[0], x[0]))

        # Wrap file-like object so that it can be read multiple times
        if hasattr(content, 'read'):
            content = Content(content, self.max_preview_size)

        # First candidate which renders successfully wins.
        # Also, we don't want to expand tabs more than once.
        expanded_content = None
        for qr, renderer in candidates:
            if force_source and not getattr(renderer, 'returns_source', False):
                continue # skip non-source renderers in force_source mode
            if isinstance(content, Content):
                content.reset()
            try:
                ann_names = ', '.join(annotations) if annotations else \
                           'no annotations'
                self.log.debug('Trying to render HTML preview using %s [%s]',
                               renderer.__class__.__name__, ann_names)

                # check if we need to perform a tab expansion
                rendered_content = content
                if getattr(renderer, 'expand_tabs', False):
                    if expanded_content is None:
                        content = content_to_unicode(self.env, content,
                                                     full_mimetype)
                        expanded_content = content.expandtabs(self.tab_width)
                    rendered_content = expanded_content

                result = renderer.render(context, full_mimetype,
                                         rendered_content, filename, url)
                if not result:
                    continue

                if not (force_source or getattr(renderer, 'returns_source',
                                                False)):
                    # Direct rendering of content
                    if isinstance(result, basestring):
                        if not isinstance(result, unicode):
                            result = to_unicode(result)
                        return Markup(to_unicode(result))
                    elif isinstance(result, Fragment):
                        return result.generate()
                    else:
                        return result

                # Render content as source code
                if annotations:
                    m = context.req.args.get('marks') if context.req else None
                    return self._render_source(context, result, annotations,
                                               m and Ranges(m))
                else:
                    if isinstance(result, list):
                        result = Markup('\n').join(result)
                    return tag.div(class_='code')(tag.pre(result)).generate()

            except Exception, e:
                self.log.warning('HTML preview using %s failed: %s',
                                 renderer.__class__.__name__,
                                 exception_to_unicode(e, traceback=True))
                if context.req and not context.get_hint('disable_warnings'):
                    from trac.web.chrome import add_warning
                    add_warning(context.req,
                        _("HTML preview using %(renderer)s failed (%(err)s)",
                          renderer=renderer.__class__.__name__,
                          err=exception_to_unicode(e)))
Пример #48
0
            "args": args,
            "show_args_form": False,
            "message": None,
            "paginator": None,
            "report_href": report_href,
        }

        res = None
        with self.env.db_query as db:
            res = self.execute_paginated_report(req, db, id, sql, args, limit, offset)

        if len(res) == 2:
            e, sql = res
            data["message"] = tag_(
                "Report execution failed: %(error)s %(sql)s",
                error=tag.pre(exception_to_unicode(e)),
                sql=tag(tag.hr(), tag.pre(sql, style="white-space: pre")),
            )
            return "report_view.html", data, None

        cols, results, num_items, missing_args, limit_offset = res
        need_paginator = limit > 0 and limit_offset
        need_reorder = limit_offset is None
        results = [list(row) for row in results]
        numrows = len(results)

        paginator = None
        if need_paginator:
            paginator = Paginator(results, page - 1, limit, num_items)
            data["paginator"] = paginator
            if paginator.has_next_page:
Пример #49
0
                'max': limit, 'args': args, 'show_args_form': False,
                'message': None, 'paginator': None,
                'report_href': report_href, 
                }

        with self.env.db_query as db:
            try:
                cols, results, num_items, missing_args = \
                    self.execute_paginated_report(req, db, id, sql, args, limit,
                                                  offset)
                results = [list(row) for row in results]
                numrows = len(results)

            except Exception, e:
                data['message'] = tag_('Report execution failed: %(error)s',
                        error=tag.pre(exception_to_unicode(e, traceback=True)))
                return 'report_view.html', data, None

        paginator = None
        if limit > 0:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
Пример #50
0
            'message': None,
            'paginator': None,
            'report_href': report_href,
        }

        try:
            cols, results, num_items, missing_args = \
                self.execute_paginated_report(req, db, id, sql, args, limit,
                                              offset)
            results = [list(row) for row in results]
            numrows = len(results)

        except Exception, e:
            db.rollback()
            data['message'] = tag_('Report execution failed: %(error)s',
                                   error=tag.pre(to_unicode(e)))
            return 'report_view.html', data, None

        paginator = None
        if limit > 0:
            paginator = Paginator(results, page - 1, limit, num_items)
            data['paginator'] = paginator
            if paginator.has_next_page:
                add_link(req, 'next', report_href(page=page + 1),
                         _('Next Page'))
            if paginator.has_previous_page:
                add_link(req, 'prev', report_href(page=page - 1),
                         _('Previous Page'))

            pagedata = []
            shown_pages = paginator.get_shown_pages(21)
Пример #51
0
    def expand_macro(self, formatter, name, content):
        args, kwargs = parse_args(content, strict=True)
        try:
            kwargs = string_keys(kwargs)
        except:
            raise TracError('Error #3922, content: %s, args: %s, kwargs: %s',
                            (str(content), str(args), kwargs))

        if len(args) >= 1:
            url = args[0]
        elif len(args) == 0:
            raise TracError('URL to the mindmap at least required.')

        embed_count = getattr(formatter, EMBED_COUNT, 0)
        embed_count += 1
        setattr(formatter, EMBED_COUNT, embed_count)

        if embed_count == 1:
            add_script(formatter.req, 'freemind/js/flashobject.js')

        url = get_absolute_url(url, formatter)
        base = url[:url.rfind('/') + 1]

        #script = '''\
        #    $(document).ready(function() {
        #        $("#flashcontent%(count)02d").mouseover(function() {
        #            document.visorFreeMind%(count)02d.focus();
        #        });
        #
        #        var fo = new FlashObject("%(visor)s", "visorFreeMind%(count)02d", "100%%", "100%%", 6, "#9999ff");
        #
        #        fo.addParam("quality","high");
        #        fo.addParam("bgcolor","#a0a0f0");
        #        fo.addVariable("openUrl","_blank");
        #        fo.addVariable("startCollapsedToLevel","3");
        #        fo.addVariable("maxNodeWidth","200");
        #        fo.addVariable("mainNodeShape","elipse");
        #        fo.addVariable("justMap","false");
        #        fo.addVariable("initLoadFile","%(file)s");
        #        fo.addVariable("defaultToolTipWordWrap",200);
        #        fo.addVariable("offsetX","left");
        #        fo.addVariable("offsetY","top");
        #        fo.addVariable("buttonsPos","top");
        #        fo.addVariable("min_alpha_buttons",20);
        #        fo.addVariable("max_alpha_buttons",100);
        #        fo.addVariable("scaleTooltips","false");
        #        fo.addVariable("baseImagePath","%(base)s");
        #        fo.addVariable("CSSFile","%(css)s");
        #        //fo.addVariable("toolTipsBgColor","0xa0a0f0");
        #        //fo.addVariable("genAllShots","true");
        #        //fo.addVariable("unfoldAll","true");
        #        fo.write("flashcontent%(count)02d");
        #    });
        #''' % {
        #    'count': embed_count,
        #    'visor': get_absolute_url('htdocs://freemind/swf/visorFreemind.swf', formatter),
        #    'file': url,
        #    'base': base,
        #    'css': get_absolute_url('htdocs://freemind/css/flashfreemind.css', formatter),
        #}

        script = '''\
            $(document).ready(function() {
                $("#flashcontent%(count)02d").mouseover(function() {
                    document.visorFreeMind%(count)02d.focus();
                });
            });
            
            // url: %(url)s
            // base: %(base)s
            
            
        ''' % {
            'count': embed_count,
            'url': url,
            'base': base
        }

        flash_dict = {
            'openUrl': '_blank',
            'initLoadFile': url,
            'startCollapsedToLevel': '3',
            'defaultToolTipWordWrap': '200',
            'baseImagePath': base,
            'min_alpha_buttons': '20',
            'max_alpha_buttons': '100'
        }

        flash_vars = '&'.join(
            ['%s=%s' % (k, v) for k, v in flash_dict.items()])

        embed = tag.embed(type='application/x-shockwave-flash',
                          src=get_absolute_url(
                              'htdocs://freemind/swf/visorFreemind.swf',
                              formatter),
                          id='visorFreeMind%02d' % embed_count,
                          bgcolor='#ffffff',
                          quality='high',
                          flashvars=flash_vars,
                          align='middle',
                          height='100%',
                          width='100%')

        # Debugging.
        if 'debug' in args:
            import os
            import datetime

            output = "FreemindMacro Debug Log\n"\
                     "=======================\n\n"\
                     "time: %(time)s\n"\
                     "version: %(version)s\n"\
                     "content: %(content)s\n"\
                     "args: %(args)s\n"\
                     "kwargs: %(kwargs)s\n"\
                     "formatter.href.base: %(base)s\n"\
                     "script: \n\n"\
                     "%(script)s" % {

                'time': datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%SZ'),
                'version': __version__,
                'content': content,
                'args': str(args),
                'kwargs': str(kwargs),
                'base': str(formatter.href.base),
                'script': script
            }

            return tag.pre(
                output,
                style='border: 2px dashed red; padding: 5px; background: #eee;'
            )

        style_dict = xform_style(kwargs.get('style', ''))

        width = kwargs.pop('width', style_dict.get('width', '800px'))
        height = kwargs.pop('height', style_dict.get('height', '600px'))

        style_dict['border'] = style_dict.get('border', '1px solid #cccccc;')
        style_dict['margin'] = style_dict.get('margin', '0 auto')
        style_dict['width'] = width
        style_dict['height'] = height

        kwargs['style'] = xform_style(style_dict)

        # You can't touch this...
        kwargs.pop('id', None)

        if 'class' in kwargs:
            kwargs['class_'] = kwargs.pop('class')

        tags = []
        #tags.append(tag.div('Flash plugin or JavaScript are turned off. Activate both and reload to view the mindmap.',
        #                    id='flashcontent%02d' % embed_count, **kwargs))

        tags.append(
            tag.div(embed, id='flashcontent%02d' % embed_count, **kwargs))
        tags.append(tag.script(script))

        return ''.join([str(i) for i in tags])
Пример #52
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)
                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(_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()))