Exemple #1
0
	def filter_stream(self, req, method, filename, stream, data):
		if not filename == 'report_list.html':
			return stream
			
		user = req.authname

		buffer = StreamBuffer()

		def check_report_permission():
			delimiter = '</tr>'

			reportstream = str(buffer)

			reports_raw = reportstream.split(delimiter)
			reportstream = ''

			for report in reports_raw:
				if report != None and len(report) != 0:

					# determine the report id
					s = report.find('/report/')
					if s == -1:
						continue

					e = report.find('\"',s)
					if e == -1:
						continue
					report_id = report[s+len('/report/'):e]

					if self._has_permission(user,report_id):
						reportstream += report

			return HTML(reportstream)

		return stream | Transformer('//tbody/tr') \
		.copy(buffer) \
		.replace(check_report_permission)
Exemple #2
0
    def filter(self, stream):
        # Add vocab tags to the bottom of the sidebar.
        from pylons import request
        from genshi.filters import Transformer
        from genshi.input import HTML
        routes = request.environ.get('pylons.routes_dict')
        context = {'model': model}
        if routes.get('controller') == 'package' \
            and routes.get('action') == 'read':
            for vocab in (GENRE_VOCAB, COMPOSER_VOCAB):
                try:
                    vocab = get_action('vocabulary_show')(context, {
                        'id': vocab
                    })
                    vocab_tags = [
                        t for t in c.pkg_dict.get('tags', [])
                        if t.get('vocabulary_id') == vocab['id']
                    ]
                except NotFound:
                    vocab_tags = None

                if not vocab_tags:
                    continue

                html = '<li class="sidebar-section">'
                if vocab['name'] == GENRE_VOCAB:
                    html = html + '<h3>Musical Genre</h3>'
                elif vocab['name'] == COMPOSER_VOCAB:
                    html = html + '<h3>Composer</h3>'
                html = html + '<ul class="tags clearfix">'
                for tag in vocab_tags:
                    html = html + '<li>%s</li>' % tag['name']
                html = html + "</ul></li>"
                stream = stream | Transformer(
                    "//div[@id='sidebar']//ul[@class='widget-list']").append(
                        HTML(html))
        return stream
Exemple #3
0
    def filter_stream(self, req, method, filename, stream, data):
        if filename == 'ticket.html' and req.authname != 'anonymous':
            ticket = data.get('ticket')
            if req.perm.has_permission('TICKET_ADMIN'):
                self.log.debug(
                    "TicketChangePlugin adding 'Change' links for ticket %s" %
                    ticket.id)
                buffer = StreamBuffer()

                def insert_change_link():
                    cnum = list(buffer)[0][1][1][0][1]
                    return tag(
                        " ",
                        tag.a("Change",
                              href=("../ticketchangecomment/%s?cnum=%s" %
                                    (ticket.id, cnum))))

                filter = Transformer(
                    "//div[@class='change']/div[@class='inlinebuttons']/input[@name='replyto']/@value"
                )
                return stream | filter.copy(buffer).end() \
                              .select("//div[@class='change']/div[@class='inlinebuttons']/input[@value='Reply']") \
                              .after(insert_change_link)
        return stream
    def filter_stream(self, req, method, filename, stream, data):

        if filename != "ticket.html" and filename != 'ticket_preview.html':
            return stream

        if 'ticket' in data:
            ticket = data['ticket']

            stream |= Transformer('//head').append(tag.style("""
                .relation_table {
                    width: 100%;
                }
                .relation_table td {
                    border-bottom: dotted 1px #eed;
                }
            """))

            for relation in self.build_relations().values():
                if relation.ticket_type_a == ticket['type']:
                    stream = self._generate_html(relation, relation.relation_type_a, 'a', stream, ticket)
                elif relation.ticket_type_b == ticket['type']:
                    stream = self._generate_html(relation, relation.relation_type_b, 'b', stream, ticket)

        return stream
Exemple #5
0
    def filter_stream(self, req, method, filename, stream, data):
        """
        filter hours and estimated hours fields to have them 
        correctly display on the ticket.html
        """

        if filename == 'ticket.html':
            totalhours = [
                field for field in data['fields']
                if field['name'] == 'totalhours'
            ][0]
            ticket_id = data['ticket'].id
            if ticket_id is None:  # new ticket
                field = '0'
            else:
                hours = '%.1f' % (self.get_total_hours(ticket_id) / 3600.0)
                field = tag.a(hours,
                              href=req.href('hours', data['ticket'].id),
                              title="hours for ticket %s" % data['ticket'].id)
            totalhours['rendered'] = field
            stream |= Transformer("//input[@id='field-totalhours']").replace(
                field)

        return stream
class PPTicketViewTweak(Component):
  '''
    BETA: computes links on ticket dependency entries
    while using ProjectPlanPlugin in the standard configuration this component is NEEDED
  '''
  implements(ITemplateStreamFilter, IRequestFilter)
  
  field = None
  fieldrev = None
  useTable = True
  
  def lazy_init( self , authname):
    self.field = PPConfiguration( self.env ).get('custom_dependency_field')
    self.fieldrev = PPConfiguration( self.env ).get('custom_reverse_dependency_field')
    self.dataaccess = DataAccessDependencies(self.env, authname)
    
    #if self.useTable:
      #self.dataaccess = DataAccessDependenciesInExtraTable(self.env, authname)
    #else:
      #self.dataaccess = DataAccessDependenciesInCustomFields(self.env)

  def cleanUp( self, req ):
    '''
      TODO
    '''
    if self.useTable:
      try:
        req.args.__delitem__('field_%s' % (self.field,))
      except:
        pass
      try:
        req.args.__delitem__('field_%s' % (self.fieldrev,))
      except:
        pass
      self.dataaccess.commit()
  
  # ITemplateStreamFilter methods
  def filter_stream(self, req, method, filename, stream, data):  
    '''
      replace the dependency-field by links
    '''
    
    # stop if this is not a ticket view
    if not req.path_info.startswith('/ticket/') and not req.path_info.startswith('/newticket'):
      return stream
    
    self.lazy_init(req.authname)
    
    current_ticket_id = None
    try:
      current_ticket_id = str(data['ticket'].id)
      dependencies = self.getDependsOn(current_ticket_id)
      #dependencies = '1, 8; 2 y 3, 99,x' # test
    except Exception,e:
      self.env.log.warning('filter_stream fail '+repr(e))
      return stream
    
    deptickets = self.splitStringToTicketList(dependencies)
    blocking_tickets_string = self.createNormalizedTicketString( deptickets ) # normalized
    
    blocked_tickets = self.getBlockedTickets( current_ticket_id ) 
    blocked_tickets_string = self.createNormalizedTicketString(blocked_tickets) # normalized
    
    nodeptickets = [ t for t in deptickets if str(t).strip() != "" and not isNumber(t) ]
    actualdeptickets = [ t for t in deptickets if str(t).strip() != "" and isNumber(t) ]
    
    depwithlinks = self.getTicketLinkList(req, actualdeptickets, nodeptickets)
    
    blocked_tickets_with_links = self.getTicketLinkList(req, blocked_tickets, [])
    
    self.env.log.debug('nodeptickets of '+str(current_ticket_id)+': '+repr(nodeptickets))
    self.env.log.debug('actualdeptickets of '+str(current_ticket_id)+': '+repr(actualdeptickets))
    self.env.log.debug('dependencies of '+str(current_ticket_id)+': '+repr(blocking_tickets_string))
    
    # change summary block
    if str(depwithlinks) != '' or PPConfiguration(self.env).isMasterticketsCompatible(): # change HTML only if there is actually a link to show
      stream |= Transformer('//*[@headers="h_%s"]/text()' % self.field).replace(depwithlinks)
   
    if str(blocked_tickets_with_links) != '' or PPConfiguration(self.env).isMasterticketsCompatible():
      stream |= Transformer('//*[@headers="h_%s"]/text()' % self.fieldrev).replace( blocked_tickets_with_links )
    
    # change fields
    stream |= Transformer('//*[@id="field-%s"]' % (self.field)).attr('value', blocking_tickets_string)
    stream |= Transformer('//*[@id="field-%s"]' % (self.fieldrev)).attr('value', blocked_tickets_string)  
    # create a backup field containing the earlier value
    stream |= Transformer('//*[@id="propertyform"]').prepend( tag.input(name='field_%s_backup' % (self.field), value=blocking_tickets_string, style='display:none') )
    stream |= Transformer('//*[@id="propertyform"]').prepend( tag.input(name='field_%s_backup' % (self.fieldrev), value=blocked_tickets_string, style='display:none') )
    
    
    
    # publish data that should be used by javascript
    stream |= Transformer('body/div[@id="main"]').prepend(
      tag.div( 
        tag.div( req.environ.get( 'ticketclosedf' ), id='ppDateFormat'),
        tag.div( 'field-'+self.field, id='ppDependenciesField'),
        tag.div( 'field-'+self.fieldrev, id='ppDependenciesReverseField'),
        id='ppTicketViewTweakConf'
    ))
    
    return stream
