Exemple #1
0
 def walk_tagged_names(self, names, tags, predicate):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     tags = set(tags)
     names = set(names)
     args = []
     sql = "SELECT * FROM (SELECT id, %s, %s AS allfields FROM ticket) s" % (
         ','.join(self.fields), '||'.join(
             ["COALESCE(%s, '')" % f for f in self.fields]))
     constraints = []
     if names:
         constraints.append("id IN (" + ', '.join(['%s'
                                                   for n in names]) + ")")
         args += [unicode(n) for n in names]
     if tags:
         constraints.append("(" +
                            ' OR '.join(["allfields LIKE %s"
                                         for t in tags]) + ")")
         args += ['%' + t + '%' for t in tags]
     if constraints:
         sql += " WHERE " + " AND ".join(constraints)
     sql += " ORDER BY id"
     cursor.execute(sql, args)
     for row in cursor:
         id, ttags = row[0], ' '.join([f for f in row[1:-1] if f])
         ticket_tags = set(self._keyword_split.findall(ttags))
         if not tags or ticket_tags.intersection(tags):
             if predicate(id, ticket_tags):
                 yield (id, ticket_tags)
Exemple #2
0
 def walk_tagged_names(self, names, tags, predicate):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     tags = set(tags)
     names = set(names)
     args = []
     sql = "SELECT * FROM (SELECT id, %s, %s AS allfields FROM ticket) s" % (','.join(self.fields),
         '||'.join(["COALESCE(%s, '')" % f for f in self.fields]))
     constraints = []
     if names:
         constraints.append("id IN (" + ', '.join(['%s' for n in names]) + ")")
         args += [unicode(n) for n in names]
     if tags:
         constraints.append("(" + ' OR '.join(["allfields LIKE %s" for t in tags]) + ")")
         args += ['%' + t + '%' for t in tags]
     if constraints:
         sql += " WHERE " + " AND ".join(constraints)
     sql += " ORDER BY id"
     cursor.execute(sql, args)
     for row in cursor:
         id, ttags = row[0], ' '.join([f for f in row[1:-1] if f])
         ticket_tags = set(self._keyword_split.findall(ttags))
         if not tags or ticket_tags.intersection(tags):
             if predicate(id, ticket_tags):
                 yield (id, ticket_tags)
Exemple #3
0
 def get_name_tags(self, name):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.execute(
         "SELECT keywords FROM ticket WHERE id=%s AND keywords IS NOT NULL AND keywords != ''",
         (name, ))
     for row in cursor:
         return set(self._keyword_split.findall(row[0]))
Exemple #4
0
 def walk_tagged_names(self, names, tags, predicate):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     tags = set(tags)
     names = set(names)
     args = []
     sql = "SELECT id, keywords FROM ticket WHERE keywords IS NOT NULL AND keywords != ''"
     if names:
         sql += " AND id IN (" + ', '.join(['%s' for n in names]) + ")"
         args += [unicode(n) for n in names]
     if tags:
         sql += " AND (" + ' OR '.join(["keywords LIKE %s" for t in tags]) + ")"
         args += ['%' + t + '%' for t in tags]
     sql += " ORDER BY id"
     cursor.execute(sql, args)
     for id, ttags in cursor:
         ticket_tags = set(self._keyword_split.findall(ttags))
         if not tags or ticket_tags.intersection(tags):
             if predicate(id, ticket_tags):
                 yield (id, ticket_tags)
Exemple #5
0
 def walk_tagged_names(self, names, tags, predicate):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     tags = set(tags)
     names = set(names)
     args = []
     sql = "SELECT id, keywords FROM ticket WHERE keywords IS NOT NULL AND keywords != ''"
     if names:
         sql += " AND id IN (" + ', '.join(['%s' for n in names]) + ")"
         args += [unicode(n) for n in names]
     if tags:
         sql += " AND (" + ' OR '.join(["keywords LIKE %s"
                                        for t in tags]) + ")"
         args += ['%' + t + '%' for t in tags]
     sql += " ORDER BY id"
     cursor.execute(sql, args)
     for id, ttags in cursor:
         ticket_tags = set(self._keyword_split.findall(ttags))
         if not tags or ticket_tags.intersection(tags):
             if predicate(id, ticket_tags):
                 yield (id, ticket_tags)
