def expand_macro(self, formatter, name, content): db = self.env.get_db_cnx() txt = content or '' args = txt.split('|') url = args.pop(0).replace("'", "''") if ":" in url: base, name = url.split(":") if base != "wiki": return "Use 'wiki:' prefix in wiki page url", base, name else: name = url sql = "SELECT text from wiki where name = '%s' order by version desc limit 1" % name cs = db.cursor() cs.execute(sql) result = cs.fetchone() if not result: return '<b>Wiki Page %s not found!</b>' % url text = result[0] out = StringIO() codepage = self.env.config.get('trac', 'charset', 'ISO8859-15') Formatter(self.env, formatter.context).format(text, out, False) text = out.getvalue().encode(codepage) return text
def expand_macro(self, formatter, name, content): env = formatter.env abs = env.abs_href.base abs = abs[:len(abs) - len(env.href.base)] f = Formatter(formatter.env, formatter.context) def convert(m): pre, target, suf = filter(None, m.groups()) out = StringIO() f.format(target, out) url = re.search(HREF, out.getvalue()).groups()[0] # Trac creates relative links, which Markdown won't touch inside # <autolinks> because they look like HTML if pre == '<' and url != target: pre += abs return pre + str(url) + suf try: from markdown import markdown return markdown(re.sub(LINK, convert, content)) except ImportError: msg = 'Error importing Python Markdown, install it from ' url = 'http://www.freewisdom.org/projects/python-markdown/' return system_message(tag(msg, tag.a('here', href="%s" % url), '.'))
def test_expand_macro(self): """ Testing the expand_macro method. """ processor = CodeExample(self.env) args = 'test' formatter = Formatter(self.env, self.context) name = 'CodeExample' expected = '<div ' \ 'class="example">\n <div class="title">\n\t' \ '<span class="select_code" id="link1">' \ 'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n \n ' \ '<div class="code">' \ '\n <pre id="codelink1">test\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args)) args = '##type=bad\ntest' expected = '<div ' \ 'class="bad_example">\n <div class="title">\n\t' \ '<span class="select_code" id="link2">' \ 'SELECT ALL</span>\n\t\n\t<span>INCORRECT EXAMPLE:</span>\n' \ '</div>\n \n <div class="code">' \ '\n <pre id="codelink2">test\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args)) args = '##type=good\ntest' expected = '<div ' \ 'class="good_example">\n <div class="title">\n\t' \ '<span class="select_code" id="link3">' \ 'SELECT ALL</span>\n\t\n\t<span>CORRECT EXAMPLE:</span>\n</div>' \ '\n \n <div class="code">' \ '\n <pre id="codelink3">test\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args))
def render_macro(self, req, name, content): from trac.wiki.formatter import Formatter formatter = Formatter(self.env, req) def getparm(category, target): return req.perm.perms formatter.perm = getparm return self.expand_macro(formatter, name, content)
def expand_macro(self, formatter, name, content): args, kwargs = parse_args(content) pattern = args[0] if len(args) > 1 and args[1].strip().upper() == "COMPLETED": completed = "AND completed>0" else: completed = "AND completed=0" if len(args) > 2 and args[2].strip().upper() == "ASC": ordering = "ASC" else: ordering = "DESC" db = self.env.get_db_cnx() cursor = db.cursor() print """ SELECT name FROM milestone WHERE name %s %s ORDER BY name %s """ % (db.like(), completed, ordering) cursor.execute( """ SELECT name FROM milestone WHERE name %s %s ORDER BY name %s """ % (db.like(), completed, ordering), (pattern, )) out = StringIO() for name, in cursor.fetchall(): wikitext = """ == [milestone:%(milestonename)s %(milestonename)s] == [[TicketQuery(milestone=%(milestonename)s,order=id,desc=0,format=table,col=summary|owner|ticket_status|type|status)]] """ % { 'milestonename': name } Formatter(self.env, formatter.context).format(wikitext, out) return Markup(out.getvalue())
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') if 'id' in req.args.keys(): try: ticket = int(req.args.get('id')) except ValueError: raise TracError('Need integer ticket id.') sql = ("SELECT 1 FROM ticket WHERE id=%s" % ticket) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(sql) row = cursor.fetchone() if not row: raise TracError( 'Cannot build dependency graph for non-existent ticket %d.' % ticket) depth = -1 for key in req.args.keys(): if key == 'depth': depth = req.args[key] options = '%s,%s' % (ticket, depth) add_ctxtnav(req, 'Back to Ticket #%s' % ticket, req.href.ticket(ticket)) title = 'Ticket #%s Dependency Graph' % ticket headline = 'Dependency Graph for Ticket #%s' % ticket else: constraints = {} for key in req.args.keys(): if isinstance(req.args[key], (list, tuple)): constraints[key] = '|'.join(req.args[key]) else: constraints[key] = req.args[key] options = 'query:' + '&'.join(key + '=' + constraints[key] for key in constraints) title = 'Ticket query Dependency Graph' headline = 'Dependency Graph for Query' add_ctxtnav(req, 'Back to query', req.href('query', **req.args)) data = {} context = Context.from_request(req, '') formatter = Formatter(self.env, context) graph = DepGraphMacro(self.env).expand_macro(formatter, 'DepGraph', options) data['title'] = title data['headline'] = headline data['depgraph'] = Markup(graph) return 'depgraph.html', data, None
def test_wiki_link_foreign(self): attachment = Attachment(self.env, 'ticket', 123) attachment.insert('foo.txt', tempfile.TemporaryFile(), 0) ns, func = AttachmentModule(self.env).get_link_resolvers().next() self.assertEqual('attachment', ns) req = Mock(path_info='/wiki') formatter = Formatter(self.env, req) self.assertEqual('<a class="attachment" title="Attachment #123: ' 'foo.txt" href="/trac.cgi/attachment/ticket/123/' 'foo.txt">Foo</a>', func(formatter, ns, 'ticket:123:foo.txt', 'Foo'))
def test_wiki_link_subpage(self): attachment = Attachment(self.env, 'wiki', 'SomePage/SubPage') attachment.insert('foo.txt', tempfile.TemporaryFile(), 0) ns, func = AttachmentModule(self.env).get_link_resolvers().next() self.assertEqual('attachment', ns) req = Mock(path_info='/wiki/SomePage/SubPage') formatter = Formatter(self.env, req) self.assertEqual( '<a class="attachment" ' 'title="Attachment SomePage/SubPage: foo.txt" ' 'href="/trac.cgi/attachment/wiki/SomePage/SubPage/' 'foo.txt">Foo</a>', func(formatter, ns, 'foo.txt', 'Foo'))
def test_expand_macro_with_unicode(self): """ Testing the expand_macro method with unicode symbols. """ processor = CodeExample(self.env) args = 'ТЕСТ' formatter = Formatter(self.env, self.context) name = 'CodeExample' expected = '<div ' \ 'class="example">\n <div class="title">\n\t' \ '<span class="select_code" id="link1">' \ 'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n \n ' \ '<div class="code">' \ '\n <pre id="codelink1">ТЕСТ\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args))
def expand_macro(self, formatter, name, content): env = formatter.env abs = env.abs_href.base abs = abs[:len(abs) - len(env.href.base)] f = Formatter(formatter.env, formatter.context) def convert_links(m): pre, target, suf = filter(None, m.groups()) out = StringIO() f.format(target, out) url = re.search(HREF, out.getvalue()).groups()[0] # Trac creates relative links, which Markdown won't touch inside # <autolinks> because they look like HTML if pre == '<' and url != target: pre += abs return pre + str(url) + suf def emojify(html): pattern = ":([a-z0-9\\+\\-_]+):" link = "<img\ alt=\"\\1\"\ title=\":\\1:\"\ height=\"20\"\ style=\"vertical-align:middle\"\ width=\"20\"\ src=\"/chrome/markdown/emoji/\\1.png\" />" emojify_html = re.sub(pattern, link, html) return emojify_html try: # Import & convert import markdown2 # autolink http:// n stuff autolinked_content = re.sub(LINK, convert_links, content) # convert to markdown html = markdown2.markdown(autolinked_content, extras=MD_EXTRAS) # substitute emojis emojified_html = emojify(html) return emojified_html except ImportError: # no markdown2 package found? msg = 'Error importing python-markdown2, install it from ' url = 'https://github.com/trentm/python-markdown2' return system_message(tag(msg, tag.a('here', href="%s" % url), '.'))
def test(self): """Testing WikiFormatter""" # Environment stub from trac.core import ComponentManager from trac.config import Configuration from trac.log import logger_factory from trac.test import InMemoryDatabase from trac.web.href import Href db = InMemoryDatabase() class DummyEnvironment(ComponentManager): def __init__(self): ComponentManager.__init__(self) self.log = logger_factory('null') self.config = Configuration(None) self.href = Href('/') self.abs_href = Href('http://www.example.com/') self._wiki_pages = {} self.path = '' def component_activated(self, component): component.env = self component.config = self.config component.log = self.log def get_db_cnx(self): return db # Load all the components that provide IWikiSyntaxProvider # implementations that are tested. Ideally those should be tested # in separate unit tests. import trac.versioncontrol.web_ui.browser import trac.versioncontrol.web_ui.changeset import trac.Milestone import trac.ticket.query import trac.ticket.report import trac.Search env = DummyEnvironment() out = StringIO.StringIO() Formatter(env).format(self.input, out) v = out.getvalue().replace('\r','') self.assertEquals(self.correct, v)
def process_request(self, req): """Process the request. For ClearSilver, return a (template_name, content_type) tuple, where `template` is the ClearSilver template to use (either a `neo_cs.CS` object, or the file name of the template), and `content_type` is the MIME type of the content. For Genshi, return a (template_name, data, content_type) tuple, where `data` is a dictionary of substitutions for the template. For both templating systems, "text/html" is assumed if `content_type` is `None`. Note that if template processing should not occur, this method can simply send the response itself and not return anything. """ formatter = Formatter(self.env, Context.from_request(req)) intertrac = InterTracDispatcher(self.env) macro = intertrac.expand_macro(formatter, 'InterTrac', '') data = {'macro': macro} return ("intertracinfo.html", data, 'text/html')
def test_path_recognition(self): """ Testing correct path requirements. """ processor = CodeExample(self.env) args = '##path=test\nТЕСТ' formatter = Formatter(self.env, self.context) name = 'CodeExample' expected = '<div ' \ 'class="example">\n <div class="title">\n\t' \ '<span class="select_code" id="link1">' \ 'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n \n ' \ '<div class="system-message">\n <strong>' \ 'During the example analyzing the following problems' \ ' appear:</strong>\n <ul>\n ' \ '<li>Path element is not found.</li>\n '\ '</ul>\n </div>' \ '\n \n <div class="code">' \ '\n <pre id="codelink1">ТЕСТ\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args))
def expand_macro(self, formatter, name, content): (args, kwargs) = parse_args(content, False) page_name = self.MACRO_PAGES + name page = WikiPage(self.env, page_name) if not page.exists: raise RuntimeError(u'Can\'t find page', page_name) for i, arg in enumerate(args): kwargs[unicode(i+1)] = arg text = RelaxedIdTemplate(page.text).safe_substitute(kwargs) out = StringIO() Formatter(self.env, formatter.context).format(text, out) out = out.getvalue().strip() if out.startswith(u'<p>'): out = out[3:] if out.endswith(u'</p>'): out = out[:-4] return out
def test_macro_with_invalid_lang(self): """ Testing the expand_macro method with invalid language. """ processor = CodeExample(self.env) args = '#!python1\ntest' formatter = Formatter(self.env, self.context) name = 'CodeExample' expected = '<div ' \ 'class="example">\n <div class="title">\n\t' \ '<span class="select_code" id="link1">' \ 'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n \n ' \ '<div class="system-message">\n <strong>' \ 'During the example analyzing the following problems appear:' \ '</strong>\n ' \ '<ul>\n <li>no lexer for alias \'python1\' found</li>' \ '\n </ul>\n </div>\n \n ' \ '<div class="code">' \ '\n <pre id="codelink1">test\n</pre>\n </div>\n</div>' self.assertEqual(expected, processor.expand_macro(formatter, name, args))
def pre_process_request(self, req, handler): if req.path_info.startswith('/wiki'): if req.method == 'POST' and req.args.get('action', 'view') == 'view': post_handler = None for poster in self.macro_posters: if not hasattr(poster, 'match_macro_post'): continue rv = poster.match_macro_post(req) if isinstance(rv, (str, unicode)): rv = rv in req.args.keys() if rv: post_handler = poster break if post_handler: post_handler.process_macro_post(req) else: # Silly stuff here self.log.debug( 'MacroPostModule: Unclaimed POST, scanning page %s', req.path_info[6:]) page = WikiPage(self.env, req.path_info[6:]) matches = self.macro_re.findall( page.text) + self.proc_re.findall(page.text) for name in matches: self.log.debug('MacroPostModule: Found macro "%s"', name) resource = Resource('wiki', name) context = Context.from_request(req, resource) wp = WikiProcessor(Formatter(self.env, context), name) if wp.macro_provider is None: self.log.debug( 'MacroPostModule: Invalid name!!! How did that happen' ) continue if hasattr(wp.macro_provider, 'process_macro_post') and \ not hasattr(wp.macro_provider, 'match_macro_post'): wp.macro_provider.process_macro_post(req) req.environ['REQUEST_METHOD'] = 'GET' # Revert back to a GET return handler
def process_request(self, req): req.perm.require('TAGS_VIEW') add_ctxtnav(req, 'Cloud', req.href.tags()) match = re.match(r'/tags/?(.*)', req.path_info) if match.group(1): req.redirect(req.href('tags', q=match.group(1))) add_stylesheet(req, 'tags/css/tractags.css') query = req.args.get('q', '') data = {'title': 'Tags'} formatter = Formatter(self.env, Context.from_request(req, Resource('tag'))) realms = [p.get_taggable_realm() for p in self.tag_providers] checked_realms = [r for r in realms if r in req.args] or realms data['tag_realms'] = [{ 'name': realm, 'checked': realm in checked_realms } for realm in realms] if query: data['tag_title'] = 'Showing objects matching "%s"' % query data['tag_query'] = query from tractags.macros import TagCloudMacro, ListTaggedMacro if not query: macro = TagCloudMacro(self.env) else: macro = ListTaggedMacro(self.env) query = '(%s) (%s)' % (' or '.join( ['realm:' + r for r in realms if r in checked_realms]), query) self.env.log.debug('Tag query: %s', query) try: data['tag_body'] = macro.expand_macro(formatter, None, query) except InvalidQuery, e: data['tag_query_error'] = to_unicode(e) data['tag_body'] = TagCloudMacro(self.env) \ .expand_macro(formatter, None, '')
def filter_stream(self, req, method, filename, stream, data): """Return a filtered Genshi event stream, or the original unfiltered stream if no match. `req` is the current request object, `method` is the Genshi render method (xml, xhtml or text), `filename` is the filename of the template to be rendered, `stream` is the event stream and `data` is the data for the current template. See the Genshi documentation for more information. """ if filename in ('ticket.html', 'agilo_ticket_new.html',): add_stylesheet(req, 'tags/css/tractags.css') add_stylesheet(req, 'loomingclouds/css/tagcloud.css') add_script(req, 'loomingclouds/js/tag_filler.js') formatter = Formatter(self.env, Context.from_request(req)) macro = TagCloudMacro(self.env) cloud = macro.expand_macro(formatter, 'TagCloud', '') stream |= Transformer("//input[@id='field-keywords']").after(cloud).after(tag.a('More...',href='#',class_='tag-cloud-filler')) return stream
def process_request(self, req): req.perm.require('TAGS_VIEW') match = re.match(r'/tags/?(.*)', req.path_info) tag_id = match.group(1) and match.group(1) or None query = req.args.get('q', '') # Consider only providers, that are permitted for display. tag_system = TagSystem(self.env) all_realms = tag_system.get_taggable_realms(req.perm) if not (tag_id or query) or [r for r in all_realms if r in req.args ] == []: for realm in all_realms: if not realm in self.exclude_realms: req.args[realm] = 'on' checked_realms = [r for r in all_realms if r in req.args] if query: # Add permitted realms from query expression. checked_realms.extend(query_realms(query, all_realms)) realm_args = dict( zip([r for r in checked_realms], ['on' for r in checked_realms])) # Switch between single tag and tag query expression mode. if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE): # Convert complex, invalid tag ID's --> query expression. req.redirect(req.href.tags(realm_args, q=tag_id)) elif query: single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE) if single_page: # Convert simple query --> single tag. req.redirect(req.href.tags(single_page.group(2), realm_args)) data = dict(page_title=_("Tags"), checked_realms=checked_realms) # Populate the TagsQuery form field. data['tag_query'] = tag_id and tag_id or query data['tag_realms'] = list( dict(name=realm, checked=realm in checked_realms) for realm in all_realms) if tag_id: data['tag_page'] = WikiPage(self.env, tag_system.wiki_page_prefix + tag_id) if query or tag_id: macro = 'ListTagged' # TRANSLATOR: The meta-nav link label. add_ctxtnav(req, _("Back to Cloud"), req.href.tags()) args = "%s,format=%s,cols=%s" % \ (tag_id and tag_id or query, self.default_format, self.default_cols) data['mincount'] = None else: macro = 'TagCloud' mincount = as_int(req.args.get('mincount', None), self.cloud_mincount) args = mincount and "mincount=%s" % mincount or None data['mincount'] = mincount formatter = Formatter(self.env, Context.from_request(req, Resource('tag'))) self.env.log.debug("%s macro arguments: %s" % (macro, args and args or '(none)')) macros = TagWikiMacros(self.env) try: # Query string without realm throws 'NotImplementedError'. data['tag_body'] = checked_realms and \ macros.expand_macro(formatter, macro, args, realms=checked_realms) \ or '' except InvalidQuery, e: data['tag_query_error'] = to_unicode(e) data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '')
def wiki(self, text): out = StringIO.StringIO() Formatter(self.formatter.env, self.formatter.context).format(text, out) return out.getvalue()
def formatter(self, env): return Formatter(env)
def code_formatter(env, context, language, text): processor = WikiProcessor(Formatter(env, context), language) html = processor.process(text) raw = nodes.raw('', html, format='html') return raw
def formatter(self): return Formatter(self.env, self.req)
def expand_macro(self, formatter, name, args): u"""パラメータを展開する。パラメータは、カンマで区切ることとする。 パラメータのキーと値は以下のような感じで定義する(キーと値は":"でつなぐ) x -> 横軸の表示内容(抽出内容)を"|"で区切ってセット。 なお、表示対象とするフィールド名は先頭に記載し、具体的な値は"="でつなぐ。値を省略した場合は項目の一覧を自動取得。 グループ化したいときは "+"でつなぐ。改名したいときは AS で別名をつける。 例)x:status=new|accepted + assigned AS doing|closed|reopened y -> 縦軸の表示内容。設定方法はxと同じ q -> 抽出条件(SQLのWHERE条件)。複数の条件を指定する場合は"&"でつなぐ。 q:milestone=milestone1&owner=hoge xa-> x軸部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。 xa:order=id&group=status のような感じで指定する。指定がない場合はorder=idのみを自動的に付加する。 ya-> y軸部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。 指定方法はxaと同様。 m -> 表部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。 指定方法はxa/yaと同様。 """ # とりあえず、パラメータ中に";"が含まれている場合はエラーとする if ';' in args: raise TracError('Parameter Error') # パラメータをカンマで区切って展開 # ":"でキーと値に分割してDictionaryに格納(":"で2つに分割できなかったものは処理対象外) params = {} for value in args.split(','): v = value.split(':') if len(v) == 2: params[v[0]] = v[1] # 抽出条件を構築(SQLのWHERE節を構築) condition = self.createcondition(params) # x軸(横軸)の処理 xaxiswork = params['x'].split('=') xaxiskey = xaxiswork[0] xaxiscolname = xaxiskey # y軸(縦軸)の処理 yaxiswork = params['y'].split('=') yaxiskey = yaxiswork[0] yaxiscolname = yaxiskey # Ticketのフィールド一覧を取得する xfield = None yfield = None for field in TicketSystem(self.env).get_ticket_fields(): if field['name'] == xaxiskey: xfield = field xaxislabel = xfield['label'] if field['name'] == yaxiskey: yfield = field yaxislabel = yfield['label'] # それぞれの軸がカスタムフィールドか否か xcustom = 'custom' in xfield and xfield['custom'] ycustom = 'custom' in yfield and yfield['custom'] if xcustom: xaxiskey = 'cx.value' if ycustom: yaxiskey = 'cy.value' yaxis = self.getaxisvalues(yaxiswork, yfield, ycustom, yaxiskey, yaxiscolname, condition) xaxis = self.getaxisvalues(xaxiswork, xfield, xcustom, xaxiskey, xaxiscolname, condition) if len(xaxis) == 0 or len(yaxis) == 0: return u'<ul><i>抽出条件に合致するチケットが存在しませんでした</i></ul>' query = u'SELECT ' query += 'CASE ' for y in yaxis: query += 'when %s in (%s) then \'%s\' \n' % (yaxiskey, ",".join(["'%s'" % v.strip() for v in y.split("+")]), y) query += 'END as %s' % yaxiskey for x in xaxis: query += ",sum(case when coalesce(%s,'') IN (%s) then 1 else 0 end)" % (xaxiskey, ",".join(["'%s'" % v.strip() for v in x.split("+")])) query += " from ticket " # カスタムフィールドを使用している場合はticket_customテーブルを連結する必要あり # なお、カスタムフィールドの場合は取得する際の列名がいったんvalueに置き換わってしまうので注意 if xcustom: query += " left outer join ticket_custom as cx on cx.ticket=id and cx.name='%s'" % xaxiscolname if ycustom: query += " left outer join ticket_custom as cy on cy.ticket=id and cy.name='%s'" % yaxiscolname # 条件文及びgroup値を追加 query += " %s group by %s" % (condition, yaxiskey) self.env.log.info(query) result = {} for row in self.env.db_query(query): result[row[0] or ''] = row[1:] # queryリンクのパラメータの各要素を構築する querycond = 'q' in params and "&%s" % params['q'] or '&order=priority' xquery = 'xa' in params and "&%s" % params['xa'] or "&order=id" yquery = 'ya' in params and "&%s" % params['ya'] or "&order=id" mquery = 'm' in params and "&%s" % params['m'] or "&order=id" # 出力テキスト構築 # x軸のタイトル行を構築する xaxislabels = [(yaxislabel + u'\' + xaxislabel)] + xaxiswork[1] + [u"小計"] wikitext = "||%s||\n" % "||".join(["= %s =" % x for x in xaxislabels]) # 縦計を格納する ysum = {} for x in xaxis: ysum[x] = 0 for yindex, y in enumerate(yaxis): # タイトル列 wikitext += "||= %s =||" % yaxiswork[1][yindex] if y in result: each = result[y] linesum = 0 for cnt2, x in enumerate(xaxis): # テーブル部分本体 eachval = each[cnt2] wikitext += self.q_or_0("%s=%s&%s=%s%s%s", (yaxiscolname, y, xaxiscolname, x, querycond, mquery), each[cnt2]) linesum += eachval ysum[x] += eachval # 小計列 wikitext += self.q_or_0("%s=%s%s%s", (yaxiscolname, y, querycond, yquery), linesum, term="\n") else: # 該当するy軸に対応するデータがない場合はリンクは付加しない for x in xaxis: wikitext += "0||" wikitext += "0||\n" # 合計行 wikitext += "||= %s =||" % u"【合計】" linesum = 0 for x in xaxis: ysumval = ysum[x] wikitext += self.q_or_0("%s=%s%s%s", (xaxiscolname, x, querycond, xquery), ysum[x]) linesum += ysumval # 総合計 wikitext += self.q_or_0("%s", (querycond[1:],), linesum, term="\n") # 構築したwikiテキストをhtmlに変換(expand_macroの戻り値はhtmlそのものとなる)。 out = StringIO() Formatter(self.env, formatter.context).format(wikitext, out) return Markup(out.getvalue())
def process_request(self, req): req.perm.require('TAGS_VIEW') match = re.match(r'/tags/?(.*)', req.path_info) tag_id = match.group(1) and match.group(1) or None query = req.args.get('q', '') realms = [p.get_taggable_realm() for p in self.tag_providers if (not hasattr(p, 'check_permission') or \ p.check_permission(req.perm, 'view'))] if not (tag_id or query) or [r for r in realms if r in req.args] == []: for realm in realms: if not realm in self.exclude_realms: req.args[realm] = 'on' checked_realms = [r for r in realms if r in req.args] realm_args = dict( zip([r for r in checked_realms], ['on' for r in checked_realms])) if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE): # Convert complex, invalid tag ID's to query expression. req.redirect(req.href.tags(realm_args, q=tag_id)) elif query: single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE) if single_page: # Convert simple query for single tag ID. req.redirect(req.href.tags(single_page.group(2), realm_args)) data = dict(page_title=_("Tags"), checked_realms=checked_realms) # Populate the TagsQuery form field. data['tag_query'] = tag_id and tag_id or query data['tag_realms'] = list( dict(name=realm, checked=realm in checked_realms) for realm in realms) if tag_id: page_name = tag_id page = WikiPage(self.env, page_name) data['tag_page'] = page macros = TagWikiMacros(self.env) if query or tag_id: # TRANSLATOR: The meta-nav link label. add_ctxtnav(req, _("Back to Cloud"), req.href.tags()) macro = 'ListTagged' args = '%s,format=%s,cols=%s,realm=%s' \ % (tag_id and tag_id or query, self.default_format, self.default_cols, '|'.join(checked_realms)) data['mincount'] = None else: macro = 'TagCloud' mincount = as_int(req.args.get('mincount', None), self.cloud_mincount) args = 'mincount=%s,realm=%s' % (mincount, '|'.join(checked_realms)) data['mincount'] = mincount formatter = Formatter(self.env, Context.from_request(req, Resource('tag'))) self.env.log.debug('Tag macro arguments: %s', args) try: # Query string without realm throws 'NotImplementedError'. data['tag_body'] = len(checked_realms) > 0 and \ macros.expand_macro(formatter, macro, args) \ or '' except InvalidQuery, e: data['tag_query_error'] = to_unicode(e) data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '')
def expand_macro(self, formatter, name, args): """ Return a list of translated pages with the native language names. The list of languages supported can be configured by adding new entries to TracLanguages page. Refer to ISO 639-1 for more information. """ args, kw = parse_args(args) # first handle special cases show = u"" lang = None silent = u'silent' in args outdated = u"" if u'lang' in kw: lang = kw[u'lang'] if u'outdated' in kw: outdated = self.outdated_tx % kw[u'outdated'] if u'showproblems' in args: show += self._get_problems(silent) if u'showstatus' in args: show += self._get_status(lang) if u'showoutdated' in args: label = None if u'label_outdated' in kw: label = kw[u'label_outdated'] show += self._get_outdated(lang, label) if u'showmissing' in args: show += self._get_missing(lang) if u'showuntranslated' in args: show += self._get_untranslated(silent) if len(show): outshow = StringIO() Formatter(self.env, formatter.context).format(show, outshow) val = outshow.getvalue() val = re.sub('>\$\$\$([a-z]+?)\$\$\$<a class=".*?"', \ ' style="background-color:\\1"><a style="color:#151B8D"', val) # try again more secure in case previous fails due to Wiki engine changes val = re.sub('>\$\$\$([a-z]+?)\$\$\$', \ ' style="background-color:\\1">', val) return val page_name = formatter.context.resource.id prefix, base_page_name, lang_code = self._get_page_info(page_name) lang_link_list = [] for translation in self._get_translations(prefix, base_page_name): if translation != lang_code: page_name = self._get_translated_page(prefix, base_page_name, translation) lang_link_list.append(u" * [[wiki:/%s|%s]]" % (page_name, \ self._get_language_name(translation))) else: lang_link_list.append(u" * '''%s'''" % self._get_language_name(translation)) baselink = "" if lang_code != self.base_lang and u'revision' in kw: basepage = self._get_translated_page(prefix, base_page_name, self.base_lang) newver = WikiPage(self.env, basepage).version oldver = abs(int(kw[u'revision'])) if oldver < newver: baselink = u"\n * [[wiki:/%s?action=diff&old_version=%s|@%s - @%s]]" \ % (basepage, oldver, oldver, newver) if len(lang_link_list) <= 1: return outdated out = StringIO() Formatter(self.env, formatter.context).format(u'\n'.join(lang_link_list) \ +baselink, out) desc = u"Languages" if self.description.has_key(lang_code): desc = self.description[lang_code] return outdated + u""" <div class="wiki-toc trac-nav" style="clear:both"> <h4>%s:</h4> %s </div>""" % (desc, out.getvalue())
def process_request(self, req): req.perm.require('TAGS_VIEW') match = re.match(r'/tags/?(.*)', req.path_info) tag_id = match.group(1) and match.group(1) or None query = req.args.get('q', '') # Consider only providers, that are permitted for display. tag_system = TagSystem(self.env) all_realms = tag_system.get_taggable_realms(req.perm) if not (tag_id or query) or [r for r in all_realms if r in req.args] == []: for realm in all_realms: if realm not in self.exclude_realms: req.args[realm] = 'on' checked_realms = [r for r in all_realms if r in req.args] if query: # Add permitted realms from query expression. checked_realms.extend(query_realms(query, all_realms)) realm_args = dict(zip([r for r in checked_realms], ['on' for r in checked_realms])) # Switch between single tag and tag query expression mode. if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE): # Convert complex, invalid tag ID's --> query expression. req.redirect(req.href.tags(realm_args, q=tag_id)) elif query: single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE) if single_page: # Convert simple query --> single tag. req.redirect(req.href.tags(single_page.group(2), realm_args)) data = dict(page_title=_("Tags"), checked_realms=checked_realms) # Populate the TagsQuery form field. data['tag_query'] = tag_id and tag_id or query data['tag_realms'] = list(dict(name=realm, checked=realm in checked_realms) for realm in all_realms) if tag_id: data['tag_page'] = WikiPage(self.env, tag_system.wiki_page_prefix + tag_id) if query or tag_id: macro = 'ListTagged' # TRANSLATOR: The meta-nav link label. add_ctxtnav(req, _("Back to Cloud"), req.href.tags()) args = "%s,format=%s,cols=%s" % \ (tag_id and tag_id or query, self.default_format, self.default_cols) data['mincount'] = 0 else: macro = 'TagCloud' mincount = as_int(req.args.get('mincount', 0), self.cloud_mincount) args = mincount and "mincount=%s" % mincount or None data['mincount'] = mincount # When using the given req the page isn't rendered properly. The call # to expand_macro() leads to Chrome().render_template(req, ...). # The function render_template() breaks something in the request handling. # That used to work with Genshi. # # With this mocked req everything is just fine. mock_req = MockRequest(self.env, path_info=req.path_info, authname=req.authname, script_name=req.href()) formatter = Formatter(self.env, web_context(mock_req, Resource('tag'))) self.env.log.debug("%s macro arguments: %s", macro, args and args or '(none)') macros = TagWikiMacros(self.env) try: # Query string without realm throws 'NotImplementedError'. data['tag_body'] = checked_realms and \ macros.expand_macro(formatter, macro, args, realms=checked_realms) \ or '' data['tag_body'] = Markup(to_unicode(data['tag_body'])) except InvalidQuery as e: data['tag_query_error'] = to_unicode(e) data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '') data['realm_args'] = realm_args add_stylesheet(req, 'tags/css/tractags.css') return 'tag_view.html', data, {'domain': 'tractags'}
def convert_content(self, req, input_type, source, output_type): # get parameters from trac ini file self.img_max_x = self.env.config.get('pagetodoc', 'img_max_x', self.img_max_x) self.img_max_y = self.env.config.get('pagetodoc', 'img_max_y', self.img_max_y) self.img_max_y = self.env.config.get('pagetodoc', 'dpi', self.dpi) # XSL-Transformation xsltfilepath = self.env.config.get('pagetodoc', 'xsltfile', '') # TBD: Fehler ausgeben, wenn xsltfile nicht gelesen werden kann # TBD: Parameter aus der trac.ini an zentraler Stelle auslesen if xsltfilepath == '': message = "You have to set the 'xsltfile' option in the " \ "[pagetodoc] section in trac.ini" raise_dependency_issue(message, req, self.env) if not os.path.exists(xsltfilepath): message = ("Value for 'xsltfile' in the [pagetodoc] section in " \ "trac.ini does not exist: '%s'.")% xsltfilepath raise_dependency_issue(message, req, self.env) # maybe for later use #codepage = self.env.config.get('trac', 'charset', 'iso-8859-1') codepage = 'iso-8859-1' # Convert Wiki markup to HTML, new style out = StringIO() context = Context.from_request(req, 'wiki', req.path_info[6:]) Formatter(self.env, context).format(source, out) html = Markup(out.getvalue()).encode(codepage, 'replace') # remove the bad HTML produced by the breadcrumbs plugin # RFE: find a universal way to do this html = re.compile('(<lh[^>]*>)').sub('', html) # temporary files and folders self.tempdir = mkdtemp(prefix="page2doc") htmlfilehandle, htmlfilepath = mkstemp(prefix='trac_', dir=self.tempdir, suffix = ".html") wordfilehandle, wordfilepath = mkstemp(prefix='word_', dir=self.tempdir, suffix = ".doc") os.close(wordfilehandle) # for debug: set all rights #self.chmod_tmp_dir(self.tempdir) # images # replace href with absolute path and if existing, base auth login try: # this will work if the authentication type is basic (and not over SSL?) login = base64.b64decode(req.environ['HTTP_AUTHORIZATION'][6:]) + '@' except (KeyError, TypeError): login = '' html = re.sub('<img src="(?!\w+://)', '<img src="%s://%s%s:%d' % (req.scheme, login, req.server_name, req.server_port), html) # save images to disk html = re.sub('<img src="([^"]*)"', self.download_image, html) # write HTML page to disk os.write(htmlfilehandle, '<html><body>' + html + '</body></html>') os.close(htmlfilehandle) # clean up the HTML page using HTML Tidy args = '-m -asxhtml -latin1 --doctype omit' tidypath = self.env.config.get('pagetodoc', 'tidypath', 'tidy') # verify that Tidy exists and is setup correctly tidy_error = dependency_failure("tidy", tidypath, "-v") if tidy_error: raise_dependency_issue(tidy_error, req, self.env) cmd = '"%s" %s %s' % (tidypath, args, htmlfilepath) self.execute_external_program(cmd) # workaround namespace self.perform_workarounds(htmlfilepath, 'html') if self.verbose: verb = '-v' else: verb = '' xsltprocpath = self.env.config.get('pagetodoc', 'xsltprocpath', 'xsltproc') # verify that Tidy exists and is setup correctly xsltproc_error = dependency_failure("xsltproc", xsltprocpath, "-V") if xsltproc_error: raise_dependency_issue(xsltproc_error, req, self.env) cmd = '%s %s --html -o %s %s %s' % ( xsltprocpath, verb, wordfilepath, xsltfilepath, htmlfilepath) self.execute_external_program(cmd) # workaround pre-tags self.perform_workarounds(wordfilepath, 'pre') zipfilepath = os.path.join( self.tempdir, os.path.basename(str(req.path_info) + '.zip')) # create a zip file and store all files into it zipfilehandle = zipfile.ZipFile(zipfilepath, "w") zipfilehandle.write(wordfilepath, os.path.basename(str(req.path_info) + '.htm')) for image in self.images: zipfilehandle.write(image, self.imagesubdir + os.path.basename(image)) zipfilehandle.close() zip_file = open(zipfilepath, "rb") zip = zip_file.read() zip_file.close() # delete temporary folders and files self.remove_dir(os.path.join(self.tempdir, self.logsubdir)) self.remove_dir(os.path.join(self.tempdir, self.imagesubdir)) self.remove_dir(self.tempdir) # reset image list self.images = [] return (zip, 'application/zip')
def process_request(self, req): """Process the request. For ClearSilver, return a (template_name, content_type) tuple, where `template` is the ClearSilver template to use (either a `neo_cs.CS` object, or the file name of the template), and `content_type` is the MIME type of the content. For Genshi, return a (template_name, data, content_type) tuple, where `data` is a dictionary of substitutions for the template. For both templating systems, "text/html" is assumed if `content_type` is `None`. Note that if template processing should not occur, this method can simply send the response itself and not return anything. """ # get the GeoTicket component assert self.env.is_component_enabled(GeoTicket) geoticket = GeoTicket(self.env) # add the query script add_script(req, 'common/js/query.js') # get the panel configuration config = self.panels() # build the panels panels = [] located_tickets = geoticket.tickets_with_location() for panel in config: # query the tickets query_string = panel['query'] query = Query.from_string(self.env, query_string) # decide the date to sort by if query.order == 'time': date_to_display = 'time_created' else: date_to_display = 'time_changed' results = query.execute(req) n_tickets = len(results) results = [ result for result in results if result['id'] in located_tickets ] locations = [] tickets = [] results = results[:self.dashboard_tickets] for result in results: ticket = Ticket(self.env, result['id']) try: address, (lat, lon) = geoticket.locate_ticket(ticket) content = geoticket.feature_content(req, ticket) # style for the markers style = {} for extension in self.marker_style: style.update(extension.style(ticket, req, **style)) style = style or None locations.append({ 'latitude': lat, 'longitude': lon, 'style': style, 'content': Markup(content) }) tickets.append(ticket) except GeolocationException: continue title = panel['label'] panels.append({ 'title': title, 'id': panel['id'], 'locations': Markup(simplejson.dumps(locations)), 'tickets': tickets, 'n_tickets': n_tickets, 'date_to_display': date_to_display, 'query_href': query.get_href(req.href) }) # add the tag cloud, if enabled cloud = None if self.display_cloud: if TagCloudMacro is None: self.log.warn( "[geo] display_cloud is set but the TagsPlugin is not installed" ) else: formatter = Formatter(self.env, Context.from_request(req)) macro = TagCloudMacro(self.env) cloud = macro.expand_macro(formatter, 'TagCloud', '') add_stylesheet(req, 'tags/css/tractags.css') add_stylesheet(req, 'tags/css/tagcloud.css') # compile data for the genshi template data = dict(panels=panels, cloud=cloud, openlayers_url=self.openlayers_url) return ('mapdashboard.html', data, 'text/html')