Exemple #7
0
    def filter_stream(self, req, method, filename, stream, data):
        """
        filter the stream for the roadmap (/roadmap)
        and milestones /milestone/<milestone>
        """

        if filename in ('roadmap.html', 'milestone_view.html') and \
                'TICKET_VIEW_HOURS' in req.perm:
            trac_hours = TracHoursPlugin(self.env)

            hours = {}

            milestones = data.get('milestones')
            this_milestone = None

            if milestones is None:
                # /milestone view : only one milestone
                milestones = [data['milestone']]
                this_milestone = milestones[0].name
                find_xpath = "//div[@class='milestone']/h1"
                xpath = "//div[@class='milestone']/div[1]"
            else:
                # /roadmap view
                find_xpath = "//*[@class='milestone']//h2/a"
                xpath = "//*[@class='milestone']/div[1]"

            for milestone in milestones:
                hours[milestone.name] = dict(
                    totalhours=0.,
                    estimatedhours=0.,
                )

                tickets = [
                    tid for tid, in self.env.db_query(
                        """
                    SELECT id FROM ticket WHERE milestone=%s
                    """, (milestone.name, ))
                ]

                if tickets:
                    hours[milestone.name]['date'] = \
                        Ticket(self.env, tickets[0])['time']
                for ticket in tickets:
                    ticket = Ticket(self.env, ticket)

                    # estimated hours for the ticket
                    try:
                        estimated_hours = float(ticket['estimatedhours'])
                    except (ValueError, TypeError):
                        estimated_hours = 0.
                    hours[milestone.name]['estimatedhours'] += estimated_hours

                    # total hours for the ticket (seconds -> hours)
                    total_hours = trac_hours.get_total_hours(
                        ticket.id) / 3600.0
                    hours[milestone.name]['totalhours'] += total_hours

                    # update date for oldest ticket
                    if ticket['time'] < hours[milestone.name]['date']:
                        hours[milestone.name]['date'] = ticket['time']

            b = StreamBuffer()
            stream |= Transformer(find_xpath).copy(b).end().select(xpath). \
                append(
                self.MilestoneMarkup(b, hours, req.href, this_milestone))

        return stream
 def prepend_title(template):
     return template | Transformer('head/title').append(' - Flask-Genshi')
 def filter_stream(self, req, method, filename, stream, data):
     if filename == 'timeline.html':
         # Insert the new field for entering user names
         filter = Transformer('//form[@id="prefs"]/fieldset')
         return stream | filter.before(tag.br()) | filter.before(tag.label("Filter Components (none for all): ")) | filter.before(tag.br()) | filter.before(self._components_field_input(req))
     return stream
    def filter_stream(self, req, method, template, stream, data):
        if not (template == 'browser.html' and data.get('dir')):
            if ((not data.get('dir')) and (data.get('path'))
                    and (data.get('path').endswith('.md'))
                ):  # Rendering single markdown file preview
                stream = stream | Transformer(
                    "//head/script[not(@src)][1]"
                ).after(
                    tag.script(Markup(
                        "jQuery(document).ready(function($) {"
                        "  $('#preview').each(function() {"
                        "    $(this).html(marked( $(this).children('pre').first().text() ));"
                        "  });"
                        "});"),
                               type="text/javascript"))
            return stream

        add_stylesheet(req, 'common/css/code.css')

        repos = data.get('repos') or self.env.get_repository()
        rev = req.args.get('rev', None)

        for entry in data['dir'][
                'entries']:  # Rendering all READMEs in a directory preview
            try:
                if not entry.isdir and entry.name.lower().startswith('readme'):
                    node = repos.get_node(entry.path, rev)
                    req.perm(data['context'].resource).require('FILE_VIEW')
                    mimeview = Mimeview(self.env)
                    content = node.get_content()
                    mimetype = node.content_type
                    divclass = 'searchable'
                    if entry.name.lower().endswith('.wiki'):
                        mimetype = 'text/x-trac-wiki'
                        divclass = 'searchable wiki'
                    elif entry.name.lower().endswith('.md'):
                        mimetype = 'text/x-markdown'
                        divclass = 'searchable markdown'
                    if not mimetype or mimetype == 'application/octet-stream':
                        mimetype = mimeview.get_mimetype(
                            node.name,
                            content.read(4096)) or mimetype or 'text/plain'
                    del content
                    self.log.debug(
                        "ReadmeRenderer: rendering node %s@%s as %s" %
                        (node.name, str(rev), mimetype))
                    output = mimeview.preview_data(data['context'],
                                                   node.get_content(),
                                                   node.get_content_length(),
                                                   mimetype,
                                                   node.created_path,
                                                   '',
                                                   annotations=[],
                                                   force_source=False)

                    if output:
                        if isinstance(output['rendered'], Stream):
                            #content = output['rendered'].select('./pre/node()')
                            #content = output['rendered'].select('./pre')
                            content = output['rendered'].select('.')
                        else:
                            self.log.debug("GOT THERE")
                            content = output['rendered']
                        insert = tag.div(
                            tag.h1(entry.name,
                                   tag.a(Markup(' &para;'),
                                         class_="anchor",
                                         href='#' + entry.name,
                                         title='Link to file'),
                                   id_=entry.name),
                            tag.div(
                                content,
                                #xml:space = "preserve",
                                class_=divclass,
                                title=entry.name),
                            class_="readme",
                            style="padding-top: 1em;")
                        stream = stream | Transformer(
                            "//div[@id='content']/div[@id='help']").before(
                                insert)
            except Exception, e:
                self.log.debug(to_unicode(e))
