예제 #1
0
def render_cloud(env, req, cloud, renderer=None):
    """Render a tag cloud

    :cloud: Dictionary of {object: count} representing the cloud.
    :param renderer: A callable with signature (tag, count, percent) used to
                     render the cloud objects.
    """
    min_px = 10.0
    max_px = 30.0
    scale = 1.0

    if renderer is None:
        def default_renderer(tag, count, percent):
            href = get_resource_url(env, Resource('tag', tag), req.href)
            return builder.a(tag, rel='tag', title='%i' % count, href=href,
                             style='font-size: %ipx' %
                                   int(min_px + percent * (max_px - min_px)))
        renderer = default_renderer

    # A LUT from count to n/len(cloud)
    size_lut = dict([(c, float(i)) for i, c in
                     enumerate(sorted(set([r for r in cloud.values()])))])
    if size_lut:
        scale = 1.0 / len(size_lut)

    ul = builder.ul(class_='tagcloud')
    last = len(cloud) - 1
    for i, (tag, count) in enumerate(sorted(cloud.iteritems())):
        percent = size_lut[count] * scale
        li = builder.li(renderer(tag, count, percent))
        if i == last:
            li(class_='last')
        li()
        ul(li)
    return ul
예제 #2
0
 def get_months_authors_categories(self, from_dt=None, to_dt=None,
                                             user=None, perm=None):
     """ Returns a structure of post metadata:
         ([ ((year1, month1), count), ((year1, month2), count) ], # newest first
          [ (author1, count), (author2, count) ],                 # alphabetical
          [ (category1, count), (category2, count) ],             # alphabetical
          total)                                                  # num of posts
     * Use 'from_dt' and 'to_dt' (datetime objects) to restrict search to
     posts with a publish_time within the intervals (None means ignore).
     * If user and perm is provided, the list is also filtered for permissions.
     * Note also that it only fetches from most recent version. """
     blog_posts = get_blog_posts(self.env, from_dt=from_dt, to_dt=to_dt)
     a_dict = {}
     c_dict = {}
     m_dict = {}
     total = 0
     for post in blog_posts:
         if user and perm:
             # Check permissions
             bp = BlogPost(self.env, post[0], post[1])
             if not 'BLOG_VIEW' in perm(bp.resource):
                 continue # Skip this post
         post_time = post[2]
         m_dict[(post_time.year, post_time.month)] = m_dict.get(
                 (post_time.year, post_time.month), 0) + 1
         author = post[3]
         a_dict[author] = a_dict.get(author, 0) + 1
         categories = post[6] # a list
         for category in set(categories):
             c_dict[category] = c_dict.get(category, 0) + 1
         total += 1
     return ([(m, m_dict.get(m, 0)) for m in sorted(m_dict.keys(), reverse=True)],
             [(a, a_dict.get(a, 0)) for a in sorted(a_dict.keys())],
             [(c, c_dict.get(c, 0)) for c in sorted(c_dict.keys())],
             total)
예제 #3
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            # In case of an invalid ticket, the data is invalid
            if not data:
                return template, data, content_type
            tkt = data['ticket']
            links = TicketLinks(self.env, tkt)

            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    add_script(req, 'mastertickets/disable_resolve.js')
                    break

            # Add link to depgraph if needed
            if links:
                add_ctxtnav(req, 'Depgraph',
                            req.href.depgraph('ticket', tkt.id))

            for change in data.get('changes', {}):
                if not change.has_key('fields'):
                    continue
                for field, field_data in change['fields'].iteritems():
                    if field in self.fields:
                        if field_data['new'].strip():
                            new = set(
                                [int(n) for n in field_data['new'].split(',')])
                        else:
                            new = set()
                        if field_data['old'].strip():
                            old = set(
                                [int(n) for n in field_data['old'].split(',')])
                        else:
                            old = set()
                        add = new - old
                        sub = old - new
                        elms = tag()
                        if add:
                            elms.append(
                                tag.em(u', '.join(
                                    [unicode(n) for n in sorted(add)])))
                            elms.append(u' added')
                        if add and sub:
                            elms.append(u'; ')
                        if sub:
                            elms.append(
                                tag.em(u', '.join(
                                    [unicode(n) for n in sorted(sub)])))
                            elms.append(u' removed')
                        field_data['rendered'] = elms

        #add a link to generate a dependency graph for all the tickets in the milestone
        if req.path_info.startswith('/milestone/'):
            if not data:
                return template, data, content_type
            milestone = data['milestone']
            add_ctxtnav(req, 'Depgraph',
                        req.href.depgraph('milestone', milestone.name))

        return template, data, content_type
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            # In case of an invalid ticket, the data is invalid
            if not data:
                return template, data, content_type
            tkt = data['ticket']
            links = TicketLinks(self.env, tkt)
            
            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    add_script(req, 'mastertickets/disable_resolve.js')
                    break

            # Add link to depgraph if needed
            if links:
                add_ctxtnav(req, 'Depgraph', req.href.depgraph(tkt.id))
            
            for change in data.get('changes', {}):
                if not change.has_key('fields'):
                    continue
                for field, field_data in change['fields'].iteritems():
                    if field in self.fields:
                        if field_data['new'].strip():
                            new = set([int(n) for n in field_data['new'].split(',')])
                        else:
                            new = set()
                        if field_data['old'].strip():
                            old = set([int(n) for n in field_data['old'].split(',')])
                        else:
                            old = set()
                        add = new - old
                        sub = old - new
                        elms = tag()
                        if add:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(add)]))
                            )
                            elms.append(u' added')
                        if add and sub:
                            elms.append(u'; ')
                        if sub:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(sub)]))
                            )
                            elms.append(u' removed')
                        field_data['rendered'] = elms
            
        #add a link to generate a dependency graph for all the tickets in the milestone
        if req.path_info.startswith('/milestone/'):
            if not data:
                return template, data, content_type
            milestone=data['milestone']
            add_ctxtnav(req, 'Depgraph', req.href.depgraph('milestone', milestone.name))


        return template, data, content_type
예제 #5
0
    def render_admin_panel(self, req, cat, page, path_info):
        assert req.perm.has_permission('TRAC_ADMIN')

        excludes_match = self._patterns_match(self.excludes)
        if page not in self._get_sections_set(excludes_match):
            raise TracError("Invalid section %s" % page)

        options = sorted(
            [option for (section, name), option
                    in Option.registry.iteritems()
                    if section == page and \
                       not excludes_match('%s:%s' % (section, name))],
            key=lambda opt: opt.name)

        # Apply changes
        if req.method == 'POST':
            modified = False
            for name, value in req.args.iteritems():
                if any(name == opt.name for opt in options):
                    if self.config.get(page, name) != value:
                        self.config.set(page, name, value)
                        modified = True
            if modified:
                self.log.debug("Updating trac.ini")
                self.config.save()
            req.redirect(req.href.admin(cat, page))

        add_stylesheet(req, 'iniadmin/css/iniadmin.css')

        password_match = self._patterns_match(self.passwords)
        options_data = []
        for option in options:
            doc = self._get_doc(option)
            value = self.config.get(page, option.name)
            # We assume the classes all end in "Option"
            type = option.__class__.__name__.lower()[:-6] or 'text'
            if type == 'list' and not isinstance(value, basestring):
                value = unicode(option.sep).join(list(value))
            option_data = {
                'name': option.name,
                'default': option.default,
                'doc': doc,
                'value': value,
                'type': type
            }
            if type == 'extension':
                option_data['options'] = sorted(
                    impl.__class__.__name__
                    for impl in option.xtnpt.extensions(self))
            elif type == 'text' and \
                 password_match('%s:%s' % (option.section, option.name)):
                option_data['type'] = 'password'
            options_data.append(option_data)

        data = {'iniadmin': {'section': page, 'options': options_data}}
        return 'iniadmin.html', data
