Exemple #1
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)
    def _get_permitted_tickets(self, req, constraints=None, columns=None):
        """
        If we don't pass a list of column/field values, the Query module 
        defaults to the first seven colums - see get_default_columns().
        """

        if columns is None:
            columns = []
        else:
            columns = columns[:] # avoid mutating callers list
        # make sure that we get certain ticket fields
        for f in ('summary', 'type', 'remaininghours', 'effort', 'date'):
            if f not in columns:
                columns.append(f)

        # what field data should we get
        query = Query(self.env, constraints=constraints, max=0, cols=columns)
        tickets = []
        for ticket in query.execute(req):
            if 'TICKET_VIEW' in req.perm('ticket', ticket['id']):
                for k in ('effort', 'remaininghours'):
                    try:
                        ticket[k] = float(ticket[k])
                    except KeyError:
                        pass
                    except TypeError:
                        ticket[k] = 0.0
                tickets.append(ticket)
        return tickets
Exemple #3
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 #4
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 #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_verbose(self):
        query = Query(self.env, order='id', verbose=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.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""")
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #7
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 #8
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 #9
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 #10
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.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""")
        self.assertEqual([], args)
        tickets = query.execute(Mock(href=self.env.href))
Exemple #11
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 #12
0
    def test_all_ordered_by_version_desc(self):
        query = Query(self.env, order='version', 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.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""")
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #13
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 #14
0
    def test_all_grouped_by_milestone_desc(self):
        query = Query(self.env, order='id', group='milestone', groupdesc=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.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.completed,0)=0 DESC,milestone.completed DESC,COALESCE(milestone.due,0)=0 DESC,milestone.due DESC,t.milestone DESC,COALESCE(t.id,0)=0,t.id""")
        self.assertEqual([], args)
        tickets = query.execute(self.req)
