def _wiki_link(self, req, args, kwargs, wiki, label, a_class, check=None): """Build links to wiki pages.""" check_sign = None url = self.env.href.wiki(wiki) if WikiSystem(self.env).has_page(wiki.lstrip("/")): a_class += " page" title = _("Go to page %s") % wiki if check and check[0] == "link": chrome_path = "/".join([req.base_path, "chrome"]) ok_img = "wikicalendar/check_ok.png" ok = tag.image(src="/".join([chrome_path, ok_img]), alt="ok", title="ok") nok_img = "wikicalendar/check_nok.png" nok = tag.image(src="/".join([chrome_path, nok_img]), alt="X", title="X") unk_img = "wikicalendar/check_unknown.png" unk = tag.image(src="/".join([chrome_path, unk_img]), alt="?", title="?") result = self._do_check(check[1], wiki) check_sign = result and (result == 1 and ok or nok) or unk else: # The default (empty page) is used, if template name is invalid. url += "?action=edit" # Add page template to create new wiki pages, if specified. template = None if len(args) >= 6 or kwargs.has_key("base"): try: template = kwargs["base"] except KeyError: template = args[5] if template: url += "&template=" + template title = _("Create page %s") % wiki link = tag.a(tag(label), href=url) link(class_=a_class, title_=title) return tag(link, check_sign)
def _render_change(old, new): rendered = None if old and not new: rendered = tag( Markup(_("%(value)s reset to default value", value=tag.em(old)))) elif new and not old: rendered = tag( Markup(_("from default value set to %(value)s", value=tag.em(new)))) elif old and new: if len(old) < 20 and len(new) < 20: rendered = tag( Markup( _("changed from %(old)s to %(new)s", old=tag.em(old), new=tag.em(new)))) else: nbsp = tag.br() # TRANSLATOR: same as before, but with additional line breaks rendered = tag( Markup( _("changed from %(old)s to %(new)s", old=tag.em(nbsp, old), new=tag.em(nbsp, new)))) return rendered
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup( _("""Please type [%(token)s] as verification token, exactly replicating everything within the braces.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label( _("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag( insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field."))) return insert, data
def format_search_results(self, res): title = res['hilited_name'] or res['name'] product = res.get('product') if product: return tag(u'[', product, u'] ', title) else: return tag(title)
def render_timeline_event(self, context, field, event): bp_resource, bp, bc = event[3] compat_format_0_11_2 = 'oneliner' if hasattr(context, '_hints'): compat_format_0_11_2 = None if bc: # A blog comment if field == 'url': return context.href.blog(bp.name) + '#comment-%d' % bc.number elif field == 'title': return tag('Blog: ', tag.em(bp.title), ' comment added') elif field == 'description': comment = compat_format_0_11_2 and shorten_line(bc.comment) \ or bc.comment return format_to(self.env, compat_format_0_11_2, context(resource=bp_resource), comment) else: # A blog post if field == 'url': return context.href.blog(bp.name) elif field == 'title': return tag('Blog: ', tag.em(bp.title), bp.version > 1 and ' edited' or ' created') elif field == 'description': comment = compat_format_0_11_2 and shorten_line(bp.version_comment) \ or bp.version_comment return format_to(self.env, compat_format_0_11_2, context(resource=bp_resource), comment)
def render_timeline_event(self, context, field, event): # Decompose event data. title, description, path = event[3] # Return apropriate content. if field == 'url': if not path: # method is DELETE return '' files_core = FilesCoreComponent(self.env) req = None try: req = context.req except AttributeError as e: pass download_config = files_core.files_download_config(req=req) node = FileSystemNode(download_config.base_path) node.populate_file_data(get_normalized_relative_path(node.base_path, path, assume_relative_path=True)) if node.exists(): return context.href.files(node.relative_path) else: return "" elif field == 'title': return tag(title) elif field == 'description': return tag(description)
def render_timeline_event(self, context, field, event): # Decompose event data. title, description, path = event[3] # Return apropriate content. if field == 'url': if not path: # method is DELETE return '' files_core = FilesCoreComponent(self.env) req = None try: req = context.req except AttributeError as e: pass download_config = files_core.files_download_config(req=req) node = FileSystemNode(download_config.base_path) node.populate_file_data( get_normalized_relative_path(node.base_path, path, assume_relative_path=True)) if node.exists(): return context.href.files(node.relative_path) else: return "" elif field == 'title': return tag(title) elif field == 'description': return tag(description)
def get_resource_description(self, resource, format=None, **kwargs): env = self.env href = kwargs.get('href') if resource.parent is None: return _("Unparented form %(id)s", id=resource.id) parent_name = get_resource_name(env, resource.parent) parent_url = href and \ get_resource_url(env, resource.parent, href) or None parent = parent_url is not None and \ tag.a(parent_name, href=parent_url) or parent_name # DEVEL: resource description not implemented yet #if format == 'summary': # return Form(self.env, resource).description if resource.id: if format == 'compact': return _("Form %(form_id)s (%(parent)s)", form_id=resource.id, parent=get_resource_shortname(env, resource.parent)) # TRANSLATOR: Most verbose title, i.e. for form history page return tag(Markup(_("Form %(form_id)s (in %(parent)s)", form_id=resource.id, parent=parent))) else: # TRANSLATOR: Title printed i.e. in form select page if format == 'compact': return tag(Markup(_("Forms (%(parent)s)", parent=parent))) return tag(Markup(_("Forms in %(parent)s", parent=parent)))
def serializeNode(self, node, indent): if node.type == simpletree.TextNode.type: if (node.parent.name not in html5lib.constants.rcdataElements and node.parent.name != "plaintext"): value = cgi.escape(node.value, True) else: value = node.value if node.parent.name in ("pre", "textarea"): value = "\n" + value rv = tag.code(value, class_="text") elif node.type == simpletree.Element.type: rv = tag("") rv.append(tag.code("<" + node.name, class_=tagClasses["element"])) if node.attributes: for key, value in node.attributes.iteritems(): value = cgi.escape(value, True) rv.append(tag(" ", tag.code(key, class_=tagClasses["attr_name"]), "=", tag.code("\""+value+"\"", class_=tagClasses["attr_value"]))) rv.append(tag.code(">", class_=tagClasses["element"])) elif node.type == simpletree.CommentNode.type: rv = tag.code("<!--"+node.data+"-->", class_=tagClasses["comment"]) elif node.type == simpletree.DocumentType.type: rv = tag.code("<!DOCTYPE " + node.name + ">", class_=tagClasses["doctype"]) return rv
def _render_ticket_event(self, field, context): if (field == 'url'): self._read_idx += 1 #next index now #call the original render function output = self._old_render_fn[self._read_idx](field, context) if field == 'title': #now it's time to insert the project name #split the whole string until we can insert splitted_output = to_unicode(output).split("</em>") tooltip = splitted_output[0].split('\"') ticket_no = splitted_output[0].split('>') if len(tooltip) == 3: #it's a ticket #now rebuild the puzzle by inserting the name output = tag( 'Ticket' + ' ', tag.em(ticket_no[1], title=tooltip[1]), ' ', tag.span(self._current_project[self._read_idx], style="background-color: #ffffd0;"), splitted_output[1]) elif len(tooltip) == 1 and len( splitted_output) == 3: #it's an attachment output += tag( ' ', tag.span(self._current_project[self._read_idx], style="background-color: #ffffd0;")) return output
def render_registration_fields(self, req, data): """Add an email address text input field to the registration form.""" # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('email', '').strip() insert = tag.label(_("Email:"), tag.input(type='text', name='email', size=20, class_='textwidget', value=old_value) ) # Deferred import required to aviod circular import dependencies. from acct_mgr.web_ui import AccountModule reset_password = AccountModule(self.env).reset_password_enabled verify_account = is_enabled(self.env, EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email if verify_account: # TRANSLATOR: Registration form hints for a mandatory input field. hint = tag.p(_("""The email address is required for Trac to send you a verification token."""), class_='hint') if reset_password: hint = tag(hint, tag.p(_( """Entering your email address will also enable you to reset your password if you ever forget it."""), class_='hint') ) return tag(insert, hint), data elif reset_password: # TRANSLATOR: Registration form hint, if email input is optional. hint = tag.p(_("""Entering your email address will enable you to reset your password if you ever forget it."""), class_='hint') return dict(optional=tag(insert, hint)), data else: # Always return the email text input itself as optional field. return dict(optional=insert), data
def _render_property(self, name, mode, context, props): repos, revs = props[name] def link(rev): chgset = repos.get_changeset(rev) return tag.a(rev, class_="changeset", title=shorten_line(chgset.message), href=context.href.changeset(rev, repos.reponame)) if name == 'Parents' and len(revs) == 2: # merge new = context.resource.id parent_links = [ (link(rev), ' (', tag.a('diff', title=_("Diff against this parent " "(show the changes merged from the other parents)"), href=context.href.changeset(new, repos.reponame, old=rev)), ')') for rev in revs] return tag([(parent, ', ') for parent in parent_links[:-1]], parent_links[-1], tag.br(), tag.span(tag_("Note: this is a %(merge)s changeset, " "the changes displayed below correspond " "to the merge itself.", merge=tag.strong('merge')), class_='hint'), tag.br(), # TODO: only keep chunks present in both parents # (conflicts) or in none (extra changes) # tag.span('No changes means the merge was clean.', # class_='hint'), tag.br(), tag.span(tag_("Use the %(diff)s links above to see all " "the changes relative to each parent.", diff=tag.tt('(diff)')), class_='hint')) return tag([tag(link(rev), ', ') for rev in revs[:-1]], link(revs[-1]))
def _do_account(self, req): if not req.authname or req.authname == 'anonymous': req.redirect(req.href.wiki()) action = req.args.get('action') delete_enabled = AccountManager(self.env).supports('delete_user') data = {'delete_enabled': delete_enabled} force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': data.update(self._do_change_password(req)) if force_change_password: del(req.session['force_change_passwd']) req.session.save() chrome.add_notice(req, Markup(tag( "Thank you for taking the time to update your password." ))) force_change_password = False elif action == 'delete' and delete_enabled: data.update(self._do_delete(req)) else: data.update({'error': 'Invalid action'}) if force_change_password: chrome.add_warning(req, Markup(tag( "You are required to change password because of a recent " "password change request. ", tag.b("Please change your password now.")))) return data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Apologies for the inconvenience, but please use the Sugarlabs Wiki, find the page referring to find the gold in the pot, and insert here the four words on the second line, or send mail to systems mailing list.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def _gen_wiki_links(self, wiki, label, a_class, url, wiki_page_template, check=None): check_sign = None if WikiSystem(self.env).has_page(wiki.lstrip('/')): a_class += " page" title = _("Go to page %s") % wiki if check and check[0] == 'link': chrome_path = '/'.join([self.ref.req.base_path, 'chrome']) ok_img = 'wikicalendar/check_ok.png' ok = tag.image(src='/'.join([chrome_path, ok_img]), alt='ok', title='ok') nok_img = 'wikicalendar/check_nok.png' nok = tag.image(src='/'.join([chrome_path, nok_img]), alt='X', title='X') unk_img = 'wikicalendar/check_unknown.png' unk = tag.image(src='/'.join([chrome_path, unk_img]), alt='?', title='?') result = self._do_check(check[1], wiki) check_sign = result and (result == 1 and ok or nok) or unk else: url += "?action=edit" # adding template name, if specified if wiki_page_template != "": url += "&template=" + wiki_page_template title = _("Create page %s") % wiki link = tag.a(tag(label), href=url) link(class_=a_class, title_=title) return tag(link, check_sign)
def _format_reminder(self, req, ticket, id, time, author, origin, description, delete_button=True): now = to_datetime(None) time = to_datetime(time) if now >= time: when = tag(tag.strong("Right now"), " (pending)") else: when = tag("In ", tag.strong(pretty_timedelta(time)), " (", format_date(time), ")") if description: context = Context.from_request(req, ticket.resource) desc = tag.div(format_to_oneliner(self.env, context, description), class_="description") else: desc = tag() return tag( self._reminder_delete_form(req, id) if delete_button else None, when, " - added by ", tag.em(Chrome(self.env).authorinfo(req, author)), " ", tag.span(pretty_timedelta(origin), title=format_datetime( origin, req.session.get('datefmt', 'iso8601'), req.tz)), " ago.", desc)
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Please type [%(token)s] as verification token, exactly replicating everything within the braces.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def handle_edit_locale_admins(self, req, locale_id): if not locale_id: req.redirect(req.href.admin('translations', 'locales')) Session = session(self.env) locale = Session.query(Locale).get(int(locale_id)) known_users = self.env.get_known_users() errors = [] perm = PermissionSystem(self.env) sids_without_necessary_perms = [] for admin in locale.admins: if not 'L10N_MODERATE' in perm.get_user_permissions(admin.sid): sids_without_necessary_perms.append(admin.sid) if sids_without_necessary_perms: msg = ngettext( "%s does not have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), "%s don't have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), len(sids_without_necessary_perms)) errors.append( tag(msg, _(" Don't forget to "), tag.a(_('update permissions'), href=req.href.admin('general', 'perm')), '.')) if req.method == 'POST' and len(req.args.getlist('admins')) >= 1: current_admins = req.args.getlist('current_admins') selected = req.args.getlist('admins') self.log.debug('Current Admins: %s', current_admins) self.log.debug('Selected Admins: %s', selected) allow_delete_admins = len(selected) >= 1 if not allow_delete_admins: errors.append( tag(_("There must be at least on admin for each locale."))) for admin in current_admins: if not allow_delete_admins: break if admin not in selected: locale_admin = Session.query(LocaleAdmin). \ filter(locale_admin_table.c.sid==admin).first() Session.delete(locale_admin) for admin in selected: if admin not in locale.admins: locale.admins.append(LocaleAdmin(locale, admin)) Session.commit() req.redirect(req.href.admin('translations', 'locales')) elif req.method == 'POST' and len(req.args.getlist('admins')) < 1: errors.append( tag(_("There must be at least on admin for each locale."))) data = {'locale': locale, 'known_users': known_users} if errors: data['error'] = tag.ul(*[tag.li(e) for e in errors if e]) return 'l10n_admin_locale_admins.html', data
def validate_registration(self, req): if req.path_info == '/prefs': return acctmgr = AccountManager(self.env) username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) if not username: raise RegistrationError(N_("Username cannot be empty.")) # Always exclude some special characters, i.e. # ':' can't be used in HtPasswdStore # '[' and ']' can't be used in SvnServePasswordStore blacklist = acctmgr.username_char_blacklist if containsAny(username, blacklist): pretty_blacklist = '' for c in blacklist: if pretty_blacklist == '': pretty_blacklist = tag(' \'', tag.b(c), '\'') else: pretty_blacklist = tag(pretty_blacklist, ', \'', tag.b(c), '\'') raise RegistrationError( N_("The username must not contain any of these characters: %s" ), tag.b(pretty_blacklist)) # All upper-cased names are reserved for permission action names. if username.isupper(): raise RegistrationError( N_("A username with only upper-cased characters is not allowed." )) # Prohibit some user names, that are important for Trac and therefor # reserved, even if not in the permission store for some reason. if username.lower() in ['anonymous', 'authenticated']: raise RegistrationError(N_("Username %s is not allowed."), tag.b(username)) # NOTE: A user may exist in a password store but not in the permission # store. I.e. this happens, when the user (from the password store) # never logged in into Trac. So we have to perform this test here # and cannot just check for the user being in the permission store. # And better obfuscate whether an existing user or group name # was responsible for rejection of this user name. for store_user in acctmgr.get_users(): # Do it carefully by disregarding case. if store_user.lower() == username.lower(): raise RegistrationError( N_("Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username)) # Password consistency checks follow. password = req.args.get('password') if not password: raise RegistrationError(N_("Password cannot be empty.")) elif password != req.args.get('password_confirm'): raise RegistrationError(N_("The passwords must match."))
def validate_registration(self, req): acctmgr = AccountManager(self.env) username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) if not username: raise RegistrationError(N_("Username cannot be empty.")) # Always exclude some special characters, i.e. # ':' can't be used in HtPasswdStore # '[' and ']' can't be used in SvnServePasswordStore blacklist = acctmgr.username_char_blacklist if containsAny(username, blacklist): pretty_blacklist = '' for c in blacklist: if pretty_blacklist == '': pretty_blacklist = tag(' \'', tag.b(c), '\'') else: pretty_blacklist = tag(pretty_blacklist, ', \'', tag.b(c), '\'') raise RegistrationError(N_( "The username must not contain any of these characters: %s"), tag.b(pretty_blacklist) ) # All upper-cased names are reserved for permission action names. if username.isupper(): raise RegistrationError(N_( "A username with only upper-cased characters is not allowed.") ) # Prohibit some user names, that are important for Trac and therefor # reserved, even if not in the permission store for some reason. if username.lower() in ['anonymous', 'authenticated']: raise RegistrationError(N_("Username %s is not allowed."), tag.b(username) ) # NOTE: A user may exist in a password store but not in the permission # store. I.e. this happens, when the user (from the password store) # never logged in into Trac. So we have to perform this test here # and cannot just check for the user being in the permission store. # And better obfuscate whether an existing user or group name # was responsible for rejection of this user name. for store_user in acctmgr.get_users(): # Do it carefully by disregarding case. if store_user.lower() == username.lower(): raise RegistrationError(N_( "Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username) ) # Password consistency checks follow. password = req.args.get('password') if not password: raise RegistrationError(N_("Password cannot be empty.")) elif password != req.args.get('password_confirm'): raise RegistrationError(N_("The passwords must match."))
def render_timeline_event(self, context, field, event): codereview_page, name, notes, reviewersList = event[3] if field == 'url': return context.href.peerReviewView(Review=codereview_page.id) if field == 'title': return tag('Code review ', tag.em(name), ' has been raised') if field == 'description': return tag('Assigned to: ', reviewersList, tag.br(), ' Additional notes: ', notes)
def render_hierarchy(group): return tag.ul( tag.li(tag(tag.a(elt[0], href=formatter.href.wiki(elt[1])) if elt[1] else tag(elt[0]), render_hierarchy(elt[2])) if len(elt) == 3 else tag.a('/'.join(elt[0]), href=formatter.href.wiki(elt[1]))) for elt in group)
def format_search_results(self, res): #TODO: add better milestone rendering name = res['hilited_name'] or res['name'] product = res.get('product') if product: return tag(u'[', product, u'] Milestone:', name) else: return tag(u'Milestone:', name)
def moreless(text, length): """Turns `text` into HTML code where everything behind `length` can be uncovered using a ''show more'' link and later covered again with a ''show less'' link.""" try: if len(text) <= length: return tag(text) except: return tag(text) return tag(tag.span(text[:length]),tag.a(' [', tag.strong(Markup('…')), ']', class_="more"), tag.span(text[length:],class_="moretext"),tag.a(' [', tag.strong('-'), ']', class_="less"))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description = event[3] # Return apropriate content. if field == 'url': return context.href.screenshots(id) elif field == 'title': return tag('New screenshot ', tag.em(name), ' created') elif field == 'description': return tag('%s' % (description, ))
def render_timeline_event(self, context, field, event): (start, sprint) = event[3] if field == 'url': return context.href.sprint(sprint.name) elif field == 'title': if start: return tag('Sprint ', tag.em(sprint.name), ' started') return tag('Sprint ', tag.em(sprint.name), ' finished') elif field == 'description': return format_to(self.env, None, context(resource=sprint), sprint.description)
def render_property(self, name, mode, context, props): import string from genshi.builder import tag fragments = [] vals = string.split(props[name], ' ') for val in vals[1:]: title = "ticket %s" % (val) fragments.append(tag.a("#%s" % val, class_="ticket", title=title, href=context.href.ticket(val))) return tag([tag(f, ', ') for f in fragments[:-1]], fragments[-1])
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description = event[3] # Return apropriate content. if field == 'url': return context.href.screenshots(id) elif field == 'title': return tag('New screenshot ', tag.em(name), ' created') elif field == 'description': return tag('%s' % (description,))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description, size = event[3] # Return apropriate content. if field == 'url': return context.req.href.downloads(id) elif field == 'title': return tag('New download ', tag.em(name), ' created') elif field == 'description': return tag('(%s) ' % (pretty_size(size),), format_to_oneliner( self.env, context, description))
def moreless(text, length): """Turns `text` into HTML code where everything behind `length` can be uncovered using a ''show more'' link and later covered again with a ''show less'' link.""" try: if len(text) <= length: return tag(text) except: return tag(text) return tag(tag.span(text[:length]), tag.a(' [', tag.strong(Markup('…')), ']', class_="more"), tag.span(text[length:], class_="moretext"), tag.a(' [', tag.strong('-'), ']', class_="less"))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description, size = event[3] # Return apropriate content. if field == 'url': return context.req.href.downloads(id) elif field == 'title': return tag('New download ', tag.em(name), ' created') elif field == 'description': return tag('(%s) ' % (pretty_size(size), ), format_to_oneliner(self.env, context, description))
def render_property(self, name, mode, context, props): import string from genshi.builder import tag fragments = [] vals = string.split(props[name], ' ') for val in vals[1:]: title = "ticket %s" % (val) fragments.append( tag.a("#%s" % val, class_="ticket", title=title, href=context.href.ticket(val))) return tag([tag(f, ', ') for f in fragments[:-1]], fragments[-1])
def serializeNode(self, node, indent): rv = tag(" "*indent+"|") if node.type == simpletree.TextNode.type: text = node.value.split("\n") rv.append(tag(tag.code("#text: ", class_=tagClasses["text_marker"]), tag.code(text[0], class_=tagClasses["text"]))) for line in text[1:]: rv.append(tag(tag("\n" + " "*indent+"|"), tag.code(line, class_=tagClasses["text"]))) elif node.type == simpletree.Element.type: rv.append(tag.code(node.name, class_=tagClasses["element"])) if node.attributes: for key, value in node.attributes.iteritems(): rv.append(tag(" ", tag.code(key, class_=tagClasses["attr_name"]), "=", tag.code("\""+value+"\"", class_=tagClasses["attr_value"]))) elif node.type == simpletree.CommentNode.type: rv.append(tag(tag.code("#comment: ", class_=tagClasses["comment_marker"]), tag.code(node.data, class_=tagClasses["comment"]))) elif node.type == simpletree.DocumentType.type: rv.append(tag(tag.code("DOCTYPE: ", class_=tagClasses["doctype_marker"]), tag.code(node.name, class_=tagClasses["doctype"]))) rv.append(tag("\n")) return rv
def render_timeline_event(self, context, field, event): # Decompose event data. title, description, ids = event[3] # Return apropriate content. if field == 'url': url = context.href.discussion(*ids) if len(ids) == 3: url = '%s#%s' % (url, ids[2]) return url elif field == 'title': return tag(title) elif field == 'description': return tag(description)
def render_property_diff(self, req, ticket, field, old, new, resource_new=None): "Version for Trac 0.11" rendered = None # per type special rendering of diffs type_ = None for f in ticket.fields: if f['name'] == field: type_ = f['type'] break if type_ == 'checkbox': rendered = new == '1' and "set" or "unset" elif type_ == 'textarea': if not resource_new: rendered = _('modified') else: href = get_resource_url(self.env, resource_new, req.href, action='diff') rendered = tag('modified (', tag.a('diff', href=href), ')') # per name special rendering of diffs old_list, new_list = None, None render_elt = lambda x: x sep = ', ' if field == 'cc': chrome = Chrome(self.env) old_list, new_list = chrome.cc_list(old), chrome.cc_list(new) if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource_new or ticket.resource)): render_elt = obfuscate_email_address elif field == 'keywords': old_list, new_list = (old or '').split(), new.split() sep = ' ' if (old_list, new_list) != (None, None): added = [tag.em(render_elt(x)) for x in new_list if x not in old_list] remvd = [tag.em(render_elt(x)) for x in old_list if x not in new_list] added = added and tag(separated(added, sep), " added") remvd = remvd and tag(separated(remvd, sep), " removed") if added or remvd: rendered = tag(added, added and remvd and '; ', remvd) return rendered if field in ('reporter', 'owner'): if not (Chrome(self.env).show_email_addresses or 'EMAIL_VIEW' in req.perm(resource_new or ticket.resource)): old = obfuscate_email_address(old) new = obfuscate_email_address(new) # Added by MS if field == 'attachment': rendered = tag(tag.em(new), " added") # changed 'if' to 'elif': elif old and not new: rendered = tag(tag.em(old), " deleted") elif new and not old: rendered = tag("set to ", tag.em(new)) elif old and new: rendered = tag("changed from ", tag.em(old), " to ", tag.em(new)) return rendered
def _get_template_values(self): html_attrs = self.document.settings.html_tag_attr html_attrs = html_attrs and ' ' + ' '.join(html_attrs) or '' self.head = self.metatags + self.stylesheets + self.scripts for key, value in self.docinfo.items(): self.head.append(tag.meta(name=key, content=value)) self.indent_head() self.head = ''.join(XHTMLSerializer()(tag(*self.head))) self.body = ''.join(XHTMLSerializer()(tag(*self.context.stack))) values = {} values['html_attr'] = html_attrs values['head'] = self.head values['body'] = self.body return values
def format_change(field,oldvalue,newvalue): """Formats tickets changes.""" fieldtag = tag.strong(field) if field == 'cc': oldvalues = set(oldvalue and oldvalue.split(', ') or []) newvalues = set(newvalue and newvalue.split(', ') or []) added = newvalues.difference(oldvalues) removed = oldvalues.difference(newvalues) strng = fieldtag if added: strng += tag(" ", tag.em(', '.join(added)), _(" added")) if removed: if added: strng += tag(', ') strng += tag(" ", tag.em(', '.join(removed)), _(" removed")) return strng elif field == 'description': return fieldtag + tag(_(" modified"), " (", tag.a(_("diff"), href=req.href('ticket',id,action='diff', version=self.commentnum)), ")") elif field == 'comment': self.commentnum = oldvalue self.comment = newvalue return tag("") elif not oldvalue: return fieldtag + tag(" ", tag.em(newvalue), _(" added")) elif not newvalue: return fieldtag + tag(" ", tag.em(oldvalue), _(" deleted")) else: return fieldtag + tag(_(" changed from "), tag.em(oldvalue), _(" to "), tag.em(newvalue))
def format_change(field, oldvalue, newvalue): """Formats tickets changes.""" fieldtag = tag.strong(field) if field == "cc": oldvalues = set(oldvalue and oldvalue.split(", ") or []) newvalues = set(newvalue and newvalue.split(", ") or []) added = newvalues.difference(oldvalues) removed = oldvalues.difference(newvalues) strng = fieldtag if added: strng += tag(" ", tag.em(", ".join(added)), " added") if removed: if added: strng += tag(", ") strng += tag(" ", tag.em(", ".join(removed)), " removed") return strng elif field == "description": return fieldtag + tag( " modified (", tag.a("diff", href=href("ticket", id, action="diff", version=self.commentnum)), ")", ) elif field == "comment": self.commentnum = oldvalue self.comment = newvalue return tag("") elif not oldvalue: return fieldtag + tag(" ", tag.em(newvalue), " added") elif not newvalue: return fieldtag + tag(" ", tag.em(oldvalue), " deleted") else: return fieldtag + tag(" changed from ", tag.em(oldvalue), " to ", tag.em(newvalue))
def _do_update(self, req): """Update component enable state.""" components = req.args.getlist('component') enabled = req.args.getlist('enable') added, removed = [], [] # FIXME: this needs to be more intelligent and minimize multiple # component names to prefix rules for component in components: is_enabled = bool(self.env.is_component_enabled(component)) must_enable = component in enabled if is_enabled != must_enable: self.config.set('components', component, 'disabled' if is_enabled else 'enabled') self.log.info("%sabling component %s", "Dis" if is_enabled else "En", component) if must_enable: added.append(component) else: removed.append(component) if added or removed: def make_list(items): parts = [item.rsplit('.', 1) for item in items] return tag.table(tag.tbody( tag.tr(tag.td(c, class_='trac-name'), tag.td('(%s.*)' % m, class_='trac-name')) for m, c in parts), class_='trac-pluglist') added.sort() removed.sort() notices = [] if removed: msg = ngettext("The following component has been disabled:", "The following components have been disabled:", len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext("The following component has been enabled:", "The following components have been enabled:", len(added)) notices.append(tag(msg, make_list(added))) # set the default value of options for only the enabled components for component in added: self.config.set_defaults(component=component) _save_config(self.config, req, self.log, notices)
def filter_stream(self, req, method, filename, stream, data): if req.path_info.startswith('/report/'): link_builder = req.href.chrome debug = IttecoEvnSetup(self.env).debug def script_tag(path=None, content=None): kw = { 'type' : "text/javascript"} if path: kw['src'] = link_builder(map_script(path, debug)) return tag.script(content , **kw) stream |= Transformer("//head").prepend( tag.link(type="text/css", rel="stylesheet", href=link_builder("itteco/css/report.css")) ).append( tag( script_tag('stuff/plugins/jquery.rpc.js'), script_tag('stuff/ui/plugins/jquery.jeditable.js'), script_tag("editable_report.js"), script_tag( content= "$(document).ready(function(){"+ "$('#main').editableReport("+ "{"+ "rpcurl: '"+req.href('login','xmlrpc')+"',"+ "fields: "+self.fields_dict(data.get('header_groups',[]))+"})"+ "});" ) ) ) try: stream |= Transformer("//head").prepend( tag( # TODO fix scripts base path tag.link(type="text/css", rel="stylesheet", href=link_builder("itteco/css/common.css")), tag.link(type="text/css", rel="stylesheet", href=link_builder("itteco/css/report.css")), #tag.link(type="text/css", rel="stylesheet", href=link_builder("itteco/css/colorbox/colorbox.css")) ) ).append( tag( script_tag("stuff/ui/ui.core.js"), script_tag("stuff/ui/ui.draggable.js"), script_tag("stuff/ui/ui.droppable.js"), script_tag("stuff/ui/ui.resizable.js"), script_tag('stuff/ui/plugins/jquery.colorbox.js'), script_tag('custom_select.js') ) ) except ValueError,e: #we do not fail the report it self, may be it works in read only mode self.env.log.debug('Report decoration failed: %s' % e)
def render_timeline_event(self, context, field, event): wiki_page, comment = event[3] if field == 'url': return context.href.wiki(wiki_page.id, version=wiki_page.version) elif field == 'title': return tag(tag.em(get_resource_name(self.env, wiki_page)), wiki_page.version > 1 and ' edited' or ' created') elif field == 'description': markup = format_to(self.env, None, context(resource=wiki_page), comment) if wiki_page.version > 1: diff_href = context.href.wiki( wiki_page.id, version=wiki_page.version, action='diff') markup = tag(markup, ' ', tag.a('(diff)', href=diff_href)) return markup
def render_timeline_event(self, context, field, event): # Decompose event data. title, description, ids = event[3] # Return apropriate content. if field == 'url': url = context.href.discussion(*ids) if len(ids) == 3: url = context.href.discussion(*ids[0]) url = '%s#%s%s' % (url,ids[1], ids[2]) return url elif field == 'title': return tag(title) elif field == 'description': return tag(description)
def macroFactory(self, macro_name, arg_string, body, context,wiki): if macro_name == 'html': return self.getFragment(body) elif macro_name == 'title': return wiki.page_title # elif macro_name == 'span': # return builder.tag.span(self.parse.generate(body,context='inline'),id_=arg_string.strip()) # elif macro_name == 'div': # return builder.tag.div(self.parse.generate(body),id_=arg_string.strip()) elif macro_name == 'html2': return Markup(body) elif macro_name == 'htmlblock': return self.getStream(body) elif macro_name == 'pre': return builder.tag.pre('**' + body + '**') elif macro_name == 'steve': return '**' + arg_string + '**' # elif macro_name == 'luca': # return builder.tag.strong(arg_string) elif macro_name == 'mateo': return builder.tag.em(body) elif macro_name == 'ReverseFrag': return builder.tag(body[::-1]) elif macro_name == 'Reverse': return body[::-1] elif macro_name == 'Reverse-it': return body[::-1] elif macro_name == 'ReverseIt': return body[::-1] elif macro_name == 'lib.ReverseIt-now': return body[::-1] elif macro_name == 'ifloggedin': return body elif macro_name == 'username': return 'Joe Blow' elif macro_name == 'center': return builder.tag.span(body, class_='centered') elif macro_name == 'footer': return '<<center>>This is a footer.<</center>>' elif macro_name == 'footer2': return '<<center>>\nThis is a footer.\n<</center>>' elif macro_name == 'reverse-lines': if body is not None: l = reversed(body.rstrip().split('\n')) if arg_string.strip() == 'output=wiki': return '\n'.join(l) + '\n' else: return builder.tag('\n'.join(l) + '\n')
def post_process_request(self, req, template, data, content_type): page_path = req.args.get('page', None) if not page_path or page_path == 'WikiStart': return template, data, content_type href = req.href nav = req.chrome['ctxtnav'] wikiStartIndex = None for i, elm in enumerate(nav): if type(elm) == Element and elm.tag == 'a' and elm.attrib.get( 'href') == href.wiki('WikiStart'): wikiStartIndex = i break if wikiStartIndex is None: return template, data, content_type page_paths = page_path.split('/') # reverse it so we can .pop() in the necessary order page_paths.reverse() _links = [] _prev_path = "" while page_paths: page_path = page_paths.pop() _prev_path += "/" + page_path _link = None if page_paths: _link = href.wiki(_prev_path) t = (page_path, _link) _links.append(t) # always prepend the default start page link _links = [('Start Page', href.wiki('WikiStart'))] + _links r = [] for link in _links: text, _href = link if _href: r += tag(tag.a(text, href=_href), ' %s ' % self.sep_character) else: # last entry in list # ..so _href is None # ..so no sep char appended r += tag(text) nav[i] = r return template, data, content_type
def notify(self, resid, subject, author=None): self.subject = subject config = self.config['notification'] if not config.getbool('smtp_enabled'): return from_email, from_name = '', '' if author and config.getbool('smtp_from_author'): from_email = self.get_smtp_address(author) if from_email: from_name = self.name_map.get(author, '') if not from_name: mo = self.longaddr_re.search(author) if mo: from_name = mo.group(1) if not from_email: from_email = config.get('smtp_from') from_name = config.get('smtp_from_name') or self.env.project_name self.replyto_email = config.get('smtp_replyto') self.from_email = from_email or self.replyto_email self.from_name = from_name if not self.from_email and not self.replyto_email: message = tag( tag.p(_('Unable to send email due to identity crisis.')), # convert explicitly to `Fragment` to avoid breaking message # when passing `LazyProxy` object to `Fragment` tag.p(to_fragment(tag_( "Neither %(from_)s nor %(reply_to)s are specified in the " "configuration.", from_=tag.strong("[notification] smtp_from"), reply_to=tag.strong("[notification] smtp_replyto"))))) raise TracError(message, _("SMTP Notification Error")) Notify.notify(self, resid)
def render_ticket_action_control(self, req, ticket, action): id, grade = self._get_grade(req, action) review_options = self._get_review_options(action) actions = ConfigurableTicketWorkflow(self.env).actions selected_value = grade or review_options[0][0] label = actions[action]['name'] control = tag([ "as: ", tag.select([ tag.option(option, selected=(option == selected_value or None)) for option, status in review_options ], name=id, id=id) ]) if grade: new_status = self._get_new_status(req, ticket, action, review_options) hint = "Next status will be '%s'" % new_status else: hint = "Next status will be one of " + \ ', '.join(["'%s'" % status for option, status in review_options]) return (label, control, hint)
def render_group(group): return tag.ul( tag.li(tag(tag.strong(elt[0].strip('/')), render_group(elt[1])) if isinstance(elt, tuple) else tag.a(wiki.format_page_name(omitprefix(elt)), href=formatter.href.wiki(elt))) for elt in group)
def test_tracerror_with_tracerror_with_fragment(self): message = tag('Powered by ', tag.a('Trac', href='http://trac.edgewall.org/')) rv = to_fragment(TracError(TracError(message))) self.assertEqual(Fragment, type(rv)) self.assertEqual('Powered by <a href="http://trac.edgewall.org/">Trac' '</a>', unicode(rv))
def __get__(self, instance, owner): if instance is None: return self order = ListOption.__get__(self, instance, owner) components = [] implementing_classes = [] for impl in self.xtnpt.extensions(instance): implementing_classes.append(impl.__class__.__name__) if self.include_missing or impl.__class__.__name__ in order: components.append(impl) not_found = sorted(set(order) - set(implementing_classes)) if not_found: raise ConfigurationError( tag_( "Cannot find implementation(s) of the %(interface)s " "interface named %(implementation)s. Please check " "that the Component is enabled or update the option " "%(option)s in trac.ini.", interface=tag.code(self.xtnpt.interface.__name__), implementation=tag( (', ' if idx != 0 else None, tag.code(impl)) for idx, impl in enumerate(not_found)), option=tag.code("[%s] %s" % (self.section, self.name)))) def compare(x, y): x, y = x.__class__.__name__, y.__class__.__name__ if x not in order: return int(y in order) if y not in order: return -int(x in order) return cmp(order.index(x), order.index(y)) components.sort(compare) return components