예제 #6
0
    def render_cloud(self, req, cloud, renderer=None, caseless_sort=False,
                     mincount=None):
        """Render a tag cloud.

        :cloud: Dictionary of {object: count} representing the cloud.
        :param renderer: A callable with signature (tag, count, percent)
                         used to render the cloud objects.
        :param caseless_sort: Boolean, whether tag cloud should be sorted
                              case-sensitive.
        :param mincount: Integer threshold to hide tags with smaller count.
        """
        min_px = 10.0
        max_px = 30.0
        scale = 1.0

        if renderer is None:
            def default_renderer(tag, count, percent):
                href = self.get_href(req, tag=Resource('tag', tag))
                return builder.a(tag, rel='tag', title='%i' % count,
                                 href=href, style='font-size: %ipx'
                                 % int(min_px + percent * (max_px - min_px)))
            renderer = default_renderer

        # A LUT from count to n/len(cloud)
        size_lut = dict([(c, float(i)) for i, c in
                         enumerate(sorted(set([r for r in cloud.values()])))])
        if size_lut:
            scale = 1.0 / len(size_lut)

        if caseless_sort:
            # Preserve upper-case precedence within similar tags.
            items = reversed(sorted(cloud.iteritems(),
                                    key=lambda t: t[0].lower(), reverse=True))
        else:
            items = sorted(cloud.iteritems())
        ul = li = None
        for i, (tag, count) in enumerate(items):
            percent = size_lut[count] * scale
            if mincount and count < as_int(mincount, 1):
                # Tag count is too low.
                continue
            if ul:
                # Found new tag for cloud; now add previously prepared one. 
                ul('\n', li)
            else:
                # Found first tag for cloud; now create the list.
                ul = builder.ul(class_='tagcloud')
            # Prepare current tag entry.
            li = builder.li(renderer(tag, count, percent))
        if li:
            # All tags checked; mark latest tag as last one (no tailing colon).
            li(class_='last')
            ul('\n', li, '\n')
        return ul and ul or _("No tags found")
예제 #7
0
    def render_cloud(self, req, cloud, renderer=None, caseless_sort=False,
                     mincount=None, realms=()):
        """Render a tag cloud.

        :cloud: Dictionary of {object: count} representing the cloud.
        :param renderer: A callable with signature (tag, count, percent)
                         used to render the cloud objects.
        :param caseless_sort: Boolean, whether tag cloud should be sorted
                              case-sensitive.
        :param mincount: Integer threshold to hide tags with smaller count.
        """
        min_px = 10.0
        max_px = 30.0
        scale = 1.0

        if renderer is None:
            def default_renderer(tag, count, percent):
                href = self.get_href(req, realms, tag=Resource('tag', tag))
                return builder.a(tag, rel='tag', title='%i' % count,
                                 href=href, style='font-size: %ipx'
                                 % int(min_px + percent * (max_px - min_px)))
            renderer = default_renderer

        # A LUT from count to n/len(cloud)
        size_lut = dict([(c, float(i)) for i, c in
                         enumerate(sorted(set([r for r in cloud.values()])))])
        if size_lut:
            scale = 1.0 / len(size_lut)

        if caseless_sort:
            # Preserve upper-case precedence within similar tags.
            items = reversed(sorted(cloud.iteritems(),
                                    key=lambda t: t[0].lower(), reverse=True))
        else:
            items = sorted(cloud.iteritems())
        ul = li = None
        for i, (tag, count) in enumerate(items):
            percent = size_lut[count] * scale
            if mincount and count < as_int(mincount, 1):
                # Tag count is too low.
                continue
            if ul:
                # Found new tag for cloud; now add previously prepared one. 
                ul('\n', li)
            else:
                # Found first tag for cloud; now create the list.
                ul = builder.ul(class_='tagcloud')
            # Prepare current tag entry.
            li = builder.li(renderer(tag, count, percent))
        if li:
            # All tags checked; mark latest tag as last one (no tailing colon).
            li(class_='last')
            ul('\n', li, '\n')
        return ul and ul or _("No tags found")
예제 #8
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            tkt = data['ticket']
            links = TicketLinks(self.env, tkt)

            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    add_script(req, 'mastertickets/disable_resolve.js')
                    break

            data['mastertickets'] = {
                'field_values': {
                    'blocking': linkify_ids(self.env, req, links.blocking),
                    'blockedby': linkify_ids(self.env, req, links.blocked_by),
                },
            }

            # Add link to depgraph if needed
            if links:
                add_ctxtnav(req, 'Depgraph', req.href.depgraph(tkt.id))

            for change in data.get('changes', []):
                for field, field_data in change['fields'].iteritems():
                    if field in self.fields:
                        if field_data['new'].strip():
                            new = set(
                                [int(n) for n in field_data['new'].split(',')])
                        else:
                            new = set()
                        if field_data['old'].strip():
                            old = set(
                                [int(n) for n in field_data['old'].split(',')])
                        else:
                            old = set()
                        add = new - old
                        sub = old - new
                        elms = tag()
                        if add:
                            elms.append(
                                tag.em(u', '.join(
                                    [unicode(n) for n in sorted(add)])))
                            elms.append(u' added')
                        if add and sub:
                            elms.append(u'; ')
                        if sub:
                            elms.append(
                                tag.em(u', '.join(
                                    [unicode(n) for n in sorted(sub)])))
                            elms.append(u' removed')
                        field_data['rendered'] = elms

        return template, data, content_type
예제 #9
0
    def get_months_authors_categories(self, from_dt=None, to_dt=None,
                                                user=None, perm=None):
        """ Returns a structure of post metadata:
            ([ ((year1, month1), count), ((year1, month2), count) ], # newest first
             [ (author1, count), (author2, count) ],                 # alphabetical
             [ (category1, count), (category2, count) ],             # alphabetical
             total)                                                  # num of posts
        * Use 'from_dt' and 'to_dt' (datetime objects) to restrict search to
        posts with a publish_time within the intervals (None means ignore).
        * If user and perm is provided, the list is also filtered for permissions.
        * Note also that it only fetches from most recent version. """
#        cache_months_authors_categories= self.env.project_name + "_months_authors_categories"
        cache_months_authors_categories = self.env.project_name + '_blog_posts_months'