Exemple #15
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 #16
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 #17
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()
        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""")
        self.assertEqual([], args)
        tickets = query.execute(Mock(href=self.env.href))
Exemple #18
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 #19
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 #20
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 #21
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)
    def save_change(self, req, milestone):
        """Try to save changes and return new data, else return error dict.

        As with getting ticket data, we check for a custom save method,
        and else use the standard implementation
        """
        try:
            ticket_id = int(req.args.get("ticket"))
        except (ValueError, TypeError):
            return self._save_error(req, ["Must supply a ticket to change"])

        field = req.args.get("group_name")
        if not field or re.search("[^a-zA-Z0-9_]", field):
            return self._save_error(req, ["Invalid field name"])
        else:
            # Check to see if we process this field in a unique way
            try:
                save_f = getattr(self, "_save_%s_change" % field)
            except AttributeError:
                save_f = self._save_standard_change_

            # Try to save the ticket using the relevant save method
            try:
                if save_f.__name__ == "_save_standard_change_":
                    save_f(req, ticket_id, field, req.args.get("value"))
                else:
                    save_f(req, ticket_id, req.args.get("action"))

                # Retrieve new ticket information
                query = Query(self.env,
                              constraints={'id': [str(ticket_id)]},
                              cols=['id', 'type', 'effort', 'remaininghours'])
                results = query.execute(req)
                req.perm('ticket', ticket_id).require('TICKET_VIEW')
                for k in ('effort', 'remaininghours'):
                    try:
                        results[0][k] = float(results[0][k])
                    except KeyError:
                        pass
                return self.get_ticket_data(req, milestone, field, results)
            except ValueError, e:
                return self._save_error(req, list(e))
            except TracError, e:
                return self._save_error(req, [e])
Exemple #23
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 #24
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 #25
0
		# pulled directly from request.GET.
		query_module = QueryModule(self.env)
		req = FakeTracRequest(request)
		constraints = query_module._get_constraints(req)
		
		qd = request.GET
		
		kwargs = {
			'cols': qd.getlist('col'),
			'rows': qd.getlist('row'),
			'constraints': constraints
		}
		
		kwargs.update(dict([
			(k, qd.get(k))
			for k in ('format', 'max', 'report', 'order', 'group', 'page')
		]))
		
		kwargs.update(dict([
			(k, k in qd) for k in 'desc', 'groupdesc', 'verbose'
		]))
		
		orig_list = None
		orig_time = datetime.now(utc)
		query = Query(self.env, **kwargs)
		tickets = query.execute()
		return tickets
	
	def get_attachment(self, request):
		pass
Exemple #26
0
    def process_request(self, req):
        path_info = req.path_info[10:]

        img_format = req.args.get('format')
        m = self.IMAGE_RE.search(path_info)
        is_img = m is not None
        if is_img:
            img_format = m.group(1)
            path_info = path_info[:-(10+len(img_format))]

        is_full_graph = not path_info
        with_clusters   = req.args.getbool('with_clusters', False)

        cur_pid = self.pm.get_current_project(req)

        #list of tickets to generate the depgraph for
        tkt_ids=[]

        if is_full_graph:
            # depgraph for full project
            # cluster by milestone
            self.pm.check_component_enabled(self, pid=cur_pid)
            db = self.env.get_read_db()
            cursor = db.cursor()
            if with_clusters:
                q = '''
                    SELECT milestone, id
                    FROM ticket
                    WHERE project_id=%s
                    ORDER BY milestone, id
                '''
            else:
                q = '''
                    SELECT id
                    FROM ticket
                    WHERE project_id=%s
                    ORDER BY id
                '''
            cursor.execute(q, (cur_pid,))
            rows = cursor.fetchall()
            if with_clusters:
                tkt_ids = rows
            else:
                tkt_ids = [r[0] for r in rows]
        else:
            # degraph for resource
            resource = get_real_resource_from_url(self.env, path_info, req.args)

            # project check
            res_pid = resource.pid
            self.pm.check_component_enabled(self, pid=res_pid)
            if res_pid != cur_pid:
                self.pm.redirect_to_project(req, res_pid)

            is_milestone = isinstance(resource, Milestone)
            #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 is_milestone:
                #we need to query the list of tickets in the milestone
                milestone = resource
                query=Query(self.env, constraints={'milestone' : [milestone.name]}, max=0, project=milestone.pid)
                tkt_ids=[fields['id'] for fields in query.execute()]
            else:
                #the list is a single ticket
                ticket = resource
                tkt_ids = [ticket.id]

        #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'))

        clustering = is_full_graph and with_clusters
        g = self._build_graph(req, tkt_ids, label_summary=label_summary, with_clusters=clustering)
        if is_img or img_format:
            if img_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 img_format == 'debug':
                import pprint
                req.send(
                    pprint.pformat(
                        [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]
                        ),
                    'text/plain')
            elif img_format == 'svg':
                req.send(g.render(self.dot_path, img_format), 'image/svg+xml')
            elif img_format is not None:
                req.send(g.render(self.dot_path, img_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 = {
                'graph': g,
                'graph_render': partial(g.render, self.dot_path),
                'use_gs': self.use_gs,
                'full_graph': is_full_graph,
                'img_format': self.default_format,
                'summary': label_summary,
                'with_clusters': with_clusters,
            }

            if is_full_graph:
                rsc_url = None
            else:
                if is_milestone:
                    resource = milestone.resource
                    add_ctxtnav(req, _('Back to Milestone %(name)s', name=milestone.name),
                                get_resource_url(self.env, resource, req.href))
                    data['milestone'] = milestone.name
                else: # ticket
                    data['tkt'] = ticket
                    resource = ticket.resource
                    add_ctxtnav(req, _('Back to Ticket #%(id)s', id=ticket.id),
                                get_resource_url(self.env, resource, req.href))
                rsc_url = get_resource_url(self.env, resource)

            data['img_url'] = req.href.depgraph(rsc_url, 'depgraph.%s' % self.default_format,
                                                summary=g.label_summary, with_clusters=int(with_clusters))

            return 'depgraph.html', data, None
Exemple #27
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')
 def _get_permitted_tickets(self, req, constraints=None):
     qry = Query(self.env, constraints=constraints, cols=self.fields, max=0, order="_dynamic")
     return [ticket for ticket in qry.execute(req)
             if 'TICKET_VIEW' in req.perm('ticket', ticket['id'])]
    def process_request(self, req):
        realm = req.args['realm']
        id = req.args['id']

        #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 for
        tkt_ids = []
        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:
            #the list is a single ticket
            tkt_ids = [int(id)]

        #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, 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:
                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'] = partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            return 'depgraph.html', data, None
Exemple #30
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
 def _load_ticket_ids(self):
     query = Query(self.env, cols=['id'], order='id')
     return query.execute()
Exemple #32
0
    def _make_data(self,req,opts):
        arg_x_min = opts['start']
        arg_x_max = opts['end']
        per = opts['per']
        query_str = opts['query']
        fieldlist = opts['col']
        upper = opts['upper']
        
        if len(query_str)>1 and query_str[0]!='?':
            query_str = query_str + ''.join(['&col=%s'%field
                                             for field in fieldlist])
            query = Query.from_string(self.env, query_str)
        elif len(query_str)>1 and query_str[0]=='?':
            constraints = self._get_constraints(self._urlstring_to_reqarg(query_str))
            query = Query(self.env, constraints=constraints, cols=fieldlist)
        else:
            constraints = self._get_constraints(req.args)
            query = Query(self.env, constraints=constraints, cols=fieldlist)
                          
        self.log.debug(query.get_sql())
        result = query.execute(req, db=None, cached_ids=None)
        result_len = len(result)
        daylists = []
        edgedays = []
        for fieldname in fieldlist:
            daylist =[]
            dayids = {}
            for ticket in result:
                try:
                    dtin = ticket[fieldname]

                    # parse date
                    if isinstance(dtin, (str,unicode)):
                        dt = parse_date(dtin)
                    else:
                        dt = to_datetime(dtin)
                except:
                    continue

                d = datetime(dt.year,dt.month,dt.day,tzinfo=req.tz)
                daylist.append(d)


            daylists.append( (daylist,dayids) )

            if len(daylist)>0 :
                edgedays.append(min(daylist))
                edgedays.append(max(daylist))

        if len(edgedays)==0:
            return None#'''No data to output.'''

        x_min = arg_x_min or min(edgedays)
        x_max = arg_x_max or max(edgedays)
        x_min = datetime(x_min.year,x_min.month,x_min.day,tzinfo=x_min.tzinfo)
        x_max = datetime(x_max.year,x_max.month,x_max.day,tzinfo=x_max.tzinfo)

        if per=='week':
            x_axis = [x_min+timedelta(x)
                      for x in range(0,(x_max-x_min).days+7,7)]
            x_max = x_axis[-1] # As x_axis[-1] may be larger than x_max.
        else: #'day','free'
            x_axis = [x_min+timedelta(x)
                      for x in range(0,(x_max-x_min).days+1)]

        counts={}
        linenum = 0
        for daylist,dayids in daylists:
            for x in x_axis:
                
                count = len([1 for c in daylist if c <= x])
                #ids = [dayids[c] for c in daylist if c <= x and c>last_x ]
                #points.append(Point(x,count))
                if not upper:
                    count = result_len - count
                counts[(x,linenum)] = count
            linenum += 1


        return {'x_axis':x_axis,
                'counts':counts,
                'linenum':linenum,
                'x_min':x_min,
                'x_max':x_max,
                'fieldlist':fieldlist,
                'result_len':result_len}