Exemple #1
0
    def get_query(self, constraints=None, args=None):
        req = self.req
        if not args:
            args = req.args
        if not constraints:
            # If no constraints are given in the URL, use the default ones.
            if req.authname and req.authname != 'anonymous':
                qstring = self.default_query
                user = req.authname
            else:
                email = req.session.get('email')
                name = req.session.get('name')
                qstring = self.default_anonymous_query
                user = email or name or None

            query = Query.from_string(self.env, qstring)
            args = {'order': query.order, 'col': query.cols, 'max': 0}
            constraints = query.constraints

            # Substitute $USER, or ensure no field constraints that depend
            # on $USER are used if we have no username.
            for clause in constraints:
                for field, vals in clause.items():
                    for (i, val) in enumerate(vals):
                        if user:
                            vals[i] = val.replace('$USER', user)
                        elif val.endswith('$USER'):
                            del clause[field]
                            break

        query = Query(self.env, args.get('report'), constraints,
                      self._get_cols(), args.get('order'), args.get('desc'))
        self._set_no_paginator(query)
        return query
Exemple #2
0
 def _sticky_from_report(self, req, data):
     ids = []
     for value_for_group, row_group in data['row_groups']:
         ids.extend([int(row['id']) for row in row_group
                     if row['resource'] and
                        row['resource'].realm == 'ticket' and
                        'TICKET_VIEW' in req.perm(row['resource'])])
     cols = ['id', 'summary', 'type']
     for col in self._fields:
         if col not in cols:
             cols.append(col)
     if hasattr(self.env, 'get_read_db'):
         db = self.env.get_read_db()
     else:
         db = self.env.get_db_cnx()
     start = 0
     count = 100
     tickets = []
     while start < len(ids):
         constraints = [{
             'id': [str(id) for id in ids[start:start + count]],
         }]
         query = Query(self.env, constraints=constraints, cols=cols, max=0)
         tickets.extend(query.execute(req, db))
         start += count
     tickets_dict = dict((int(ticket['id']), ticket) for ticket in tickets)
     tickets = [tickets_dict[id] for id in ids if id in tickets_dict]
     return self._sticky(req, tickets)
Exemple #3
0
    def test_all_ordered_by_priority_desc(self):
        query = Query(self.env, desc=1) # priority is default order
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(t.priority,'')='' DESC,priority.value DESC,t.id""")
        tickets = query.execute()
Exemple #4
0
    def test_all_ordered_by_id_verbose(self):
        query = Query(self.env, order='id', verbose=1)
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.reporter AS reporter,t.description AS description,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(t.id,0)=0,t.id""")
        tickets = query.execute()
Exemple #5
0
    def test_grouped_by_priority(self):
        query = Query(self.env, group='priority')
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.milestone AS milestone,t.component AS component,t.priority AS priority,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(t.priority,'')='',priority.value,t.id""")
        tickets = query.execute()
Exemple #6
0
    def test_all_ordered_by_id_desc(self):
        query = Query(self.env, order='id', desc=1)
        sql, args = query.get_sql()
        self.assertEqualSQL(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.product AS product,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(t.id,0)=0 DESC,t.id DESC""")
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #7
0
    def test_all_ordered_by_version_desc(self):
        query = Query(self.env, order='version', desc=1)
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.version AS version,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
  LEFT OUTER JOIN version ON (version.name=version)
ORDER BY COALESCE(t.version,'')='' DESC,COALESCE(version.time,0)=0 DESC,version.time DESC,t.version DESC,t.id""")
        tickets = query.execute()
Exemple #8
0
    def test_all_grouped_by_milestone_desc(self):
        query = Query(self.env, order='id', group='milestone', groupdesc=1)
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.component AS component,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
  LEFT OUTER JOIN milestone ON (milestone.name=milestone)
ORDER BY COALESCE(t.milestone,'')='' DESC,COALESCE(milestone.due,0)=0 DESC,milestone.due DESC,t.milestone DESC,COALESCE(t.id,0)=0,t.id""")
        tickets = query.execute()
Exemple #9
0
    def test_all_ordered_by_id(self):
        query = Query(self.env, order='id')
        sql, args = query.get_sql()
        self.assertEqual(
            sql,
            """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(t.id,0)=0,t.id""")
        self.assertEqual([], args)
        tickets = query.execute(Mock(href=self.env.href))