#        if  user:
#            cache_months_authors_categories += "_user_" + user
        if  from_dt:   
            s_from_dt = str(from_dt)
            cache_months_authors_categories += s_from_dt.replace(" ", "").replace(":", "").replace("-", "").replace("+", "")
        if  to_dt:        
             s_to_dt= str(to_dt)
             cache_months_authors_categories += s_to_dt.replace(" ", "").replace(":", "").replace("-", "").replace("+", "")       
            
        if cache.c(cache_months_authors_categories):
            self.env.log.debug("%r  found Cache ,return Cache...318......." % cache_months_authors_categories)       
            return cache.c(cache_months_authors_categories)
        else:
            self.env.log.debug("%r not found. Cacheing.. 322." % cache_months_authors_categories)
            
            blog_posts = get_all_blog_posts(self.env, from_dt=from_dt, to_dt=to_dt)
            a_dict = {}
            c_dict = {}
            m_dict = {}
            total = 0
            for post in blog_posts:
                if user and perm:
                    # Check permissions
                    bp = BlogPost(self.env, post[0], post[1])
                    if not 'BLOG_VIEW' in perm(bp.resource):
                        continue # Skip this post
                post_time = post[2]
                m_dict[(post_time.year, post_time.month)] = m_dict.get(
                        (post_time.year, post_time.month), 0) + 1
                author = post[3]
                a_dict[author] = a_dict.get(author, 0) + 1
                categories = post[6] # a list
                for category in set(categories):
                    c_dict[category] = c_dict.get(category, 0) + 1
                total += 1
            return cache.c(cache_months_authors_categories,([(m, m_dict.get(m, 0)) for m in sorted(m_dict.keys(), reverse=True)],
                    [(a, a_dict.get(a, 0)) for a in sorted(a_dict.keys())],
                    [(c, c_dict.get(c, 0)) for c in sorted(c_dict.keys())],
                    total))
예제 #10
0
    def post_process_request(self,
                             req,
                             template,
                             data,
                             content_type,
                             method=None):
        if req.path_info.startswith('/ticket/'):
            # In case of an invalid ticket, the data is invalid
            if not data:
                return template, data, content_type, method
            tkt = data['ticket']
            with self.env.db_query as db:
                links = CrashDumpTicketLinks(self.env, tkt, db=db)

                for change in data.get('changes', {}):
                    if not change.has_key('fields'):
                        continue
                    for field, field_data in change['fields'].iteritems():
                        if field in self.crashdump_link_fields:
                            if field_data['new'].strip():
                                new = set([
                                    CrashDumpSystem.get_crash_id(n)
                                    for n in field_data['new'].split(',')
                                ])
                            else:
                                new = set()
                            if field_data['old'].strip():
                                old = set([
                                    CrashDumpSystem.get_crash_id(n)
                                    for n in field_data['old'].split(',')
                                ])
                            else:
                                old = set()
                            add = new - old
                            sub = old - new
                            elms = tag()
                            if add:
                                elms.append(
                                    tag.em(u', '.join(
                                        [unicode(n) for n in sorted(add)])))
                                elms.append(u' added')
                            if add and sub:
                                elms.append(u'; ')
                            if sub:
                                elms.append(
                                    tag.em(u', '.join(
                                        [unicode(n) for n in sorted(sub)])))
                                elms.append(u' removed')
                            field_data['rendered'] = elms
                            links.crashes = new

        return template, data, content_type, method
예제 #11
0
    def render_admin_panel(self, req, cat, page, path_info):
        assert req.perm.has_permission('TRAC_ADMIN')

        excludes_match = self._patterns_match(self.excludes)
        if page not in self._get_sections_set(excludes_match):
            raise TracError("Invalid section %s" % page)

        options = sorted(
            [option for (section, name), option
                    in Option.registry.iteritems()
                    if section == page and \
                       not excludes_match('%s:%s' % (section, name))],
            key=lambda opt: opt.name)

        # Apply changes
        if req.method == 'POST':
            modified = False
            for name, value in req.args.iteritems():
                if any(name == opt.name for opt in options):
                    if self.config.get(page, name) != value:
                        self.config.set(page, name, value)
                        modified = True
            if modified:
                self.log.debug("Updating trac.ini")
                self.config.save()
            req.redirect(req.href.admin(cat, page))

        add_stylesheet(req, 'iniadmin/css/iniadmin.css')

        password_match = self._patterns_match(self.passwords)
        options_data = []
        for option in options:
            doc = self._get_doc(option)
            value = self.config.get(page, option.name)
            # We assume the classes all end in "Option"
            type = option.__class__.__name__.lower()[:-6] or 'text'
            if type == 'list' and not isinstance(value,basestring):
                value = unicode(option.sep).join(list(value))
            option_data = {'name': option.name, 'default': option.default,
                           'doc': doc, 'value': value, 'type': type}
            if type == 'extension':
                option_data['options'] = sorted(
                    impl.__class__.__name__
                    for impl in option.xtnpt.extensions(self))
            elif type == 'text' and \
                 password_match('%s:%s' % (option.section, option.name)):
                option_data['type'] = 'password'
            options_data.append(option_data)

        data = {'iniadmin': {'section': page, 'options': options_data}}
        return 'iniadmin.html', data
예제 #12
0
    def post_process_request(self, req, template, origData, content_type):
        if req.path_info.startswith('/newticket'):
            mode = 'new'
        elif req.path_info.startswith('/ticket/'):
            mode = 'view'
        else:
            return template, origData, content_type
        fieldData = {}
        fieldData['condfields'] = {}

        all_fields = []
        standard_fields = set()
        for f in TicketSystem(self.env).get_ticket_fields():
            all_fields.append(f['name'])
            if not f.get('custom'):
                standard_fields.add(f['name'])

        if 'owner' in all_fields:
            curr_idx = all_fields.index('owner')
            if 'cc' in all_fields:
                insert_idx = all_fields.index('cc')
            else:
                insert_idx = len(all_fields)
            if curr_idx < insert_idx:
                all_fields.insert(insert_idx, all_fields[curr_idx])
                del all_fields[curr_idx]

        for t in self.types:
            fieldData['condfields'][t] = self.get_fields(t, all_fields, standard_fields)
            # fields = set(getattr(self, t+'_fields'))
            # if self.include_std:
            #     fields.update(standard_fields)
            # fields.update(self.forced_fields)
            # fieldData['condfields'][t] = dict([
            #     (f, f in fields) for f in all_fields
            # ])

        self.log.debug(all_fields)
        self.log.info(standard_fields)

        fieldData['mode'] = mode
        fieldData['all_fields'] = list(all_fields)
        fieldData['ok_view_fields'] = sorted(set(all_fields) - self.forced_fields,
                                             key=lambda x: all_fields.index(x))
        fieldData['ok_new_fields'] = sorted((set(all_fields) - self.forced_fields) - set(['owner']),
                                            key=lambda x: all_fields.index(x))

        add_script_data(req, fieldData)
        add_script(req, '/condfields.js')
        return template, origData, content_type