Exemple #6
0
    def render_tagcloud(self,
                        req,
                        smallest=10,
                        biggest=20,
                        showcount=True,
                        tagspace=None,
                        mincount=1,
                        tagspaces=[],
                        **kwargs):
        """ This macro displays a [http://en.wikipedia.org/wiki/Tag_cloud tag cloud] (weighted list)
            of all tags.

            ||'''Argument'''||'''Description'''||
            ||`tagspace=<tagspace>`||Specify the tagspace the macro should operate on.||
            ||`tagspaces=(<tagspace>,...)`||Specify a set of tagspaces the macro should operate on.||
            ||`smallest=<n>`||The lower bound of the font size for the tag cloud.||
            ||`biggest=<n>`||The upper bound of the font size for the tag cloud.||
            ||`showcount=true|false`||Show the count of objects for each tag?||
            ||`mincount=<n>`||Hide tags with a count less than `<n>`.||
            """

        smallest = int(smallest)
        biggest = int(biggest)
        mincount = int(mincount)

        engine = TagEngine(self.env)
        # Get wiki tagspace
        if tagspace:
            tagspaces = [tagspace]
        else:
            tagspaces = tagspaces or engine.tagspaces
        cloud = {}

        for tag, names in engine.get_tags(tagspaces=tagspaces,
                                          detailed=True).iteritems():
            count = len(names)
            if count >= mincount:
                cloud[tag] = len(names)

        tags = cloud.keys()

        # No tags?
        if not tags: return ''

        # by_count maps tag counts to an index in the set of counts
        by_count = list(set(cloud.values()))
        by_count.sort()
        by_count = dict([(c, float(i)) for i, c in enumerate(by_count)])

        taginfo = self._tag_details({}, tags)
        tags.sort()
        rlen = float(biggest - smallest)
        tlen = float(len(by_count))
        scale = 1.0
        if tlen:
            scale = rlen / tlen
        out = StringIO()
        out.write('<ul class="tagcloud">\n')
        last = tags[-1]
        for tag in tags:
            if tag == last:
                cls = ' class="last"'
            else:
                cls = ''
            if showcount != 'false':
                count = ' <span class="tagcount">(%i)</span>' % cloud[tag]
            else:
                count = ''
            out.write(
                '<li%s><a rel="tag" title="%s" style="font-size: %ipx" href="%s">%s</a>%s</li>\n'
                % (cls, taginfo[tag][1] + ' (%i)' % cloud[tag],
                   smallest + int(by_count[cloud[tag]] * scale),
                   taginfo[tag][0], tag, count))
        out.write('</ul>\n')
        return out.getvalue()