Exemple #11
0
    def filter_stream(self, req, method, filename, stream, data):

        if filename == 'ticket.html':

            # setup variables
            javascript = [self.javascript()]

            onload = []
            onsubmit = []
            policy_dict = self.policy_dict()

            # add JS functions to the head block
            for policy in self.policies:
                policy_javascript = policy.javascript()
                
                if policy_javascript:
                    add_script(req, policy_javascript)
#                    javascript.append(policy_javascript)

            policies = self.parse()
            
            for name, policy in policies.items():

                # insert the condition into the JS
                conditions = policy['condition']
                _conditions = []
                for condition in conditions:
                    _condition = {}
                    _condition['field'] = condition['field']
                    _condition['comparitor'] = camelCase(condition['comparitor'])
                    comp_type =  self.comparitors[condition['comparitor']]
                    value = condition['value']
                    if comp_type == 'Array':
                        _condition['value'] = '[ %s ]' % ', '.join(["'%s'" % v for v in value])
                    else:
                        _condition['value'] = "'%s'" % value
                    _conditions.append("{field: '%(field)s', comparitor: %(comparitor)s, value: %(value)s}" % _condition)
                condition = '%s = [ %s ];' % (name, ', '.join(_conditions))
                javascript.append(condition)

                # find the correct handler for the policy
                for action in policy['actions']:
                    handler =  policy_dict.get(action['name'])
                    if handler is None:
                        self.log.error('No ITicketSubmitPolicy found for "%s"' % action['name'])
                        continue
                
                    # filter the stream
                    stream = handler.filter_stream(stream, name, policy['condition'], *action['args'])


                    # add other necessary JS to the page
                    policy_onload = handler.onload(name, policy['condition'], *action['args'])
                    if policy_onload:
                        onload.append(policy_onload)
                    policy_onsubmit = handler.onsubmit(name, policy['condition'], *action['args'])
                    if policy_onsubmit:
                        onsubmit.append(policy_onsubmit)

            # insert onload, onsubmit hooks if supplied
            if onload:
                javascript.append(self.onload(onload))

            if onsubmit:
                javascript.append(self.onsubmit(onsubmit))
                stream |= Transformer("//form[@id='propertyform']").attr('onsubmit', 'validate()')

            # insert head javascript
            if javascript:
                javascript = '\n%s\n' % '\n'.join(javascript)
                javascript = tag.script(Markup(javascript), **{ "type": "text/javascript"})
                
                stream |= Transformer("head").append(javascript)

        return stream
Exemple #12
0
    def filter(self, stream):
        """
        Required to implement IGenshiStreamFilter.

        If this is the package controller with the read action:
        Adds HTML to the document HEAD, the package heading and
        the bottom of the BODY to create the follow/unfollow button
        and the follower count button.

        If this is the user controller with the read action:
        Adds HTML to the BODY to display the currently followed
        packages, if any exist.
        """
        routes = request.environ.get('pylons.routes_dict')

        # if this is the read action of a package, show follower info
        if (routes.get('controller') == 'package'
                and routes.get('action') == 'read' and c.pkg.id):
            # pass data to the javascript file that creates the
            # follower count and follow/unfollow buttons
            user_id = controller.get_user_id(
                request.environ.get('REMOTE_USER')) or ""
            data = {
                'package_id': c.pkg.id,
                'package_name': c.pkg.name,
                'user_id': user_id
            }
            # add CSS styles for follower HTML
            stream = stream | Transformer('head').append(HTML(html.HEAD_CODE))
            # add jquery and follower.js links
            stream = stream | Transformer('body')\
                .append(HTML(html.BODY_CODE % data))
            # add the follower DIV to the package title, after the
            # RSS 'subscribe' link
            stream = stream | Transformer('body//div[@id="package"]//h2[@class="head"]')\
                .append(HTML(html.FOLLOWER_CODE))
            # add the follower error DIV after the H2 tag
            stream = stream | Transformer('body//div[@id="package"]//h2[@class="head"]')\
                .after(HTML(html.ERROR_CODE))

        # if this is the read action of a user page, show packages being followed
        if (routes.get('controller') == 'user'
                and routes.get('action') == 'read' and c.user):
            user_id = controller.get_user_id(c.user)
            packages = controller.packages_followed_by(user_id)
            if packages:
                packages_html = ""
                for package_number, package in enumerate(packages):
                    # add a link to the package page
                    package_name = controller.get_package_name(package)
                    packages_html += \
                        h.link_to(package_name,
                                  h.url_for(controller='package', action='read',
                                            id=package_name))
                    # add comma and space if this isn't the last package in the
                    # list
                    if package_number < len(packages) - 1:
                        packages_html += ", "
                packages_followed = {'packages_followed': packages_html}
                stream = stream | Transformer('body//div[@class="activity"]//ul')\
                    .append(HTML(html.PACKAGES_FOLLOWED_CODE % packages_followed))

        return stream
Exemple #13
0
    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 _render_readme(self, req, stream, data):
        add_stylesheet(req, 'common/css/code.css')

        repos = data.get('repos') or self.env.get_repository()
        rev = req.args.get('rev', None)

        # Rendering all READMEs in a directory preview
        for entry in data['dir']['entries']:
            try:
                if not entry.isdir and entry.name.lower().startswith('readme'):
                    node = repos.get_node(entry.path, rev)
                    req.perm(data['context'].resource).require('FILE_VIEW')
                    mimeview = Mimeview(self.env)
                    content = node.get_content()
                    mimetype = node.content_type
                    divclass = 'searchable'
                    if entry.name.lower().endswith('.wiki'):
                        mimetype = 'text/x-trac-wiki'
                        divclass = 'searchable wiki'
                    elif entry.name.lower().endswith('.md'):
                        mimetype = 'text/x-markdown'
                        divclass = 'searchable markdown'
                    if not mimetype or mimetype == 'application/octet-stream':
                        mimetype = mimeview.get_mimetype(
                            node.name, content.read(4096)) or \
                            mimetype or 'text/plain'
                    del content
                    self.log.debug(
                        "ReadmeRenderer: rendering node %s@%s as %s",
                        node.name, rev, mimetype)
                    output = mimeview.preview_data(
                        data['context'],
                        node.get_content(),
                        node.get_content_length(),
                        mimetype,
                        node.created_path,
                        '',
                        annotations=[],
                        force_source=False)

                    if output:
                        if isinstance(output['rendered'], Stream):
                            content = output['rendered'].select('.')
                        else:
                            content = output['rendered']
                        insert = tag.div(
                            tag.h1(entry.name,
                                   tag.a(Markup(' &para;'),
                                         class_="anchor",
                                         href='#' + entry.name,
                                         title='Link to file'),
                                   id_=entry.name),
                            tag.div(content,
                                    class_=divclass,
                                    title=entry.name),
                            class_="readme",
                            style="padding-top: 1em;"
                        )
                        xpath = "//div[@id='content']/div[@id='help']"
                        stream |= Transformer(xpath).before(insert)
            except Exception, e:
                self.log.debug(to_unicode(e))
    def filter_stream(self, req, method, filename, stream, data):
        """ overloaded from ITemplateStreamFilter """
        #        print "-------- >  filename: %s" % filename
        if filename == 'ticket.html' and data:
            if self._check_init() == False:
                self.create_table()
                self.log.info("table successfully initialized")
            tkt = data['ticket']
            if tkt and tkt.id:
                self._load_budget(tkt.id)
            else:
                self._budgets = {}

            input_html, preview_html = self._get_ticket_html()
            if 'TICKET_MODIFY' in req.perm(tkt.resource):
                visibility = ' style="visibility:hidden"'
                if self._budgets:
                    visibility = ''

                # Load default values for Type, Estimation, Cost an State from trac.ini
                def_type = self.config.get('budgeting-plugin', 'default_type')
                if not def_type:
                    # If the configured default-type is not available, submit -1 ==> first element in type list will be selected
                    def_type = '-1'
                def_est = self.config.get('budgeting-plugin',
                                          'default_estimation')
                if not def_est:
                    def_est = '0.0'
                def_cost = self.config.get('budgeting-plugin', 'default_cost')
                if not def_cost:
                    def_est = '0.0'
                def_state = self.config.get('budgeting-plugin',
                                            'default_state')
                if not def_state:
                    def_state = '0'

                fieldset_str = self._get_budget_fieldset() % (visibility,
                                                              input_html)
                html = HTML('<div style="display: none" id="selectTypes">%s</div>' \
                           '<div style="display: none" id="selectNames">%s</div>' \
                           '<div style="display: none" id="def_name">%s</div>' \
                           '<div style="display: none" id="def_type">%s</div>' \
                           '<div style="display: none" id="def_est">%s</div>' \
                           '<div style="display: none" id="def_cost">%s</div>' \
                           '<div style="display: none" id="def_state">%s</div>' \
                           '%s' % (self._type_list, self._name_list_str, req.authname, def_type , def_est, def_cost, def_state, fieldset_str))

                stream |= Transformer('.//fieldset [@id="properties"]').after(
                    html)

            if preview_html:
                #                print "preview_html: %s" % preview_html
                fieldset_str = self._get_budget_preview() % preview_html
                stream |= Transformer('//div [@id="content"]//div [@id="ticket"]') \
                            .after(HTML(fieldset_str))
        elif filename == 'milestone_view.html':
            #            print "________________ MILESTONE !!"
            #            print "req.args: %s " % req.args
            by = 'component'
            if 'by' in req.args:
                by = req.args['by']