예제 #13
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            tkt = data['ticket']
            links = TicketLinks(self.env, tkt)
            
            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    add_script(req, 'mastertickets/disable_resolve.js')
                    break

            data['mastertickets'] = {
                'field_values': {
                    'blocking': linkify_ids(self.env, req, links.blocking),
                    'blockedby': linkify_ids(self.env, req, links.blocked_by),
                },
            }
            
            # Add link to depgraph if needed
            if links:
                add_ctxtnav(req, 'Depgraph', req.href.depgraph(tkt.id))
            
            for change in data.get('changes', []):
                for field, field_data in change['fields'].iteritems():
                    if field in self.fields:
                        if field_data['new'].strip():
                            new = set([int(n) for n in field_data['new'].split(',')])
                        else:
                            new = set()
                        if field_data['old'].strip():
                            old = set([int(n) for n in field_data['old'].split(',')])
                        else:
                            old = set()
                        add = new - old
                        sub = old - new
                        elms = tag()
                        if add:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(add)]))
                            )
                            elms.append(u' added')
                        if add and sub:
                            elms.append(u'; ')
                        if sub:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(sub)]))
                            )
                            elms.append(u' removed')
                        field_data['rendered'] = elms
            
        return template, data, content_type
예제 #14
0
    def render_admin_panel(self, req, cat, page, version):
        req.perm.require('TAGS_ADMIN')
        data = {}
        tag_system = TagSystem(self.env)
        if req.method == 'POST':
            # Replace Tag
            allow_delete = req.args.get('allow_delete')
            new_tag = req.args.get('tag_new_name').strip()
            new_tag = not new_tag == u'' and new_tag or None
            if not (allow_delete or new_tag):
                data['error'] = _("""Selected current tag(s) and either
                                  new tag or delete approval are required""")
            else:
                comment = req.args.get('comment', u'')
                old_tags = req.args.get('tag_name')
                if old_tags:
                    # Provide list regardless of single or multiple selection.
                    old_tags = isinstance(old_tags, list) and old_tags or \
                               [old_tags]
                    tag_system.replace_tag(req, old_tags, new_tag, comment,
                                           allow_delete)
                data['selected'] = new_tag

        all_tags = sorted(tag_system.get_all_tags(req, '-dummy'))
        data['tags'] = all_tags
        try:
            Chrome(self.env).add_textarea_grips(req)
        except AttributeError:
            # Element modifiers unavailable before Trac 0.12, skip gracefully.
            pass
        return 'admin_tag_change.html', data
예제 #15
0
    def _page_tags(self, req):
        pagename = req.args.get('page', 'WikiStart')

        tag_system = TagSystem(self.env)
        resource = Resource('wiki', pagename)
        tags = sorted(tag_system.get_tags(req, resource))
        return tags
예제 #16
0
 def post_process_request(self, req, template, data, content_type):
     if req.method == 'GET' and req.path_info.startswith('/wiki/') and \
             req.args.get('action') == 'edit' and \
             req.args.get('template') and 'tags' not in req.args:
         # Retrieve template resource to be queried for tags.
         template_page = WikiPage(
             self.env, ''.join([
                 WikiModule.PAGE_TEMPLATES_PREFIX,
                 req.args.get('template')
             ]))
         if template_page and template_page.exists and \
                 'TAGS_VIEW' in req.perm(template_page.resource):
             ts = TagSystem(self.env)
             tags = sorted(ts.get_tags(req, template_page.resource))
             # Prepare tags as content for the editor field.
             tags_str = ' '.join(tags)
             self.env.log.debug("Tags retrieved from template: '%s'" \
                                % unicode(tags_str).encode('utf-8'))
             # DEVEL: More arguments need to be propagated here?
             req.redirect(
                 req.href(req.path_info,
                          action='edit',
                          tags=tags_str,
                          template=req.args.get('template')))
     return (template, data, content_type)
예제 #17
0
    def _build_graph(self, req, tkt_id):
        links = TicketLinks(self.env, tkt_id)

        g = graphviz.Graph()

        node_default = g['node']
        node_default['style'] = 'filled'

        edge_default = g['edge']
        edge_default['style'] = ''

        # Force this to the top of the graph
        g[tkt_id]

        links = sorted(links.walk(), key=lambda link: link.tkt.id)
        for link in links:
            tkt = link.tkt
            node = g[tkt.id]
            node['label'] = u'#%s' % tkt.id
            node['fillcolor'] = tkt['status'] == 'closed' and 'green' or 'red'
            node['URL'] = req.href.ticket(tkt.id)
            node['alt'] = u'Ticket #%s' % tkt.id
            node['tooltip'] = tkt['summary']

            for n in link.blocking:
                node > g[n]

        return g
예제 #18
0
    def _build_graph(self, req, tkt_ids, label_summary=0):
        g = graphviz.Graph()
        g.label_summary = label_summary

        g.attributes['rankdir'] = self.graph_direction

        node_default = g['node']
        node_default['style'] = 'filled'

        edge_default = g['edge']
        edge_default['style'] = ''

        # Force this to the top of the graph
        for id in tkt_ids:
            g[id]

        links = TicketLinks.walk_tickets(self.env, tkt_ids)
        links = sorted(links, key=lambda link: link.tkt.id)
        for link in links:
            tkt = link.tkt
            node = g[tkt.id]
            if label_summary:
                node['label'] = u'#%s %s' % (tkt.id, tkt['summary'])
            else:
                node['label'] = u'#%s' % tkt.id
            node['fillcolor'] = tkt[
                'status'] == 'closed' and self.closed_color or self.opened_color
            node['URL'] = req.href.ticket(tkt.id)
            node['alt'] = u'Ticket #%s' % tkt.id
            node['tooltip'] = tkt['summary']

            for n in link.blocking:
                node > g[n]

        return g
예제 #19
0
def render_table(items, colspec, render_item, colspace=1):
    try:
        columns = max(int(colspec), 1)
    except Exception:
        columns = 3

    nbsp = Markup('&nbsp;')
    # hdr = [tag.th(nbsp, 'Display'), tag.th('Markup', nbsp)]
    spacer_style = 'width:%dem;border:none' % colspace
    # Find max width to make value cols equally wide
    width = 0
    for i in items:
        if (isinstance(i, str) or isinstance(i, unicode)) and len(i) > width:
            width = len(i)
    value_style = 'border:none'
    #noinspection PyUnusedLocal
    value_style += ';width:%dem' % (width*2/3) if width else '' # empirical...

    def render_def(s):
        rendered = s and render_item(s) or None
        if isinstance(s, str):
            s = Markup(s.replace('&', '&amp;'))
        return [tag.td(rendered, nbsp, style='border:none'),
                tag.td(tag.kbd(s), style=value_style)]
    
    return tag.table(#tag.tr((hdr + [tag.td(style=spacer_style)]) *
                     #       (columns-1) + hdr),
                     [tag.tr([render_def(s) + [tag.td(style=spacer_style)]
                              for s in row[:-1]] + render_def(row[-1]))
                      for row in group_over(sorted(items), columns)],
                     class_='wiki', style='border:none')
예제 #20
0
def prepare_to_cumulate(sorted_events):
    dhist = {}
    for date, date_events in groupby(sorted_events, lambda (t, events): to_datetime(t).date()):
        evset = {'Enter': set(), 'Leave': set(), 'Finish': set()}
        dhist[date] = evset
        date_events_list = list(date_events)
        for (t, events) in date_events_list:
            for k, ids in events.iteritems():
                evset[k] |= ids
        # resolve Enter / Leave conflicts
        enter_leave_ids = evset['Enter'] & evset['Leave']
        if enter_leave_ids:
            evs = {'Enter': None, 'Leave': None}
            last = {'Enter': None, 'Leave': None}
            for k in ('Enter', 'Leave'):
                evs[k] = sorted([(t, evs['Enter']) for (t, evs) in date_events_list],
                                key=lambda (t, ids): t)
            for id in enter_leave_ids:
                for k in ('Enter', 'Leave'):
                    last[k] = 0
                    for t, ids in reversed(evs[k]):
                        if id in ids:
                            last[k] = t
                            break
                to_del = (last['Enter'] > last['Leave']) and 'Leave' or 'Enter'
                evset[to_del].remove(id)
