def product_media_data(icons, product): return dict(href=product.href(), thumb=icons.get(product.prefix, no_thumbnail), title=product.name, description=format_to_html(self.env, product_ctx(product), product.description), links={'extras': (([{'href': req.href.products( product.prefix, action='edit'), 'title': _('Edit product %(prefix)s', prefix=product.prefix), 'icon': tag.i(class_='icon-edit'), 'label': _('Edit')},] if 'PRODUCT_MODIFY' in req.perm else []) + [{'href': product.href(), 'title': _('Home page'), 'icon': tag.i(class_='icon-home'), 'label': _('Home')}, {'href': product.href.dashboard(), 'title': _('Tickets dashboard'), 'icon': tag.i(class_='icon-tasks'), 'label': _('Tickets')}, {'href': product.href.wiki(), 'title': _('Wiki'), 'icon': tag.i(class_='icon-book'), 'label': _('Wiki')}]), 'main': {'href': product.href(), 'title': None, 'icon': tag.i(class_='icon-chevron-right'), 'label': _('Browse')}})
def get_macro_descr(): for macro_provider in formatter.wiki.macro_providers: names = list(macro_provider.get_macros() or []) if name_filter and not any(name.startswith(name_filter) for name in names): continue try: name_descriptions = [ (name, macro_provider.get_macro_description(name)) for name in names] except Exception, e: yield system_message( _("Error: Can't get description for macro %(name)s", name=names[0]), e), names else: for descr, pairs in groupby(name_descriptions, key=lambda p: p[1]): if descr: if isinstance(descr, (tuple, list)): descr = dgettext(descr[0], to_unicode(descr[1])) \ if descr[1] else '' else: descr = to_unicode(descr) or '' if content == '*': descr = format_to_oneliner( self.env, formatter.context, descr, shorten=True) else: descr = format_to_html( self.env, formatter.context, descr) yield descr, [name for name, descr in pairs]
def expand_macro(self, formatter, name, content, 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')
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")
def _ticket_links(env, formatter, t, a_class=""): """Build links to tickets.""" tkt_id = str(t.get("id")) status = t.get("status") summary = to_unicode(t.get("summary")) owner = to_unicode(t.get("owner")) description = to_unicode(t.get("description")) url = t.get("href") if status == "closed": a_class = a_class + "closed" else: a_class = a_class + "open" # Reduce content for tooltips. markup = format_to_html(env, formatter.context, description) extractor = TextExtractor() extractor.feed(markup) tip = tag.span(shorten_line(extractor.getvalue())) ticket = tag.a("#" + tkt_id, href=url) ticket(tip, class_="tip", target="_blank") ticket = tag.div(ticket, class_=a_class, align="left") # Fix stripping of regular leading space in IE. blank = " " ticket(Markup(blank), summary, " (", owner, ")") summary = tag(summary, " (", owner, ")") ticket_short = tag.span(tag.a("#" + tkt_id, href=url, target="_blank", title_=summary), class_=a_class) return ticket, ticket_short
def expand_macro(self, formatter, name, content): add_stylesheet(formatter.req, 'notebox/css/notebox.css') args, kwargs = parse_args(content) width = len(args) > 2 and args[2] or '70%' return tag.div(format_to_html(self.env, formatter.context, args[1]), class_='notebox-%s' % (args[0],), style='width: %s' % (width,))
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)
def serialized(self, env, context): return { 'id': self.id, 'stack': self.stack, 'rank': self.rank, 'title': self.title, 'title_html': format_to_html(env, context, self.title), }
def render(self, context, mimetype, content, filename=None, url=None): if url is not None: match = re.match(self.PREVIEW_PATTERN, urllib.unquote(str(url))) if match: path_info = match.groupdict() macro = unicode(self.MACRO_FORMAT % path_info, self.ENCODING) return format_to_html(self.env, context, macro) return None
def render_timeline_event(self, context, field, event): ev = event[3] if field=='title': return tag(tag.em(ev[0]), ' found on ', ev[1]) elif field=='description': return format_to_html(self.env, context, ev[3]) elif field=='url': return ev[2]
def getPageHTML(self, req, pagename, version=None): """ Return latest version of page as rendered HTML, utf8 encoded. """ page = self._fetch_page(req, pagename, version) fields = {"text": page.text} for manipulator in self.manipulators: manipulator.prepare_wiki_page(req, page, fields) context = Context.from_request(req, page.resource, absurls=True) html = format_to_html(self.env, context, fields["text"]) return "<html><body>%s</body></html>" % html.encode("utf-8")
def _gen_ticket_entry(self, t, a_class=''): id = str(t.get('id')) status = t.get('status') priority = t.get('priority') hours = t.get(self.hours_field_name) summary = to_unicode(t.get('summary')) owner = to_unicode(t.get('owner')) description = to_unicode(t.get('description')[:1024]) url = t.get('href') if status == 'closed': a_class = a_class + 'closed' else: a_class = a_class + 'open' a_class += " ticket priority-" + priority markup = format_to_html(self.env, self.ref.context, description) # Escape, if requested if self.sanitize is True: try: description = HTMLParser(StringIO(markup) ).parse() | HTMLSanitizer() except ParseError: description = escape(markup) else: description = markup # Replace tags that destruct tooltips too much desc = self.end_RE.sub(']', Markup(description)) desc = self.del_RE.sub('', desc) # need 2nd run after purging newline in table cells in 1st run desc = self.del_RE.sub('', desc) desc = self.item_RE.sub('X', desc) desc = self.tab_RE.sub('[|||]', desc) description = self.open_RE.sub('[', desc) tip = tag.span(Markup(description)) ticket = '#' + id ticket = tag.a(ticket, href=url) ticket(tip, class_='tip', target='_blank') ticket = tag.div(ticket) ticket(class_=a_class, align='left', **{"data-ticketid": id}) # fix stripping of regular leading space in IE blank = ' ' ticket(Markup(blank), summary, ' (', owner, ')') ticket(tag.span(str(hours) + "h", class_="hours")) summary = tag(summary, ' (', owner, ')') ticket_short = '#' + id ticket_short = tag.a(ticket_short, href=url) ticket_short(target='_blank', title_=summary) ticket_short = tag.span(ticket_short) ticket_short(class_=a_class) return ticket,ticket_short
def expand_macro(self, formatter, name, content, args): self.log.debug("SpoilerMacro: expand_macro") add_stylesheet(formatter.req, 'spoiler/css/spoiler.css') add_javascript(formatter.req, 'spoiler/js/spoiler.js') if '\n' in content: output = tag.div(class_="spoiler")(format_to_html(self.env, formatter.context,content)) else: output = tag.span(class_="spoiler")(format_to_oneliner(self.env, formatter.context,content)) self.log.debug("SpoilerMacro: expand_macro output") return output
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is True: default = 'true' elif default is False: default = 'false' elif default == 0: default = '0.0' if isinstance(default, float) else '0' elif default: default = ', '.join(to_unicode(val) for val in default) \ if isinstance(default, (list, tuple)) \ else to_unicode(default) else: return tag.td(_("(no default)"), class_='nodefault') return tag.td(tag.code(default), class_='default') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, getdoc(option))), default_cell(option)) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def _discussion_attachment_link(self, formatter, namespace, params, label): id, name = params.split(':') # Create request context. context = Context.from_request(formatter.req) context.realm = 'discussion-wiki' # Get database access. db = self.env.get_db_cnx() context.cursor = db.cursor() if namespace == 'topic-attachment': return format_to_html(self.env, context, '[attachment:discussion:topic/%s:%s %s]' % (id, name, label)) elif namespace == 'raw-topic-attachment': return format_to_html(self.env, context, '[raw-attachment:discussion:topic/%s:%s %s]' % (id, name, label)) else: return tag.a(label, href = formatter.href.discussion('topic', id), title = label.replace('"', ''), class_ = 'missing')
def wikipage_to_html(self, text, page_name, req): """ Converts a wiki text to HTML, and makes some replacements in order to fix internal and external links and references """ self.env.log.debug('WikiPrint => Start function wikipage_to_html') #Remove exclude expressions for r in EXCLUDE_RES: text = r.sub('', text) #Escape [[PageOutline]], to avoid wiki processing for r in [re.compile(r'\[\[TOC(\(.*\))?\]\]'), re.compile(r'\[\[PageOutline(\(.*\))?\]\]')]: text = r.sub('![[pdf-toc]]', text) for macro in self.omit_macros: r = re.compile(r'\[\[' + macro + r'\(.*?\]\]') text = r.sub('', text) r = re.compile(r'^\{\{\{\r?\n#!' + macro + r'\r?\n(^.*\r?\n)*?^\}\}\}', re.MULTILINE) text = r.sub('', text) link_format = req.args.get('link_format', None) if self.omit_links: r1 = re.compile(r'\[wiki:(.*?) (.*?)\]') text = r1.sub('[\g<2>]', text) r2 = re.compile(r'\[wiki:(.*?)\]') text = r2.sub('[\g<1>]', text) elif link_format: #Keep links to the same export format r = re.compile(r'(?<=\[wiki:)(.*?)(?=(?: .*?)?\])') text = r.sub('\g<1>?format=%s&link_format=%s' % (link_format, link_format), text) if self.rebase_links: r = re.compile(r'\[wiki:(.*?)\]') text = r.sub('[%s/wiki/\g<1>]' % self.rebase_links, text) self.env.log.debug('WikiPrint => Wiki input for WikiPrint: %r' % text) #First create a Context object from the wiki page context = Context(Resource('wiki', page_name), req.abs_href, req.perm) context.req = req #Now convert in that context page = format_to_html(self.env, context, text) self.env.log.debug('WikiPrint => Wiki to HTML output: %r' % page) self.env.log.debug('WikiPrint => HTML output for WikiPrint is: %r' % page) self.env.log.debug('WikiPrint => Finish function wikipage_to_html') return page
def wiki2html(self, wiki): """ The easiest way to convert wiki to html """ req = Mock(href=Href(self.env.abs_href.base), abs_href=self.env.abs_href, authname='anonymous', perm=MockPerm(), args={}) context = Context.from_request(req, 'wiki') try: html = format_to_html(self.env, context, wiki).encode('utf8','ignore') except AttributeError: html = wiki return html
def renderWiki(self, context, items, convertList): ''' Convert selected wiki fields from the database into html Return values to calling application for publishing to the web page. ''' for data_row in items: ''' Index through data row, process select elements of record set. ''' for wikify in convertList: data_row[wikify] = format_to_html(self.env, context, data_row[wikify]) return items
def expand_macro(self, formatter, name, txt): db = self.env.get_db_cnx() txt = txt or '' args = txt.split(',') # strip off quotes and re markers pagename = args[0].replace('"','') pagename = pagename.replace('$','') pagename = pagename.replace('^','') # get the page sql = "SELECT text from wiki where name = '%s' order by version desc limit 1" % pagename cs = db.cursor() cs.execute(sql ) row = cs.fetchone() if row == None: return '' text = row[0] # put in the heading if a style is provided if len(args) == 3: return tag.div(class_=args[2])( tag.div(class_=args[1])(pagename), format_to_html(self.env, formatter.context, text) ) if len(args) == 2: return tag.div(tag.div(class_=args[1])(pagename), format_to_html(self.env, formatter.context, text) ) else: return format_to_html(self.env, formatter.context, text)
def expand_macro(self, formatter, name, txt): if txt: sourcepage = txt.strip('"') else: sourcepage = 'Fortune Cookies' wikiobj = randomwiki(self.env.get_db_cnx()) pagelist = wikiobj.getentries(sourcepage,1) if pagelist[0]: pagelist[0] = pagelist[0].replace('*','') return format_to_html(self.env,formatter.context,pagelist[0]) else: return "Quotes not found"
def expand_macro(self, formatter, name, content): """Called by the formatter when rendering the parsed wiki text.""" # Parse access rule action = permissions = body = lines = None multiline = content.find("\n") != -1 if multiline: lines = content.split("\n") if not lines[0] or lines[0][0] != '#': raise TracError('Missing permission specification') match = self.PARSE_RULE.match(lines[0][1:]) if match: action = match.group(1) permissions = self.SPLIT_LIST.split(match.group(2).strip()) else: raise TracError("Invalid permission specification: %s" % lines[0][1:]) else: match = self.PARSE_RULE.match(content) if match: action = match.group(1) permissions = self.SPLIT_LIST.split(match.group(2).strip()) body = match.group(3).lstrip() if not body or body[0] != ',': raise TracError("Invalid permission specification: %s" % content) body = body[1:] else: raise TracError("Invalid permission specification: %s" % content) # Check access allow = None if action.lower() == "allow": allow = False for p in permissions: if p in formatter.req.perm: allow = True break else: allow = True for p in permissions: if p in formatter.req.perm: allow = False break # Process text if not allow: return '' elif multiline: return format_to_html(self.env, formatter.context, "\n".join(lines[1:])) else: return body
def get_macro_descr(): for macro_provider in formatter.wiki.macro_providers: for macro_name in macro_provider.get_macros(): if content and macro_name != content: continue try: descr = macro_provider.get_macro_description(macro_name) descr = format_to_html(self.env, formatter.context, to_unicode(descr) or '') except Exception, e: descr = system_message(_("Error: Can't get description " "for macro %(name)s", name=macro_name), e) yield (macro_name, descr)
def expand_macro(self, formatter, name, content): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(content) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() def getdoc(option_or_section): doc = to_unicode(option_or_section.__doc__) if doc: doc = dgettext(option_or_section.doc_domain, doc) return doc registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, getdoc(section)) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') def default_cell(option): default = option.default if default is not None and default != '': return tag.td(tag.code(option.dumps(default)), class_='default') else: return tag.td(_("(no default)"), class_='nodefault') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, getdoc(option))), default_cell(option), class_='odd' if idx % 2 else 'even') for idx, option in enumerate(sorted(options.get(section, {}).itervalues(), key=lambda o: o.name)) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def expand_macro(self, formatter, name, content): """Called by the formatter when rendering the parsed wiki text.""" if name in LEVELS: level = LEVELS[name] if level["action"] in formatter.req.perm: # authorized content = "\n".join((line for line in content.split("\n") if not line.startswith("#:"))) else: # unauthorized content = "\n".join((line[2:] for line in content.split("\n") if line.startswith("#:"))) if content: return tag.div(format_to_html(self.env, formatter.context, content), style=level["style"]) else: return ""
def _get_wiki_html(env, data, is_new_ticket): wiki_page = is_new_ticket and NEW_TICKET_PAGE_NAME or MODIFY_TICKET_PAGE_NAME page = WikiPage(env, wiki_page) if len(page.text) != 0: text = page.text else: if is_new_ticket: text = 'No ticket guidelines for creating a new ticket have been specified. ' \ 'Please create [wiki:%s this wiki page] to specify these guidelines.' \ % NEW_TICKET_PAGE_NAME else: text = 'No ticket guidelines for modifying a ticket have been specified. ' \ 'Please create [wiki:%s this wiki page] to specify these guidelines.' \ % MODIFY_TICKET_PAGE_NAME return tag.div(format_to_html(env, data['context'], text), class_='ticket-guidelines')
def expand_macro(self, formatter, name, txt): (sourcepage,number) = txt.split(',') sourcepage = sourcepage.strip('"') if number is None: number = 1 else: number = int(number) out = '' wikiobj = randomwiki(self.env.get_db_cnx()) pagelist = wikiobj.getentries(sourcepage,number) for page in pagelist: page = self.fixup_images(page,sourcepage) out += format_to_html(self.env,formatter.context,page) return out
def expand_macro(self, formatter, name, content): args = content.split(',') num_args = len(args) if not (1 <= num_args <= 2): raise TracError('Incorrect number of arguments (two required). ' 'Usage: [[subpage(page, [true/false])]] where ' 'true/false determines whether or not an Edit ' 'Section link is shown.') page_name = args[0].strip() if num_args == 2: edit_link = args[1].lower().strip() if edit_link not in ('true', 'false'): raise TracError('Incorrect second argument (should be "true" ' 'or "false"). Usage: [[subpage(true/false, ' 'page)]] where true/false determines whether ' 'or not an Edit Section link is shown.') edit_link = edit_link == 'true' else: edit_link = True # TODO: The error raised if the wiki page # doesn't exist isn't descriptive at all wikiparser = formatter.wikiparser target_url = wikiparser.link_resolvers['wiki'](formatter, 'wiki', page_name, None).attrib.get('href') wiki_body = '' for page_text, in self.env.db_query(""" SELECT text FROM wiki WHERE wiki.name=%s ORDER BY wiki.version DESC LIMIT 1 """, (page_name,)): wiki_body = format_to_html(self.env, formatter.context, page_text) break link_tag = Markup('<p><a href="%s?action=edit" class="wiki">' 'Edit Section</a></p>' % target_url) return wiki_body + (link_tag if edit_link else '')
def expand_macro(self, formatter, name, content): num_args = len(content.split(',')) if not (1 <= num_args <= 2): raise TracError(('Incorrect number of arguments (two required). ' 'Usage: [[subpage(page, [true/false])]] where ' 'true/false determines whether or not an Edit ' 'Section link is shown.')) wiki_page = content.split(',')[0].strip() if num_args == 2: edit_link = content.split(',')[1].lower().strip() if not edit_link in ('true', 'false'): raise TracError(('Incorrect second argument (should be "true" ' 'or "false"). Usage: [[subpage(true/false, ' 'page)]] where true/false determines whether ' 'or not an Edit Section link is shown.')) edit_link = edit_link == 'true' else: edit_link = True # TODO: The error raised if the wiki page # doesn't exist isn't descriptive at all wikiparser = formatter.wikiparser target_url = wikiparser.link_resolvers['wiki'](formatter, 'wiki', wiki_page, None).attrib.get('href') db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(("SELECT text FROM wiki WHERE wiki.name = '%s' ORDER " "BY wiki.version DESC LIMIT 1;") % (wiki_page)) wiki_body = [page for page in cursor][0][0] body = format_to_html(self.env, formatter.context, wiki_body) link_tag = ('<p><a href="%s?action=edit" class="wiki">Edit Section</a>' '</p>' % (target_url)) return unicode(body) + (edit_link and link_tag or '')
def process_request(self, req): path = req.path_info[ len("/watchlist/manual") : ].strip('/') if path.startswith('attachments'): return self.handle_attachment(req, path) language = path if not language: language = req.session.get('language', 'en-US') # Try to find a suitable language if no manual exists # in the requested one. if language not in self.manuals: # Try to find a main language, # e.g. 'xy' instead of 'xy-ZV' l = language.split('-')[0] language = 'en-US' # fallback if no other is found if l in self.manuals: language = l else: # Prefer 'en-US' before any other English dialect if l == 'en' and 'en-US' in self.manuals: language = 'en-US' else: # If there is none try to find # any other 'xy-*' language l += '-' for lang in sorted(self.manuals.keys()): if lang.startswith(l): language = lang break req.redirect(req.href.watchlist('manual',language)) try: f = open(self.manuals[language], 'r') text = to_unicode( f.read() ) except Exception as e: raise HTTPNotFound(e) wldict = dict( format_text=lambda text: format_to_html(self.env, Context.from_request(req), text), text=text) return ("watchlist_manual.html", wldict, "text/html")
def expand_macro(self, formatter, name, args): from trac.config import ConfigSection, Option section_filter = key_filter = '' args, kw = parse_args(args) if args: section_filter = args.pop(0).strip() if args: key_filter = args.pop(0).strip() registry = ConfigSection.get_registry(self.compmgr) sections = dict((name, dgettext(section.doc_domain, to_unicode(section.__doc__))) for name, section in registry.iteritems() if name.startswith(section_filter)) registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in registry.iteritems(): if section.startswith(section_filter): options.setdefault(section, {})[key] = option sections.setdefault(section, '') return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td(tag.tt(option.name)), tag.td(format_to_oneliner( self.env, formatter.context, dgettext(option.doc_domain, to_unicode(option.__doc__)))), tag.td(tag.code(option.default or 'false') if option.default or option.default is False else _("(no default)"), class_='default' if option.default or option.default is False else 'nodefault')) for option in sorted(options.get(section, {}).itervalues(), key=lambda o: o.name) if option.name.startswith(key_filter)))) for section, section_doc in sorted(sections.iteritems()))
def process_request(self, req): page_name = req.args.get('page') location = req.args.get('location') theme = req.args.get('theme', self.default_theme) page = WikiPage(self.env, page_name) if not page.exists: raise TracError('Invalid wiki page "%s"' % page.name) page_text = self.fixup_images_re.sub(r'[[Image(wiki:%s:\1)]]' % page.name, page.text) in_section = -1 text = title = html_title = title_page = handout = '' slides = [] context = Context.from_request(req, page.resource) for line in page_text.splitlines(): match = self.heading_re.match(line) if match: # Insert accumulated text into appropriate location if in_section == 1: title_page = format_to_html(self.env, context, text) elif in_section == 2: text = self.fixup_re.sub(r'\1', text) slides.append({'body': format_to_html(self.env, context, text), 'handout': format_to_html(self.env, context, handout)}) if match.lastgroup == 'title': title = match.group(match.lastgroup) html_title = format_to_html(self.env, context, title) title = plaintext(html_title) in_section = 1 else: in_section = 2 text = '' text += line + '\n' if in_section == 1: title_page = format_to_html(self.env, context, text) elif in_section == 2: text = self.fixup_re.sub(r'\1', text) slides.append({'body': format_to_html(self.env, context, text), 'handout': format_to_html(self.env, context, handout)}) add_stylesheet(req, 'common/css/code.css') add_stylesheet(req, 'common/css/diff.css') data = { 'html_title': html_title, 'location': location, 'slides': slides, 'theme': theme, 'title': title, 'title_page': title_page } return 'slideshow.html', data, 'text/html'
def expand_macro(self, formatter, name, content, args=None): _start_time = time.time() # save start time _largs, _kwargs = parse_args(content) _show_referrers = _largs and 'show_referrers' in _largs _ignored_referrers = _kwargs.get('ignored_referrers', None) # 'filter' is an alias for option 'ignored_referrers' if not _ignored_referrers: _ignored_referrers = _kwargs.get('filter', None) # default option is 'exclusive' for backward compatibility _filtertype = _kwargs.get('filtertype', 'exclusive') # get all wiki page names and their content self.page_names, self.page_texts = \ self.get_wiki_pages(_ignored_referrers, _filtertype) _ml_parser = MissingLinksHTMLParser() # OrderedDict is needed to run test cases, but was only added in Python 2.7 try: _missing_links = OrderedDict() except: _missing_links = dict() for _name, _text in zip(self.page_names, self.page_texts): # set up context for relative links formatter.resource.id = _name # parse formatted wiki page for missing links _ml_parser.feed( format_to_oneliner(self.env, formatter.context, _text)) if _ml_parser.data: for _page in _ml_parser.data: if _missing_links.has_key(_page): if _missing_links[_page].count(_name) == 0: _missing_links[_page] = _missing_links[_page] + \ [_name,] else: _missing_links[_page] = [ _name, ] _ml_parser.reset() if _show_referrers: _data = '||Missing link||Referrer(s)||\n' else: _data = '||Missing link||\n' _missing_link_count = 0 for _page in _missing_links: _data = _data + '||[[%s]]' % \ _page.partition('/wiki/')[2].replace('%20',' ') if _show_referrers: _first = True for _name in _missing_links[_page]: if _first: _data = _data + "||%s" % _name _first = False else: _data = _data + ", %s" % _name _missing_link_count = _missing_link_count + 1 _data = _data + "||\n" # reset context for relative links formatter.resource.id = '' self.log.debug("Found %d missing pages in %s seconds'" % \ (_missing_link_count, (time.time() - _start_time))) return format_to_html(self.env, formatter.context, _data)
def get_summary(self, req, fromdate=None, todate=None): def myformat_date(dte): if dte: return format_date(dte, '%e %b %Y') return "No date set" def myformat_hours(hrs, fallback='No estimate available'): from math import floor if hrs: hrs = float(hrs) if 0 != hrs: neg = False if hrs < 0: neg = True hrs *= -1 mins = floor((hrs - floor(hrs)) * 60) s = '' if neg: s = '-' if hrs: s = "%s%sh" % (s, int(floor(hrs))) if mins: s = "%s %sm" % (s, int(mins)) return s return fallback client = self.client xml = etree.Element('clientsplugin') # Place basic client info here xclient = etree.SubElement(xml, 'client') etree.SubElement(xclient, 'name').text = client if fromdate: etree.SubElement(xclient, 'lastupdate').text = \ myformat_date(fromdate) # Information about milestones months = {} xmonths = etree.SubElement(xml, 'months') have_data = False # Load in a summary of the client's tickets sql = ("""\ SELECT t.id, t.summary, t.description, t.status, SUM(tchng.newvalue) AS totalhours, CONCAT(MONTHNAME(FROM_UNIXTIME(tchng.time/1000000)), " ", YEAR(FROM_UNIXTIME(tchng.time/1000000))) AS month FROM ticket_custom AS tcust INNER JOIN ticket AS t ON tcust.ticket=t.id INNER JOIN ticket_change AS tchng ON t.id=tchng.ticket AND tchng.field='hours' AND tchng.oldvalue=0 WHERE tcust.name = 'client' AND tcust.value = %s AND tchng.time >= (UNIX_TIMESTAMP(PERIOD_ADD(EXTRACT(YEAR_MONTH FROM NOW()), -3)*100+1)*1000000) GROUP BY t.id, MONTH(FROM_UNIXTIME(tchng.time/1000000)) ORDER BY tchng.time DESC; """) xsummary = etree.SubElement(xml, 'summary') for tid, summary, description, status, totalhours, month \ in self.env.db_query(sql, (client,)): have_data = True if month not in months: xmonth = etree.SubElement(xmonths, 'month') etree.SubElement(xmonth, 'name').text = month months[month] = {'totalhours': 0, 'xml': xmonth} # Add hours to create a total. months[month]['totalhours'] += float(totalhours) self.log.debug(" Summarising ticket #%s in %s", tid, month) ticket = etree.SubElement(xsummary, 'ticket') etree.SubElement(ticket, 'id').text = str(tid) etree.SubElement(ticket, 'summary').text = summary ticket.append( etree.XML('<description>%s</description>' % format_to_html(self.env, web_context(req), extract_client_text(description)))) etree.SubElement(ticket, 'status').text = status etree.SubElement(ticket, 'month').text = month etree.SubElement(ticket, 'totalhours').text = myformat_hours( totalhours, 'None') # Put the total hours into the month info for month in months: etree.SubElement(months[month]['xml'], 'totalhours').\ text = myformat_hours(months[month]['totalhours']) if self.debug: with open('/tmp/send-client-email.xml', 'w') as file_: file_.write(etree.tostring(xml, pretty_print=True)) self.log.debug(" Wrote XML to /tmp/send-client-email.xml") if not have_data: return None return xml
def expand_macro(self, formatter, name, content, args=[]): try: cols = [] # Sentinel group = '' # Sentinel groups = {} lines = content.split('\r\n') for line in lines: if line.startswith('||= href =||= '): cols = line[14:].split(' =||= ') elif line.startswith('|| group: '): group = line[10:] if group in [u'', u'None']: group = None groups[group] = [] # initialize for the group elif line.startswith('|| '): values = iter(line[3:].split(' || ')) ticket = {'href': values.next()} for col in cols: ticket[col] = values.next() groups[group].append(ticket) else: pass ticketsystem = TicketSystem(self.env) # labels = ticketsystem.get_ticket_field_labels() headers = [{ 'name': col, 'label': labels.get(col, _('Ticket')) } for col in cols] # fields = {} ticket_fields = ticketsystem.get_ticket_fields() for field in ticket_fields: fields[field['name']] = { 'label': field['label'] } # transform list to expected dict # fail safe fields[None] = 'NONE' for group in groups.keys(): if not 'group' in fields: fields[group] = group # group_name = 'group' in args and args['group'] or None if group_name not in fields: group_name = None query = {'group': group_name} # groups = [(name, groups[name]) for name in groups] # transform dict to expected tuple # data = { 'paginator': None, 'headers': headers, 'query': query, 'fields': fields, 'groups': groups, } add_stylesheet(formatter.req, 'common/css/report.css') chrome = Chrome(self.env) data = chrome.populate_data(formatter.req, data) template = chrome.load_template('query_results.html') content = template.generate(**data) # ticket id list as static tickets = '' if 'id' in cols: ticket_id_list = [ ticket.get('id') for group in groups for ticket in group[1] ] if len(ticket_id_list) > 0: tickets = '([ticket:' + ','.join( ticket_id_list) + ' query by ticket id])' return tag.div( content, format_to_html(self.env, formatter.context, tickets)) except StopIteration: errorinfo = _('Not Enough fields in ticket: %s') % line except Exception: errorinfo = sys.exc_info() return tag.div(tag.div(errorinfo, class_='message'), class_='error', id='content')
def _format_to_html(self, authname, wiki): resource = Resource('wiki', 'WikiStart') req = MockRequest(self.env, authname=authname) return str(format_to_html(self.env, web_context(req, resource), wiki))
def get_summary(self, req, fromdate=None, todate=None): def myformat_date(dte): if dte: return format_date(dte, '%e %b %Y') return 'No date set' def myformat_hours(hrs): from math import floor if hrs: hrs = float(hrs) if 0 != hrs: neg = False if hrs < 0: neg = True mins = floor((hrs - floor(hrs)) * 60) str = '' if neg: str = '-' if hrs: str = "%s%sh" % (str, int(floor(hrs))) if mins: str = "%s %sm" % (str, int(mins)) return str return 'No estimate available' client = self.client xml = etree.Element('clientsplugin') # Place basic client info here xclient = etree.SubElement(xml, 'client') etree.SubElement(xclient, 'name').text = client if fromdate: etree.SubElement(xclient, 'lastupdate').text = myformat_date(fromdate) have_data = False # Load in any changes that have happend sql = ("""\ SELECT t.id, t.summary, t.description, t.status, t.resolution, t.milestone, m.due, tchng.field, tchng.oldvalue, tchng.newvalue FROM ticket_custom tcust INNER JOIN ticket AS t ON tcust.ticket=t.id INNER JOIN ticket_change AS tchng ON t.id=tchng.ticket LEFT JOIN milestone AS m ON t.milestone=m.name WHERE tcust.name = 'client' AND tcust.value = %s AND tchng.field IN ('comment', 'status', 'resolution', 'milestone') AND tchng.time >= %s AND tchng.time < %s AND t.milestone IN ( SELECT DISTINCT st.milestone FROM ticket_custom AS stcust INNER JOIN ticket AS st ON stcust.ticket=st.id INNER JOIN milestone AS sm ON st.milestone=sm.name WHERE stcust.name = tcust.name AND stcust.value = tcust.value AND sm.due > 0) ORDER BY t.time """) changes = etree.SubElement(xml, 'changes') lasttid = 0 for tid, summary, description, status, resolution, milestone, \ due, cgfield, oldvalue, newvalue \ in self.env.db_query(sql, (client, fromdate * 1000000, todate * 1000000)): text = '' if 'status' == cgfield: text = 'Status changed from "%s" to "%s"' % (oldvalue, newvalue) elif 'milestone' == cgfield: text = 'Milestone changed from "%s" to "%s" - ' \ 'please check for revised delivery date.' \ % (oldvalue, newvalue) elif 'resolution' == cgfield: if oldvalue and not newvalue: text = 'Resolution removed' elif not oldvalue and newvalue: text = 'Resolution set to "%s"' % (newvalue) else: text = 'Resolution changed from "%s" to "%s"' % (oldvalue, newvalue) elif 'comment' == cgfield: # Todo - extract... text = extract_client_text(newvalue).strip() if '' == text: # No comments for the client here so ignore it. continue text = "''Comment for your information:''[[BR]][[BR]]" + text else: # Client should not know any more than this continue if self.debug: self.log.debug(" Change notification (%s) for ticket #%s", cgfield, tid) have_data = True if lasttid != tid: ticket = etree.SubElement(changes, 'ticket') etree.SubElement(ticket, 'id').text = str(tid) etree.SubElement(ticket, 'summary').text = summary ticket.append( etree.XML( '<description>%s</description>' % format_to_html(self.env, web_context(req), extract_client_text(description)))) etree.SubElement(ticket, 'status').text = status etree.SubElement(ticket, 'resolution').text = resolution etree.SubElement(ticket, 'milestone').text = milestone etree.SubElement(ticket, 'due').text = myformat_date(due) changelog = etree.SubElement(ticket, 'changelog') detail = etree.XML( '<detail>%s</detail>' % format_to_html(self.env, web_context(req)), extract_client_text(description)) detail.set('field', cgfield) if oldvalue: detail.set('oldvalue', oldvalue) if newvalue: detail.set('newvalue', newvalue) changelog.append(detail) lasttid = tid if self.debug: file = open('/tmp/send-client-email.xml', 'w') file.write(etree.tostring(xml, pretty_print=True)) file.close() self.log.debug(" Wrote XML to /tmp/send-client-email.xml") if not have_data: return None return xml
def wiki_to_pdf(text, env, req, base_dir, codepage): global IMG_CACHE env.log.debug('WikiToPdf => Start function wiki_to_pdf') #Remove exclude expressions for r in EXCLUDE_RES: text = r.sub('', text) env.log.debug('WikiToPdf => Wiki intput for WikiToPdf: %r' % text) context = Context.from_request(req, resource='wiki', id=req.args.get('page', 'False')) page = format_to_html(env, context, text) page = page.replace('<img', '<img border="0"') page = page.replace('?format=raw', '') """I need improve this... Ticket #3427""" page = page.replace('<a class="wiki" href="/' + env.config.get('wikitopdf', 'folder_name') + '/wiki/', '<a class="wiki" href="' + env.config.get('wikitopdf', 'link') + '/wiki/') page = page.replace('<pre class="wiki">', '<table align="center" width="95%" border="1" bordercolor="#d7d7d7">' + '<tr><td bgcolor="#f7f7f7"><pre class="wiki">') page = page.replace('</pre>', '</pre></td></tr></table>') page = page.replace('<table class="wiki">', '<table class="wiki" border="1" width="100%">') tracuri = env.config.get('wikitopdf', 'trac_uri') tmp_dir = env.config.get('wikitopdf', 'tmp_dir') imgpos = page.find('<img') if tracuri != '' and tmp_dir != '': # Download images so that dynamic images also work right # Create a random prefix random.seed() tmp_dir += '/%(#)04x_' %{"#":random.randint(0,65535)} # Create temp dir os.system('mkdir %s 2>/dev/null' % (tmp_dir)) imgcounter = 0 while imgpos != -1: addrpos = page.find('src="', imgpos) theimg = page[addrpos+5:] thepos = theimg.find('"') theimg = theimg[:thepos] if theimg[:1] == '/': theimg = tracuri + theimg try: newimg = IMG_CACHE[theimg] except: #newimg = tmp_dir + '%(#)d_' %{"#":imgcounter} + theimg[theimg.rfind('/')+1:] file = NamedTemporaryFile(mode='w', prefix='%(#)d_' %{"#":imgcounter}, dir=tmp_dir) newimg = file.name file.close() theimg = xml.sax.saxutils.unescape(theimg) theimg = theimg.replace(" ","%20") urlretrieve(theimg, newimg) IMG_CACHE[theimg] = newimg env.log.debug("ISLAM the image is %s new image is %s" % ( theimg, newimg)) imgcounter += 1 page = page[:addrpos+5] + newimg + page[addrpos+5+thepos:] simgpos = page.find('<img', addrpos) else: # Use old search for images in path page = page.replace('raw-attachment', 'attachments') while imgpos != -1: addrpos = page.find('src="', imgpos) # base_dir = base_dir.encode('ascii') page = page[:addrpos+5] + base_dir + page[addrpos+5:] imgpos = page.find('<img', addrpos) # Add center tags, since htmldoc 1.9 does not handle align="center" (tablepos,tableend) = tagattrfind(page, 'table', 'align="center"', 0) while tablepos != -1: endpos = page.find('</table>',tablepos) page = page[:endpos+8] + '</center>' + page[endpos+8:] page = page[:tablepos] + '<center>' + page[tablepos:]; endpos = page.find('</table>',tablepos) (tablepos,tableend) = tagattrfind(page, 'table', 'align="center"', endpos) # Add table around '<div class="code">' (tablepos,tableend) = tagattrfind(page, 'div', 'class="code"', 0) while tablepos != -1: endpos = page.find('</div>',tablepos) page = page[:endpos+6] + '</td></tr></table></center>' + page[endpos+6:] page = page[:tableend] + '<center><table align="center" width="95%" border="1" bordercolor="#d7d7d7"><tr><td>' + page[tableend:] endpos = page.find('</div>',tablepos) (tablepos,tableend) = tagattrfind(page, 'div', 'class="code"', endpos) # Add table around '<div class="system-message">' (tablepos,tableend) = tagattrfind(page, 'div', 'class="system-message"', 0) while tablepos != -1: endpos = page.find('</div>',tablepos) page = page[:endpos+6] + '</td></tr></table>' + page[endpos+6:] page = page[:tableend] + '<table width="100%" border="2" bordercolor="#dd0000" bgcolor="#ffddcc"><tr><td>' + page[tableend:] endpos = page.find('</div>',tablepos) (tablepos,tableend) = tagattrfind(page, 'div', 'class="system-message"', endpos) # Add table around '<div class="error">' (tablepos,tableend) = tagattrfind(page, 'div', 'class="error"', 0) while tablepos != -1: endpos = page.find('</div>',tablepos) page = page[:endpos+6] + '</td></tr></table>' + page[endpos+6:] page = page[:tableend] + '<table width="100%" border="2" bordercolor="#dd0000" bgcolor="#ffddcc"><tr><td>' + page[tableend:] endpos = page.find('</div>',tablepos) (tablepos,tableend) = tagattrfind(page, 'div', 'class="error"', endpos) # Add table around '<div class="important">' (tablepos,tableend) = tagattrfind(page, 'div', 'class="important"', 0) while tablepos != -1: endpos = page.find('</div>',tablepos) page = page[:endpos+6] + '</td></tr></table>' + page[endpos+6:] page = page[:tableend] + '<table width="100%" border="2" bordercolor="#550000" bgcolor="#ffccbb"><tr><td>' + page[tableend:] endpos = page.find('</div>',tablepos) (tablepos,tableend) = tagattrfind(page, 'div', 'class="important"', endpos) meta = ('<meta http-equiv="Content-Type" content="text/html; charset=%s"/>' % codepage) css = '' if env.config.get('wikitopdf', 'css_file') != '': css = ('<link rel="stylesheet" href="%s" type="text/css"/>' % env.config.get('wikitopdf', 'css_file')).encode(codepage) page = '<html><head>' + meta + css + '</head><body>' + page + '</body></html>' page = page.encode(codepage,'replace') env.log.debug('WikiToPdf => HTML output for WikiToPdf in charset %s is: %r' % (codepage, page)) env.log.debug('WikiToPdf => Finish function wiki_to_pdf') return page
def expand_macro(self, formatter, name, text, args): template_data = {'css_class': 'trac-kanban-board'} template_file = 'kanbanboard.html' board = None template_data['height'] = '300px' if args: template_data['height'] = args.get('height', '300px') project_name = self.env.path.split('/')[-1] page_name = formatter.req.path_info.split('/')[-1] is_editable = 'WIKI_MODIFY' in formatter.req.perm and 'TICKET_MODIFY' in formatter.req.perm js_globals = { 'KANBAN_BOARD_ID': page_name, 'TRAC_PROJECT_NAME': project_name, 'TRAC_USER_NAME': formatter.req.authname, 'IS_EDITABLE': is_editable } if not self.ticket_fields: self.ticket_fields = TicketSystem(self.env).get_ticket_fields() if text is None: template_data['error'] = 'Board data is not defined' template_data['usage'] = format_to_html(self.env, formatter.context, self.__doc__) else: try: board = KanbanBoard(page_name, [], self.ticket_fields, self.env, self.log) except InvalidDataError as e: template_data['error'] = e.msg template_data['usage'] = format_to_html( self.env, formatter.context, self.__doc__) except InvalidFieldError as e: template_data[ 'error'] = 'Invalid ticket fields: %s' % ', '.join( e.fields) valid_fields = map(lambda x: x['name'], self.ticket_fields) template_data[ 'usage'] = 'Valid field names are: %s.' % ', '.join( valid_fields) if board: # TICKET_FIELDS is comma-separated list of user defined ticket field names js_globals['TICKET_FIELDS'] = board.get_field_string() add_stylesheet(formatter.req, 'trackanbanboard/css/kanbanboard.css') add_script_data(formatter.req, js_globals) if 'error' in template_data: template_file = 'kanbanerror.html' else: add_script(formatter.req, 'trackanbanboard/js/libs/jquery-1.8.3.js') add_script( formatter.req, 'trackanbanboard/js/libs/jquery-ui-1.9.2.custom.min.js') add_script(formatter.req, 'trackanbanboard/js/libs/knockout-2.2.0.js') add_script(formatter.req, 'trackanbanboard/js/libs/knockout.mapping.js') add_script(formatter.req, 'trackanbanboard/js/libs/knockout-sortable.min.js') add_script(formatter.req, 'trackanbanboard/js/kanbanutil.js') add_script(formatter.req, 'trackanbanboard/js/kanbanboard.js') add_stylesheet( formatter.req, 'trackanbanboard/css/jquery-ui-1.9.2.custom.min.css') return Chrome(self.env).render_template( formatter.req, template_file, template_data, None, fragment=True).render(strip_whitespace=False)
def _format_to_html(self, context, wikidom, **options): return format_to_html(self.env, context, wikidom, **options)
def expand_macro(self, formatter, name, content): from trac.config import ConfigSection, Option args, kw = parse_args(content) filters = {} for name, index in (('section', 0), ('option', 1)): pattern = kw.get(name, '').strip() if pattern: filters[name] = fnmatch.translate(pattern) continue prefix = args[index].strip() if index < len(args) else '' if prefix: filters[name] = re.escape(prefix) has_option_filter = 'option' in filters for name in ('section', 'option'): filters[name] = re.compile(filters[name], re.IGNORECASE).match \ if name in filters \ else lambda v: True section_filter = filters['section'] option_filter = filters['option'] section_registry = ConfigSection.get_registry(self.compmgr) option_registry = Option.get_registry(self.compmgr) options = {} for (section, key), option in option_registry.iteritems(): if section_filter(section) and option_filter(key): options.setdefault(section, {})[key] = option if not has_option_filter: for section in section_registry: if section_filter(section): options.setdefault(section, {}) for section in options: options[section] = sorted(options[section].itervalues(), key=lambda option: option.name) sections = [(section, section_registry[section].doc if section in section_registry else '') for section in sorted(options)] def default_cell(option): default = option.default if default is not None and default != '': return tag.td(tag.code(option.dumps(default)), class_='default') else: return tag.td(_("(no default)"), class_='nodefault') def options_table(section, options): if options: return tag.table(class_='wiki')(tag.tbody( tag.tr(tag.td( tag.a(tag.code(option.name), class_='tracini-option', href='#%s-%s-option' % (section, option.name))), tag.td( format_to_html(self.env, formatter.context, option.doc)), default_cell(option), id='%s-%s-option' % (section, option.name), class_='odd' if idx % 2 else 'even') for idx, option in enumerate(options))) return tag.div(class_='tracini')( (tag.h3(tag.code('[%s]' % section), id='%s-section' % section), format_to_html(self.env, formatter.context, section_doc), options_table(section, options.get(section))) for section, section_doc in sections)
def get_summary(self, req, fromdate=None, todate=None): def myformat_date(dte): if dte: return format_date(dte, '%e %b %Y') return 'No date set' def myformat_hours(hrs, fallback='No estimate available'): from math import floor if hrs: hrs = float(hrs) if 0 != hrs: neg = False if hrs < 0: neg = True hrs *= -1 mins = floor((hrs - floor(hrs)) * 60) s = '' if neg: s = '-' if hrs: s = "%s%sh" % (s, int(floor(hrs))) if mins: s = "%s %sm" % (s, int(mins)) return s return fallback client = self.client xml = etree.Element('clientsplugin') # Place basic client info here xclient = etree.SubElement(xml, 'client') etree.SubElement(xclient, 'name').text = client if fromdate: etree.SubElement(xclient, 'lastupdate').text = \ myformat_date(fromdate) # Information about milestones milestones = {} xmilestones = etree.SubElement(xml, 'milestones') db = self.env.get_read_db() have_data = False # Load in a summary of the client's tickets sql = ("""\ SELECT t.id, t.summary, t.description, t.status, t.milestone, m.due, m.completed, m.description AS mdesc, tcust2.value AS estimatedhours, tcust3.value AS totalhours FROM ticket_custom AS tcust INNER JOIN ticket AS t ON tcust.ticket=t.id LEFT JOIN ticket_custom AS tcust2 ON t.id=tcust2.ticket AND tcust2.name='estimatedhours' LEFT JOIN ticket_custom AS tcust3 ON t.id=tcust3.ticket AND tcust3.name='totalhours' LEFT JOIN milestone m ON t.milestone=m.name WHERE tcust.name = 'client' AND tcust.value = %s AND t.milestone IN ( SELECT DISTINCT st.milestone FROM ticket_custom AS stcust INNER JOIN ticket AS st ON stcust.ticket=st.id INNER JOIN milestone AS sm ON st.milestone=sm.name WHERE stcust.name = tcust.name AND stcust.value = tcust.value AND (sm.due > %s OR sm.completed > %s)) ORDER BY m.due ASC """) now = int(time.time() * 1000000) now2 = now - (7 * 24 * 60 * 60 * 1000000) xsummary = etree.SubElement(xml, 'summary') for tid, summary, description, status, milestone, due, completed, \ mdescription, estimatedhours, totalhours \ in self.env.db_query(sql, (client, now, now2)): have_data = True if milestone: if milestone not in milestones: xmilestone = etree.SubElement(xmilestones, 'milestone') etree.SubElement(xmilestone, 'name').text = milestone etree.SubElement(xmilestone, 'duetimestamp').text = \ str(due) etree.SubElement(xmilestone, 'due').text = \ myformat_date(due) if completed: etree.SubElement(xmilestone, 'completed').text = \ myformat_date(completed) if mdescription: wdescription = \ format_to_html(self.env, web_context(req), extract_client_text(mdescription)) xmilestone.append( etree.XML('<description>%s</description>' % wdescription)) else: etree.SubElement(xmilestone, 'description').text = '' # Store for use milestones[milestone] = {'hours': 0, 'xml': xmilestone} # Add hours to create a total. if estimatedhours: milestones[milestone]['hours'] += float(estimatedhours) self.log.debug(" Summarising ticket #%s", tid) ticket = etree.SubElement(xsummary, 'ticket') etree.SubElement(ticket, 'id').text = str(tid) etree.SubElement(ticket, 'summary').text = summary text = format_to_html(self.env, web_context(req), extract_client_text(description)) ticket.append(etree.XML('<description>%s</description>' % text)) etree.SubElement(ticket, 'status').text = status etree.SubElement(ticket, 'milestone').text = milestone # For convenience, put the date here too (keeps the XSLTs simpler) etree.SubElement(ticket, 'due').text = myformat_date(due) if estimatedhours: etree.SubElement(ticket, 'estimatedhours').text = \ myformat_hours(estimatedhours) if totalhours: etree.SubElement(ticket, 'totalhours').text = \ myformat_hours(totalhours, 'None') # Put the total hours into the milestone info for milestone in milestones: etree.SubElement(milestones[milestone]['xml'], 'estimatedhours'). \ text = myformat_hours(milestones[milestone]['hours']) if self.debug: with open('/tmp/send-client-email.xml', 'w') as file_: file_.write(etree.tostring(xml, pretty_print=True)) self.log.debug(" Wrote XML to /tmp/send-client-email.xml") if not have_data: return None return xml
def expand_macro(self, formatter, name, content): return '<fieldset class="client"><legend>' \ 'Comments to Client</legend>%s</fieldset>' \ % format_to_html(self.env, web_context(formatter.req), content)
def render(self, context, mimetype, content, filename=None, url=None): from trac.wiki.formatter import format_to_html return format_to_html(self.env, context, content_to_unicode(self.env, content, mimetype))
def render_property(self, name, mode, context, props): if name in self.wiki_properties: return format_to_html(self.env, context, props[name]) else: return format_to_oneliner(self.env, context, props[name])