#            print "------------- link to by: %s " % req.href.query(component=by)
            budget_stats, stats_by = self._get_milestone_html(req, by)
            stats_by = "<fieldset><legend>Budget</legend><table>%s</table></fieldset>" % stats_by
            stream |= Transformer('//form[@id="stats"]').append(HTML(stats_by))
            stream |= Transformer('//div[@class="info"]').append(
                HTML(budget_stats))
            # print input / preview
        return stream
Exemple #16
0
    def filter_stream(self, req, method, filename, stream, data):
        """
        Quick and dirty solution - modify page on the fly to inject special field. It would be
        nicer if we can do it by creating custom field as this depends on page structure.
        """
        #embed(header='Ticket Stream Filter')
        if filename == 'ticket.html':
            # Disable any direct bounty input
            filter = Transformer('.//input[@id="field-bounty"]')
            stream |= filter.attr("disabled", "disabled")

            ticket = data.get('ticket')
            if ticket and ticket.exists:
                identifier = ticket.id
                user = req.authname if req.authname != 'anonymous' else None
                request = self.call_api('GET', '/issue/%s' % identifier)
                fragment = tag()
                sponsorships = {}
                status = self.convert_status(ticket.values['status'])
                owner = ticket.values['owner']
                tooltip = None
                if request != None and (request.status_code == 200
                                        or request.status_code == 404):
                    sponsorships = self.get_sponsorships(identifier)

                    pledged_amount = sum_amounts(sponsorships.values())
                    user_sponsorship = sponsorships.get(user, Sponsorship())

                    # Bounty
                    tooltip = u"Pledged: %d\u20ac" % pledged_amount

                    if status == 'STARTED' or status == 'COMPLETED':
                        confirmed_amount = sum_amounts(
                            sponsorships.values(),
                            ('CONFIRMED', 'VALIDATED', 'REJECTED',
                             'TRANSFERRED', 'REFUNDED'))
                        tooltip += u" \nConfirmed: %d\u20ac" % confirmed_amount
                    if status == 'COMPLETED':
                        validated_amount = sum_amounts(sponsorships.values(),
                                                       'VALIDATED')
                        tooltip += u" \nValidated: %d\u20ac" % validated_amount

                    # Action
                    action = None
                    if (((status == 'STARTED' or status == 'COMPLETED')
                         and user_sponsorship.status == 'PLEDGED') or
                        (status == 'STARTED' and user != None and user != owner
                         and user_sponsorship.status == None)):
                        response = self.call_api('GET',
                                                 '/config/payment_gateways')
                        gateways = response.json().get('gateways')
                        gateway_tags = []
                        if 'DUMMY' in gateways:
                            gateway_tags.append(
                                tag.input(type="submit",
                                          value="Payment Card",
                                          name='DUMMY'))
                        if 'PAYPAL_STANDARD' in gateways:
                            gateway_tags.append(
                                tag.input(type="submit",
                                          value="PayPal",
                                          name='PAYPAL_STANDARD'))
                        if 'PAYPAL_ADAPTIVE' in gateways:
                            gateway_tags.append(
                                tag.input(type="submit",
                                          value="PayPal",
                                          name='PAYPAL_ADAPTIVE'))
                        if user_sponsorship.status == 'PLEDGED':
                            action = tag.form(
                                tag.input(type="button",
                                          name="confirm",
                                          value=u"Confirm %d\u20ac" %
                                          user_sponsorship.amount,
                                          id="confirm-button"),
                                tag.span(gateway_tags, id="confirm-options"),
                                tag.input(type="submit",
                                          name="delete",
                                          value="Delete"),
                                method="post",
                                action=req.href.ticket(identifier, "confirm"))
                        else:
                            #TODO: should be separate action
                            action = tag.form(
                                tag.input(name="amount",
                                          type="text",
                                          size="3",
                                          value="0",
                                          pattern="[0-9]*",
                                          title="money amount"),
                                tag.input(type="button",
                                          value="Pledge & Confirm",
                                          id="confirm-button"),
                                tag.span(gateway_tags, id="confirm-options"),
                                method="post",
                                action=req.href.ticket(identifier, "confirm"))

                    elif status == 'COMPLETED' and user_sponsorship.status in (
                            'CONFIRMED', 'REJECTED', 'VALIDATED'):
                        action = tag.form(method="post",
                                          action=req.href.ticket(
                                              identifier, "validate"))
                        if user_sponsorship.status == 'CONFIRMED' or user_sponsorship.status == 'REJECTED':
                            action.append(
                                tag.input(type="submit",
                                          name='validate',
                                          value=u"Validate %d\u20ac" %
                                          user_sponsorship.amount))
                        if user_sponsorship.status == 'CONFIRMED' or user_sponsorship.status == 'VALIDATED':
                            action.append(
                                tag.input(type="submit",
                                          name='reject',
                                          value="Reject"))
                    elif (status == 'READY' and user != None):
                        if user_sponsorship.status == None:
                            action = tag.form(
                                tag.input(name="amount",
                                          type="text",
                                          size="3",
                                          value=user_sponsorship.amount,
                                          pattern="[0-9]*",
                                          title="money amount"),
                                tag.input(type="submit", value="Pledge"),
                                method="post",
                                action=req.href.ticket(identifier, "sponsor"))
                        elif user_sponsorship.status == 'PLEDGED':
                            action = tag.form(
                                tag.input(name="amount",
                                          type="text",
                                          size=3,
                                          value=user_sponsorship.amount,
                                          pattern="[0-9]*",
                                          title="money amount"),
                                tag.input(type="submit",
                                          name="update",
                                          value="Update"),
                                tag.input(type="submit",
                                          name="delete",
                                          value="Delete"),
                                method="post",
                                action=req.href.ticket(identifier,
                                                       "update_sponsorship"))

                    elif (user == None):
                        action = tag.span(
                            u"\u00A0", tag.a("Login",
                                             href=req.href.login()), " or ",
                            tag.a("Register", href=req.href.register()),
                            " to sponsor")

                    if action != None:
                        fragment.append(" ")
                        fragment.append(action)

                else:
                    error = "Connection error"
                    if request:
                        error = request.json().get("error", "Unknown error")
                    fragment.append(
                        tag.span("[BountyFunding Error]", title=error))

                #chrome = Chrome(self.env)
                #chrome.add_jquery_ui(req)

                add_stylesheet(req, 'htdocs/styles/bountyfunding.css')
                add_script(req, 'htdocs/scripts/bountyfunding.js')

                if tooltip != None:
                    filter = Transformer('.//td[@headers="h_bounty"]/text()')
                    stream |= filter.wrap(tag.span(title=tooltip))

                filter = Transformer('.//td[@headers="h_bounty"]')
                stream |= filter.attr("class", "bountyfunding")
                stream |= filter.append(fragment)

        return stream