예제 #21
0
    def _page_tags(self, req):
        pagename = req.args.get('page', 'WikiStart')

        tag_system = TagSystem(self.env)
        resource = Resource('wiki', pagename)
        tags = sorted(tag_system.get_tags(req, resource))
        return tags
예제 #22
0
def render_table(items, colspec, render_item, colspace=1):
    try:
        columns = max(int(colspec), 1)
    except Exception:
        columns = 3

    nbsp = Markup('&nbsp;')
    # hdr = [tag.th(nbsp, 'Display'), tag.th('Markup', nbsp)]
    spacer_style = 'width:%dem;border:none' % colspace
    # Find max width to make value cols equally wide
    width = 0
    for i in items:
        if (isinstance(i, str) or isinstance(i, unicode)) and len(i) > width:
            width = len(i)
    value_style = 'border:none'
    #noinspection PyUnusedLocal
    if width:
        # empirical...
        value_style = '%s;width:%dem' % (value_style, width*2/3)

    def render_def(s):
        rendered = s and render_item(s) or None
        if isinstance(s, str):
            s = Markup(s.replace('&', '&amp;'))
        return [tag.td(rendered, nbsp, style='border:none'),
                tag.td(tag.kbd(s), style=value_style)]
    
    return tag.table(#tag.tr((hdr + [tag.td(style=spacer_style)]) *
                     #       (columns-1) + hdr),
                     [tag.tr([render_def(s) + [tag.td(style=spacer_style)]
                              for s in row[:-1]] + render_def(row[-1]))
                      for row in group_over(sorted(items), columns)],
                     class_='wiki', style='border:none')
예제 #23
0
def to_ranges(revs):
    """Converts a list of revisions to a minimal set of ranges.

    >>> to_ranges([2, 12, 3, 6, 9, 1, 5, 11])
    '1-3,5-6,9,11-12'
    >>> to_ranges([])
    ''
    """
    ranges = []
    begin = end = None

    def store():
        if end == begin:
            ranges.append(str(begin))
        else:
            ranges.append('%d-%d' % (begin, end))

    for rev in sorted(revs):
        if begin is None:
            begin = end = rev
        elif rev == end + 1:
            end = rev
        else:
            store()
            begin = end = rev
    if begin is not None:
        store()
    return ','.join(ranges)
예제 #24
0
def to_ranges(revs):
    """Converts a list of revisions to a minimal set of ranges.
    
    >>> to_ranges([2, 12, 3, 6, 9, 1, 5, 11])
    '1-3,5-6,9,11-12'
    >>> to_ranges([])
    ''
    """
    ranges = []
    begin = end = None
    def store():
        if end == begin:
            ranges.append(str(begin))
        else:
            ranges.append('%d-%d' % (begin, end))
    for rev in sorted(revs):
        if begin is None:
            begin = end = rev
        elif rev == end + 1:
            end = rev
        else:
            store()
            begin = end = rev
    if begin is not None:
        store()
    return ','.join(ranges)
    def _build_graph(self, req, tkt_ids, label_summary=0):
        g = graphviz.Graph()
        g.label_summary = label_summary

        g.attributes['rankdir'] = self.graph_direction
        
        node_default = g['node']
        node_default['style'] = 'filled'
        
        edge_default = g['edge']
        edge_default['style'] = ''
        
        # Force this to the top of the graph
        for id in tkt_ids:
            g[id] 
        
        links = TicketLinks.walk_tickets(self.env, tkt_ids)
        links = sorted(links, key=lambda link: link.tkt.id)
        for link in links:
            tkt = link.tkt
            node = g[tkt.id]
            if label_summary:
                node['label'] = u'#%s %s' % (tkt.id, tkt['summary'])
            else:
                node['label'] = u'#%s'%tkt.id
            node['fillcolor'] = tkt['status'] == 'closed' and self.closed_color or self.opened_color
            node['URL'] = req.href.ticket(tkt.id)
            node['alt'] = u'Ticket #%s'%tkt.id
            node['tooltip'] = tkt['summary']
            
            for n in link.blocking:
                node > g[n]
        
        return g
예제 #26
0
파일: admin.py 프로젝트: nyuhuhuu/trachacks
    def render_admin_panel(self, req, cat, page, version):
        req.perm.require("TAGS_ADMIN")
        data = {}
        tag_system = TagSystem(self.env)
        if req.method == "POST":
            # Replace Tag
            allow_delete = req.args.get("allow_delete")
            new_tag = req.args.get("tag_new_name").strip()
            new_tag = not new_tag == u"" and new_tag or None
            if not (allow_delete or new_tag):
                data["error"] = _(
                    """Selected current tag(s) and either
                                  new tag or delete approval are required"""
                )
            else:
                comment = req.args.get("comment", u"")
                old_tags = req.args.get("tag_name")
                if old_tags:
                    # Provide list regardless of single or multiple selection.
                    old_tags = isinstance(old_tags, list) and old_tags or [old_tags]
                    tag_system.replace_tag(req, old_tags, new_tag, comment, allow_delete)
                data["selected"] = new_tag

        all_tags = sorted(tag_system.get_all_tags(req, "-dummy"))
        data["tags"] = all_tags
        try:
            Chrome(self.env).add_textarea_grips(req)
        except AttributeError:
            # Element modifiers unavailable before Trac 0.12, skip gracefully.
            pass
        return "admin_tag_change.html", data
예제 #27
0
 def test_attachments(self):
     # Note: Quite similar to the tracrpc.tests.json.JsonTestCase.test_binary
     image_url = os.path.join(rpc_testenv.trac_src, 'trac', 'htdocs',
                              'feed.png')
     image_in = StringIO(open(image_url, 'r').read())
     # Create attachment
     self.admin.wiki.putAttachmentEx('TitleIndex', 'feed2.png',
                                     'test image',
                                     xmlrpclib.Binary(image_in.getvalue()))
     self.assertEquals(
         image_in.getvalue(),
         self.admin.wiki.getAttachment('TitleIndex/feed2.png').data)
     # Update attachment (adding new)
     self.admin.wiki.putAttachmentEx('TitleIndex', 'feed2.png',
                                     'test image',
                                     xmlrpclib.Binary(image_in.getvalue()),
                                     False)
     self.assertEquals(
         image_in.getvalue(),
         self.admin.wiki.getAttachment('TitleIndex/feed2.2.png').data)
     # List attachments
     self.assertEquals(['TitleIndex/feed2.2.png', 'TitleIndex/feed2.png'],
                       sorted(
                           self.admin.wiki.listAttachments('TitleIndex')))
     # Delete both attachments
     self.admin.wiki.deleteAttachment('TitleIndex/feed2.png')
     self.admin.wiki.deleteAttachment('TitleIndex/feed2.2.png')
     # List attachments again
     self.assertEquals([], self.admin.wiki.listAttachments('TitleIndex'))
