Example #1
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.req = Mock(base_path='', chrome={}, args={}, session={},
                     abs_href=Href('/'), href=Href('/'), locale='',
                     perm=MockPerm(), authname=None, tz=None)
     self.report_module = ReportModule(self.env)
Example #2
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.report_module = ReportModule(self.env)
Example #3
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.report_module = ReportModule(self.env)
Example #4
0
    def test_invalid_post_request_raises_exception(self):
        req = MockRequest(self.env, method='POST', action=None)

        self.assertRaises(HTTPBadRequest,
                          ReportModule(self.env).process_request, req)
Example #5
0
    def test_asc_argument_is_invalid(self):
        """Invalid value for `asc` argument is coerced to default."""
        req = MockRequest(self.env, args={'asc': '--'})

        self.assertRaises(HTTPBadRequest,
                          ReportModule(self.env).process_request, req)
Example #6
0
def run0(req, env, db, content):
    args = parse(content or '')
    items = []
    summary = None
    ticket = default_ticket_field
    summaries = {}
    inline = False
    nosort = False
    inline_total = False
    title = "Tickets"
    styles = default_styles.copy()
    args_re = re.compile("^(?:" + string.join(args_pat, "|") + ")$")
    # process options first
    for arg in args:
        match = args_re.match(arg)
        if not match:
            env.log.debug('TicketBox: unknown arg: %s' % arg)
            continue
        elif match.group('title'):
            title = match.group('title')[1:-1]
        elif match.group('width'):
            styles['width'] = match.group('width')
        elif match.group('keyword'):
            kw = match.group('keyword').lower()
            kwarg = unquote(match.group('kwarg') or '')
            if kw == 'summary':
                summary = kwarg or default_summary_field
            elif kw == 'ticket':
                ticket = kwarg or default_ticket_field
            elif kw == 'inline':
                inline = True
            elif kw == 'nosort':
                nosort = True
            elif kw == 'nowrap':
                styles['white-space'] = 'nowrap'
            elif kw == 'inline_total':
                inline_total = True
            elif kw in styles and kwarg:
                styles[kw] = kwarg
    # pick up ticket numbers and report numbers
    for arg in args:
        sql = None
        params = []
        match = args_re.match(arg)
        id_name = ticket
        sidx = iidx = -1
        if not match:
            continue
        elif match.group('tktnum'):
            items.append(int(match.group('tktnum')))
        elif match.group('query'):
            if not has_query:
                raise Exception('You cannot use trac query for this version of trac')
            q = Query.from_string(env, match.group('query'))
            sql, params = call(q.get_sql, locals())
            id_name = 'id'
        elif match.group('rptnum') or match.group('rptnum2'):
            num = match.group('rptnum') or match.group('rptnum2')
            #env.log.debug('dynamic variables = %s' % dv)
            curs = db.cursor()
            try:
                curs.execute('SELECT %s FROM report WHERE id=%s'
                             % (report_query_field, num))
                rows = curs.fetchall()
                if len(rows) == 0:
                    raise Exception("No such report: %s"  % num)
                sql = rows[0][0]
            finally:
                curs.close()
            if sql:
                sql = sql.strip()
                if has_query and sql.lower().startswith("query:"):
                    if sql.lower().startswith('query:?'):
                        raise Exception('URL style of query string is not supported.')
                    q = Query.from_string(env, sql[6:])
                    sql, params = call(q.get_sql, locals())
                    id_name = 'id'
        if sql:
            if not params:
                # handle dynamic variables
                # NOTE: sql_sub_vars() takes different arguments in
                #       several trac versions.
                #       For 0.10 or before, arguments are (req, query, args)
                #       For 0.10.x, arguments are (req, query, args, db)
                #       For 0.11 or later, arguments are (query, args, db)
                dv = ReportModule(env).get_var_args(req)
                sql, params = call(ReportModule(env).sql_sub_vars, locals())
            try:
                #env.log.debug('sql = %s' % sql)
                curs = db.cursor()
                curs.execute(sql, params)
                rows = curs.fetchall()
                if rows:
                    descriptions = [desc[0] for desc in curs.description]
                    try:
                        iidx = descriptions.index(id_name)
                    except:
                        raise Exception('No such column for ticket number: %r'
                                        % id_name )
                    if summary:
                        try:
                            sidx = descriptions.index(summary)
                        except:
                            raise Exception('No such column for summary: %r'
                                            % summary)
                    for row in rows:
                        items.append(row[iidx])
                        if summary and 0 <= sidx:
                            summaries[row[iidx]] = row[sidx]
            finally:
                curs.close()

    if summary:
        # get summary text
        for id in items:
            if summaries.get(id):
                continue
            tkt = Ticket(env, tkt_id=id)
            if not tkt:
                continue
            summaries[id] = tkt['summary']
    
    items = uniq(items)
    if not nosort:
        items.sort()
    html = ''

    if inline_total:
        # return simple text of total count to be placed inline.
        return '<span class="ticketbox"><span id="total">%s</span></span>' \
            % len(items)
    
    if ver < [0, 11]:
        fargs = dict(db=db)
    else:
        fargs = dict(db=db, req=req)
    if summary:
        format = '%(summary)s (%(id)s)'
        sep = '<br/>'
    else:
        format = '%(id)s'
        sep = ', '
    lines = []
    for n in items:
        kwds = dict(id="#%d" % n)
        if summary:
            kwds['summary'] = summaries[n]
        lines.append(wiki_to_oneliner(format % kwds, env, **fargs))
    html = sep.join(lines)
    if html:
        try:
            title = title % len(items)  # process %d in title
        except:
            pass
        if inline:
            for key in ['float', 'width']:
                del styles[key]
        style = ';'.join(["%s:%s" % (k,v) for k,v in styles.items() if v])
        return '<fieldset class="ticketbox" style="%s"><legend>%s</legend>%s</fieldset>' % \
               (style, title, html)
    else:
        return ''
