def filter_stream(self, req, method, filename, stream, data): if filename == 'ticket.html': # print "_____________ am in TextAreaDescription" fields = data['fields'] if self.description_descr: # print "having description_descr: %s" % self.description_descr # print "having description_template: %s" % self.descr_template html_d = self.descr_template % ('ticket-rndescr', self.description_descr) stream |= Transformer( './/th/label[@for="field-description"]').after( HTML(html_d)) for f in fields: if f['skip'] or not f[ 'type'] == 'textarea': # or not f.has_key('descr'): continue descr = self.config.get('ticket-custom', '%s.descr' % f['name']) if descr: # print "processing field %s" % f css_class = self.config.get('ticket-custom', '%s.css_class' % f['name']) # print css_class field_name = 'field-%s' % f['name'] tr_str = './/label[@for="%s"]' % field_name html = self.descr_template % (css_class, descr) stream |= Transformer(tr_str).after(HTML(html)) return stream
def _transform(html, transformer, with_attrs=False): """Apply transformation returning simplified marked stream.""" if isinstance(html, str) and not isinstance(html, str): html = HTML(html, encoding='utf-8') elif isinstance(html, str): html = HTML(html, encoding='utf-8') stream = transformer(html, keep_marks=True) return _simplify(stream, with_attrs)
def __getAnchors(self, stream): # ======================================================================= # this code fragment is evil, since it raises an error on # imported umlauts: # newStream = HTML(stream) # # *** tried also this, but didn't work: # newStream = stream.select('//h1 [@id="trac-ticket-title"]//a/text()') # # *** tried also: # stream_str = '%s' % stream # stream_str = stream_str.encode('utf-8') # self.log.info("stream: ") # self.log.info(stream_str) # newStream = HTML(stream_str) # # *** tried also: # test = Path('//h1 [@id="trac-ticket-title"]//a/text()').test() # namespaces, variables = {}, {} # head = '' # for event in stream: # if test(event, namespaces, variables): # self.log.info('%s: %s' % (event[0], event[1])) # print('%s %r' % (event[0], event[1])) # if event[0] == 'TEXT': # if isinstance(event[1], Markup): # head += event[1].striptags() # else: # head += event[1] # #START (QName('child'), Attrs([(QName('id'), u'2')])) # print "namespaces, variables; head: %s, %s; %s" % \ # (namespaces, variables, head) # ====================================================================== newStream = HTML(stream) self.anchors = {} self.keylist = [] # headline headline = newStream.select('//h1 [@id="trac-ticket-title"]//a/text()') if headline: for item in headline: self.anchors[item[1]] = "" self.keylist.append(item[1]) # further entities list = newStream.select('//h2 [@class="foldable"]/text()') if list: for index, item in enumerate(list): self.anchors[item[1]] = "no%s" % str(index + 1) self.keylist.append(item[1]) list = newStream.select('//form [@id="propertyform"]//fieldset/@id') # comment comment = newStream.select('//h2 [@id="trac-add-comment"]//a/text()') for com in comment: self.anchors[com[1]] = "comment" self.keylist.append(com[1]) return newStream
def filter_navitems(self, elements, req, data): data['prevnext'] = [] prevnext = False for elem in elements: html = HTML(elem) spclasn = str(html.select('@class')) clasn = str(html.select('a/@class')) if clasn == 'prev' or clasn == 'next' or spclasn == 'missing': prevnext = True else: req.chrome.setdefault('ctxtnav', []).append(elem) if prevnext: self.prevnext_nav(req, 'Previous', 'Next')
def filter_navitems(self, elements, req, data): data["prevnext"] = [] prevnext = False for elem in elements: html = HTML(elem) spclasn = str(html.select("@class")) clasn = str(html.select("a/@class")) if clasn == "prev" or clasn == "next" or spclasn == "missing": prevnext = True else: req.chrome.setdefault("ctxtnav", []).append(elem) if prevnext: self.prevnext_nav(req, "Previous", "Next")
def make_recommendation_box(self, username, basepath): html = "" contact = get_suggested_contact(self, username) if username == "anonymous": html += "<h2>Please log in to view suggested contacts</h2>" elif contact is None: html += "<h2>You have no suggested contacts.</h2><br />Try committing changes to the repository to see suggestions." else: # Right now this is a pile of absurdity. We really need to find out if # trac and vc logins are typically linked to email addresses so we can identify people contactlink = '<a href="' + basepath + \ '/sn_linkto?linkto=' + contact.name + \ '">' + contact.name + "</a>" html += '''<h2>Have you spoken to...</h2> <div style="padding:10px"> <h3>%s?</h3> <p><a href="mailto:[email protected]">%s@%s.com</a></p> <h4>Why?</h4> <p>%s is an expert on these files you've been working on:</p> <ul> ''' % (contactlink, contact.name, contact.name, contact.name) for file in contact.get_top_common_files(4): html += '<li><a href="' + basepath + '/browser/' + file + '">' + \ file + '</a></li>' html += ''' </ul> </div> ''' html = HTML(html) return html
def get_css(self, req): css = HTML(""" <style type="text/css"> h2 { background: #aaaaaa; color: #ffffff; border-bottom: 1px solid #888888; margin: 0; padding: 5px; } #relatedModules{ margin: 5px; margin-bottom:20px; width: 400px; float: left; background: #dddddd; border: 1px solid #888888; padding: 0; } #experts{ margin: 5px; margin-bottom:20px; width: 400px; float: left; background: #dddddd; border: 1px solid #888888; padding: 0; } </style> """) return css
def _format_html(self, event): ticket = event.target short_changes = {} long_changes = {} chrome = Chrome(self.env) for field, old_value in event.changes.items(): new_value = ticket[field] if (new_value and '\n' in new_value) or \ (old_value and '\n' in old_value): long_changes[field.capitalize()] = HTML( "<pre>\n%s\n</pre>" % ('\n'.join( diff_cleanup( difflib.unified_diff( wrap(old_value, cols=60).split('\n'), wrap(new_value, cols=60).split('\n'), lineterm='', n=3))))) else: short_changes[field.capitalize()] = (old_value, new_value) try: req = Mock(href=Href(self.env.abs_href()), abs_href=self.env.abs_href(), authname=event.author, perm=MockPerm(), chrome=dict(warnings=[], notices=[]), args={}) context = Context.from_request(req, event.realm, event.target.id) formatter = HtmlFormatter(self.env, context, event.comment) temp = formatter.generate(True) except Exception, e: self.log.error(exception_to_unicode(e, traceback=True)) temp = 'Comment in plain text: %s' % event.comment
def _apply(self, select, content=None, html=FOOBAR): class Injector(object): count = 0 def __iter__(self): self.count += 1 return iter(HTML('CONTENT %i' % self.count)) if isinstance(html, basestring): html = HTML(html) if content is None: content = Injector() elif isinstance(content, basestring): content = HTML(content) return _transform(html, getattr(Transformer(select), self.operation) (content))
def get_directory_list(self, repo): """ Returns the HTML for a form to select directories, and pass them as query args to sn_overall_files page. repo is the svn repository. """ # Get the directory dictionary dd = determine_directory_structure(self, repo) # Construct the HTML html = '\ <form method="GET" action="sn_overall_files"> \ <center>\ <table> \ <tr> \ <td width=200> \ Select directories you wish to examine \ (hold ctrl to select more than one). \ </td> \ <td> \ <select name="subdirs" multiple size=6>' + \ process_structure(self, "", dd, "") + \ '</select> \ </td> \ <td width=100> \   <input type="submit" value="Submit" /> \ </td> \ </tr> \ </table> \ </center> \ </form>' return HTML(html)
def process_request(self, req): # Allow all POST requests (with a valid __FORM_TOKEN, ensuring that # the client has at least some permission). Additionally, allow GET # requests from TRAC_ADMIN for testing purposes. if req.method != 'POST': req.perm.require('TRAC_ADMIN') # @todo: Embed "tips" within the rendered output for the editor # (recognize TracLinks, table-stuff, macros, processors) # @todo: Save the content in server-side user-specific field for recovery realm = req.args.get('realm', 'wiki') id = req.args.get('id') version = req.args.get('version') if version is not None: try: version = int(version) except ValueError: version = None text = req.args.get('text', '') flavor = req.args.get('flavor') options = {} if 'escape_newlines' in req.args: options['escape_newlines'] = bool(int(req.args['escape_newlines'] or 0)) if 'shorten' in req.args: options['shorten'] = bool(int(req.args['shorten'] or 0)) resource = Resource(realm, id=id, version=version) context = Context.from_request(req, resource) rendered = format_to_cke_html(self.env, context, text, self.code_styles, **options) # since Trac renders underlined text as `<span class="underlined">text</span> # instead of u-tag, we need to adjust it for compatibility's sake # see also discussion at Google Groups: # https://groups.google.com/group/trac-dev/browse_thread/thread/833206a932d1f918 html = HTML(rendered) html |= Transformer('//span[@class="underline"]').rename('u').attr('class', None) # CKEditor renders indentation by using p style="margin-left: 40px" # instead of blockquote-tag html |= Transformer('//blockquote/p').attr('style', 'margin-left: 40px') html |= Transformer('//blockquote').unwrap() buffer = StringIO() html.render(out=buffer, encoding='utf-8') req.send( buffer.getvalue() )
def _select(self, select): html = HTML(FOOBAR) if isinstance(select, basestring): select = [select] transformer = Transformer(select[0]) for sel in select[1:]: transformer = transformer.select(sel) return _transform(html, transformer)
def linebreaks(value): """Converts newlines in strings into <p> and <br />s.""" if not value: return '' value = re.sub(r'\r\n|\r|\n', '\n', value) # normalize newlines paras = re.split('\n{2,}', value) paras = ['<p>%s</p>' % p.strip().replace('\n', '<br />') for p in paras] return HTML(''.join(paras))
def _select(self, select): html = HTML(FOOBAR, encoding='utf-8') if isinstance(select, str): select = [select] transformer = Transformer(select[0]) for sel in select[1:]: transformer = transformer.select(sel) return _transform(html, transformer)
def modify_browser(self, req, data): ctxtnavitems = req.chrome.pop('ctxtnav', []) add_ctxtnav(req, _('All sources')) prev = False for elem in ctxtnavitems: html = HTML(elem) clasn = str(html.select('a/@class')) if clasn == 'prev': prev = True elif clasn == 'next': self.prevnext_ctxnav(req, 'Prev', 'Next', 'Latest Rev') elif str(html.select('@class')) == 'missing': if prev: self.prevnext_ctxnav(req, 'Prev', 'Next') else: if str(html.select('text()')).lower() != 'latest revision': req.chrome.setdefault('ctxtnav', []).append(elem) add_ctxtnav(req, _("Diff changesets"), _("javascript: applydiff()"))
def modify_browser(self, req, data): ctxtnavitems = req.chrome.pop("ctxtnav", []) add_ctxtnav(req, _("All sources")) prev = False for elem in ctxtnavitems: html = HTML(elem) clasn = str(html.select("a/@class")) if clasn == "prev": prev = True elif clasn == "next": self.prevnext_ctxnav(req, "Prev", "Next", "Latest Rev") elif str(html.select("@class")) == "missing": if prev: self.prevnext_ctxnav(req, "Prev", "Next") else: if str(html.select("text()")).lower() != "latest revision": req.chrome.setdefault("ctxtnav", []).append(elem) add_ctxtnav(req, _("Diff changesets"), _("javascript: applydiff()"))
def process_request(self, req): # Allow all POST requests (with a valid __FORM_TOKEN, ensuring that # the client has at least some permission). Additionally, allow GET # requests from TRAC_ADMIN for testing purposes. if req.method != "POST": req.perm.require("TRAC_ADMIN") # @todo: Embed "tips" within the rendered output for the editor # (recognize TracLinks, table-stuff, macros, processors) # @todo: Save the content in server-side user-specific field for recovery realm = req.args.get("realm", "wiki") id = req.args.get("id") version = req.args.get("version") if version is not None: try: version = int(version) except ValueError: version = None text = req.args.get("text", "") flavor = req.args.get("flavor") options = {} if "escape_newlines" in req.args: options["escape_newlines"] = bool(int(req.args["escape_newlines"] or 0)) if "shorten" in req.args: options["shorten"] = bool(int(req.args["shorten"] or 0)) resource = Resource(realm, id=id, version=version) context = Context.from_request(req, resource) rendered = format_to_cke_html(self.env, context, text, self.code_styles, **options) # since Trac renders underlined text as `<span class="underlined">text</span> # instead of u-tag, we need to adjust it for compatibility's sake # see also discussion at Google Groups: # https://groups.google.com/group/trac-dev/browse_thread/thread/833206a932d1f918 html = HTML(rendered) html |= Transformer('//span[@class="underline"]').rename("u").attr("class", None) # CKEditor renders indentation by using p style="margin-left: 40px" # instead of blockquote-tag html |= Transformer("//blockquote/p").attr("style", "margin-left: 40px") html |= Transformer("//blockquote").unwrap() buffer = StringIO() html.render(out=buffer, encoding="utf-8") req.send(buffer.getvalue())
def _format_html(self, event): ticket = event.target short_changes = {} long_changes = {} chrome = Chrome(self.env) for field, old_value in event.changes.items(): new_value = ticket[field] if (new_value and '\n' in new_value) or \ (old_value and '\n' in old_value): long_changes[field.capitalize()] = HTML( "<pre>\n%s\n</pre>" % ( '\n'.join( diff_cleanup( difflib.unified_diff( wrap(old_value, cols=60).split('\n'), wrap(new_value, cols=60).split('\n'), lineterm='', n=3 ) ) ) ) ) else: short_changes[field.capitalize()] = (old_value, new_value) data = dict( ticket = ticket, author = event.author, header = self._header_fields(ticket), comment = event.comment, category = event.category, ticket_link = self.env.abs_href('ticket', ticket.id), project_name = self.env.project_name, project_desc = self.env.project_description, project_link = self.env.project_url or self.env.abs_href(), has_changes = short_changes or long_changes, long_changes = long_changes, short_changes = short_changes, attachment= event.attachment ) chrome = Chrome(self.env) dirs = [] for provider in chrome.template_providers: dirs += provider.get_templates_dirs() templates = TemplateLoader(dirs, variable_lookup='lenient') template = templates.load('ticket_email_mimic.html', cls=MarkupTemplate) if template: stream = template.generate(**data) output = stream.render() return output
def __getAnchors(self, stream): #======================================================================= # this code fragment is evil, since it raises an error on # imported umlauts: # newStream = HTML(stream) # # *** tried also this, but didn't work: #newStream = stream.select('//h1 [@id="trac-ticket-title"]//a/text()') # # *** tried also: #stream_str = '%s' % stream #stream_str = stream_str.encode('utf-8') #self.log.info("stream: ") #self.log.info(stream_str) #newStream = HTML(stream_str) # # *** tried also: #test = Path('//h1 [@id="trac-ticket-title"]//a/text()').test() #namespaces, variables = {}, {} #head = '' #for event in stream: # if test(event, namespaces, variables): # self.log.info('%s: %s' % (event[0], event[1])) # print('%s %r' % (event[0], event[1])) # if event[0] == 'TEXT': # if isinstance(event[1], Markup): # head += event[1].striptags() # else: # head += event[1] # #START (QName('child'), Attrs([(QName('id'), u'2')])) #print "namespaces, variables; head: %s, %s; %s" % \ # (namespaces, variables, head) #====================================================================== newStream = HTML(stream) self.anchors = {} self.keylist = [] #headline headline = newStream.select('//h1 [@id="trac-ticket-title"]//a/text()') if headline: for item in headline: self.anchors[item[1]] = '' self.keylist.append(item[1]) #further entities list = newStream.select('//h2 [@class="foldable"]/text()') if list: for index, item in enumerate(list): self.anchors[item[1]] = "no%s" % str(index + 1) self.keylist.append(item[1]) list = newStream.select('//form [@id="propertyform"]//fieldset/@id') #comment comment = newStream.select('//h2 [@id="trac-add-comment"]//a/text()') for com in comment: self.anchors[com[1]] = "comment" self.keylist.append(com[1]) return newStream
def _format_html(self, event): ticket = event.target attachment = event.attachment short_changes = {} long_changes = {} for field, old_value in event.changes.items(): new_value = ticket[field] if (new_value and '\n' in new_value) or \ (old_value and '\n' in old_value): long_changes[field.capitalize()] = HTML( "<pre>\n%s\n</pre>" % ( '\n'.join( diff_cleanup( difflib.unified_diff( wrap(old_value, cols=60).split('\n'), wrap(new_value, cols=60).split('\n'), lineterm='', n=3 ) ) ) ) ) else: short_changes[field.capitalize()] = (old_value, new_value) def wiki_to_html(event, wikitext): if wikitext is None: return "" try: req = Mock( href=Href(self.env.abs_href()), abs_href=self.env.abs_href, authname=event.author, perm=MockPerm(), chrome=dict( warnings=[], notices=[] ), args={} ) resource = Resource(event.realm, event.target.id) context = web_context(req, resource) formatter = HtmlFormatter(self.env, context, wikitext) return formatter.generate(True) except Exception, e: self.log.error("Failed to render %s", repr(wikitext)) self.log.error(exception_to_unicode(e, traceback=True)) raise
def expand_markup(stream, ctxt=None): """A Genshi stream filter for expanding `genshi.Markup` events. Note: Expansion may not be possible if the fragment is badly formed, or partial. """ for event in stream: if isinstance(event[1], Markup): try: for subevent in HTML(event[1]): yield subevent except ParseError: yield event else: yield event
def filter_stream(self, req, method, filename, stream, data): self.log.debug("ckintegration: template %s" % (filename)) # Act only when enabled, and editor_source defined, and current template has wiki-textareas if self.editor_source and self._check_editor_type(filename): # Some javascript global variable to add to the response to assist to tracwiki plugin add_script_data(req, { 'ck_editor_type': self.editor_type, 'ck_code_styles': self.get_styles_list(), 'trac_base_url': req.href.base, 'ck_tracwiki_path': req.href.chrome('ckintegration'), 'ck_resource_realm': 'wiki', 'ck_resource_id': '', 'form_token': req.form_token, }) # Load the needed scripts (CKEditor itself, and the tracwiki plugin add_script(req, self.editor_source) add_script(req, 'ckintegration/tracwiki.js') add_script(req, 'ckintegration/pastecode.js') # Inject a script that adds the tracwiki plugin as an external plugin to CKEditor # @todo: Perform init with a dedicated loader script # @todo: Use the init to modify the CKEditor toolbar ck_plugin_init = '<script type="text/javascript">CKEDITOR.plugins.addExternal("tracwiki", ck_tracwiki_path, "tracwiki.js");\n' ck_plugin_init += 'CKEDITOR.plugins.addExternal("pastecode", ck_tracwiki_path, "pastecode.js");</script>' stream |= Transformer('.//body').prepend(HTML(ck_plugin_init)) #add_script(req, 'ckintegration/ckloader.js') # Replace all relevant textarea fields in the template with CKEditor instances for field_name in self.template_fields[lower(filename)]: self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>''' % (field_name) #self.log.debug ("add_editor is %s" % add_editor) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) # Also replace custom textarea fields in the ticket template that have wiki format if 'ticket.html' == lower(filename) and 'fields' in data: for f in data['fields']: if f['skip'] or not lower(f['type']) == 'textarea' or \ not f.has_key('format') or not 'wiki' == lower(f['format']): continue field_name = 'field_%s' % f['name'] self.log.debug('Replacing textarea "%s" with CKEditor instance' % (field_name)) add_editor = '''<script type="text/javascript"> CKEDITOR.replace("%s", { extraPlugins : "tracwiki,pastecode" }); </script>''' % (field_name) stream |= Transformer('.//textarea[@name="%s"]' % (field_name)).after(HTML(add_editor)) return stream
def get_correction_dropdown(self, person): """ Return the HTML for the options of a dropdown list of people that person does not talk to. """ db = self.env.get_db_cnx() cursor = db.cursor() all_people, spoken_to = [], [person] # Get all the people cursor.execute("SELECT DISTINCT author FROM revision \ UNION \ SELECT DISTINCT reporter FROM ticket \ UNION \ SELECT DISTINCT author FROM ticket_change") for row in cursor: all_people.append(row[0]) # Get the people that person talks to cursor.execute( 'SELECT DISTINCT person1 \ FROM social_relations \ WHERE person2 = %s', (person, )) for row in cursor: spoken_to.append(row[0]) cursor.execute( 'SELECT DISTINCT person2 \ FROM social_relations \ WHERE person1 = %s', (person, )) for row in cursor: spoken_to.append(row[0]) # Subtract to get the people that person doesn't talk to all_people = set(all_people) spoken_to = set(spoken_to) not_spoken_to = all_people.difference(spoken_to) # Format as HTML dropdown list options drop_down = "" for p in not_spoken_to: drop_down += '<option value="' + p + '">' + p + '</option>' return HTML(drop_down)
def _add_buttom_ctx_menu(self, req, stream): if req.chrome.has_key('ctxtnav'): ctxtnav = req.chrome['ctxtnav'] ctx_str = "" for i, entry in enumerate(ctxtnav): if i == 0: ctx_str += "<li class='first'>" elif i == len(ctxtnav) -1: ctx_str += "<li class='last'>" else: ctx_str += "<li>" ctx_str = "%s%s</li>" % (ctx_str, entry) # self.log.info("ctx_str %s" % ctx_str) html = HTML( "<div id='ctxtnavbottom' class='nav'><ul>%s" "</ul></div>" % ctx_str ) stream |= Transformer('.//div[@id="help"]').before( html ) return stream return stream
def filter_stream(self, req, method, filename, stream, data): if filename == 'roadmap.html': sortcrit = self._get_settings(req, 'sortcrit', self.criterias[0]) sortdirect = self._get_settings(req, 'sortdirect', self.directions[0]) sel = ' selected = "selected"' html_str = '<div>' + _('Sort by: ') html_str += '<select name="sortcrit">' for crit in self.criterias: html_str += '<option value ="%s" %s>%s</option>' % ( crit, sel if sortcrit == crit else '', _(crit)) html_str += '</select>' html_str += '<select name="sortdirect">' for dir in self.directions: html_str += '<option value ="%s" %s>%s</option>' % ( dir, sel if sortdirect == dir else '', _(dir)) html_str += '</select></div>' html = HTML(html_str) filter = Transformer('//form[@id="prefs"]/div[@class="buttons"]') return stream | filter.before(html) return stream
def experts_html(self, req): """ Inserts a box into code browsing pages that lists expert colleagues of the file you are currently browsing. """ db = self.env.get_db_cnx() cursor = db.cursor() # Get the path of the current file this_file = (req.path_info)[9:] # Get the experts cursor.execute('SELECT author, strength \ FROM expertise \ WHERE path = %s \ AND author != %s \ ORDER BY strength DESC', (this_file, req.authname,)) # The HTML to be insterted into the code browsing page html = '<div id="experts"><h2>Experts (tracSNAP)</h2><ul>' # Create the HTML list of experts for author, strength in cursor: html += '<li><a href="' + req.base_path + \ '/sn_linkto?linkto=' + author + \ '">' + author + "</a>, \ (expert score = " + str(strength) + ")</li>" # Make sure experts actually exist if not html.endswith("</li>"): return "" html += "</ul></div>" html = HTML(html) return html
def get_recent_files(self, author, base_path): ''' Get the HTML for a list of author's most recent files. base_path should be the link to the trac environment, so that the list can include links to the files. ''' db = self.env.get_db_cnx() cursor = db.cursor() # Get author's recent files cursor.execute( 'SELECT nc.path, r.time \ FROM node_change nc, revision r\ WHERE r.author=%s \ AND nc.rev = r.rev \ AND nc.node_type="F" \ ORDER BY r.time DESC', (author, )) html = '<ul>' # HTML for the list num_recent = 0 # Number of files in the list # Construct the list for path, time in cursor: # Maximum of 10 files in the list num_recent += 1 if num_recent > 10: break # Link to the file html += '<li><a href="' + base_path + '/browser/' + path + '">' + \ path + '</a></li>' html += '</ul>' return HTML(html)
def related_files_html(self, req): """ Inserts a box into code browsing pages that lists other files that are related to the file you are browsing """ db = self.env.get_db_cnx() cursor = db.cursor() # Get the path of the current file this_file = (req.path_info)[9:] # Get related modules cursor.execute('SELECT file1, file2, strength \ FROM code_relations \ WHERE file1 = %s OR file2 = %s \ ORDER BY strength DESC', (this_file, this_file,)) # The HTML to be inserted into the code browsing page html = '<div id="relatedModules"><h2>Related Modules (tracSNAP)</h2><ul>' # Create the links to the related files for file1, file2, strength in cursor: if file2 == this_file: file1, file2 = file2, file1 html += '<li><a href="' + req.base_path + \ "/browser/" + file2 + '">' + file2 + "</a></li>" # Check to make sure there were actually some related files if not html.endswith("</li>"): return "" html += "</ul></div>" html = HTML(html) return html
def filter_stream(self, req, method, filename, stream, data): if filename == 'wiki_edit.html' and 'section' in req.args and 'merge' not in req.args: if 'section_text' in req.args: section_pre, section_text, section_post = req.args.get( 'section_pre'), req.args.get('section_text'), req.args.get( 'section_post') else: section_pre, section_text, section_post = self._split_page_text( data['page'].text, req.args['section']) section_text = ''.join(section_text) section_element = html.input(type='hidden', name='section', id='section', value=req.args.get('section')) pre_element = html.input(type='hidden', name='section_pre', id='section_pre', value=''.join(section_pre)) post_element = html.input(type='hidden', name='section_post', id='section_post', value=''.join(section_post)) section_html = html(section_element, pre_element, post_element) stream = stream | Transformer('//textarea[@name="text"]').empty( ).append(section_text).before(section_html) stream = stream | Transformer('//div[@id="content"]//h1').append( "/%s (section %s)" % (section_text[:section_text.find('\n')].strip(" = \r\n"), req.args['section'])) if not self.preview_whole_page: stream = stream | Transformer( '//div[@class="wikipage"]').empty().append( HTML(wiki_to_html(section_text, self.env, req))) return stream
def format_relations_for_flare(self, r_dict): """ Takes a dictionary of relations and returns the HTML for the data in json format (for Flare to visualize) """ #TODO: Strength is always set to 1 at the moment, since I haven't # figured out how to show edge weights yet in Flare. html = '[' for file1 in r_dict: if r_dict[file1] == []: html += '{"name":"sn/' + file1 + '","strength":1,"links":[]},' continue html += '{"name":"sn/' + file1 + '","strength":1,"links":[' for link in r_dict[file1]: html += '"sn/' + link + '",' html = html[0:len(html) - 1] + ']},' html = html[0:len(html) - 1] + ']' if html == ']': html = '[]' data = HTML(html) return data
def filter_stream(self, req, method, filename, stream, data): if req.path_info == '/socialnetwork': # ############################################################### # # ------------------- TracSNAP home page -------------------------- # ############################################################### # # Get the repository repo = self.env.get_repository(req.authname) # Clear the tables of data we've analyzed (should be commented out) # clear_tables(self) # Analyze the repository! determine_relations(self, repo) # Make a social recommendation rec = make_recommendation_box(self, req.authname, req.base_path) # Get the files recently edited by this user recent = get_recent_files(self, req.authname, req.base_path) return stream \ | Transformer('//div[@id="suggested_contact"]').prepend(rec) \ | Transformer('//div[@id="recent_files"]').append(recent) elif req.path_info == '/sn_my_files': # ############################################################### # # ----------------------- My Files ------------------------------ # # ############################################################### # # Check if depth was specified query_args = Query.from_string(self.env, req.query_string) depth = int(query_args.getfirst("depth", 1)) # HTML to be inserted into the template title = HTML('<h2>My Files</h2>') swf = HTML('<object width="600" height="500">\ <param name="movie" \ value="chrome/socialnetwork/MyFilesGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '\ &depth=' + str(depth) + '"> \ <embed src="chrome/socialnetwork/MyFilesGraph.swf" \ FlashVars="address=' + req.base_path + '\ &depth=' + str(depth) + '" \ width="600" height="500"></embed> \ </object>') fs_link = HTML('<a href="sn_fs_my_files?depth=' + str(depth) + '">View Full Screen</a>') return stream \ | Transformer('//div[@id="graph_title"]').prepend(title) \ | Transformer('//div[@id="graph"]').prepend(swf) \ | Transformer('//div[@id="fs_link"]').prepend(fs_link) elif req.path_info == '/sn_overall_files': # ############################################################### # # --------------------- Overall Files --------------------------- # # ############################################################### # # Check if subdirectories were specified query_args = Query.from_string(self.env, req.query_string) subdirs = query_args.getlist("subdirs") subdir_vars = '&subdirs=' if subdirs != []: # Show specified sub-directories for d in subdirs: subdir_vars += d + "," subdir_vars = subdir_vars[0:len(subdir_vars) - 1] # HTML to be inserted into the template title = HTML('<h2>Overall Code Relations Graph</h2>') swf = HTML('\ <object width="600" height="500">\ <param name="movie" \ value="chrome/socialnetwork/OverallFilesGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + subdir_vars + '"> \ <embed src="chrome/socialnetwork/OverallFilesGraph.swf" \ FlashVars="address=' + req.base_path + subdir_vars + '" \ width="600" height="500"></embed> \ </object>') # Get list of directories to choose from repo = self.env.get_repository(req.authname) dir_list = get_directory_list(self, repo) # Set up query string for fullscreen version subdir_vars = "" if subdirs != []: for d in subdirs: subdir_vars += "&subdirs=" + d subdir_vars = "?" + subdir_vars[1:len(subdir_vars)] fs_link = HTML('<a href="sn_fs_overall_files' + subdir_vars + '">View Full Screen</a>') return stream \ | Transformer('//div[@id="graph_title"]').prepend(title) \ | Transformer('//div[@id="dir_list"]').prepend(dir_list) \ | Transformer('//div[@id="graph"]').prepend(swf) \ | Transformer('//div[@id="fs_link"]').prepend(fs_link) elif req.path_info == '/sn_my_social': # ############################################################### # # --------------------- My Social Network ----------------------- # # ############################################################### # # Check query args to see if there is a graph correction to be made query_args = Query.from_string(self.env, req.query_string) new_person = query_args.getfirst("person", None) if new_person != None: strength = query_args.getfirst("strength", 1) self.new_social_connection(req.authname, new_person, strength) # Check query args for depth depth = int(query_args.getfirst("depth", 1)) # HTML to be inserted into the template title = HTML('<h2>My Social Network Graph</h2>') drop_down = get_correction_dropdown(self, req.authname) swf = HTML('<object width="600" height="500">\ <param name="movie" \ value="chrome/socialnetwork/MySocialGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '\ &depth=' + str(depth) + '"> \ <embed src="chrome/socialnetwork/MySocialGraph.swf" \ FlashVars="address=' + req.base_path + '\ &depth=' + str(depth) + '" \ width="600" height="500"></embed> \ </object>') fs_link = HTML('<a href="sn_fs_my_social?depth=' + str(depth) + '">View Full Screen</a>') return stream \ | Transformer('//div[@id="graph_title"]').prepend(title) \ | Transformer('//select[@name="person"]').prepend(drop_down) \ | Transformer('//div[@id="graph"]').prepend(swf) \ | Transformer('//div[@id="fs_link"]').prepend(fs_link) elif req.path_info == '/sn_overall_social': # ############################################################### # # -------------------- Overall Social Network ------------------- # # ############################################################### # # HTML to be inserted into the template title = HTML('<h2>Overall Social Network Graph</h2>') swf = HTML('<object width="600" height="500">\ <param name="movie" \ value="chrome/socialnetwork/OverallSocialGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '"> \ <embed src="chrome/socialnetwork/OverallSocialGraph.swf" \ FlashVars="address=' + req.base_path + '" \ width="600" height="500"> \ </embed> \ </object>') fs_link = HTML('<a href="sn_fs_overall_social">' + 'View Full Screen</a>') return stream \ | Transformer('//div[@id="graph_title"]').prepend(title) \ | Transformer('//div[@id="graph"]').prepend(swf) \ | Transformer('//div[@id="fs_link"]').prepend(fs_link) elif req.path_info == '/sn_linkto': # ############################################################### # # ---------------------------- Linkto --------------------------- # # ############################################################### # # Get the person who we are finding the connection to query_args = Query.from_string(self.env, req.query_string) them = query_args.getfirst("linkto", "") # HTML to be inserted into the template title = HTML('<h2>Your Social Link To ' + them + '</h2>') swf = HTML('<object width="600" height="500">\ <param name="movie" \ value="chrome/socialnetwork/Linkto.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '\ &linkto=' + them + '"> \ <embed src="chrome/socialnetwork/Linkto.swf" \ FlashVars="address=' + req.base_path + '\ &linkto=' + them + '" \ width="600" height="500"> \ </embed> \ </object>') return stream \ | Transformer('//div[@id="graph_title"]').prepend(title) \ | Transformer('//div[@id="graph"]').prepend(swf) elif req.path_info == '/sn_my_files_data': # ----------------------------------------------------------------- # ---------------------- Data: My Files --------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) depth = int(query_args.getfirst("depth", 1)) data = get_my_files_data(self, req.authname, depth) return stream \ | Transformer('//div[@id="data"]').prepend(data) elif req.path_info == '/sn_overall_files_data': # ----------------------------------------------------------------- # ------------------- Data: Overall Files ------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) subdirs = query_args.getlist("subdirs") if subdirs[0] == "": # Show overall files data = get_overall_files_data(self) else: # Show specified directories data = get_subdirs_files_data(self, subdirs) return stream \ | Transformer('//div[@id="data"]').prepend(data) elif req.path_info == '/sn_my_social_data': # ----------------------------------------------------------------- # ---------------------- Data: My Social -------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) depth = int(query_args.getfirst("depth", 1)) data = get_my_social_data(self, req.authname, depth) return stream \ | Transformer('//div[@id="data"]').prepend(data) elif req.path_info == '/sn_overall_social_data': # ----------------------------------------------------------------- # --------------------- Data: Overall Social ---------------------- # ----------------------------------------------------------------- data = get_overall_social_data(self) return stream \ | Transformer('//div[@id="data"]').prepend(data) elif req.path_info == '/sn_linkto_data': # ----------------------------------------------------------------- # ---------------------- Data: Linkto ----------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) them = query_args.getfirst("linkto", "") data = get_my_linkto(self, req.authname, them) return stream \ | Transformer('//div[@id="data"]').prepend(data) elif req.path_info == '/sn_fs_my_files': # ----------------------------------------------------------------- # ----------------------- FS My Files ----------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) depth = int(query_args.getfirst("depth", 1)) swf = HTML('<object width="800" height="800">\ <param name="movie" \ value="chrome/socialnetwork/MyFilesGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '\ &depth=' + str(depth) + '"> \ <embed src="chrome/socialnetwork/MyFilesGraph.swf" \ FlashVars="address=' + req.base_path + '\ &depth=' + str(depth) + '" \ width="800" height="800"></embed> \ </object>') return stream \ | Transformer('//div[@id="graph"]').prepend(swf) elif req.path_info == '/sn_fs_overall_files': # ----------------------------------------------------------------- # ------------------- FS Overall Files ---------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) subdirs = query_args.getlist("subdirs") subdir_vars = '&subdirs=' if subdirs != []: # Show specified sub-directories for d in subdirs: subdir_vars += d + "," subdir_vars = subdir_vars[0:len(subdir_vars) - 1] swf = HTML('\ <object width="800" height="800">\ <param name="movie" \ value="chrome/socialnetwork/OverallFilesGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + subdir_vars + '"> \ <embed src="chrome/socialnetwork/OverallFilesGraph.swf" \ FlashVars="address=' + req.base_path + subdir_vars + '" \ width="800" height="800"></embed> \ </object>') return stream \ | Transformer('//div[@id="graph"]').prepend(swf) elif req.path_info == '/sn_fs_my_social': # ----------------------------------------------------------------- # ----------------------- FS My Social ---------------------------- # ----------------------------------------------------------------- query_args = Query.from_string(self.env, req.query_string) depth = int(query_args.getfirst("depth", 1)) swf = HTML('<object width="800" height="800">\ <param name="movie" \ value="chrome/socialnetwork/MySocialGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '\ &depth=' + str(depth) + '"> \ <embed src="chrome/socialnetwork/MySocialGraph.swf" \ FlashVars="address=' + req.base_path + '\ &depth=' + str(depth) + '" \ width="800" height="800"></embed> \ </object>') return stream \ | Transformer('//div[@id="graph"]').prepend(swf) elif req.path_info == '/sn_fs_overall_social': # ----------------------------------------------------------------- # ------------------- FS Overall Social --------------------------- # ----------------------------------------------------------------- swf = HTML('<object width="800" height="800">\ <param name="movie" \ value="chrome/socialnetwork/OverallSocialGraph.swf"> \ <param name=FlashVars \ value="address=' + req.base_path + '"> \ <embed src="chrome/socialnetwork/OverallSocialGraph.swf" \ FlashVars="address=' + req.base_path + '" \ width=800 height=800> \ </embed> \ </object>') return stream \ | Transformer('//div[@id="graph"]').prepend(swf) elif req.path_info.find("/browser/") != -1: # ----------------------------------------------------------------- # ------------------- Related Files and Experts ------------------- # ----------------------------------------------------------------- css = codebrowser.get_css(self, req) rhtml = codebrowser.related_files_html(self, req) ehtml = codebrowser.experts_html(self, req) return stream \ | Transformer('//div[@id="footer"]').before(rhtml) \ | Transformer('//div[@id="footer"]').before(ehtml) \ | Transformer('//head').append(css) else: return stream
def process_request(self, req): panels, providers = self._get_panels(req) if not panels: raise HTTPNotFound(_('No administration panels available')) def _panel_order(p1, p2): if p1[::2] == ('general', 'basics'): return -1 elif p2[::2] == ('general', 'basics'): return 1 elif p1[0] == 'general': if p2[0] == 'general': return cmp(p1[1:], p2[1:]) return -1 elif p2[0] == 'general': if p1[0] == 'general': return cmp(p1[1:], p2[1:]) return 1 return cmp(p1, p2) panels.sort(_panel_order) cat_id = req.args.get('cat_id') or panels[0][0] panel_id = req.args.get('panel_id') path_info = req.args.get('path_info') if not panel_id: try: panel_id = filter(lambda panel: panel[0] == cat_id, panels)[0][2] except IndexError: raise HTTPNotFound(_('Unknown administration panel')) provider = providers.get((cat_id, panel_id), None) if not provider: raise HTTPNotFound(_('Unknown administration panel')) if hasattr(provider, 'render_admin_panel'): template, data = provider.render_admin_panel( req, cat_id, panel_id, path_info) else: # support for legacy WebAdmin panels data = {} cstmpl, ct = provider.process_admin_request( req, cat_id, panel_id, path_info) output = cstmpl.render() title = _("Untitled") for panel in panels: if (panel[0], panel[2]) == (cat_id, panel_id): title = panel[3] data.update({'page_title': title, 'page_body': HTML(output)}) template = 'admin_legacy.html' data.update({ 'active_cat': cat_id, 'active_panel': panel_id, 'panel_href': partial(req.href, 'admin', cat_id, panel_id), 'panels': [{ 'category': { 'id': panel[0], 'label': panel[1] }, 'panel': { 'id': panel[2], 'label': panel[3] } } for panel in panels] }) add_stylesheet(req, 'common/css/admin.css') return template, data, None
def filter_stream(self, req, method, filename, stream, data): if filename == 'ticket.html' and self.editor_source and self.editor_replace: self.log.debug( "further processing: template %s, editor-source %s, editor-replace %s" % (filename, self.editor_source, self.editor_replace)) # check if description should be in HTML if self.description_format == "html": add_editor = self.editor_replace.replace( "@FIELD_NAME@", "field_description") html = HTML(add_editor) self.log.debug("add_editor is %s" % add_editor) stream |= Transformer( './/textarea[@name="field_description"]').after(html) fields = data['fields'] for f in fields: if f['skip'] or not f['type'] == 'textarea' or not f.has_key( 'format') or not f['format'] == 'html': continue # only textarea-fields with format HTML should be processed at this point field_name = 'field_%s' % f['name'] add_editor = self.editor_replace.replace( "@FIELD_NAME@", field_name) html = HTML(add_editor) tr_str = './/textarea[@name="%s"]' % field_name self.log.debug("add_editor for field %s is %s; tr_str is %s" % (field_name, add_editor, tr_str)) stream |= Transformer(tr_str).after(html) return stream #=============================================================================== # UNUSED COMPONENTS # These components are not used yet, because they are not working and # are only made because in a research manner. #=============================================================================== #=============================================================================== # class DisplayDate(Component): # """DEPRECATED # # '''Deprecated - use trac itself with revision 10629 or later! ''' # (see Trac-Ticket [http://trac.edgewall.org/ticket/9777 #9777]) # Displays date next to summary as absolute date instead of timedelta. # Timedelta will be displayed only as title. # # '''Attention''': This works partly fine in German and English. Other languages / locales haven't been tested. # It doesn't set the language correct in changes (like comments / attachments). # You also have to edit your `template.htm` and place it under your project folder. # # Sample change: # {{{ # <div class="date"> # <py:choose> # <py:when test="date_format == 'absolute'"> # <p i18n:msg="created" py:if="ticket.exists">Creation date: ${dateinfo_abs(ticket.time)}</p> # <p i18n:msg="modified" py:if="ticket.changetime != ticket.time">Modify date: ${dateinfo_abs(ticket.changetime)}</p> # </py:when> # <py:otherwise> # <p i18n:msg="created" py:if="ticket.exists">Opened ${dateinfo(ticket.time)} ago</p> # <p i18n:msg="modified" py:if="ticket.changetime != ticket.time">Last modified ${dateinfo(ticket.changetime)} ago</p> # </py:otherwise> # </py:choose> # <p py:if="not ticket.exists"><i>(ticket not yet created)</i></p> # </div> # }}} # # Options: # || '''option name''' || '''values''' || '''description''' || # || date_format || `relative` | `absolute` || format of date in ticket view (default: '''relative''') || # # Sample configuration: # {{{ # [ticket] # date_format = absolute # }}} # # You might restart your webserver after installing this plugin, since it doesn't display the date correctly. # """ # implements (IRequestFilter, ITemplateStreamFilter) # # date_format = Option('ticket', 'date_format', 'relative', # """Format of date in ticket view. # Empty or relative is Trac Standard; absolute formats date as date/time.""") # # def __init__(self): # locale_dir = pkg_resources.resource_filename(__name__, 'locale') # add_domain(self.env.path, locale_dir) # # def pre_process_request(self, req, handler): # return handler # # def post_process_request(self, req, template, data, content_type): # if data and template == 'ticket.html': # self.log.info("[post_process_request] called this method with data with template: %s" % template) # def dateinfo_abs(date): # self.log.info("[post_process_request] called method 'dateinfo'") # return tag.span(format_datetime(date), # title=pretty_timedelta(date)) # data['date_format'] = self.date_format # if self.date_format == "absolute": # data['dateinfo_abs'] = dateinfo_abs # # self.log.debug("data %r" % data) # return template, data, content_type # # def filter_stream(self, req, method, filename, stream, data): # # if not self.date_format == "absolute": # # return stream # # # # if filename == 'ticket.html': # # self.log.debug( "replacing relative datetime to absolute datetime" ) # # # just a hack (works at least well in German and English) # # def replace_descr(stream): # # for mark, (kind, data, pos) in stream: # # if mark and kind is TEXT: # # test = data.upper() # # if re.match(r'[0-9]{2}', test): # # yield mark, (kind, data, pos) # # else: # # yield mark, (kind, '', pos) # # else: # # yield mark, (kind, data, pos) # # # # stream = stream | Transformer('.//div[@id="ticket"]/div[@class="date"]/p[1]') \ # # .apply( replace_descr ).prepend( _('Creation date') + ': ' ) # # stream = stream | Transformer('.//div[@id="ticket"]/div[@class="date"]/p[2]') \ # # .apply( replace_descr ).prepend( _('Modify date') + ': ' ) # # # # just a hack, which works in German, but not in English! # # def replace_comment_descr(stream): # # do_replace_text = 0 # # for mark, (kind, data, pos) in stream: # # if mark and kind is END: # # try: # # if data.localname == "h3": # # do_replace_text = 0 # # elif data.localname == "span": # # do_replace_text += 1 # # except Exception, e: # # print "*** EXEPTION *** %s" % e # # yield mark, (kind, data, pos) # # elif mark and kind is TEXT: # # test = data.upper() # # if re.match(r'[0-9]{2}', test): # # yield mark, (kind, data, pos) # # elif do_replace_text == 2: # # yield mark, (kind, '', pos) # # else: # # yield mark, (kind, data, pos) # # else: # # yield mark, (kind, data, pos) # # # # stream = stream | Transformer('.//h3 [@class="change"]') \ # # .apply( replace_comment_descr ).prepend( _('Modify date') + ': ' ) # return stream #=============================================================================== #=============================================================================== #class FileUploader(Component): # """Test for uploading images by CKEditor""" # implements (IAttachmentChangeListener, IAttachmentManipulator, IRequestHandler) # # def match_request(self, req): # """Return whether the handler wants to process the given request.""" # return re.match(r'/image_upload', req.path_info) # # 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 either 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. # """ # print "========= ____ [process_request]" # if ( req.path_info == "/image_upload" ): # add_stylesheet(req, 'hw/css/style.css') # print "========= ____ [process_request] correct path ... doing more" # data = {} # return 'ticketnav/image-uploader.html', data, None # # def prepare_attachment(self, req, attachment, fields): # """Not currently called, but should be provided for future # compatibility.""" # print "--------------.... [prepare_attachment] try to add attachment" # # def validate_attachment(self, req, attachment): # """Validate an attachment after upload but before being stored in Trac # environment. # # Must return a list of `(field, message)` tuples, one for each problem # detected. `field` can be any of `description`, `username`, `filename`, # `content`, or `None` to indicate an overall problem with the # attachment. Therefore, a return value of `[]` means everything is # OK.""" # print "_______________.... [validate_attachment] try to add attachment" # return [] # # def attachment_added(self, attachment): # """Called when an attachment is added.""" # print "_______________ [attachment_added] try to add attachment" # print "_______________ [attachment_added] add attachment: %s" % attachment ## return attachment # # def attachment_deleted(self, attachment): # """Called when an attachment is deleted.""" # print "_______________ [attachment_deleted] try to delete attachment" ## return attachment # # def attachment_reparented(self, attachment, old_parent_realm, old_parent_id): # """Called when an attachment is reparented.""" # print "_______________ [attachment_reparented] add attachment: %s" % attachment # return attachment, old_parent_realm, old_parent_id #=============================================================================== #=============================================================================== # Tested if copying ticket-box.html is working, but it is not! #=============================================================================== #class HtmlContent(Component): # implements (IRequestFilter) # """Allow description and other textarea-fields having HTML-content""" # # # IRequestHandler methods ## def match_request(self, req): ## print "===== HtmlContent, path_info: %s" % req.path_info ## return re.match(r'/(ticket|newticket)(?:_trac)?(?:/.*)?$', req.path_info) # # def pre_process_request(self, req, handler): # return handler # # # IRequestHandler methods # def post_process_request(self, req, template, data, content_type): # print "template: %s" % template # self._check_init() ## data = {} ## return handler ## return 'ticket.html', data, None # return template, data, content_type # # # def _check_init(self): # """First check if Plugin has already been initialized. # """ # # print "====== _check_init" # # template_path = self.env.path # # if template_path and template_path.endswith('/'): # template_path += 'templates' # else: # template_path += '/templates' # # if os.access(template_path, os.W_OK): # print "can write to path %s" % template_path # from pkg_resources import resource_filename ## src_name = resource_filename(__name__, 'templates/ticket-box.html') # src_name = resource_filename(__name__, 'templates') # print "src_name: %s" % src_name # shutil.copy(src_name + '/ticket-box.html', template_path + '/ticket-box.html') # elif os.access(template_path, os.R_OK): # print "can read to path %s" % template_path # # print "template_path: %s" % template_path
def postprocess(self, html): stream = HTML(html) stream |= lambda s: wrapper(self.canon, s) # rewrite_canonical_urls(self.canon, s) return stream.render('html')
def _create_genshi_fragment(self, html_fragment): return tag(HTML(html_fragment))