예제 #28
0
 def get_all_status(self):
     """Returns a sorted list of all the states all of the action
     controllers know about."""
     valid_states = set()
     for controller in self.action_controllers:
         valid_states.update(controller.get_all_status())
     return sorted(valid_states)
예제 #29
0
 def _build_graph(self, req, tkt_id):
     links = TicketLinks(self.env, tkt_id)
     
     g = graphviz.Graph()
     
     node_default = g['node']
     node_default['style'] = 'filled'
     
     edge_default = g['edge']
     edge_default['style'] = ''
     
     # Force this to the top of the graph
     g[tkt_id] 
     
     links = sorted(links.walk(), key=lambda link: link.tkt.id)
     for link in links:
         tkt = link.tkt
         node = g[tkt.id]
         node['label'] = u'#%s'%tkt.id
         node['fillcolor'] = tkt['status'] == 'closed' and 'green' or 'red'
         node['URL'] = req.href.ticket(tkt.id)
         node['alt'] = u'Ticket #%s'%tkt.id
         node['tooltip'] = tkt['summary']
         
         for n in link.blocking:
             node > g[n]
     
     return g
예제 #30
0
 def get_timeline_events(self, req, start, stop, filters):
     if "blog" in filters:
         blog_realm = Resource("blog")
         if not "BLOG_VIEW" in req.perm(blog_realm):
             return
         add_stylesheet(req, "tracfullblog/css/fullblog.css")
         # Blog posts
         blog_posts = get_blog_posts(self.env, from_dt=start, to_dt=stop, all_versions=True)
         for name, version, time, author, title, body, category_list in blog_posts:
             bp_resource = blog_realm(id=name, version=version)
             if "BLOG_VIEW" not in req.perm(bp_resource):
                 continue
             bp = BlogPost(self.env, name, version=version)
             yield ("blog", bp.version_time, bp.version_author, (bp_resource, bp, None))
         # Attachments (will be rendered by attachment module)
         for event in AttachmentModule(self.env).get_timeline_events(req, blog_realm, start, stop):
             yield event
         # Blog comments
         blog_comments = get_blog_comments(self.env, from_dt=start, to_dt=stop)
         blog_comments = sorted(blog_comments, key=itemgetter(4), reverse=True)
         for post_name, number, comment, author, time in blog_comments:
             bp_resource = blog_realm(id=post_name)
             if "BLOG_VIEW" not in req.perm(bp_resource):
                 continue
             bp = BlogPost(self.env, post_name)
             bc = BlogComment(self.env, post_name, number=number)
             yield ("blog", time, author, (bp_resource, bp, bc))
예제 #31
0
파일: perm.py 프로젝트: gdgkyoto/kyoto-gtug
 def test_mixed_case_group(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                        ('Dev', 'WIKI_MODIFY'), ('Dev', 'REPORT_ADMIN'),
                        ('Admin', 'Dev'), ('john', 'Admin')])
     self.assertEquals(['REPORT_ADMIN', 'WIKI_MODIFY'],
                       sorted(self.store.get_user_permissions('john')))
예제 #32
0
파일: model.py 프로젝트: nyuhuhuu/trachacks
 def get_comments(self):
     """ Returns a list of used comment numbers attached to the post.
     It instantiates BlogComment objects for comments attached to the
     current BlogPost, and returns them in a list sorted by number. """
     comments = sorted(get_blog_comments(self.env, post_name=self.name),
                 key=itemgetter(1))
     return [BlogComment(self.env, comment[0],
                     comment[1]) for comment in comments]
예제 #33
0
 def sections(self):
     """Return a list of section names."""
     sections = set([to_unicode(s) for s in self.parser.sections()])
     if self.parent:
         sections.update(self.parent.sections())
     else:
         sections.update(self.defaults().keys())
     return sorted(sections)
예제 #34
0
 def set_resource_tags(self, req, resource, tags):
     req.perm.require('TICKET_MODIFY', resource)
     split_into_tags = TagSystem(self.env).split_into_tags
     ticket = Ticket(self.env, resource.id)
     all = self._ticket_tags(ticket)
     keywords = split_into_tags(ticket['keywords'])
     tags.difference_update(all.difference(keywords))
     ticket['keywords'] = u' '.join(sorted(map(to_unicode, tags)))
     ticket.save_changes(req.username, u'')
예제 #35
0
 def _create_ticket(self, tags, **kwargs):
     ticket = Ticket(self.env)
     ticket['keywords'] = u' '.join(sorted(map(to_unicode, tags)))
     ticket['summary'] = 'summary'
     ticket['reporter'] = 'admin'
     for name, value in kwargs.iteritems():
         ticket[name] = value
     ticket.insert()
     return ticket
예제 #36
0
 def set_resource_tags(self, req, resource, tags):
     req.perm.require('TICKET_MODIFY', resource)
     split_into_tags = TagSystem(self.env).split_into_tags
     ticket = Ticket(self.env, resource.id)
     all = self._ticket_tags(ticket)
     keywords = split_into_tags(ticket['keywords'])
     tags.difference_update(all.difference(keywords))
     ticket['keywords'] = u' '.join(sorted(map(to_unicode, tags)))
     ticket.save_changes(req.username, u'')
예제 #37
0
 def get_versions(self):
     """ Returns a sorted list of versions stored for the blog post.
     Returns empty list ([]) if no versions exists. """
     cnx = self.env.get_db_cnx()
     cursor = cnx.cursor()
     cursor.execute("SELECT version from fullblog_posts "
                    "WHERE name=%s", (self.name, ))
     self.versions = sorted([row[0] for row in cursor])
     return self.versions
예제 #38
0
파일: perm.py 프로젝트: gdgkyoto/kyoto-gtug
 def test_simple_actions(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                        ('john', 'WIKI_MODIFY'), ('john', 'REPORT_ADMIN'),
                        ('kate', 'TICKET_CREATE')])
     self.assertEquals(['REPORT_ADMIN', 'WIKI_MODIFY'],
                       sorted(self.store.get_user_permissions('john')))
     self.assertEquals(['TICKET_CREATE'], self.store.get_user_permissions('kate'))
예제 #39
0
파일: model.py 프로젝트: nyuhuhuu/trachacks
 def get_versions(self):
     """ Returns a sorted list of versions stored for the blog post.
     Returns empty list ([]) if no versions exists. """
     cnx = self.env.get_db_cnx()
     cursor = cnx.cursor()
     cursor.execute("SELECT version from fullblog_posts "
             "WHERE name=%s", (self.name,) )
     self.versions = sorted([row[0] for row in cursor])
     return self.versions