Example #7
0
    def render_macro(self, req, name, txt):
        env = self.env
        hdf = req.hdf

        # get trac version
        ver = [int(x) for x in version.split(".")]

        ## default style values
        styles = {
            "float": "right",
            "background": "#f7f7f0",
            "width": "25%",
        }
        inline_styles = {
            "background": "#f7f7f0",
        }

        args_pat = [
            r"#?(?P<tktnum>\d+)", r"{(?P<rptnum>\d+)}",
            r"\[report:(?P<rptnum2>\d+)(?P<dv>\?.*)?\]",
            r"(?P<width>\d+(pt|px|%))", r"(?P<jourshomme>jourshomme)",
            r"(?P<table_report>table_report)",
            r"(?P<ticket_report>ticket_report)",
            r"(?P<do_not_group_none>do_not_group_none)",
            r"(?P<summary>summary)", r"(?P<inline>inline)",
            r"(?P<title1>'.*')", r'(?P<title2>".*")'
        ]

        ##def execute(hdf, txt, env):
        if not txt:
            txt = ''
        items = []
        long_items = {}
        show_summary = False
        inline = False
        title = "Tickets"
        table_report_option = False
        ticket_report_option = False
        do_not_group_none = True
        theader = ''
        args_re = re.compile("^(?:" + string.join(args_pat, "|") + ")$")
        for arg in [string.strip(s) for s in txt.split(',')]:
            match = args_re.match(arg)
            if not match:
                env.log.debug('TicketBox: unknown arg: %s' % arg)
                continue
            elif match.group('title1'):
                title = match.group('title1')[1:-1]
            elif match.group('title2'):
                title = match.group('title2')[1:-1]
            elif match.group('width'):
                styles['width'] = match.group('width')
            elif match.group('tktnum'):
                items.append(int(match.group('tktnum')))
            elif match.group('summary'):
                show_summary = True
            elif match.group('table_report'):
                table_report_option = True
            elif match.group('ticket_report'):
                ticket_report_option = True
            elif match.group('do_not_group_none'):
                do_not_group_none = False
            elif match.group('inline'):
                inline = True
        for arg in [string.strip(s) for s in txt.split(',')]:
            match = args_re.match(arg)
            if match.group('rptnum') or match.group('rptnum2'):
                num = match.group('rptnum') or match.group('rptnum2')
                dv = {}
                # username, do not override if specified
                if not dv.has_key('USER'):
                    dv['USER'] = hdf.getValue('trac.authname', 'anonymous')
                if match.group('dv'):
                    for expr in string.split(match.group('dv')[1:], '&'):
                        k, v = string.split(expr, '=')
                        dv[k] = v
                #env.log.debug('dynamic variables = %s' % dv)
                db = env.get_db_cnx()
                curs = db.cursor()
                try:
                    curs.execute('SELECT query FROM report WHERE id=%s' % num)
                    (query, ) = curs.fetchone()
                    # replace dynamic variables with sql_sub_vars()
                    # NOTE: sql_sub_vars() takes different arguments in
                    #       several trac versions.
                    #       For 0.10 or before, arguments are (req, query, args)
                    #       For 0.10.x, arguments are (req, query, args, db)
                    #       For 0.11 or later, arguments are (query, args, db)
                    if ver <= [0, 10]:
                        args = (req, query, dv)  # for 0.10 or before
                    elif ver < [0, 11]:
                        args = (req, query, dv, db)  # for 0.10.x
                    else:
                        args = (query, dv, db)  # for 0.11 or later
                    query, dv = ReportModule(env).sql_sub_vars(*args)
                    #env.log.debug('query = %s' % query)
                    curs.execute(query, dv)
                    rows = curs.fetchall()
                    if rows:
                        descriptions = [desc[0] for desc in curs.description]

                        env.log.debug('TEST %s' % descriptions)

                        for descriptions_item in descriptions:
                            theader = theader + '<td> %s </td>' % descriptions_item

                        if do_not_group_none == False:
                            idx = descriptions.index('milestone')
                        else:
                            idx = descriptions.index('ticket')

                        for row in rows:
                            items.append(row[idx])

                            if table_report_option:
                                table_field = ''
                                for descriptions_item in descriptions:
                                    if descriptions_item == 'ticket':
                                        table_field = table_field + '<td> %s </td>' % wiki_to_oneliner(
                                            "#%s" % row[descriptions.index(
                                                descriptions_item)], env,
                                            env.get_db_cnx())
                                    else:
                                        table_field = table_field + '<td> %s </td>' % row[
                                            descriptions.index(
                                                descriptions_item)]
                                long_items[row[idx]] = table_field
                            elif ticket_report_option:
                                table_field = ''
                                for descriptions_item in descriptions:
                                    if descriptions_item == 'ticket':
                                        table_field = table_field + '<li>' + descriptions_item + ': %s' % wiki_to_oneliner(
                                            "#%s" % row[descriptions.index(
                                                descriptions_item)], env,
                                            env.get_db_cnx()) + '</li>'
                                    elif descriptions_item != 'description' and descriptions_item != 'summary':
                                        table_field = table_field + '<li>' + descriptions_item + ': %s, ' % row[
                                            descriptions.index(
                                                descriptions_item)] + '</li>'
                                    long_items[row[idx]] = '<b>%s</b><br/>' % row[
                                        descriptions.index(
                                            'summary'
                                        )] + '<ul>' + table_field + ' </ul>' + wiki_to_html(
                                            row[descriptions.index(
                                                "description")] or '', env,
                                            req, env.get_db_cnx())
                            else:
                                summ = descriptions.index('summary')
                                long_items[row[idx]] = row[summ]
                finally:
                    if not hasattr(env, 'get_cnx_pool'):
                        # without db connection pool, we should close db.
                        curs.close()
                        db.close()

        y = []
        for i in items:
            if not y.count(i):
                y.append(i)

        items = y
        items.sort()
        html = ''
        tfooter = ''
        if show_summary:
            html = string.join([
                wiki_to_oneliner("%s (#%d)" % (v, k), env, env.get_db_cnx())
                for k, v in long_items.iteritems()
            ], "<br>")
        elif table_report_option:
            for k, v in long_items.iteritems():
                if "#%s" % k == "#None" and do_not_group_none and do_not_group_none:
                    tfooter = "<tfoot>%s</tfoot>" % v
                else:
                    html = html + "<tr>%s</tr>" % v
        elif ticket_report_option:
            for k, v in long_items.iteritems():
                if "#%s" % k != "#None":
                    html = html + "%s" % v
        else:
            html = wiki_to_oneliner(
                string.join(["#%s" % c for c in items], ", "), env,
                env.get_db_cnx())

        if html != '':
            try:
                title = title % len(items)  # process %d in title
            except:
                pass
            if inline:
                style = string.join([
                    "%s:%s" % (k, v)
                    for k, v in inline_styles.items() if v <> ""
                ], "; ")
            else:
                style = string.join(
                    ["%s:%s" % (k, v) for k, v in styles.items() if v <> ""],
                    "; ")

            if table_report_option:
                return '<table border=1><caption>' + title + '</caption><thead>' + theader + '</thead><tbody>' + html + '</tbody>' + tfooter + '</table>'
            if ticket_report_option:
                return html
            else:
                return '<fieldset class="ticketbox" style="%s"><legend>%s</legend>%s</fieldset>' % \
                   (style, title, html)
        else:
            return ''
