def get_existing_node(req, repos, path, rev): try: return repos.get_node(path, rev) except NoSuchNode as e: # TRANSLATOR: You can 'search' in the repository history... (link) search_a = tag.a(_("search"), href=req.href.log(repos.reponame or None, path, rev=rev, mode='path_history')) raise ResourceNotFound(tag( tag.p(e, class_="message"), tag.p(tag_("You can %(search)s in the repository history to see " "if that path existed but was later removed", search=search_a))))
def render(context, field, event): if event[0] == 'test&1': if field == 'url': return 'http://example.org/path?foo=bar&baz=1' if field == 'summary': return 'summary 1: <b>&</b>' if field == 'description': return tag(tag.h1('Title 1st'), tag.p('body & < >')) if event[0] == 'test&2': if field == 'url': return 'http://example.org/path?baz=2&foo=bar' if field == 'summary': return tag('summary 2: ', tag.b('&')) if field == 'description': return tag(tag.h1('Title 2nd'), tag.p('body & < >'))
def _render(self, formatter, cols, name_pat, size, header, limit): #noinspection PyArgumentList icon = Icons(self.env) icon_dir = icon.icon_location(size)[1] files = fnmatch.filter(os.listdir(icon_dir), '%s.png' % name_pat) icon_names = [os.path.splitext(p)[0] for p in files] if limit: displayed_icon_names = reduce_names(icon_names, limit) else: displayed_icon_names = icon_names icon_table = render_table( displayed_icon_names, cols, lambda name: icon._render_icon(formatter, name, size)) if not len(icon_names): message = 'No %s icon matches %s' % (SIZE_DESCR[size], name_pat) elif len(icon_names) == 1: message = 'Showing the only %s icon matching %s' % \ (SIZE_DESCR[size], name_pat) elif len(displayed_icon_names) == len(icon_names): message = 'Showing all %d %s icons matching %s' % \ (len(icon_names), SIZE_DESCR[size], name_pat) else: message = 'Showing %d of %d %s icons matching %s' % \ (len(displayed_icon_names), len(icon_names), SIZE_DESCR[size], name_pat) return tag.div(tag.p(tag.small(message)) if header else '', icon_table)
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) except Exception: message = content resource = Resource('repository', reponame) else: message = changeset.message rev = changeset.rev resource = repos.resource 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')
def test_tracerror_with_tracerror_with_element(self): message = tag.p('Powered by ', tag.a('Trac', href='http://trac.edgewall.org/')) rv = to_fragment(TracError(TracError(message))) self.assertEqual(Element, type(rv)) self.assertEqual('<p>Powered by <a href="http://trac.edgewall.org/">' 'Trac</a></p>', unicode(rv))
def test_find_element_with_tag(self): frag = tag(tag.p('Paragraph with a ', tag.a('link', href='http://www.edgewall.org'), ' and some ', tag.strong('strong text'))) self.assertIsNotNone(find_element(frag, tag='p')) self.assertIsNotNone(find_element(frag, tag='a')) self.assertIsNotNone(find_element(frag, tag='strong')) self.assertIsNone(find_element(frag, tag='input')) self.assertIsNone(find_element(frag, tag='textarea'))
def expand_macro(self, formatter, name, content): def wikify(text): return format_to_oneliner(self.env, formatter.context, text) return tag.div( tag.p( wikify( _(""" The following tokens can be used in the `PageTemplates/MyPage` or `PageTemplates/MyPage/<user>` wiki pages: """))), tag.dl([(tag.dt(tag.tt(token)), tag.dd(wikify(gettext(description)))) for token, description in sorted( MyPageModule(self.env).tokens.values())]), tag.p( wikify( _(""" Note that you can also use the `[[MyPageNav]]` wiki macro for creating dynamic links to other ''MyPage'' pages (use `[[MyPageNav?]]` to get help on this macro). """))))
def expand_macro(self, formatter, name, content): from trac.wiki.formatter import system_message content = content.strip() if content else '' name_filter = content.strip('*') def get_macro_descr(): for macro_provider in formatter.wiki.macro_providers: names = list(macro_provider.get_macros() or []) if name_filter and not any( name.startswith(name_filter) for name in names): continue try: name_descriptions = [ (name, macro_provider.get_macro_description(name)) for name in names ] except Exception as e: yield system_message( _("Error: Can't get description for macro %(name)s", name=names[0]), e), names else: for descr, pairs in groupby(name_descriptions, key=lambda p: p[1]): if descr: if isinstance(descr, (tuple, list)): descr = dgettext(descr[0], to_unicode(descr[1])) \ if descr[1] else '' else: descr = to_unicode(descr) or '' if content == '*': descr = format_to_oneliner(self.env, formatter.context, descr, shorten=True) else: descr = format_to_html(self.env, formatter.context, descr) yield descr, [name for name, descr in pairs] return tag.div(class_='trac-macrolist')( (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]), len(names) > 1 and tag.p( tag.strong(_("Aliases:")), [tag.code(' [[', alias, ']]') for alias in names[1:]]) or None, description or tag.em(_("Sorry, no documentation found"))) for description, names in sorted(get_macro_descr(), key=lambda item: item[1][0]))
def _provider_failure(self, exc, req, ep, current_filters, all_filters): """Raise a TracError exception explaining the failure of a provider. At the same time, the message will contain a link to the timeline without the filters corresponding to the guilty event provider `ep`. """ self.log.error("Timeline event provider failed: %s", exception_to_unicode(exc, traceback=True)) ep_kinds = {f[0]: f[1] for f in ep.get_timeline_filters(req) or []} ep_filters = set(ep_kinds.keys()) current_filters = set(current_filters) other_filters = set(current_filters) - ep_filters if not other_filters: other_filters = set(all_filters) - ep_filters args = [(a, req.args.get(a)) for a in ('from', 'format', 'max', 'daysback')] href = req.href.timeline(args + [(f, 'on') for f in other_filters]) # TRANSLATOR: ...want to see the 'other kinds of events' from... (link) other_events = tag.a(_('other kinds of events'), href=href) raise TracError( tag( tag.p(tag_( "Event provider %(name)s failed for filters " "%(kinds)s: ", name=tag.code(ep.__class__.__name__), kinds=', '.join('"%s"' % ep_kinds[f] for f in current_filters & ep_filters)), tag.strong(exception_to_unicode(exc)), class_='message'), tag.p( tag_( "You may want to see the %(other_events)s from the " "Timeline or notify your Trac administrator about the " "error (detailed information was written to the log).", other_events=other_events))))
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. cmd, T, o = [args[0]], '', '' if 'gnuplot' not in cmd[0]: cmd = [arg for arg in args] else: for arg in args: if arg[:2] == '-o': o = arg[2:] elif arg[:2] == '-T': T = arg[2:] p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if 'gnuplot' in cmd[0]: p.stdin.write(("set terminal %s transparent\nset output '%s'\n" % (T, o)).encode('utf-8')) 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(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)
def test_element(self): rv = to_fragment(tag.p('blah')) self.assertEqual(Element, type(rv)) self.assertEqual('<p>blah</p>', unicode(rv))
def expand_macro(self, formatter_or_context, name, content): """Return the HTML output of the macro. :param formatter_or_context: a Formatter when called as a macro, a RenderingContext when called by `GraphvizPlugin.render` :param name: Wiki macro command that resulted in this method being called. In this case, it should be 'graphviz', followed (or not) by the processor name, then by an output format, as following: graphviz.<processor>/<format> Valid processor names are: dot, neato, twopi, circo, and fdp. The default is dot. Valid output formats are: jpg, png, gif, svg and svgz. The default is the value specified in the out_format configuration parameter. If out_format is not specified in the configuration, then the default is png. examples: graphviz.dot/png -> dot png graphviz.neato/jpg -> neato jpg graphviz.circo -> circo png graphviz/svg -> dot svg :param content: The text the user entered for the macro to process. """ # check and load the configuration errmsg = self._load_config() if errmsg: return self._error_div(errmsg) ## Extract processor and format from name processor = out_format = None # first try with the RegExp engine try: m = re.match('graphviz\.?([a-z]*)\/?([a-z]*)', name) (processor, out_format) = m.group(1, 2) # or use the string.split method except: (d_sp, s_sp) = (name.split('.'), name.split('/')) if len(d_sp) > 1: s_sp = d_sp[1].split('/') if len(s_sp) > 1: out_format = s_sp[1] processor = s_sp[0] elif len(s_sp) > 1: out_format = s_sp[1] # assign default values, if instance ones are empty if not out_format: out_format = self.out_format if not processor: processor = self.processor if processor in Graphviz.Processors: proc_cmd = self.cmds[processor] else: self.log.error('render_macro: requested processor (%s) not found.', processor) return self._error_div('requested processor (%s) not found.' % processor) if out_format not in Graphviz.Formats: self.log.error('render_macro: requested format (%s) not found.', out_format) return self._error_div( tag.p( _( "Graphviz macro processor error: " "requested format (%(fmt)s) not valid.", fmt=out_format))) encoded_cmd = (processor + str(self.processor_options)) \ .encode(self.encoding) encoded_content = content.encode(self.encoding) sha_key = hashlib.sha256(encoded_cmd + encoded_content + ( b'S' if self.sanitizer else b'')).hexdigest() img_name = '%s.%s.%s' % (sha_key, processor, out_format) # cache: hash.<dot>.<png> img_path = os.path.join(self.cache_dir, img_name) map_name = '%s.%s.map' % (sha_key, processor) # cache: hash.<dot>.map map_path = os.path.join(self.cache_dir, map_name) # Check for URL="" presence in graph code URL_in_graph = 'URL=' in content or 'href=' in content # Create image if not in cache if not os.path.exists(img_path): self._clean_cache() if self.sanitizer: content = self._sanitize_html_labels(content) if URL_in_graph: # translate wiki TracLinks in URL if isinstance(formatter_or_context, RenderingContext): context = formatter_or_context else: context = formatter_or_context.context content = self._expand_wiki_links(context, out_format, content) encoded_content = content.encode(self.encoding) # Antialias PNGs with rsvg, if requested if out_format == 'png' and self.png_anti_alias == True: # 1. SVG output failure, errmsg = self._launch(encoded_content, proc_cmd, '-Tsvg', '-o%s.svg' % img_path, *self.processor_options) if failure: return self._error_div(errmsg) # 2. SVG to PNG rasterization failure, errmsg = self._launch(None, self.rsvg_path, '--dpi-x=%d' % self.dpi, '--dpi-y=%d' % self.dpi, '%s.svg' % img_path, img_path) if failure: return self._error_div(errmsg) else: # Render other image formats failure, errmsg = self._launch(encoded_content, proc_cmd, '-T%s' % out_format, '-o%s' % img_path, *self.processor_options) if failure: return self._error_div(errmsg) # Generate a map file for binary formats if URL_in_graph and out_format in Graphviz.Bitmap_Formats: # Create the map if not in cache if not os.path.exists(map_path): failure, errmsg = self._launch(encoded_content, proc_cmd, '-Tcmap', '-o%s' % map_path, *self.processor_options) if failure: return self._error_div(errmsg) if errmsg: # there was a warning. Ideally we should be able to use # `add_warning` here, but that's not possible as the warnings # are already emitted at this point in the template processing return self._error_div(errmsg) # Generate HTML output img_url = formatter_or_context.href.graphviz(img_name) # for SVG(z) if out_format in Graphviz.Vector_Formats: try: # try to get SVG dimensions f = open(img_path, 'r') svg = f.readlines(1024) # don't read all f.close() svg = "".join(svg).replace('\n', '') w = re.search('width="([0-9]+)(.*?)" ', svg) h = re.search('height="([0-9]+)(.*?)"', svg) (w_val, w_unit) = w.group(1, 2) (h_val, h_unit) = h.group(1, 2) # Graphviz seems to underestimate height/width for SVG images, # so we have to adjust them. # The correction factor seems to be constant. w_val, h_val = [1.35 * float(x) for x in (w_val, h_val)] width = str(w_val) + w_unit height = str(h_val) + h_unit except ValueError: width = height = '100%' # insert SVG, IE compatibility return tag.object(tag.embed(src=img_url, type="image/svg+xml", width=width, height=height), data=img_url, type="image/svg+xml", width=width, height=height) # for binary formats, add map elif URL_in_graph and os.path.exists(map_path): f = open(map_path, 'r') map = f.readlines() f.close() map = "".join(map).replace('\n', '') return tag( tag.map(Markup(to_unicode(map)), id='G' + sha_key, name='G' + sha_key), tag.img(src=img_url, usemap="#G" + sha_key, alt=_("GraphViz image"))) else: return tag.img(src=img_url, alt=_("GraphViz image"))