예제 #40
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/ticket/'):
            # In case of an invalid ticket, the data is invalid
            if not data:
                return template, data, content_type

            tkt = data['ticket']
            links = TicketLinks(self.env, tkt)            
            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    add_script(req, 'ticketrelations/disable_resolve.js')
                    break

            for change in data.get('changes', {}):
                if not change.has_key('fields'):
                    continue
                for field, field_data in change['fields'].iteritems():
                    if field in self.fields:
                        if field_data['new'].strip():
                            new = extract_ticket_ids(field_data['new'])
                        else:
                            new = set()
                        if field_data['old'].strip():
                            old = extract_ticket_ids(field_data['old'])
                        else:
                            old = set()
                        add = new - old
                        sub = old - new
                        elms = tag()
                        if add:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(add)]))
                            )
                            elms.append(u' added')
                        if add and sub:
                            elms.append(u'; ')
                        if sub:
                            elms.append(
                                tag.em(u', '.join([unicode(n) for n in sorted(sub)]))
                            )
                            elms.append(u' removed')
                        field_data['rendered'] = elms

        return template, data, content_type
예제 #41
0
 def get_comments(self):
     """ Returns a list of used comment numbers attached to the post.
     It instantiates BlogComment objects for comments attached to the
     current BlogPost, and returns them in a list sorted by number. """
     comments = sorted(get_blog_comments(self.env, post_name=self.name),
                       key=itemgetter(1))
     return [
         BlogComment(self.env, comment[0], comment[1])
         for comment in comments
     ]
예제 #42
0
 def render_list(self, req, data, hacks):
     ul = builder.ul()
     for votes, rank, resource, tags, title in sorted(hacks, key=lambda h: h[2].id):
         li = builder.li(builder.a(resource.id,
                                   href=req.href.wiki(resource.id)),
                         ' - ', title)
         ul(li)
     data['body'] = ul
     # TODO Top-n + sample
     return 'hacks_view.html', data, None
예제 #43
0
def render_cloud(env, req, cloud, renderer=None):
    """Render a tag cloud

    :cloud: Dictionary of {object: count} representing the cloud.
    :param renderer: A callable with signature (tag, count, percent) used to
                     render the cloud objects.
    """
    min_px = 10.0
    max_px = 30.0
    scale = 1.0

    if renderer is None:

        def default_renderer(tag, count, percent):
            href = get_resource_url(env, Resource('tag', tag), req.href)
            return builder.a(tag,
                             rel='tag',
                             title='%i' % count,
                             href=href,
                             style='font-size: %ipx' % int(min_px + percent *
                                                           (max_px - min_px)))

        renderer = default_renderer

    # A LUT from count to n/len(cloud)
    size_lut = dict([
        (c, float(i))
        for i, c in enumerate(sorted(set([r for r in cloud.values()])))
    ])
    if size_lut:
        scale = 1.0 / len(size_lut)

    ul = builder.ul(class_='tagcloud')
    last = len(cloud) - 1
    for i, (tag, count) in enumerate(sorted(cloud.iteritems())):
        percent = size_lut[count] * scale
        li = builder.li(renderer(tag, count, percent))
        if i == last:
            li(class_='last')
        li()
        ul(li)
    return ul
예제 #44
0
파일: perm.py 프로젝트: gdgkyoto/kyoto-gtug
 def test_builtin_groups(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                        ('authenticated', 'WIKI_MODIFY'),
                        ('authenticated', 'REPORT_ADMIN'),
                        ('anonymous', 'TICKET_CREATE')])
     self.assertEquals(['REPORT_ADMIN', 'TICKET_CREATE', 'WIKI_MODIFY'],
                       sorted(self.store.get_user_permissions('john')))
     self.assertEquals(['TICKET_CREATE'],
                       self.store.get_user_permissions('anonymous'))
예제 #45
0
    def expand_macro(self, formatter, name, content):
        req = formatter.req
        query_result = TagSystem(self.env).query(req, content)

        def link(resource):
            return render_resource_link(self.env, formatter.context, resource,
                                        'compact')

        ul = builder.ul(class_='taglist')
        # Beware: Resources can be Unicode strings.
        for resource, tags in sorted(query_result, key=lambda r: r[0].id):
            tags = sorted(tags)
            if tags:
                rendered_tags = [link(resource('tag', tag)) for tag in tags]
                li = builder.li(link(resource), ' (', rendered_tags[0],
                                [(' ', tag) for tag in rendered_tags[1:]], ')')
            else:
                li = builder.li(link(resource))
            ul(li, '\n')
        return ul
예제 #46
0
    def post_process_request(self, req, template, data, content_type, method=None):
        if req.path_info.startswith('/ticket/'):
            # In case of an invalid ticket, the data is invalid
            if not data:
                return template, data, content_type
            tkt = data['ticket']
            with self.env.db_query as db:
                links = CrashDumpTicketLinks(self.env, tkt, db=db)

                for change in data.get('changes', {}):
                    if not change.has_key('fields'):
                        continue
                    for field, field_data in change['fields'].iteritems():
                        if field in self.crashdump_link_fields:
                            if field_data['new'].strip():
                                new = set([CrashDumpSystem.get_crash_id(n) for n in field_data['new'].split(',')])
                            else:
                                new = set()
                            if field_data['old'].strip():
                                old = set([CrashDumpSystem.get_crash_id(n) for n in field_data['old'].split(',')])
                            else:
                                old = set()
                            add = new - old
                            sub = old - new
                            elms = tag()
                            if add:
                                elms.append(
                                    tag.em(u', '.join([unicode(n) for n in sorted(add)]))
                                )
                                elms.append(u' added')
                            if add and sub:
                                elms.append(u'; ')
                            if sub:
                                elms.append(
                                    tag.em(u', '.join([unicode(n) for n in sorted(sub)]))
                                )
                                elms.append(u' removed')
                            field_data['rendered'] = elms
                            links.crashes = new

        return template, data, content_type, method
예제 #47
0
파일: util.py 프로젝트: nyuhuhuu/trachacks
def linkify_ids(env, req, ids):
    data = []
    for id in sorted(ids, key=lambda x: int(x)):
        try:
            tkt = Ticket(env, id)
            data.append(tag.a('#%s'%tkt.id, href=req.href.ticket(tkt.id), class_='%s ticket'%tkt['status'], title=tkt['summary']))
        except ResourceNotFound:
            data.append('#%s'%id)
        data.append(', ')
    if data:
        del data[-1] # Remove the last comma if needed
    return tag.span(*data)
예제 #48
0
 def getUsers(self, next_action):
     allowed_group = getlist(next_action, 'owner_group', sep='|')
     if not allowed_group:
         allowed_group = self.owner_group
     users_dict = {}
     for name in self._get_users(allowed_group):
         u = GroupedSimpleUser()
         u.setUsername(name)
         u.setOptionValue(name)
         u.setOptionDisplay(name)
         users_dict.update({name: u})
     return sorted(users_dict.values())
예제 #49
0
    def _page_tags(self, req):
        pagename = req.args.get('page', 'WikiStart')
        version = req.args.get('version')
        tags_version = req.args.get('tags_version')

        page = WikiPage(self.env, pagename, version=version)
        resource = page.resource
        if version and not tags_version:
            tags_version = page.time
        tags = sorted(
            self.tag_system.get_tags(req, resource, when=tags_version))
        return tags