Exemple #17
0
 def prepend_title(template):
     return template | Transformer("head/title").append(
         " - Flask-Genshi")
    def filter_stream(self, req, method, filename, stream, data):
        """ overloaded from ITemplateStreamFilter """
        if filename == 'ticket.html' and data:
            if self._check_init() == False:
                self.create_table()
                self.log.info("table successfully initialized")
            tkt = data['ticket']
            if tkt and tkt.id:
                self._load_budget(tkt.id)
            else:
                self._budgets = {}

            input_html, preview_html = self._get_ticket_html()

            modifyAllowed = False
            for authorizedPerm in authorizedToModify:
                modifyAllowed = modifyAllowed or authorizedPerm in req.perm(
                    tkt.resource)

            if modifyAllowed:
                visibility = ' style="display: none"'
                if self._budgets:
                    visibility = ''

                fieldset = self._get_budget_fieldset() % (visibility,
                                                          input_html)
                stream |= Transformer('.//fieldset [@id="properties"]').after(
                    HTML(fieldset))

                # Load default values for Type, Estimation, Cost an State from trac.ini
                def_type = self._get_budget_attr('default_type')
                if not def_type:
                    # If the configured default-type is not available, submit -1 ==> first element in type list will be selected
                    def_type = '-1'
                def_est = self._get_budget_attr('default_estimation')
                if not def_est:
                    def_est = '0.0'
                def_cost = self._get_budget_attr('default_cost')
                if not def_cost:
                    def_est = '0.0'
                def_state = self._get_budget_attr('default_state')
                if not def_state:
                    def_state = '0'

                defaults = tag.div(tag.a(self._type_list, id="selectTypes"),
                                   tag.a(self._name_list_str,
                                         id="selectNames"),
                                   tag.a(req.authname, id="def_name"),
                                   tag.a(def_type, id="def_type"),
                                   tag.a(def_est, id="def_est"),
                                   tag.a(def_cost, id="def_cost"),
                                   tag.a(def_state, id="def_state"),
                                   style="display: none")

                stream |= Transformer('.//fieldset [@id="budget"]').append(
                    defaults)

            if preview_html:
                fieldset_str = self._get_budget_preview() % preview_html
                stream |= Transformer('//div [@id="content"]//div [@id="ticket"]') \
                            .after(HTML(fieldset_str))
        elif filename == 'milestone_view.html':
            by = 'component'
            if 'by' in req.args:
                by = req.args['by']
            budget_stats, stats_by = self._get_milestone_html(req, by)
            stats_by = "<fieldset><legend>Budget</legend><table>%s</table></fieldset>" % stats_by
            stream |= Transformer('//form[@id="stats"]').append(HTML(stats_by))
            stream |= Transformer('//div[@class="info"]').append(
                HTML(budget_stats))
        return stream
Exemple #19
0
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            #
            if ticket and ticket.exists:

                filter = Transformer('//div[@class="description"]')
                snippet = tag()

                # Are there any child tickets to display?
                childtickets = [
                    Ticket(self.env, n)
                    for n in self.env.childtickets.get(ticket.id, [])
                ]

                # (tempish) fix for #8612 : force sorting by ticket id
                childtickets = sorted(childtickets, key=lambda t: t.id)

                # trac.ini : Which columns to display in child ticket listing?
                columns = self.config.getlist('childtickets',
                                              'parent.%s.table_headers' %
                                              ticket['type'],
                                              default=['summary', 'owner'])

                # trac.ini : child tickets are allowed.
                if self.config.getbool(
                        'childtickets',
                        'parent.%s.allow_child_tickets' % ticket['type']):

                    # trac.ini : Default 'type' of child tickets?
                    default_child_type = self.config.get(
                        'childtickets',
                        'parent.%s.default_child_type' % ticket['type'],
                        default=self.config.get('ticket', 'default_type'))

                    self.env.log.debug(
                        "TracchildticketsModule : default_child_type: %s" %
                        default_child_type)

                    # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                    if 'TICKET_CREATE' in req.perm(ticket.resource):

                        # Always pass these fields
                        default_child_fields = (tag.input(type="hidden",
                                                          name="parent",
                                                          value='#' +
                                                          str(ticket.id)), )

                        #Pass extra fields defined in inherit parameter of parent
                        inherited_child_fields = [
                            tag.input(type="hidden",
                                      name="%s" % field,
                                      value=ticket[field])
                            for field in self.config.getlist(
                                'childtickets', 'parent.%s.inherit' %
                                ticket['type'])
                        ]

                        # If child types are restricted then create a set of buttons for the allowed types (This will override 'default_child_type).
                        restrict_child_types = self.config.getlist(
                            'childtickets',
                            'parent.%s.restrict_child_type' % ticket['type'],
                            default=[])
                        if not restrict_child_types:
                            # ... create a default submit button
                            submit_button_fields = (
                                tag.input(type="submit",
                                          name="childticket",
                                          value="New Child Ticket",
                                          title="Create a child ticket"),
                                tag.input(type="hidden",
                                          name="type",
                                          value=default_child_type),
                            )
                        else:
                            submit_button_fields = [
                                tag.input(type="submit",
                                          name="type",
                                          value="%s" % ticket_type,
                                          title="Create a %s child ticket" %
                                          ticket_type)
                                for ticket_type in restrict_child_types
                            ]

                        snippet.append(
                            tag.div(
                                tag.form(
                                    tag.div(default_child_fields,
                                            inherited_child_fields,
                                            submit_button_fields,
                                            class_="inlinebuttons"),
                                    method="get",
                                    action=req.href.newticket(),
                                ),
                                tag.h3("Child Tickets",
                                       id="comment:child_tickets"),
                            ))
                    else:
                        snippet.append(
                            tag.div(
                                tag.h3("Child Tickets",
                                       id="comment:child_tickets")))

                # trac.ini : child tickets are NOT allowed but (somehow?!) this parent ticket has children assigned.
                elif childtickets:
                    snippet.append(
                        tag.div(
                            tag.h3("Child Tickets",
                                   id="comment:child_tickets")))

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:
                    snippet.append(
                        tag.div(
                            tag.table(
                                tag.thead(
                                    tag.tr(tag.th("Ticket", class_="id"), [
                                        tag.th(s.title(), class_=s)
                                        for s in columns
                                    ])),
                                tag.tbody([
                                    self._table_row(req, tkt, columns)
                                    for tkt in childtickets
                                ]),
                                class_="listing tickets",
                            ), ))
                elif self.config.getbool(
                        'childtickets',
                        'parent.%s.allow_child_tickets' % ticket['type']):
                    snippet.append(tag.div(tag.p("NO SUB-TICKETS.")))

                return stream | filter.append(snippet)

        return stream
 def filter_stream(self, req, method, filename, stream, data):
     if filename == 'timeline.html':
         # Insert the new field for entering user names
         filter = Transformer('//form[@id="prefs"]/fieldset')
         return stream | filter.before(self._user_field_input(req))
     return stream