Exemple #7
0
    def render_listtagged(self, req, *tags, **kwargs):
        """ List tagged objects. Optionally accepts a list of tags to match
            against.  The special tag '''. (dot)''' inserts the current Wiki page name.

            `[[ListTagged(<tag>, ...)]]`

            ||'''Argument'''||'''Description'''||
            ||`tagspace=<tagspace>`||Specify the tagspace the macro should operate on.||
            ||`tagspaces=(<tagspace>,...)`||Specify a set of tagspaces the macro should operate on.||
            ||`operation=intersection|union`||The set operation to perform on the discovered objects.||
            ||`showheadings=true|false`||List objects under the tagspace they occur in.||
            ||`expression=<expr>`||Match object tags against the given expression.||

            The supported expression operators are: unary - (not); binary +, -
            and | (and, and not, or). All values in the expression are treated
            as tags. Any tag not in the same form as a Python variable must be
            quoted.
            
            eg. Match all objects tagged with ticket and workflow, and not
            tagged with wiki or closed.
            
                (ticket+workflow)-(wiki|closed)

            If an expression is provided operation is ignored.
        """

        if 'tagspace' in kwargs:
            tagspaces = [kwargs.get('tagspace', None)]
        else:
            tagspaces = kwargs.get('tagspaces', '') or \
                        list(TagEngine(self.env).tagspaces)
        expression = kwargs.get('expression', None)
        showheadings = kwargs.get('showheadings', 'false')
        operation = kwargs.get('operation', 'intersection')
        if operation not in ('union', 'intersection'):
            raise TracError("Invalid tag set operation '%s'" % operation)

        engine = TagEngine(self.env)
        page_name = self._current_page(req)
        if page_name:
            tags = [tag == '.' and page_name or tag for tag in tags]

        tags = set(tags)
        taginfo = {}
        out = StringIO()
        out.write('<ul class="listtagged">\n')
        # If expression was passed as an argument, do a full walk, using the
        # expression as the predicate. Silently assumes that failed expressions
        # are normal tags.
        if expression:
            from tractags.expr import Expression
            try:
                expr = Expression(expression)
                self.env.log.debug(repr(expr))
            except Exception, e:
                self.env.log.error("Invalid expression '%s'" % expression,
                                   exc_info=True)
                tags.update([
                    x.strip() for x in re.split('[+,]', expression)
                    if x.strip()
                ])
                expression = None
            else:
                self.env.log.debug(expr.ast)
                tagged_names = {}
                tags.update(expr.get_tags())
                for tagspace, name, name_tags in engine.walk_tagged_names(
                        tags=tags,
                        tagspaces=tagspaces,
                        predicate=lambda ts, n, t: expr(t)):
                    tagged_names.setdefault(tagspace, {})[name] = name_tags
                tagged_names = [
                    (tagspace, names)
                    for tagspace, names in tagged_names.iteritems()
                ]
Exemple #8
0
 def get_name_tags(self, name):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.execute("SELECT keywords FROM ticket WHERE id=%s AND keywords IS NOT NULL AND keywords != ''", (name,))
     for row in cursor:
         return set(self._keyword_split.findall(row[0]))
Exemple #9
0
 def _ticket_tags(self, ticket):
     return set(self._keyword_split.findall(' '.join([ticket[f] for f in self.fields])))
Exemple #10
0
    def render_tagcloud(self, req, smallest=10, biggest=20, showcount=True, tagspace=None, mincount=1, tagspaces=[]):
        """ This macro displays a [http://en.wikipedia.org/wiki/Tag_cloud tag cloud] (weighted list)
            of all tags.

            ||'''Argument'''||'''Description'''||
            ||`tagspace=<tagspace>`||Specify the tagspace the macro should operate on.||
            ||`tagspaces=(<tagspace>,...)`||Specify a set of tagspaces the macro should operate on.||
            ||`smallest=<n>`||The lower bound of the font size for the tag cloud.||
            ||`biggest=<n>`||The upper bound of the font size for the tag cloud.||
            ||`showcount=true|false`||Show the count of objects for each tag?||
            ||`mincount=<n>`||Hide tags with a count less than `<n>`.||
            """

        smallest = int(smallest)
        biggest = int(biggest)
        mincount = int(mincount)

        engine = TagEngine(self.env)
        # Get wiki tagspace
        if tagspace:
            tagspaces = [tagspace]
        else:
            tagspaces = tagspaces or engine.tagspaces
        cloud = {}

        for tag, names in engine.get_tags(tagspaces=tagspaces, detailed=True).iteritems():
            count = len(names)
            if count >= mincount:
                cloud[tag] = len(names)

        tags = cloud.keys()

        # No tags?
        if not tags: return ''

        # by_count maps tag counts to an index in the set of counts
        by_count = list(set(cloud.values()))
        by_count.sort()
        by_count = dict([(c, float(i)) for i, c in enumerate(by_count)])

        taginfo = self._tag_details({}, tags)
        tags.sort()
        rlen = float(biggest - smallest)
        tlen = float(len(by_count))
        scale = 1.0
        if tlen:
            scale = rlen / tlen
        out = StringIO()
        out.write('<ul class="tagcloud">\n')
        last = tags[-1]
        for tag in tags:
            if tag == last:
                cls = ' class="last"'
            else:
                cls = ''
            if showcount != 'false':
                count = ' <span class="tagcount">(%i)</span>' % cloud[tag]
            else:
                count = ''
            out.write('<li%s><a rel="tag" title="%s" style="font-size: %ipx" href="%s">%s</a>%s</li>\n' % (
                       cls,
                       taginfo[tag][1] + ' (%i)' % cloud[tag],
                       smallest + int(by_count[cloud[tag]] * scale),
                       taginfo[tag][0],
                       tag,
                       count))
        out.write('</ul>\n')
        return out.getvalue()