Exemple #10
0
    def test_grouped_by_priority(self):
        query = Query(self.env, group='priority')
        sql, args = query.get_sql()
        self.assertEqualSQL(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.product AS product,t.milestone AS milestone,t.priority AS priority,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(priority.value,'')='',%(cast_priority)s,t.id""" % {
          'cast_priority': self.env.get_read_db().cast('priority.value', 'int')})
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #11
0
    def test_grouped_by_custom_field(self):
        self.env.config.set('ticket-custom', 'foo', 'text')
        query = Query(self.env, group='foo', order='id')
        sql = query.get_sql()
        self.assertEqual(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,foo.value AS foo
FROM ticket AS t
  LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo')
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(foo.value,'')='',foo.value,COALESCE(t.id,0)=0,t.id""")
        tickets = query.execute()
Exemple #12
0
    def test_all_ordered_by_priority_desc(self):
        query = Query(self.env, desc=1)  # priority is default order
        sql, args = query.get_sql()
        self.assertEqualSQL(
            sql,
            """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
FROM ticket AS t
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(priority.value,'')='' DESC,%(cast_priority)s DESC,t.id""" % {
                'cast_priority':
                self.env.get_db_cnx().cast('priority.value', 'int')
            })
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #13
0
    def test_grouped_by_custom_field(self):
        self.env.config.set('ticket-custom', 'foo', 'text')
        query = Query(self.env, group='foo', order='id')
        sql, args = query.get_sql()
        foo = self.env.get_read_db().quote('foo')
        self.assertEqualSQL(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.product AS product,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,%s.value AS %s
FROM ticket AS t
  LEFT OUTER JOIN ticket_custom AS %s ON (id=%s.ticket AND %s.name='foo')
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(%s.value,'')='',%s.value,COALESCE(t.id,0)=0,t.id""" %
        ((foo,) * 7))
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #14
0
    def test_grouped_by_custom_field(self):
        self.env.config.set('ticket-custom', 'foo', 'text')
        query = Query(self.env, group='foo', order='id')
        sql, args = query.get_sql()
        foo = self.env.get_read_db().quote('foo')
        self.assertEqualSQL(sql,
"""SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,c.%s AS %s
FROM ticket AS t
  LEFT JOIN (SELECT id AS ticket,
    (SELECT c.value FROM ticket_custom c WHERE c.ticket=t.id AND c.name='foo') AS %s
    FROM ticket t) AS c ON (c.ticket=t.id)
  LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
ORDER BY COALESCE(c.%s,'')='',c.%s,COALESCE(t.id,0)=0,t.id""" %
        ((foo,) * 5))
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #15
0
def _create_query_object(env, query, required_columns=None):
    """Create a query object from a query string. If query is None, the default
    Query is returned

    :param required_columns: Columns that must be included in the query.
    """

    if query is None:
        return Query(env, cols=required_columns)

    query_object = Query.from_string(env, query)

    # Add the required_columns
    for column in required_columns or []:
        if column not in query_object.cols:
            query_object.cols.append(column)

    return query_object
Exemple #16
0
    def process_request(self, req):
        constraints = QueryModule(self.env)._get_constraints(req)
        if not constraints and not req.args.has_key('order'):
            # avoid displaying all tickets when the query module is invoked
            # with no parameters. Instead show only open tickets, possibly
            # associated with the user
            constraints = {'status': ('new', 'assigned', 'reopened')}
            if req.authname and req.authname != 'anonymous':
                constraints['owner'] = (req.authname,)
            else:
                email = req.session.get('email')
                name = req.session.get('name')
                if email or name:
                    constraints['cc'] = ('~%s' % email or name,)

        query = Query(self.env, constraints, req.args.get('order'),
                      req.args.has_key('desc'), req.args.get('group'),
                      req.args.has_key('groupdesc'),
                      req.args.has_key('verbose'))
                      
        format = req.args.get('format')
        self.send_converted(req, 'trac.ticket.Query', query, format, 'query')
Exemple #17
0
    def process_request(self, req):
        req.perm.assert_permission('TICKET_VIEW')

        constraints = self._get_constraints(req)
        if not constraints and not 'order' in req.args:
            # If no constraints are given in the URL, use the default ones.
            if req.authname and req.authname != 'anonymous':
                qstring = self.default_query
                user = req.authname
            else:
                email = req.session.get('email')
                name = req.session.get('name')
                qstring = self.default_anonymous_query
                user = email or name or None

            if user:
                qstring = qstring.replace('$USER', user)
            self.log.debug('TasklistPlugin: Using default query: %s', qstring)
            constraints = Query.from_string(self.env, qstring).constraints
            # Ensure no field constraints that depend on $USER are used
            # if we have no username.
            for field, vals in constraints.items():
                for val in vals:
                    if val.endswith('$USER'):
                        del constraints[field]

        cols = req.args.get('col')
        if not cols:
            cols = self.default_cols
            cols.append(self.field_name)

        if isinstance(cols, basestring):
            cols = [cols]
        form_cols = copy.copy(cols)
        # Since we don't show 'id' or the tasklist_field as an option
        # to the user, we need to re-insert it here.
        if cols and 'id' not in cols:
            cols.insert(0, 'id')
        if cols and self.field_name not in cols:
            cols.insert(0, self.field_name)

        rows = req.args.get('row', [])
        if isinstance(rows, basestring):
            rows = [rows]

        q = Query(self.env, constraints=constraints, cols=cols)
        query = Query(self.env, req.args.get('report'), constraints, cols,
                      req.args.get('order'), 'desc' in req.args,
                      req.args.get('group'), 'groupdesc' in req.args, 'verbose'
                      in req.args, rows, req.args.get('limit'))

        if 'update' in req.args:
            # Reset session vars
            for var in ('query_constraints', 'query_time', 'query_tickets'):
                if var in req.session:
                    del req.session[var]
            req.redirect(q.get_href(req.href).replace('/query', '/tasklist'))

        if 'add' in req.args:
            req.perm.require('TICKET_CREATE')
            t = Ticket(self.env)
            if req.method == 'POST' and 'field_owner' in req.args and \
                   'TICKET_MODIFY' not in req.perm:
                del req.args['field_owner']
            self._populate(req, t)
            reporter_id = req.args.get('field_reporter') or \
                          get_reporter_id(req, 'author')
            t.values['reporter'] = reporter_id
            valid = None
            valid = self._validate_ticket(req, t)
            if valid:
                t.insert()
                # Notify
                try:
                    tn = TicketNotifyEmail(self.env)
                    tn.notify(t, newticket=True)
                except Exception, e:
                    self.log.exception(
                        "Failure sending notification on creation of "
                        "ticket #%s: %s" % (t.id, e))
            req.redirect(q.get_href(req.href).replace('/query', '/tasklist'))
Exemple #18
0
    def process_request(self, req):
        realm = req.args['realm']
        id_ = req.args['id']

        if not which(self.dot_path):
            raise TracError(
                _("Path to dot executable is invalid: %(path)s",
                  path=self.dot_path))

        # Urls to generate the depgraph for a ticket is /depgraph/ticketnum
        # Urls to generate the depgraph for a milestone is
        # /depgraph/milestone/milestone_name

        # List of tickets to generate the depgraph.
        if realm == 'milestone':
            # We need to query the list of tickets in the milestone
            query = Query(self.env, constraints={'milestone': [id_]}, max=0)
            tkt_ids = [fields['id'] for fields in query.execute(req)]
        else:
            tid = as_int(id_, None)
            if tid is None:
                raise TracError(
                    tag_("%(id)s is not a valid ticket id.", id=html.tt(id_)))
            tkt_ids = [tid]

        # The summary argument defines whether we place the ticket id or
        # its summary in the node's label
        label_summary = 0
        if 'summary' in req.args:
            label_summary = int(req.args.get('summary'))

        g = self._build_graph(req, tkt_ids, label_summary=label_summary)
        if req.path_info.endswith('/depgraph.png') or 'format' in req.args:
            format_ = req.args.get('format')
            if format_ == 'text':
                # In case g.__str__ returns unicode, convert it in ascii
                req.send(
                    to_unicode(g).encode('ascii', 'replace'), 'text/plain')
            elif format_ == 'debug':
                import pprint

                req.send(
                    pprint.pformat(
                        [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]),
                    'text/plain')
            elif format_ is not None:
                if format_ in self.acceptable_formats:
                    req.send(g.render(self.dot_path, format_), 'text/plain')
                else:
                    raise TracError(
                        _("The %(format)s format is not allowed.",
                          format=format_))

            if self.use_gs:
                ps = g.render(self.dot_path, 'ps2')
                gs = subprocess.Popen([
                    self.gs_path, '-q', '-dTextAlphaBits=4',
                    '-dGraphicsAlphaBits=4', '-sDEVICE=png16m',
                    '-sOutputFile=%stdout%', '-'
                ],
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
                img, err = gs.communicate(ps)
                if err:
                    self.log.debug('MasterTickets: Error from gs: %s', err)
            else:
                img = g.render(self.dot_path)
            req.send(img, 'image/png')
        else:
            data = {}

            # Add a context link to enable/disable labels in nodes.
            if label_summary:
                add_ctxtnav(req, 'Without labels',
                            req.href(req.path_info, summary=0))
            else:
                add_ctxtnav(req, 'With labels',
                            req.href(req.path_info, summary=1))

            if realm == 'milestone':
                add_ctxtnav(req, 'Back to Milestone: %s' % id_,
                            req.href.milestone(id_))
                data['milestone'] = id_
            else:
                data['ticket'] = id_
                add_ctxtnav(req, 'Back to Ticket #%s' % id_,
                            req.href.ticket(id_))
            data['graph'] = g
            data['graph_render'] = functools.partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            return 'depgraph.html', data, None
Exemple #19
0
    def process_request(self, req):
        req.perm.assert_permission('TICKET_VIEW')

        constraints = self._get_constraints(req)
        if not constraints and not req.args.has_key('order'):
            # avoid displaying all tickets when the query module is invoked
            # with no parameters. Instead show only open tickets, possibly
            # associated with the user
            constraints = {'status': ('new', 'assigned', 'reopened')}
            if req.authname and req.authname != 'anonymous':
                constraints['owner'] = (req.authname,)
            else:
                email = req.session.get('email')
                name = req.session.get('name')
                if email or name:
                    constraints['cc'] = ('~%s' % email or name,)

        query = Query(self.env, constraints, req.args.get('order'),
                      req.args.has_key('desc'), req.args.get('group'),
                      req.args.has_key('groupdesc'),
                      req.args.has_key('verbose'))

        if req.args.has_key('update'):
            # Reset session vars
            for var in ('query_constraints', 'query_time', 'query_tickets'):
                if req.session.has_key(var):
                    del req.session[var]
            req.redirect(query.get_href())

        add_link(req, 'alternate', query.get_href('rss'), 'RSS Feed',
                 'application/rss+xml', 'rss')
        add_link(req, 'alternate', query.get_href('csv'),
                 'Comma-delimited Text', 'text/plain')
        add_link(req, 'alternate', query.get_href('tab'), 'Tab-delimited Text',
                 'text/plain')

        constraints = {}
        for k, v in query.constraints.items():
            constraint = {'values': [], 'mode': ''}
            for val in v:
                neg = val.startswith('!')
                if neg:
                    val = val[1:]
                mode = ''
                if val[:1] in ('~', '^', '$'):
                    mode, val = val[:1], val[1:]
                constraint['mode'] = (neg and '!' or '') + mode
                constraint['values'].append(val)
            constraints[k] = constraint
        req.hdf['query.constraints'] = constraints

        format = req.args.get('format')
        if format == 'rss':
            self.display_rss(req, query)
            return 'query_rss.cs', 'application/rss+xml'
        elif format == 'csv':
            self.display_csv(req, query)
        elif format == 'tab':
            self.display_csv(req, query, '\t')
        else:
            self.display_html(req, query)
            return 'query.cs', None
Exemple #20
0
    def _process_export(self, req):
        fields = [{'name': 'id', 'label': 'id'}]
        fields.extend(TicketSystem(self.env).get_ticket_fields())
        fieldsFormat = self._get_fields_format(fields)
        fieldsExport = self._get_fields_export(fields)
        fieldsWeight = self._get_fields_weight(fields)

        comment_changeset = req.args.get('export.changeset') and req.args.get(
            'export.changeset') == 'True'

        fields = [c for c in fields if fieldsExport[c['name']]]
        fieldnames = [c['name'] for c in fields]

        fields.sort(
            lambda a, b: fieldsWeight[a['name']] - fieldsWeight[b['name']])

        # ticket #8805 : unavailable for python 2.4 or 2.5
        #content = BytesIO()
        content = cStringIO.StringIO()

        headerStyle = xlwt.easyxf(
            'font: bold on; pattern: pattern solid, fore-colour grey25; borders: top thin, bottom thin, left thin, right thin'
        )

        wb = xlwt.Workbook()
        sheetName = ('Tickets - %s' % self.config.get('project', 'name', ''))
        try:
            ws = wb.add_sheet(sheetName)
        except:
            # Project name incompatible with sheet name constraints.
            sheetName = 'Tickets'
            ws = wb.add_sheet(sheetName)

        colIndex = {}
        c = 0
        for f in fields:
            ws.write(0, c, unicode(f['label']), headerStyle)
            colIndex[f['name']] = c
            c += 1
        if comment_changeset:
            ws.write(0, c, unicode('Comments in change log'), headerStyle)

        constraints = {}
        if req.args.get('filter.type') and len(req.args['filter.type']) > 0:
            if type(req.args['filter.type']) == list:
                constraints['type'] = req.args['filter.type']
            else:
                constraints['type'] = [req.args['filter.type']]

        if req.args.get('filter.version') and len(
                req.args['filter.version']) > 0:
            if type(req.args['filter.version']) == list:
                constraints['version'] = req.args['filter.version']
            else:
                constraints['version'] = [req.args['filter.version']]

        if req.args.get('filter.milestone') and len(
                req.args['filter.milestone']) > 0:
            if type(req.args['filter.milestone']) == list:
                constraints['milestone'] = req.args['filter.milestone']
            else:
                constraints['milestone'] = [req.args['filter.milestone']]

        if req.args.get('filter.component') and len(
                req.args['filter.component']) > 0:
            if type(req.args['filter.component']) == list:
                constraints['component'] = req.args['filter.component']
            else:
                constraints['component'] = [req.args['filter.component']]

        if req.args.get('filter.status') and len(
                req.args['filter.status']) > 0:
            if type(req.args['filter.status']) == list:
                constraints['status'] = req.args['filter.status']
            else:
                constraints['status'] = [req.args['filter.status']]

        if req.args.get('filter.priority') and len(
                req.args['filter.priority']) > 0:
            if type(req.args['filter.priority']) == list:
                constraints['priority'] = req.args['filter.priority']
            else:
                constraints['priority'] = [req.args['filter.priority']]

        if req.args.get('filter.severity') and len(
                req.args['filter.severity']) > 0:
            if type(req.args['filter.severity']) == list:
                constraints['severity'] = req.args['filter.severity']
            else:
                constraints['severity'] = [req.args['filter.severity']]

        if req.args.get('filter.resolution') and len(
                req.args['filter.resolution']) > 0:
            if type(req.args['filter.resolution']) == list:
                constraints['resolution'] = req.args['filter.resolution']
            else:
                constraints['resolution'] = [req.args['filter.resolution']]

        query = Query(self.env,
                      cols=fieldnames,
                      order='id',
                      max=sys.maxint,
                      constraints=constraints)
        results = query.execute(req)
        r = 0
        cols = query.get_columns()
        for result in results:
            r += 1
            for col in cols:
                value = result[col]
                format = self.formats[fieldsFormat[col]]
                value = format.convert(value)
                style = format.get_style(value)
                ws.write(r, colIndex[col], value, style)
            if comment_changeset:
                format = self.formats['longtext']
                value = format.convert(
                    self._get_changelog_comments(result['id']))
                style = format.get_style(value)
                ws.write(r, len(cols), value, style)

        if req.args.get('export.statistics') and req.args.get(
                'export.statistics') == 'True':
            wb = self._add_statistics_sheet(req, sheetName, wb, fields,
                                            colIndex, constraints)

        wb.save(content)
        return (content.getvalue(), 'application/excel')
Exemple #21
0
    def process_request(self, req):
        path_info = req.path_info[10:]

        if not path_info:
            raise TracError('No ticket specified')

        #list of tickets to generate the depgraph for
        tkt_ids = []
        milestone = None
        split_path = path_info.split('/', 2)

        #Urls to generate the depgraph for a ticket is /depgraph/ticketnum
        #Urls to generate the depgraph for a milestone is /depgraph/milestone/milestone_name
        if split_path[0] == 'milestone':
            #we need to query the list of tickets in the milestone
            milestone = split_path[1]
            query = Query(self.env,
                          constraints={'milestone': [milestone]},
                          max=0)
            tkt_ids = [fields['id'] for fields in query.execute()]
        else:
            #the list is a single ticket
            tkt_ids = [int(split_path[0])]

        #the summary argument defines whether we place the ticket id or
        #it's summary in the node's label
        label_summary = 0
        if 'summary' in req.args:
            label_summary = int(req.args.get('summary'))

        g = self._build_graph(req, tkt_ids, label_summary=label_summary)
        if path_info.endswith('/depgraph.png') or 'format' in req.args:
            format = req.args.get('format')
            if format == 'text':
                #in case g.__str__ returns unicode, we need to convert it in ascii
                req.send(
                    to_unicode(g).encode('ascii', 'replace'), 'text/plain')
            elif format == 'debug':
                import pprint
                req.send(
                    pprint.pformat(
                        [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]),
                    'text/plain')
            elif format is not None:
                req.send(g.render(self.dot_path, format), 'text/plain')

            if self.use_gs:
                ps = g.render(self.dot_path, 'ps2')
                gs = subprocess.Popen([
                    self.gs_path, '-q', '-dTextAlphaBits=4',
                    '-dGraphicsAlphaBits=4', '-sDEVICE=png16m',
                    '-sOutputFile=%stdout%', '-'
                ],
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
                img, err = gs.communicate(ps)
                if err:
                    self.log.debug('MasterTickets: Error from gs: %s', err)
            else:
                img = g.render(self.dot_path)
            req.send(img, 'image/png')
        else:
            data = {}

            #add a context link to enable/disable labels in nodes
            if label_summary:
                add_ctxtnav(req, 'Without labels',
                            req.href(req.path_info, summary=0))
            else:
                add_ctxtnav(req, 'With labels',
                            req.href(req.path_info, summary=1))

            if milestone is None:
                tkt = Ticket(self.env, tkt_ids[0])
                data['tkt'] = tkt
                add_ctxtnav(req, 'Back to Ticket #%s' % tkt.id,
                            req.href.ticket(tkt.id))
            else:
                add_ctxtnav(req, 'Back to Milestone %s' % milestone,
                            req.href.milestone(milestone))
            data['milestone'] = milestone
            data['graph'] = g
            data['graph_render'] = partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            return 'depgraph.html', data, None
Exemple #22
0
    def process_timeline(self, req):
        """/hours view"""

        if 'update' in req.args:
            # Reset session vars
            for var in ('query_constraints', 'query_time', 'query_tickets'):
                if var in req.session:
                    del req.session[var]

        if self.process_query(req):
            """the user has clicked on the 'Save Query' button; redirect them"""
            return

        ### lifted from trac.ticket.query.QueryModule.process_request

        req.perm.assert_permission('TICKET_VIEW')

        constraints = self._get_constraints(req)
        if not constraints and not 'order' in req.args:
            # If no constraints are given in the URL, use the default ones.
            if req.authname and req.authname != 'anonymous':
                qstring = 'status!=bogus'
                user = req.authname
            else:
                email = req.session.get('email')
                name = req.session.get('name')
                qstring = 'status!=bogus'
                user = email or name or None

            if user:
                qstring = qstring.replace('$USER', user)
            self.log.debug('QueryModule: Using default query: %s',
                           str(qstring))

            constraints = Query.from_string(self.env, qstring).constraints
            # Ensure no field constraints that depend on $USER are used
            # if we have no username.

            for constraint_set in constraints:
                for field, vals in constraint_set.items():
                    for val in vals:
                        if val.endswith('$USER'):
                            del constraint_set[field]

        cols = req.args.get('col')
        if isinstance(cols, basestring):
            cols = [cols]

        if not cols:
            cols = ['id', 'summary'] + self.get_default_columns()

        # Since we don't show 'id' as an option to the user,
        # we need to re-insert it here.
        if cols and 'id' not in cols:
            cols.insert(0, 'id')

        rows = req.args.get('row', [])
        if isinstance(rows, basestring):
            rows = [rows]

        format = req.args.get('format')

        max = 0  # unlimited number of tickets

        # compute estimated hours even if not selected for columns
        rm_est_hours = False
        if not 'estimatedhours' in cols:
            cols.append('estimatedhours')
            rm_est_hours = True
        query = Query(self.env, req.args.get('report'), constraints, cols,
                      req.args.get('order'), 'desc' in req.args,
                      req.args.get('group'), 'groupdesc' in req.args, 'verbose'
                      in req.args, rows, req.args.get('page'), max)
        if rm_est_hours:  # if not in the columns, remove estimatedhours
            cols.pop()

        return self.display_html(req, query)