Exemple #21
0
class CKEditorFormatter(Formatter):
    """Extends base wiki formatter by setting code processor's name 
for code blocks. Thus CKEditor can save it, so it could be processed 
later by format processor like Pygments (see TracSyntaxColoring). 
"""
    
    data_code_style = None
    
    def __init__(self, env, context, wikidom, accepted_code_processors):
        self.env = env
        self.context = context
        self.accepted_code_processors = accepted_code_processors
        if isinstance(wikidom, basestring):
            wikidom = WikiParser(env).parse(wikidom)
        self.wikidom = wikidom
        Formatter.__init__(self, env, context)

    # copied from HtmlFormatter
    def generate(self, escape_newlines=False):
        """Generate HTML elements.

        newlines in the wikidom will be preserved if `escape_newlines` is set.
        """
        # FIXME: compatibility code only for now
        out = StringIO()
        self.format(self.wikidom, out, escape_newlines)
#        self.env.log.debug('generated html: %s' % out.getvalue())
        return Markup(out.getvalue())
    
    def handle_code_block(self, line, startmatch=None):
        """Overrides Formatter.handle_code_block, so it 
adds an additional `pre`-tag with attribute `data-code-style`,  
in which the code-format is saved.

Furthermore the code block is converted into HTML, because otherwise CKEditor 
ignores empty lines. In this method linebreaks `\n` are replaced by `<br/>`.
"""
        handle_code_style = False
        if line.strip() == WikiParser.ENDBLOCK and self.code_processor: 
            clean_processor_name = self.code_processor.name
            self.env.log.debug('clean_processor_name: %s' %  clean_processor_name) 
            
            idx = clean_processor_name.find('; ')
            if idx >= 0:
                clean_processor_name = clean_processor_name[:idx]
            
            if clean_processor_name == 'default':
                handle_code_style = True
                self.data_code_style = ''
            elif clean_processor_name not in ['diff', 'td']:
                try:
                    from pygments.lexers import get_lexer_for_mimetype
                    
                    lexer = get_lexer_for_mimetype(clean_processor_name)
                    proc_aliases = lexer.aliases
                    if proc_aliases and len(proc_aliases) > 0:
                        clean_processor_name = proc_aliases[0]
                    else:
                        clean_processor_name = lexer.name
                    
                    if clean_processor_name in self.accepted_code_processors:
                        self.data_code_style = ' data-code-style="%s"' % clean_processor_name
                        handle_code_style = True
                except Exception, e:
                    self.env.log.warn( "Error when retrieving lexer by mimetype: %s" % e )
                    self.data_code_style = ''
                
        if handle_code_style:
            self.env.log.debug('processing self.data_code_style: %s' %  self.data_code_style) 
            code_text = os.linesep.join(self.code_buf)
            html_text = WikiProcessor(self, 'default').process(code_text)
            html_text = _markup_to_unicode( html_text )
            html_text = html_text.replace('\n', '<br/>')
            
            html = HTML( html_text )
            html |= Transformer('//pre').unwrap()
            buffer = StringIO()
            html.render(out=buffer, encoding='utf-8')
            
            self.out.write( '<pre%s>' % self.data_code_style )
            self.out.write( _markup_to_unicode( buffer.getvalue() ) )
            self.out.write('</pre>')
            
            self.in_code_block = 0
        else:
            Formatter.handle_code_block(self, line, startmatch)
Exemple #22
0
    def filter_stream(self, req, method, filename, stream, data):
        if filename not in ('ticket.html', 'ticket.rss'):
            return stream

        ticket_id = req.args.get('id')
        if not ticket_id:
            return stream

        # determine the username of the current user
        user = req.authname

        # determine if the user has the permission to see private comments
        perms = PermissionSystem(self.env)
        has_private_permission = \
            self.private_comment_permission in perms.get_user_permissions(user)

        # Remove private comments from Ticket Page
        if filename == 'ticket.html':
            buf = StreamBuffer()

            def check_comments():
                delimiter = '<div xmlns="http://www.w3.org/1999/xhtml" ' + \
                            'class="change" id="trac-change-'

                comment_stream = str(buf)
                # split the comment_stream to get single comments
                comments_raw = comment_stream.split(delimiter)
                comment_stream = ''

                for comment in comments_raw:
                    if comment is None or len(comment) < 1:
                        continue

                    # determine comment id
                    find = comment.find('">')
                    if find == -1:
                        continue
                    comment_id = comment[:find]

                    # concat the delimiter and the comment again
                    comment_code = delimiter + comment

                    # if the user has the permission to see the comment
                    # the comment_code will be appended to the comment_stream
                    comment_private = self._is_comment_private(
                        ticket_id, comment_id)

                    if comment_private:
                        comment_code = comment_code.replace(
                            '<span class="threading">',
                            '<span class="threading"> <span class="%s">'
                            'this comment is private</span>' %
                            str(self.css_class_private_comment_marker))

                    if has_private_permission or not comment_private:
                        comment_stream += comment_code

                return HTML(comment_stream)

            # filter all comments
            stream |= Transformer('//div[@class="change" and @id]') \
                .copy(buf).replace(check_comments)

            # if the user has the private comment permission the checkboxes
            # to change the private value will be added
            if has_private_permission:
                comment_box = tag.label(
                    _("Private Comment:"),
                    tag.input(type='checkbox', name='private_comment'))
                stream |= Transformer('//h2[@id="trac-add-comment"]') \
                    .after(comment_box)
                # Trac 1.0 and later:
                # stream |= Transformer(
                #   '//div[@id="trac-add-comment"]//fieldset').prepend(input)

        # Remove private comments from ticket RSS feed
        if filename == 'ticket.rss':
            comments = self._get_all_private_comments(ticket_id)

            self.log.debug("Private Comments for Ticket %d: %s" %
                           (ticket_id, comments))

            for comment_id in comments:
                stream |= Transformer('//item[%d]' % comment_id).remove()

        return stream