Exemple #11
0
    def render_listtagged(self, req, *tags, **kwargs):
        """ List tagged objects. Optionally accepts a list of tags to match
            against.  The special tag '''. (dot)''' inserts the current Wiki page name.

            `[[ListTagged(<tag>, ...)]]`

            ||'''Argument'''||'''Description'''||
            ||`tagspace=<tagspace>`||Specify the tagspace the macro should operate on.||
            ||`tagspaces=(<tagspace>,...)`||Specify a set of tagspaces the macro should operate on.||
            ||`operation=intersection|union`||The set operation to perform on the discovered objects.||
            ||`showheadings=true|false`||List objects under the tagspace they occur in.||
            ||`expression=<expr>`||Match object tags against the given expression.||

            The supported expression operators are: unary - (not); binary +, -
            and | (and, and not, or). All values in the expression are treated
            as tags. Any tag not in the same form as a Python variable must be
            quoted.
            
            eg. Match all objects tagged with ticket and workflow, and not
            tagged with wiki or closed.
            
                (ticket+workflow)-(wiki|closed)

            If an expression is provided operation is ignored.
        """

        if 'tagspace' in kwargs:
            tagspaces = [kwargs.get('tagspace', None)]
        else:
            tagspaces = kwargs.get('tagspaces', '') or \
                        list(TagEngine(self.env).tagspaces)
        expression = kwargs.get('expression', None)
        showheadings = kwargs.get('showheadings', 'false')
        operation = kwargs.get('operation', 'intersection')
        if operation not in ('union', 'intersection'):
            raise TracError("Invalid tag set operation '%s'" % operation)

        engine = TagEngine(self.env)
        page_name = req.hdf.get('wiki.page_name')
        if page_name:
            tags = [tag == '.' and page_name or tag for tag in tags]

        tags = set(tags)
        taginfo = {}
        out = StringIO()
        out.write('<ul class="listtagged">\n')
        # If expression was passed as an argument, do a full walk, using the
        # expression as the predicate. Silently assumes that failed expressions
        # are normal tags.
        if expression:
            from tractags.expr import Expression
            try:
                expr = Expression(expression)
            except Exception, e:
                self.env.log.error("Invalid expression '%s'" % expression, exc_info=True)
                tags.update([x.strip() for x in re.split('[+,]', expression) if x.strip()])
                expression = None
            else:
                self.env.log.debug(expr.ast)
                tagged_names = {}
                tags.update(expr.get_tags())
                for tagspace, name, name_tags in engine.walk_tagged_names(tags=tags,
                        tagspaces=tagspaces, predicate=lambda ts, n, t: expr(t)):
                    tagged_names.setdefault(tagspace, {})[name] = name_tags
                tagged_names = [(tagspace, names) for tagspace, names in tagged_names.iteritems()]
Exemple #12
0
 def _ticket_tags(self, ticket):
     return set(self._keyword_split.findall(ticket['keywords']))
Exemple #13
0
 def _ticket_tags(self, ticket):
     return set(
         self._keyword_split.findall(' '.join(
             [ticket[f] for f in self.fields])))
Exemple #14
0
 def _ticket_tags(self, ticket):
     return set(self._keyword_split.findall(ticket['keywords']))