예제 #50
0
 def getUsers(self, next_action):
     allowed_group = getlist(next_action, 'owner_group', sep='|')
     if not allowed_group:
         allowed_group = self.owner_group
     users_dict = {}
     for name in self._get_users(allowed_group):
         u = GroupedSimpleUser()
         u.setUsername(name)
         u.setOptionValue(name)
         u.setOptionDisplay(name)
         users_dict.update({name:u})
     return sorted(users_dict.values())
예제 #51
0
 def get_versions(self):
     """ Returns a sorted list of versions stored for the blog post.
     Returns empty list ([]) if no versions exists. """
     sql = "SELECT version from fullblog_posts WHERE name=%s"
     args = (self.name, )
     if hasattr(self.env, 'db_query'):
         cursor = self.env.db_query(sql, args)
     else:
         db = self.env.get_db_cnx()
         cursor = db.cursor()
         cursor.execute(sql, args)
     self.versions = sorted([row[0] for row in cursor])
     return self.versions
예제 #52
0
파일: api.py 프로젝트: gdgkyoto/kyoto-gtug
 def get_available_actions(self, req, ticket):
     """Returns a sorted list of available actions"""
     # The list should not have duplicates.
     actions = {}
     for controller in self.action_controllers:
         weighted_actions = controller.get_ticket_actions(req, ticket)
         for weight, action in weighted_actions:
             if action in actions:
                 actions[action] = max(actions[action], weight)
             else:
                 actions[action] = weight
     all_weighted_actions = [(weight, action) for action, weight in actions.items()]
     return [x[1] for x in sorted(all_weighted_actions, reverse=True)]
예제 #53
0
 def get_available_actions(self, req, crashobj):
     """Returns a sorted list of available actions"""
     # The list should not have duplicates.
     actions = {}
     #for controller in self.action_controllers:
         #weighted_actions = controller.get_ticket_actions(req, crashobj) or []
         #for weight, action in weighted_actions:
             #if action in actions:
                 #actions[action] = max(actions[action], weight)
             #else:
                 #actions[action] = weight
     all_weighted_actions = [(weight, action) for action, weight in
                             actions.items()]
     return [x[1] for x in sorted(all_weighted_actions, reverse=True)]
예제 #54
0
    def render_admin_panel(self, req, cat, page, version):
        req.perm.require('TAGS_ADMIN')

        realms = [p.get_taggable_realm() for p in self.tag_providers
                  if (not hasattr(p, 'check_permission') or \
                      p.check_permission(req.perm, 'view'))]
        # Check request for enabled filters, or use default.
        if [r for r in realms if r in req.args] == []:
            for realm in realms:
                req.args[realm] = 'on'
        checked_realms = [r for r in realms if r in req.args]
        data = dict(checked_realms=checked_realms,
                    tag_realms=list(
                        dict(name=realm, checked=realm in checked_realms)
                        for realm in realms))

        tag_system = TagSystem(self.env)
        if req.method == 'POST':
            # Replace Tag
            allow_delete = req.args.get('allow_delete')
            new_tag = req.args.get('tag_new_name').strip()
            new_tag = not new_tag == u'' and new_tag or None
            if not (allow_delete or new_tag):
                data['error'] = _("Selected current tag(s) and either "
                                  "new tag or delete approval are required")
            else:
                comment = req.args.get('comment', u'')
                old_tags = req.args.get('tag_name')
                if old_tags:
                    # Provide list regardless of single or multiple selection.
                    old_tags = isinstance(old_tags, list) and old_tags or \
                               [old_tags]
                    tag_system.replace_tag(req,
                                           old_tags,
                                           new_tag,
                                           comment,
                                           allow_delete,
                                           filter=checked_realms)
                data['selected'] = new_tag

        query = ' or '.join(['realm:%s' % r for r in checked_realms])
        all_tags = sorted(tag_system.get_all_tags(req, query))
        data['tags'] = all_tags
        try:
            Chrome(self.env).add_textarea_grips(req)
        except AttributeError:
            # Element modifiers unavailable before Trac 0.12, skip gracefully.
            pass
        return 'admin_tag_change.html', data
예제 #55
0
    def _post_process_request_history(self, req, data):
        history = []
        page_histories = data.get('history', [])
        resource = data['resource']
        tags_histories = tag_changes(self.env, resource)

        for page_history in page_histories:
            while tags_histories and \
                    tags_histories[0][0] >= page_history['date']:
                tags_history = tags_histories.pop(0)
                date = tags_history[0]
                author = tags_history[1]
                old_tags = split_into_tags(tags_history[2] or '')
                new_tags = split_into_tags(tags_history[3] or '')
                added = sorted(new_tags - old_tags)
                added = added and \
                        tagn_("%(tags)s added", "%(tags)s added",
                              len(added), tags=tag.em(', '.join(added)))
                removed = sorted(old_tags - new_tags)
                removed = removed and \
                          tagn_("%(tags)s removed", "%(tags)s removed",
                                len(removed), tags=tag.em(', '.join(removed)))
                # TRANSLATOR: How to delimit added and removed tags.
                delim = added and removed and _("; ")
                comment = tag(tag.strong(_("Tags")), ' ', added, delim,
                              removed)
                url = req.href(resource.realm, resource.id,
                               version=page_history['version'],
                               tags_version=to_utimestamp(date))
                history.append({'version': '*', 'url': url, 'date': date,
                                'author': author, 'comment': comment,
                                'ipnr': ''})
            history.append(page_history)

        data.update(dict(history=history,
                         wiki_to_oneliner=self._wiki_to_oneliner))
예제 #56
0
def linkify_ids(env, req, ids):
    data = []
    for id in sorted(ids, key=lambda x: int(x)):
        try:
            tkt = Ticket(env, id)
            data.append(
                tag.a('#%s' % tkt.id,
                      href=req.href.ticket(tkt.id),
                      class_='%s ticket' % tkt['status'],
                      title=tkt['summary']))
        except ResourceNotFound:
            data.append('#%s' % id)
        data.append(', ')
    if data:
        del data[-1]  # Remove the last comma if needed
    return tag.span(*data)
예제 #57
0
 def _next_comment_number(self):
     """ Function that returns the next available comment number.
     If no blog post exists (can't attach comment), it returns 0. """
     cnx = self.env.get_db_cnx()
     cursor = cnx.cursor()
     cursor.execute("SELECT number FROM fullblog_comments "
                    "WHERE name=%s", (self.post_name, ))
     cmts = sorted([row[0] for row in cursor])
     if cmts:
         return cmts[-1] + 1  # Add 1 for next free
     # No item found - need to double-check to find out why
     bp = BlogPost(self.env, self.post_name)
     if bp.get_versions():
         return 1
     else:
         return 0
예제 #58
0
def render_table(items, colspec, render_item):
    try:
        columns = max(int(colspec), 1)
    except:
        columns = 3

    nbsp = Markup('&nbsp;')
    hdr = [tag.th('Markup', nbsp), tag.th(nbsp, 'Display')]
    def render_def(s):
        rendered = s and render_item(s) or None
        return [tag.td(s), tag.td(rendered)] 
    
    return tag.table(tag.tr((hdr + [tag.th(nbsp)]) * (columns-1) + hdr),
                     [tag.tr([render_def(s) + [tag.td(nbsp)]
                              for s in row[:-1]] + render_def(row[-1]))
                      for row in group(sorted(items), columns)],
                     class_="wiki")