Changeset 4088

Show
Ignore:
Timestamp:
07/30/08 15:03:51 (4 months ago)
Author:
gotoh
Message:

Unify the versions for 0.9, 0.10, 0.11 and 0.12.
Tested on 0.9.6, 0.10.5, 0.11 and 0.12dev-r7419.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ticketboxmacro/0.11/TicketBox.py

    r4087 r4088  
    1212[[TicketBox([report:1])]]              ... alternate format of report 
    1313[[TicketBox([report:9?name=val])]]     ... report with dynamic variable 
    14 [[TicketBox({1},#50,{2},100)]]         ... convination of above 
     14[[TicketBox([query:status=new])]]]     ... query string 
     15[[TicketBox({1},[query:status=new])]]  ... conbination 
    1516[[TicketBox(500pt,{1})]]               ... with box width as 50 point 
    1617[[TicketBox(200px,{1})]]               ... with box width as 200 pixel 
     
    4142import re 
    4243import string 
     44from trac import __version__ as version 
    4345from trac.wiki.formatter import wiki_to_oneliner 
    4446from trac.ticket.report import ReportModule 
    4547from trac.ticket.model import Ticket 
     48try: 
     49    from trac.ticket.query import Query 
     50    has_query = True 
     51except: 
     52    has_query = False 
     53 
     54## Mock request object for trac 0.10.x or before 
     55class MockReq(object): 
     56    def __init__(self, hdf): 
     57        self.hdf = dict() 
     58        self.args = {} 
     59        self.authname = hdf.getValue('trac.authname', 'anonymous') 
     60         
     61 
     62# get trac version 
     63verstr = re.compile('([0-9.]+).*').match(version).group(1) 
     64ver = [int(x) for x in verstr.split(".")] 
     65 
     66if ver <= [0, 10]: 
     67    report_query_field = 'sql' 
     68    call_args = dict(get_sql=[], 
     69                     sql_sub_vars=['req', 'sql', 'dv'], 
     70                     ) 
     71elif ver < [0, 11]: 
     72    report_query_field = 'query' 
     73    call_args = dict(get_sql=[], 
     74                     sql_sub_vars=['req', 'sql', 'dv', 'db'], 
     75                     ) 
     76else: 
     77    report_query_field = 'query' 
     78    call_args = dict(get_sql=['req'], 
     79                     sql_sub_vars=['sql', 'dv', 'db'], 
     80                     ) 
    4681 
    4782## default style values 
    4883default_styles = { "float": "right", 
     84                   "color": None, 
    4985                   "background": "#f7f7f0", 
    5086                   "width": "25%", 
     87                   "border-color": None, 
    5188                   } 
    5289 
     
    5491            r"{(?P<rptnum>\d+)}", 
    5592            r"\[report:(?P<rptnum2>\d+)(?P<dv>\?.*)?\]", 
     93            r"\[query:(?P<query>[^\]]*)\]", 
    5694            r"(?P<width>\d+(pt|px|%))", 
    5795            r"(?P<title>'[^']*'|\"[^\"]*\")", 
     
    134172        result.append(item) 
    135173    return result 
     174 
     175def call(func, vars): 
     176    from win32api import OutputDebugString as dbg 
     177    names = call_args[func.__name__] 
     178    args = [vars[x] for x in names] 
     179    dbg('call: ' + ', '.join(['%s=%s' % (k,v) for k,v in zip(names, args)])) 
     180    return func(*args) 
    136181     
    137 def execute(formatter, content): 
    138     req = formatter.req 
    139     env = formatter.env 
     182def run0(req, env, db, content): 
    140183    args = parse(content or '') 
    141184    items = [] 
     
    169212            elif kw == 'nosort': 
    170213                nosort = True 
     214            elif kw == 'nowrap': 
     215                styles['white-space'] = 'nowrap' 
    171216            elif kw in styles and kwarg: 
    172217                styles[kw] = kwarg 
    173218    # pick up ticket numbers and report numbers 
    174219    for arg in args: 
     220        sql = None 
     221        params = [] 
    175222        match = args_re.match(arg) 
     223        id_name = ticket 
     224        sidx = iidx = -1 
    176225        if not match: 
    177226            continue 
    178227        elif match.group('tktnum'): 
    179228            items.append(int(match.group('tktnum'))) 
     229        elif match.group('query'): 
     230            if not has_query: 
     231                raise Exception('You cannot use trac query for this version of trac') 
     232            q = Query.from_string(env, match.group('query')) 
     233            sql, params = call(q.get_sql, locals()) 
     234            id_name = 'id' 
    180235        elif match.group('rptnum') or match.group('rptnum2'): 
    181236            num = match.group('rptnum') or match.group('rptnum2') 
    182             dv = {} 
    183             # username, do not override if specified 
    184             if not dv.has_key('USER'): 
    185                 dv['USER'] = req.authname 
    186             if match.group('dv'): 
    187                 for expr in string.split(match.group('dv')[1:], '&'): 
    188                     k, v = string.split(expr, '=') 
    189                     dv[k] = v 
    190237            #env.log.debug('dynamic variables = %s' % dv) 
    191             db = env.get_db_cnx() 
    192238            curs = db.cursor() 
    193239            try: 
    194                 curs.execute('SELECT query FROM report WHERE id=%s' % num) 
    195                 (query,) = curs.fetchone() 
    196                 # replace dynamic variables with sql_sub_vars() 
     240                curs.execute('SELECT %s FROM report WHERE id=%s' 
     241                             % (report_query_field, num)) 
     242                rows = curs.fetchall() 
     243                if len(rows) == 0: 
     244                    raise Exception("No such report: %s"  % num) 
     245                sql = rows[0][0] 
     246            finally: 
     247                curs.close() 
     248            if sql: 
     249                sql = sql.strip() 
     250                if has_query and sql.lower().startswith("query:"): 
     251                    if sql.lower().startswith('query:?'): 
     252                        raise Exception('URL style of query string is not supported.') 
     253                    q = Query.from_string(env, sql[6:]) 
     254                    sql, params = call(q.get_sql, locals()) 
     255                    id_name = 'id' 
     256        if sql: 
     257            if not params: 
     258                # handle dynamic variables 
    197259                # NOTE: sql_sub_vars() takes different arguments in 
    198260                #       several trac versions. 
     
    200262                #       For 0.10.x, arguments are (req, query, args, db) 
    201263                #       For 0.11 or later, arguments are (query, args, db) 
    202                 query, dv = ReportModule(env).sql_sub_vars(query, dv, db) 
    203                 #env.log.debug('query = %s' % query) 
    204                 curs.execute(query, dv) 
     264                dv = ReportModule(env).get_var_args(req) 
     265                sql, params = call(ReportModule(env).sql_sub_vars, locals()) 
     266            try: 
     267                #env.log.debug('sql = %s' % sql) 
     268                curs = db.cursor() 
     269                curs.execute(sql, params) 
    205270                rows = curs.fetchall() 
    206271                if rows: 
    207272                    descriptions = [desc[0] for desc in curs.description] 
    208273                    try: 
    209                         idx = descriptions.index(ticket
     274                        iidx = descriptions.index(id_name
    210275                    except: 
    211                         raise Exception('No such column for ticket: %r' 
    212                                         % ticket
     276                        raise Exception('No such column for ticket number: %r' 
     277                                        % id_name
    213278                    if summary: 
    214279                        try: 
     
    218283                                            % summary) 
    219284                    for row in rows: 
    220                         items.append(row[idx]) 
    221                         if summary
    222                             summaries[row[idx]] = row[sidx] 
     285                        items.append(row[iidx]) 
     286                        if summary and 0 <= sidx
     287                            summaries[row[iidx]] = row[sidx] 
    223288            finally: 
    224                 if not hasattr(env, 'get_cnx_pool'): 
    225                     # without db connection pool, we should close db. 
    226                     curs.close() 
    227                     db.close() 
     289                curs.close() 
     290 
    228291    if summary: 
    229292        # get summary text 
     
    240303        items.sort() 
    241304    html = '' 
     305 
     306    if ver < [0, 11]: 
     307        fargs = dict(db=db) 
     308    else: 
     309        fargs = dict(db=db, req=req) 
    242310    if summary: 
    243         html = string.join([wiki_to_oneliner("%s (#%d)" % (summaries[n],n), 
    244                                              env, 
    245                                              env.get_db_cnx(), 
    246                                              req=formatter.req) for n in items], "<br>") 
    247     else: 
    248         html = wiki_to_oneliner(string.join(["#%d" % c for c in items], ", "), 
    249                                 env, env.get_db_cnx(), req=formatter.req) 
    250     if html != '': 
     311        format = '%(summary)s (%(id)s)' 
     312        sep = '<br/>' 
     313    else: 
     314        format = '%(id)s' 
     315        sep = ', ' 
     316    lines = [] 
     317    for n in items: 
     318        kwds = dict(id="#%d" % n) 
     319        if summary: 
     320            kwds['summary'] = summaries[n] 
     321        lines.append(wiki_to_oneliner(format % kwds, env, **fargs)) 
     322    html = sep.join(lines) 
     323    if html: 
    251324        try: 
    252325            title = title % len(items)  # process %d in title 
     
    262335        return '' 
    263336 
    264  
    265 from trac.wiki.macros import WikiMacroBase 
    266  
    267 class TicketBoxMacro(WikiMacroBase): 
    268  
    269     def expand_macro(self, formatter, name, args): 
    270         """Return some output that will be displayed in the Wiki content. 
    271  
    272         `name` is the actual name of the macro (no surprise, here it'll be 
    273         `'HelloWorld'`), 
    274         `args` is the text enclosed in parenthesis at the call of the macro. 
    275           Note that if there are ''no'' parenthesis (like in, e.g. 
    276           [[HelloWorld]]), then `args` is `None`. 
    277         """ 
    278         return execute(formatter, args) 
    279  
     337def run(req, env, content): 
     338    db = env.get_db_cnx() 
     339    try: 
     340        return run0(req, env, db, content) 
     341    finally: 
     342        if db and not hasattr(env, 'get_cnx_pool'): 
     343            # for old version which does not have db connection pool, 
     344            # we should close db. 
     345            db.close() 
     346 
     347# single file macro I/F (not plugin, for 0.10.x or before) 
     348def execute(hdf, txt, env): 
     349    req = MockReq(hdf) 
     350    return run(req, env, txt) 
     351 
     352 
     353try: 
     354    from trac.wiki.macros import WikiMacroBase 
     355 
     356    class TicketBoxMacro(WikiMacroBase): 
     357 
     358        # plugin macro I/F for trac 0.10.x 
     359        def render_macro(self, req, name, content): 
     360            db = env.get_db_cnx() 
     361            try: 
     362                run(req, self.env, db, content) 
     363            finally: 
     364                if db and not hasattr(env, 'get_cnx_pool'): 
     365                    # for old version which does not have db connection pool, 
     366                    # we should close db. 
     367                    db.close() 
     368 
     369        # plugin macro I/F for trac 0.11 or later 
     370        def expand_macro(self, formatter, name, args): 
     371            """Return some output that will be displayed in the Wiki content. 
     372 
     373            `name` is the actual name of the macro (no surprise, here it'll be 
     374            `'HelloWorld'`), 
     375            `args` is the text enclosed in parenthesis at the call of the macro. 
     376              Note that if there are ''no'' parenthesis (like in, e.g. 
     377              [[HelloWorld]]), then `args` is `None`. 
     378            """ 
     379            return run(formatter.req, formatter.env, args) 
     380except ImportError: 
     381    # trac 0.9 
     382    pass 
    280383 
    281384if __name__ == '__main__':