Ticket #5516: show-enabled-plugins-in-error-page-r6675.diff
| File show-enabled-plugins-in-error-page-r6675.diff, 12.2 kB (added by cboos, 6 months ago) |
|---|
-
trac/htdocs/css/trac.css
489 489 #content.error form.newticket { display: inline; } 490 490 #content.error form.newticket textarea { display: none; } 491 491 492 #content.error #systeminfo { margin: 1em; width: auto; } 493 #content.error #systeminfo th { font-weight: bold; text-align: right; } 492 #content.error #systeminfo, 493 #content.error #plugins { margin: 1em; width: auto; } 494 #content.error #systeminfo th, 495 #content.error #plugins th { font-weight: bold; text-align: right; } 494 496 495 497 #content.error #traceback { margin-left: 1em; } 496 498 #content.error #traceback :link, #content.error #traceback :visited { … … 504 506 font-style: normal; 505 507 font-weight: bold; 506 508 } 507 #content.error #traceback span.file { color: #666; font-size: 85%; } 509 #content.error #traceback span.file, 510 #content.error #plugins span.file { color: #666; font-size: 85%; } 511 508 512 #content.error #traceback ul { list-style: none; margin: .5em 0; padding: 0; } 509 513 #content.error #traceback ol { 510 514 border: 1px dotted #d7d7d7; -
trac/admin/web_ui.py
467 467 if changes: 468 468 self.config.save() 469 469 470 def _render_view(self, req):470 def get_plugins_data(self): 471 471 plugins = {} 472 472 plugins_dir = os.path.realpath(os.path.join(self.env.path, 'plugins')) 473 473 plugins_dir = os.path.normcase(plugins_dir) # needs to match loader.py … … 490 490 if plugin_filename and os.access(dist.location, 491 491 os.F_OK + os.W_OK): 492 492 readonly = False 493 if plugin_filename: 493 # retrieve plugin metadata 494 info = get_pkginfo(dist) 495 if not info: 494 496 info = {'summary': description} 495 for k in 'author author_email home_page license'.split(): 497 for k in ('author author_email home_page url license trac' 498 .split()): 496 499 v = getattr(module, k, '') 497 500 if v: 501 if k == 'home_page' or k == 'url': 502 k = 'home_page' 503 v = v.replace('$', '').replace('URL: ', '') 498 504 info[k] = v 505 # retrieve plugin version info 506 version = dist.version 507 if not version: 499 508 version = (getattr(module, 'version', '') or 500 509 getattr(module, 'revision', '')) 501 510 # special handling for "$Rev$" strings 502 511 version = version.replace('$', '').replace('Rev: ', 'r') 503 else:504 info = get_pkginfo(dist)505 version = dist.version506 512 plugins[dist.project_name] = { 507 513 'name': dist.project_name, 'version': version, 508 514 'path': dist.location, 'description': description, … … 531 537 addons.sort() 532 538 plugin_list += [plugins[category] for category in addons] 533 539 534 data ={540 return { 535 541 'plugins': plugin_list, 536 542 'readonly': not os.access(plugins_dir, os.F_OK + os.W_OK) 537 543 } 538 return 'admin_plugins.html', data539 544 545 def _render_view(self, req): 546 return 'admin_plugins.html', self.get_plugins_data() 547 540 548 def _find_distribution(self, module): 541 549 path = get_module_path(module) 542 550 if path == self.trac_path: -
trac/templates/error.html
42 42 descr = descr.replace(/==== System Information ====\s+/m, 43 43 "User Agent was: `" + navigator.userAgent + "`\n\n$&" 44 44 ); 45 descr = descr.replace(/\|\|\s+==== Python Traceback====/m,45 descr = descr.replace(/\|\|\s+==== Enabled Plugins ====/m, 46 46 "||\n|| '''jQuery:''' || `" + $().jquery + "` $&" 47 47 ); 48 48 $("#description").text(descr); … … 75 75 <py:for each="k, v in trac.systeminfo"> 76 76 || '''$k''' || ${'`%s`' % (v and v.replace('\n', '` [[br]] `'))} ||</py:for> 77 77 78 <py:if test="plugins_list"> 79 ==== Enabled Plugins ==== 80 <py:for each="plugin in plugins_list"> 81 || '''`$plugin.name`''' || `$plugin.version` || ${('frame_idx' in plugin and "'''`%s`'''" or "`%s`") % plugin.path} ||</py:for> 82 </py:if> 83 78 84 ==== Python Traceback ==== 79 85 {{{ 80 86 ${traceback} … … 121 127 </p> 122 128 </py:when> 123 129 <py:otherwise> 124 <p>If you think this should work you can reproduce the problem, 125 you should consider reporting this to the Trac team.</p> 130 <p>If you think this should work and you can reproduce the problem, 131 you should consider creating a bug report.</p> 132 <py:with vars="faulty_plugins = [p for p in plugins_list if 'frame_idx' in p]"> 133 <p py:if="faulty_plugins" py:choose="len(faulty_plugins)"> 134 <py:when test="1"> 135 Note that the ${faulty_plugins[0].name} plugin seems to be involved in this problem. 136 </py:when> 137 <py:otherwise> 138 Note that the following plugins seem to be involved in this problem: 139 ${', '.join([p.name for p in faulty_plugins])}. 140 </py:otherwise> 141 <br /> 142 <strong>Please report this issue to the ${tracker.name} plugin maintainer.</strong> 143 </p> 144 </py:with> 126 145 <p>Before you do that, though, please first try 127 146 <a py:with="q = quote_plus(message[:80])" 128 href= "${trac.homepage}/search?ticket=yes&noquickjump=1&q=$q">searching</a>147 href='${tracker.url}/search?ticket=yes&noquickjump=1&q="$q"'>searching</a> 129 148 for similar issues, as it is quite likely that this problem 130 149 has been reported before. For questions about installation 131 and configuration of Trac , please try the150 and configuration of Trac or its plugins, please try the 132 151 <a href="${trac.homepage}/wiki/MailingList">mailing list</a> 133 instead of filing a ticket.152 instead of creating a ticket. 134 153 </p> 135 <form class="newticket" method="get" action="${trac .homepage}/newticket">136 <p>Otherwise, please ${create_ticket( True)} a new ticket at137 the Trac project site, where you can describe the problem and154 <form class="newticket" method="get" action="${tracker.url}/newticket"> 155 <p>Otherwise, please ${create_ticket(teo=tracker.url=='http://trac.egdewall.org')} a new bug report at 156 the ${tracker.name}'s Trac, where you can describe the problem and 138 157 explain how to reproduce it.</p> 139 158 </form> 140 159 <py:if test="traceback"> … … 184 203 <td>$value</td> 185 204 </tr> 186 205 </table> 206 <py:if test="plugins_list"> 207 <h2>Enabled Plugins</h2> 208 <table class="listing" id="plugins"> 209 <tr py:for="plugin in plugins_list"> 210 <th py:with="url = plugin.info.home_page; 211 email = plugin.info.author_email; 212 report_url = url or email and 'mailto:'+email"> 213 <a py:strip="not report_url" href="$report_url">$plugin.name</a> 214 </th> 215 <td>$plugin.version</td> 216 <td> 217 <span class="file"><a py:strip="not plugin.frame_idx" href="#frame$plugin.frame_idx">$plugin.path</a></span> 218 </td> 219 </tr> 220 </table> 221 </py:if> 222 187 223 </py:otherwise> 188 224 </py:choose> 189 225 </py:when> -
trac/web/main.py
39 39 from trac.perm import PermissionCache, PermissionError, PermissionSystem 40 40 from trac.resource import ResourceNotFound 41 41 from trac.util import get_lines_from_file, get_last_traceback, hex_entropy 42 from trac.util.compat import partial, reversed 42 from trac.util.compat import partial, reversed, any 43 43 from trac.util.datefmt import format_datetime, http_date, localtz, timezone 44 44 from trac.util.text import shorten_line, to_unicode 45 45 from trac.web.api import * … … 446 446 message = "%s: %s" % (e.__class__.__name__, to_unicode(e)) 447 447 traceback = get_last_traceback() 448 448 449 # gather frame information 449 450 frames = [] 450 451 has_admin = False 451 452 try: … … 471 472 'vars': tb.tb_frame.f_locals}] 472 473 tb = tb.tb_next 473 474 475 # gather plugins information 476 from trac.admin.web_ui import PluginAdminPanel 477 plugins_data = PluginAdminPanel(env).get_plugins_data() 478 # plugins: only keep those which have at least one component enabled 479 plugins_list = [p for p in plugins_data['plugins'][1:] 480 if any([c['enabled'] for c in p['components']])] 481 # plugins: verify if one of their source file is in the backtrace 482 egg_frames = [(i, f) for i, f in enumerate(frames) 483 if f['filename'].startswith('build')] 484 for plugin in plugins_list: 485 plugin_base, ext = os.path.splitext(plugin['path']) 486 if ext == '.egg' and egg_frames: 487 try: 488 for dist in pkg_resources.find_distributions( 489 plugin['path'], only=True): 490 sources = dist.get_metadata("SOURCES.txt") 491 for src in sources.splitlines(): 492 if src.endswith('.py'): 493 nsrc = os.path.normpath(src) 494 for i, f in egg_frames: 495 if f['filename'].endswith(nsrc): 496 plugin['frame_idx'] = i 497 raise StopIteration 498 except StopIteration: 499 pass 500 else: 501 for i, f in enumerate(frames): 502 if f['filename'].startswith(plugin_base): 503 plugin['frame_idx'] = i 504 break 505 # identify tracker in which the bug should be reported 506 teo = 'http://trac.edgewall.org' 507 th = 'http://trac-hacks.org' 508 tracker_name = 'Trac project' 509 tracker_url = teo 510 topmost = 0 511 for plugin in plugins_list: 512 if 'frame_idx' in plugin: 513 i = plugin['frame_idx'] 514 if i > topmost: 515 topmost = i 516 tracker_name = plugin['name'] 517 if 'trac' in plugin['info']: 518 tracker_url = plugin['info']['trac'] 519 elif plugin['info'].get('home_page', '').startswith(th): 520 tracker_url = th 521 474 522 data = {'title': 'Internal Error', 475 523 'type': 'internal', 'message': message, 476 524 'traceback': traceback, 'frames': frames, 477 'shorten_line': shorten_line} 525 'shorten_line': shorten_line, 526 'plugins_list': plugins_list, 527 'tracker': {'name': tracker_name, 'url': tracker_url}} 478 528 479 529 try: 480 530 req.send_error(exc_info, status=500, env=env, data=data)