Exemple #23
0
    def filter_stream(self, req, method, filename, stream, data):
        """
        filter the stream for the roadmap (/roadmap)
        and milestones /milestone/<milestone>
        """

        if filename in ('roadmap.html', 'milestone_view.html'):
            trac_hours = TracHoursPlugin(self.env)

            hours = {}

            milestones = data.get('milestones')
            this_milestone = None

            if milestones is None:
                # /milestone view : only one milestone
                milestones = [data['milestone']]
                this_milestone = milestones[0].name
                find_xpath = "//div[@class='milestone']//h1"
                xpath = "//div[@class='milestone']//div[@class='info']"
            else:
                # /roadmap view
                find_xpath = "//li[@class='milestone']//h2/a"
                xpath = "//li[@class='milestone']//div[@class='info']"

            for milestone in milestones:
                hours[milestone.name] = dict(
                    totalhours=0.,
                    estimatedhours=0.,
                )

                db = self.env.get_db_cnx()
                cursor = db.cursor()
                cursor.execute("select id from ticket where milestone=%s",
                               (milestone.name, ))
                tickets = [i[0] for i in cursor.fetchall()]

                if tickets:
                    hours[milestone.name]['date'] = \
                        Ticket(self.env, tickets[0]).time_created
                for ticket in tickets:
                    ticket = Ticket(self.env, ticket)

                    # estimated hours for the ticket
                    try:
                        estimated_hours = float(ticket['estimatedhours'])
                    except (ValueError, TypeError):
                        estimated_hours = 0.
                    hours[milestone.name]['estimatedhours'] += estimated_hours

                    # total hours for the ticket (seconds -> hours)
                    total_hours = trac_hours.get_total_hours(
                        ticket.id) / 3600.0
                    hours[milestone.name]['totalhours'] += total_hours

                    # update date for oldest ticket
                    if ticket.time_created < hours[milestone.name]['date']:
                        hours[milestone.name]['date'] = ticket.time_created

            b = StreamBuffer()
            stream |= Transformer(find_xpath).copy(b).end().select(xpath). \
                append(self.MilestoneMarkup(b, hours, req.href, this_milestone))

        return stream
Exemple #24
0
    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 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 filter_stream(self, req, method, filename, stream, data):
        if not req.path_info.startswith('/ticket/'):
            return stream

        div = None
        link = None
        button = None

        if 'ticket' in data:
            # get parents data
            ticket = data['ticket']
            # title
            div = tag.div(class_='description')
            if 'TICKET_CREATE' in req.perm(ticket.resource) \
                    and ticket['status'] != 'closed':
                opt_inherit = self.env.config.getlist(
                    'subtickets', 'type.%(type)s.child_inherits' % ticket)
                if self.opt_add_style == 'link':
                    inh = {f: ticket[f] for f in opt_inherit}
                    link = tag.a(_('add'),
                                 href=req.href.newticket(parents=ticket.id,
                                                         **inh))
                    link = tag.span('(', link, ')', class_='addsubticket')
                else:
                    inh = [
                        tag.input(type='hidden', name=f, value=ticket[f])
                        for f in opt_inherit
                    ]

                    button = tag.form(tag.div(tag.input(
                        type="submit",
                        value=_("Create"),
                        title=_("Create a child ticket")),
                                              inh,
                                              tag.input(type="hidden",
                                                        name="parents",
                                                        value=str(ticket.id)),
                                              class_="inlinebuttons"),
                                      method="get",
                                      action=req.href.newticket())
            div.append(button)
            div.append(tag.h3(_('Subtickets '), link))

        if 'subtickets' in data:
            # table
            tbody = tag.tbody()
            div.append(tag.table(tbody, class_='subtickets'))
            # tickets
            self._create_subtickets_table(req, data['subtickets'], tbody)

        if div:
            add_stylesheet(req, 'subtickets/css/subtickets.css')
            '''
            If rendered in preview mode, DIV we're interested in isn't a child
            but the root and transformation won't succeed.
            According to HTML specification, id's must be unique within a
            document, so it's safe to omit the leading '.' in XPath expression
            to select all matching regardless of hierarchy their in.
            '''
            stream |= Transformer('//div[@id="ticket"]').append(div)

        return stream
Exemple #26
0
    def filter_stream(self, req, method, filename, stream, data):
        if filename == 'admin_enums.html':
            text = 'var hide_selects = %s' % ('false', 'true')[bool(self.hide_selects)]
            stream |= Transformer('//head').append(tag.script(text, type='text/javascript'))

        return stream
Exemple #27
0
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Add our own styles for the ticket lists.
            add_stylesheet(req, 'ct/css/childtickets.css')

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            # 
            if ticket and ticket.exists:

                # The additional section on the ticket is built up of (potentially) three parts: header, ticket table, buttons. These
                # are all 'wrapped up' in a 'div' with the 'attachments' id (we'll just pinch this to make look and feel consistent with any
                # future changes!)
                filter = Transformer('//div[@id="ticket"]')
                snippet = tag.div()

                # Are there any child tickets to display?
                childtickets = [ Ticket(self.env,n) for n in self.childtickets.get(ticket.id,[]) ]

                # (tempish) fix for #8612 : force sorting by ticket id
                childtickets = sorted(childtickets, key=lambda t: t.id)

                # Are child tickets allowed?
                childtickets_allowed = self.config.getbool('childtickets', 'parent.%s.allow_child_tickets' % ticket['type'])

                # If there are no childtickets and the ticket should not have any child tickets, we can simply drop out here.
                if not childtickets_allowed and not childtickets:
                    return stream

                # Our 'main' display consists of two divs.
                buttondiv = tag.div()
                tablediv = tag.div()

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:

                    # trac.ini : Which columns to display in child ticket listing?
                    columns = self.config.getlist('childtickets', 'parent.%s.table_headers' % ticket['type'], default=['summary','owner'])

                    tablediv = tag.div(
                                tag.table(
                                    tag.thead(
                                        tag.tr(
                                            tag.th("Ticket",class_="id"),
                                            [ tag.th(s.title(),class_=s) for s in columns ])
                                        ),
                                    tag.tbody([ self._table_row(req,tkt,columns) for tkt in childtickets ]),
                                    class_="listing tickets",
                                    ),
                                tag.br(),
                                )

                # trac.ini : child tickets are allowed - Set up 'create new ticket' buttons.
                if childtickets_allowed:

                    # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                    if 'TICKET_CREATE' in req.perm(ticket.resource):

                        # Always pass these fields
                        default_child_fields = (
                                tag.input(type="hidden", name="parent", value='#'+str(ticket.id)),
                                )

                        #Pass extra fields defined in inherit parameter of parent
                        inherited_child_fields = [
                                tag.input(type="hidden",name="%s"%field,value=ticket[field]) for field in self.config.getlist('childtickets','parent.%s.inherit' % ticket['type'])
                                ]

                        # If child types are restricted then create a set of buttons for the allowed types (This will override 'default_child_type).
                        restrict_child_types = self.config.getlist('childtickets','parent.%s.restrict_child_type' % ticket['type'],default=[])

                        if not restrict_child_types:
                            # trac.ini : Default 'type' of child tickets?
                            default_child_type = self.config.get('childtickets', 'parent.%s.default_child_type' % ticket['type'], default=self.config.get('ticket','default_type'))

                            # ... create a default submit button
                            if ticket['status'] == 'closed':
                                submit_button_fields = (
                                        tag.input(type="submit",disabled="disabled",name="childticket",value="New Child Ticket",title="Create a child ticket"),
                                        tag.input(type="hidden", name="type", value=default_child_type),
                                        )
                            else:
                                submit_button_fields = (
                                        tag.input(type="submit",name="childticket",value="New Child Ticket",title="Create a child ticket"),
                                        tag.input(type="hidden",name="type",value=default_child_type),
                                        )
                        else:
                            if ticket['status'] == 'closed':
                                submit_button_fields = [ tag.input(type="submit",disabled="disabled",name="type",value="%s" % ticket_type,title="Create a %s child ticket" % ticket_type) for ticket_type in restrict_child_types ]
                            else:
                                submit_button_fields = [ tag.input(type="submit",name="type",value="%s" % ticket_type,title="Create a %s child ticket" % ticket_type) for ticket_type in restrict_child_types ]
                        buttondiv = tag.form(
                                    tag.div( default_child_fields, inherited_child_fields, submit_button_fields),
                                    method="get", action=req.href.newticket(),
                                    )

                snippet.append(tag.h2("Child Tickets",class_="foldable"))
                snippet.append(tag.div(tablediv, buttondiv, id="childtickets"))

                return stream | filter.after(snippet)

        return stream