Example #8
0
 def get_report_data(self, req, id):
     db = self.env.get_db_cnx()
     _template, data, _content_type = ReportModule(self.env)._render_view(
         req, db, id)
     return data
Example #9
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/report'):
            data['main_reports'] = [int(id) for id in self.main_reports]
            data['available_reports'] = self.available_reports(req)
        if data and data.get('row_groups'):
            id = req.args.get('id')
            action = req.args.get('action', 'view')
            header_groups = data.get('header_groups')
            row_groups = data.get('row_groups')

            if id and action == 'view':
                req.session['last_used_report'] = id
                if header_groups and len(header_groups) > 0:
                    all_col_names = [
                        col['col'] for header_group in header_groups
                        for col in header_group
                    ]
                    data['column_classes'] = dict(
                        [ (key, value.get('classname')) \
                            for key, value in self.fields_config().items() \
                                if key in all_col_names])
                    if self._are_all_mandatory_fields_found(all_col_names):
                        id_col = all_col_names[0]

                        args = ReportModule(self.env).get_var_args(req)
                        db = self.env.get_db_cnx()
                        cursor = db.cursor()
                        cursor.execute("SELECT query FROM report WHERE id=%s",
                                       (id, ))
                        sql, = cursor.fetchone()
                        sql, args = ReportModule(self.env).sql_sub_vars(
                            sql, args, db)
                        cursor.execute("SELECT DISTINCT __group__, __group_preset__, count("+id_col+") as q, count(*) as fq "+\
                            "FROM (%s) as group_config GROUP BY  __group__, __group_preset__" % sql, args)

                        exec_groups = [(group, preset, quantity, full_quantity)
                                       for group, preset, quantity,
                                       full_quantity in cursor]
                        data['exec_groups'] = req.args[
                            'exec_groups'] = exec_groups
                        paginator = data['paginator']
                        range_start, range_end = paginator.span

                        num_rows = 0
                        num_none_filtered = 0
                        for x, y, quantity, full_quantity in exec_groups:
                            num_rows = num_rows + quantity
                            num_none_filtered = num_none_filtered + full_quantity
                            delta = full_quantity - quantity
                            if range_start and delta and range_start > num_none_filtered:
                                range_start = range_start - delta
                                range_end = range_end - delta

                        paginator.num_items = num_rows

                        num_filtered_on_page = 0
                        for i, (value_for_group,
                                row_group) in enumerate(row_groups):
                            filtered_row_group = [
                                row for row in row_group
                                if (('id' not in row) or row['id'])
                            ]
                            row_groups[i] = (value_for_group,
                                             filtered_row_group)
                            range_end = range_end - (len(row_group) -
                                                     len(filtered_row_group))
                        if range_end > paginator.num_items:
                            range_end = paginator.num_items
                        paginator.span = range_start, range_end
        return (template, data, content_type)