Changeset 4088
- Timestamp:
- 07/30/08 15:03:51 (4 months ago)
- Files:
-
- ticketboxmacro/0.11/TicketBox.py (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
ticketboxmacro/0.11/TicketBox.py
r4087 r4088 12 12 [[TicketBox([report:1])]] ... alternate format of report 13 13 [[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 15 16 [[TicketBox(500pt,{1})]] ... with box width as 50 point 16 17 [[TicketBox(200px,{1})]] ... with box width as 200 pixel … … 41 42 import re 42 43 import string 44 from trac import __version__ as version 43 45 from trac.wiki.formatter import wiki_to_oneliner 44 46 from trac.ticket.report import ReportModule 45 47 from trac.ticket.model import Ticket 48 try: 49 from trac.ticket.query import Query 50 has_query = True 51 except: 52 has_query = False 53 54 ## Mock request object for trac 0.10.x or before 55 class 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 63 verstr = re.compile('([0-9.]+).*').match(version).group(1) 64 ver = [int(x) for x in verstr.split(".")] 65 66 if ver <= [0, 10]: 67 report_query_field = 'sql' 68 call_args = dict(get_sql=[], 69 sql_sub_vars=['req', 'sql', 'dv'], 70 ) 71 elif ver < [0, 11]: 72 report_query_field = 'query' 73 call_args = dict(get_sql=[], 74 sql_sub_vars=['req', 'sql', 'dv', 'db'], 75 ) 76 else: 77 report_query_field = 'query' 78 call_args = dict(get_sql=['req'], 79 sql_sub_vars=['sql', 'dv', 'db'], 80 ) 46 81 47 82 ## default style values 48 83 default_styles = { "float": "right", 84 "color": None, 49 85 "background": "#f7f7f0", 50 86 "width": "25%", 87 "border-color": None, 51 88 } 52 89 … … 54 91 r"{(?P<rptnum>\d+)}", 55 92 r"\[report:(?P<rptnum2>\d+)(?P<dv>\?.*)?\]", 93 r"\[query:(?P<query>[^\]]*)\]", 56 94 r"(?P<width>\d+(pt|px|%))", 57 95 r"(?P<title>'[^']*'|\"[^\"]*\")", … … 134 172 result.append(item) 135 173 return result 174 175 def 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) 136 181 137 def execute(formatter, content): 138 req = formatter.req 139 env = formatter.env 182 def run0(req, env, db, content): 140 183 args = parse(content or '') 141 184 items = [] … … 169 212 elif kw == 'nosort': 170 213 nosort = True 214 elif kw == 'nowrap': 215 styles['white-space'] = 'nowrap' 171 216 elif kw in styles and kwarg: 172 217 styles[kw] = kwarg 173 218 # pick up ticket numbers and report numbers 174 219 for arg in args: 220 sql = None 221 params = [] 175 222 match = args_re.match(arg) 223 id_name = ticket 224 sidx = iidx = -1 176 225 if not match: 177 226 continue 178 227 elif match.group('tktnum'): 179 228 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' 180 235 elif match.group('rptnum') or match.group('rptnum2'): 181 236 num = match.group('rptnum') or match.group('rptnum2') 182 dv = {}183 # username, do not override if specified184 if not dv.has_key('USER'):185 dv['USER'] = req.authname186 if match.group('dv'):187 for expr in string.split(match.group('dv')[1:], '&'):188 k, v = string.split(expr, '=')189 dv[k] = v190 237 #env.log.debug('dynamic variables = %s' % dv) 191 db = env.get_db_cnx()192 238 curs = db.cursor() 193 239 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 197 259 # NOTE: sql_sub_vars() takes different arguments in 198 260 # several trac versions. … … 200 262 # For 0.10.x, arguments are (req, query, args, db) 201 263 # 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) 205 270 rows = curs.fetchall() 206 271 if rows: 207 272 descriptions = [desc[0] for desc in curs.description] 208 273 try: 209 i dx = descriptions.index(ticket)274 iidx = descriptions.index(id_name) 210 275 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 ) 213 278 if summary: 214 279 try: … … 218 283 % summary) 219 284 for row in rows: 220 items.append(row[i dx])221 if summary :222 summaries[row[i dx]] = row[sidx]285 items.append(row[iidx]) 286 if summary and 0 <= sidx: 287 summaries[row[iidx]] = row[sidx] 223 288 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 228 291 if summary: 229 292 # get summary text … … 240 303 items.sort() 241 304 html = '' 305 306 if ver < [0, 11]: 307 fargs = dict(db=db) 308 else: 309 fargs = dict(db=db, req=req) 242 310 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: 251 324 try: 252 325 title = title % len(items) # process %d in title … … 262 335 return '' 263 336 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 337 def 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) 348 def execute(hdf, txt, env): 349 req = MockReq(hdf) 350 return run(req, env, txt) 351 352 353 try: 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) 380 except ImportError: 381 # trac 0.9 382 pass 280 383 281 384 if __name__ == '__main__':