Exemple #28
0
 def filter_stream(self, req, method, filename, stream, data):
     if filename == 'roadmap.html':
         # Insert the new field for entering user names
         filter = Transformer('//form[@id="prefs"]/div[@class="buttons"]')
         return stream | filter.before(self._user_field_input(req))
     return stream
Exemple #29
0
MASTER_BRANCH = u'develop'
MAX_NEW_COMMITS = 10

GIT_BASE_URL = 'http://git.sagemath.org/sage.git/'
GIT_COMMIT_URL = GIT_BASE_URL + 'commit/?id={commit}'
GIT_DIFF_URL = GIT_BASE_URL + 'diff/?id={commit}'
GIT_DIFF_RANGE_URL = GIT_BASE_URL + 'diff/?id={branch}&id2={base}'
GIT_LOG_RANGE_URL = GIT_BASE_URL + 'log/?h={branch}&qt=range&q={base}..{branch}'

GIT_SPECIAL_MERGES = ('GIT_FASTFORWARD', 'GIT_UPTODATE', 'GIT_FAILED_MERGE')
for _merge in GIT_SPECIAL_MERGES:
    globals()[_merge] = _merge

TRAC_SIGNATURE = pygit2.Signature('trac', '*****@*****.**')

FILTER = Transformer('//td[@headers="h_branch"]')
FILTER_TEXT = Transformer('//td[@headers="h_branch"]/text()')


class TicketBranch(Component):
    """
    A Sage specific plugin which formats the ``branch`` field of a ticket and
    applies changes to the ``branch`` field to the git repository.
    """
    implements(ITemplateStreamFilter)
    implements(ITicketManipulator)

    def __init__(self, *args, **kwargs):
        Component.__init__(self, *args, **kwargs)
        self.git_dir = self.config.get("trac", "repository_dir", "")
        if not self.git_dir:
class ReadmeRendererPlugin(Component):
    implements(ITemplateStreamFilter, ITemplateProvider, IHTMLPreviewRenderer)

    # http://tools.ietf.org/html/draft-ietf-appsawg-text-markdown-01
    # http://tools.ietf.org/html/draft-seantek-text-markdown-media-type-00
    #returns_source = True
    def get_quality_ratio(self, mimetype):
        if mimetype in ('text/markdown', 'text/x-markdown',
                        'text/x-web-markdown',
                        'text/vnd.daringfireball.markdown'):
            return 8
        return 0

    def render(self, context, mimetype, content, filename=None, url=None):
        self.log.debug("Using Markdown Mimeviewer")
        req = context.req
        add_stylesheet(req, 'readme/readme.css')
        add_script(req, 'readme/marked.js')
        content = content_to_unicode(self.env, content, mimetype)
        # for some insane reason genshi will only preserve whitespace of <pre> elements, trac calls Stream.render() inappropriately.
        return tag.pre(content.encode('utf-8'))

    def filter_stream(self, req, method, template, stream, data):
        if not (template == 'browser.html' and data.get('dir')):
            if ((not data.get('dir')) and (data.get('path'))
                    and (data.get('path').endswith('.md'))
                ):  # Rendering single markdown file preview
                stream = stream | Transformer(
                    "//head/script[not(@src)][1]"
                ).after(
                    tag.script(Markup(
                        "jQuery(document).ready(function($) {"
                        "  $('#preview').each(function() {"
                        "    $(this).html(marked( $(this).children('pre').first().text() ));"
                        "  });"
                        "});"),
                               type="text/javascript"))
            return stream

        add_stylesheet(req, 'common/css/code.css')

        repos = data.get('repos') or self.env.get_repository()
        rev = req.args.get('rev', None)

        for entry in data['dir'][
                'entries']:  # Rendering all READMEs in a directory preview
            try:
                if not entry.isdir and entry.name.lower().startswith('readme'):
                    node = repos.get_node(entry.path, rev)
                    req.perm(data['context'].resource).require('FILE_VIEW')
                    mimeview = Mimeview(self.env)
                    content = node.get_content()
                    mimetype = node.content_type
                    divclass = 'searchable'
                    if entry.name.lower().endswith('.wiki'):
                        mimetype = 'text/x-trac-wiki'
                        divclass = 'searchable wiki'
                    elif entry.name.lower().endswith('.md'):
                        mimetype = 'text/x-markdown'
                        divclass = 'searchable markdown'
                    if not mimetype or mimetype == 'application/octet-stream':
                        mimetype = mimeview.get_mimetype(
                            node.name,
                            content.read(4096)) or mimetype or 'text/plain'
                    del content
                    self.log.debug(
                        "ReadmeRenderer: rendering node %s@%s as %s" %
                        (node.name, str(rev), mimetype))
                    output = mimeview.preview_data(data['context'],
                                                   node.get_content(),
                                                   node.get_content_length(),
                                                   mimetype,
                                                   node.created_path,
                                                   '',
                                                   annotations=[],
                                                   force_source=False)

                    if output:
                        if isinstance(output['rendered'], Stream):
                            #content = output['rendered'].select('./pre/node()')
                            #content = output['rendered'].select('./pre')
                            content = output['rendered'].select('.')
                        else:
                            self.log.debug("GOT THERE")
                            content = output['rendered']
                        insert = tag.div(
                            tag.h1(entry.name,
                                   tag.a(Markup(' &para;'),
                                         class_="anchor",
                                         href='#' + entry.name,
                                         title='Link to file'),
                                   id_=entry.name),
                            tag.div(
                                content,
                                #xml:space = "preserve",
                                class_=divclass,
                                title=entry.name),
                            class_="readme",
                            style="padding-top: 1em;")
                        stream = stream | Transformer(
                            "//div[@id='content']/div[@id='help']").before(
                                insert)
            except Exception, e:
                self.log.debug(to_unicode(e))
        stream = stream | Transformer("//head/script[not(@src)][1]").after(
            tag.script(Markup(
                "jQuery(document).ready(function($) {"
                "  $('.markdown').each(function() {"
                "    $(this).html(marked( $(this).children('pre').first().html() ));"
                "  });"
                "});"),
                       type="text/javascript"))
        return stream