def process_request(self, req): # !!!: Wow, this is hackish. <NPK> add_stylesheet(req, 'common/css/wiki.css') wiki_hdf = HDFWrapper() wiki_hdf.readString(req.__CACHED_PAGE) req.hdf.copy('wiki', wiki_hdf.hdf) return 'wiki.cs', None
def test_icon_links(self): env = EnvironmentStub() req = Mock(hdf=HDFWrapper(), cgi_location='/trac.cgi', path_info='') # No icon set in config, so no icon links env.config.set('project', 'icon', '') Chrome(env).populate_hdf(req, None) assert 'chrome.links.icon' not in req.hdf assert 'chrome.links.shortcut icon' not in req.hdf # Relative URL for icon config option env.config.set('project', 'icon', 'trac.ico') Chrome(env).populate_hdf(req, None) self.assertEqual('/trac.cgi/chrome/common/trac.ico', req.hdf['chrome.links.icon.0.href']) self.assertEqual('/trac.cgi/chrome/common/trac.ico', req.hdf['chrome.links.shortcut icon.0.href']) # URL relative to the server root for icon config option req.hdf = HDFWrapper() env.config.set('project', 'icon', '/favicon.ico') Chrome(env).populate_hdf(req, None) self.assertEqual('/favicon.ico', req.hdf['chrome.links.icon.0.href']) self.assertEqual('/favicon.ico', req.hdf['chrome.links.shortcut icon.0.href']) # Absolute URL for icon config option req.hdf = HDFWrapper() env.config.set('project', 'icon', 'http://example.com/favicon.ico') Chrome(env).populate_hdf(req, None) self.assertEqual('http://example.com/favicon.ico', req.hdf['chrome.links.icon.0.href']) self.assertEqual('http://example.com/favicon.ico', req.hdf['chrome.links.shortcut icon.0.href'])
def test_logo(self): env = EnvironmentStub() req = Mock(hdf=HDFWrapper(), cgi_location='/trac.cgi', path_info='') # Verify that no logo data is put in the HDF if no logo is configured env.config.set('header_logo', 'src', '') Chrome(env).populate_hdf(req, None) assert 'chrome.logo.src' not in req.hdf # Test with a relative path to the logo image req.hdf = HDFWrapper() env.config.set('header_logo', 'src', 'foo.png') Chrome(env).populate_hdf(req, None) self.assertEqual('/trac.cgi/chrome/common/foo.png', req.hdf['chrome.logo.src']) # Test with a server-relative path to the logo image req.hdf = HDFWrapper() env.config.set('header_logo', 'src', '/img/foo.png') Chrome(env).populate_hdf(req, None) self.assertEqual('/img/foo.png', req.hdf['chrome.logo.src']) # Test with an absolute path to the logo image req.hdf = HDFWrapper() env.config.set('header_logo', 'src', 'http://www.example.org/foo.png') Chrome(env).populate_hdf(req, None) self.assertEqual('http://www.example.org/foo.png', req.hdf['chrome.logo.src'])
def send_project_index(req, options, env_paths=None): from trac.web.clearsilver import HDFWrapper if 'TRAC_ENV_INDEX_TEMPLATE' in options: tmpl_path, template = os.path.split(options['TRAC_ENV_INDEX_TEMPLATE']) from trac.config import default_dir req.hdf = HDFWrapper(loadpaths=[default_dir('templates'), tmpl_path]) tmpl_vars = {} if 'TRAC_TEMPLATE_VARS' in options: for pair in options['TRAC_TEMPLATE_VARS'].split(','): key, val = pair.split('=') req.hdf[key] = val else: req.hdf = HDFWrapper() template = req.hdf.parse('''<html> <head><title>Available Projects</title></head> <body><h1>Available Projects</h1><ul><?cs each:project = projects ?><li><?cs if:project.href ?> <a href="<?cs var:project.href ?>" title="<?cs var:project.description ?>"> <?cs var:project.name ?></a><?cs else ?> <small><?cs var:project.name ?>: <em>Error</em> <br /> (<?cs var:project.description ?>)</small><?cs /if ?> </li><?cs /each ?></ul></body> </html>''') if not env_paths and 'TRAC_ENV_PARENT_DIR' in options: dir = options['TRAC_ENV_PARENT_DIR'] env_paths = [os.path.join(dir, f) for f in os.listdir(dir)] href = Href(req.idx_location) try: projects = [] for env_path in env_paths: if not os.path.isdir(env_path): continue env_dir, project = os.path.split(env_path) try: env = _open_environment(env_path) proj = { 'name': env.config.get('project', 'name'), 'description': env.config.get('project', 'descr'), 'href': href(project) } except Exception, e: proj = {'name': project, 'description': str(e)} projects.append(proj) projects.sort(lambda x, y: cmp(x['name'], y['name'])) req.hdf['projects'] = projects # TODO maybe this should be 404 if index wasn't specifically requested req.display(template, response=200)
def test_nav_contributor_order(self): class TestNavigationContributor1(Component): implements(INavigationContributor) def get_active_navigation_item(self, req): return None def get_navigation_items(self, req): yield 'metanav', 'test1', 'Test 1' class TestNavigationContributor2(Component): implements(INavigationContributor) def get_active_navigation_item(self, req): return None def get_navigation_items(self, req): yield 'metanav', 'test2', 'Test 2' env = EnvironmentStub( enable=[TestNavigationContributor1, TestNavigationContributor2]) req = Mock(hdf=HDFWrapper(), path_info='/', cgi_location='/trac.cgi') chrome = Chrome(env) # Test with both items set in the order option env.config.set('trac', 'metanav', 'test2, test1') chrome.populate_hdf(req, None) node = req.hdf.getObj('chrome.nav.metanav').child() self.assertEqual('test2', node.name()) self.assertEqual('test1', node.next().name()) # Test with only test1 in the order options req.hdf = HDFWrapper() env.config.set('trac', 'metanav', 'test1') chrome.populate_hdf(req, None) node = req.hdf.getObj('chrome.nav.metanav').child() self.assertEqual('test1', node.name()) self.assertEqual('test2', node.next().name()) # Test with only test2 in the order options req.hdf = HDFWrapper() env.config.set('trac', 'metanav', 'test2') chrome.populate_hdf(req, None) node = req.hdf.getObj('chrome.nav.metanav').child() self.assertEqual('test2', node.name()) self.assertEqual('test1', node.next().name()) # Test with none in the order options (order corresponds to # registration order) req.hdf = HDFWrapper() env.config.set('trac', 'metanav', 'foo, bar') chrome.populate_hdf(req, None) node = req.hdf.getObj('chrome.nav.metanav').child() self.assertEqual('test1', node.name()) self.assertEqual('test2', node.next().name())
def render(self, req, mimetype, content, filename=None, rev=None): from trac.web.clearsilver import HDFWrapper content = content_to_unicode(self.env, content, mimetype) d = self._diff_to_hdf(content.splitlines(), Mimeview(self.env).tab_width) if not d: raise TracError, u'Contenu diff unifié invalide' hdf = HDFWrapper(loadpaths=[self.env.get_templates_dir(), self.config.get('trac', 'templates_dir')]) hdf['diff.files'] = d add_stylesheet(req, 'common/css/diff.css') return hdf.render(hdf.parse(self.diff_cs))
def render(self, req, mimetype, content, filename=None, rev=None): from trac.web.clearsilver import HDFWrapper content = content_to_unicode(self.env, content, mimetype) d = self._diff_to_hdf(content.splitlines(), Mimeview(self.env).tab_width) if not d: raise TracError, 'Invalid unified diff content' hdf = HDFWrapper(loadpaths=[self.env.get_templates_dir(), self.config.get('trac', 'templates_dir')]) hdf['diff.files'] = d add_stylesheet(req, 'common/css/diff.css') return hdf.render(hdf.parse(self.diff_cs))
def render(self, req, mimetype, content, filename=None, rev=None): from trac.web.clearsilver import HDFWrapper tabwidth = int(self.config.get('diff', 'tab_width')) d = self._diff_to_hdf(content.splitlines(), tabwidth) if not d: raise TracError, 'Invalid unified diff content' hdf = HDFWrapper(loadpaths=[ self.env.get_templates_dir(), self.config.get('trac', 'templates_dir') ]) hdf['diff.files'] = d add_stylesheet(req, 'common/css/diff.css') return hdf.render(hdf.parse(self.diff_cs))
def render_summary(self, req, config, build, step, category): assert category == 'lint' #assert category in ('lint', 'pylint', 'nblint') db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" SELECT MAX(lint_file.value) AS file, MAX(CAST(lint_line.value as INT)) AS line, MAX(lint_type.value) AS type, MAX(lint_tag.value) AS tag, MAX(lint_msg.value) AS msg, MAX(lint_category.value) as cat FROM bitten_report AS report LEFT OUTER JOIN bitten_report_item AS lint_file ON(lint_file.report=report.id AND lint_file.name='file') LEFT OUTER JOIN bitten_report_item AS lint_line ON(lint_line.report=report.id AND lint_line.item=lint_file.item AND lint_line.name='line') LEFT OUTER JOIN bitten_report_item AS lint_type ON(lint_type.report=report.id AND lint_type.item=lint_file.item AND lint_type.name='type') LEFT OUTER JOIN bitten_report_item AS lint_tag ON(lint_tag.report=report.id AND lint_tag.item=lint_file.item AND lint_tag.name='tag') LEFT OUTER JOIN bitten_report_item AS lint_msg ON(lint_msg.report=report.id AND lint_msg.item=lint_file.item AND lint_msg.name='msg') LEFT OUTER JOIN bitten_report_item AS lint_category ON(lint_category.report=report.id AND lint_category.item=lint_file.item AND lint_category.name='category') WHERE category=%s AND build=%s AND step=%s GROUP BY lint_file.value, lint_line.value, lint_type.value ORDER BY file, line, type""", (category, build.id, step.name)) data = [] for fname, line, ltype, tag, msg, cat in cursor: data.append( { 'href': self.env.href.browser(config.path, fname), 'file': fname, 'line': line, 'type': ltype, 'tag': tag, 'msg': msg, 'cat': cat } ) hdf = HDFWrapper(loadpaths=Chrome(self.env).get_all_templates_dirs()) hdf['data'] = data return hdf.render('nosebitten_pylint_summary.cs')
def test_add_link_advanced(self): req = Mock(hdf=HDFWrapper()) add_link(req, 'start', '/trac/wiki', 'Start page', 'text/html', 'home') self.assertEqual('/trac/wiki', req.hdf['chrome.links.start.0.href']) self.assertEqual('Start page', req.hdf['chrome.links.start.0.title']) self.assertEqual('text/html', req.hdf['chrome.links.start.0.type']) self.assertEqual('home', req.hdf['chrome.links.start.0.class'])
def __init__(self, env): self.env = env self.config = env.config self.db = env.get_db_cnx() self.hdf = HDFWrapper(loadpaths=[env.get_templates_dir(), self.config.get('trac', 'templates_dir')]) populate_hdf(self.hdf, env)
def send_project_index(environ, start_response, parent_dir=None, env_paths=None): req = Request(environ, start_response) loadpaths = [pkg_resources.resource_filename('trac', 'templates')] use_clearsilver = False if req.environ.get('trac.env_index_template'): tmpl_path, template = os.path.split( req.environ['trac.env_index_template']) loadpaths.insert(0, tmpl_path) use_clearsilver = template.endswith('.cs') # assume Clearsilver if use_clearsilver: req.hdf = HDFWrapper( loadpaths) # keep that for custom .cs templates else: template = 'index.html' data = { 'trac': { 'version': TRAC_VERSION, 'time': format_datetime() }, 'req': req } if req.environ.get('trac.template_vars'): for pair in req.environ['trac.template_vars'].split(','): key, val = pair.split('=') data[key] = val if use_clearsilver: req.hdf[key] = val try: href = Href(req.base_path) projects = [] for env_name, env_path in get_environments(environ).items(): try: env = open_environment(env_path, use_cache=not environ['wsgi.run_once']) proj = { 'env': env, 'name': env.project_name, 'description': env.project_description, 'href': href(env_name) } except Exception, e: proj = {'name': env_name, 'description': to_unicode(e)} projects.append(proj) projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) data['projects'] = projects if use_clearsilver: req.hdf['projects'] = projects req.display(template) loader = TemplateLoader(loadpaths, variable_lookup='lenient') tmpl = loader.load(template) stream = tmpl.generate(**data) output = stream.render('xhtml', doctype=DocType.XHTML_STRICT) req.send(output, 'text/html')
def __init__(self, env): self.env = env self.config = env.config self.db = env.get_db_cnx() loadpaths = Chrome(self.env).get_all_templates_dirs() self.hdf = HDFWrapper(loadpaths) populate_hdf(self.hdf, env)
def setUp(self): self.env = EnvironmentStub() self.ticket_module = TicketModule(self.env) self.mimeview = Mimeview(self.env) self.req = Mock(hdf=HDFWrapper(['./templates']), base_path='/trac.cgi', path_info='', href=Href('/trac.cgi'))
def send_pretty_error(e, env, req=None): """Send a "pretty" HTML error page to the client.""" import traceback import StringIO tb = StringIO.StringIO() traceback.print_exc(file=tb) if not req: from trac.web.cgi_frontend import CGIRequest from trac.web.clearsilver import HDFWrapper req = CGIRequest() req.authname = '' req.hdf = HDFWrapper() try: if not env: from trac.env import open_environment env = open_environment() env.href = Href(req.cgi_location) if env and env.log: env.log.exception(e) populate_hdf(req.hdf, env, req) if isinstance(e, TracError): req.hdf['title'] = e.title or 'Error' req.hdf['error.title'] = e.title or 'Error' req.hdf['error.type'] = 'TracError' req.hdf['error.message'] = e.message if e.show_traceback: req.hdf['error.traceback'] = escape(tb.getvalue()) req.display('error.cs', response=500) elif isinstance(e, PermissionError): req.hdf['title'] = 'Permission Denied' req.hdf['error.type'] = 'permission' req.hdf['error.action'] = e.action req.hdf['error.message'] = e req.display('error.cs', response=403) else: req.hdf['title'] = 'Oops' req.hdf['error.type'] = 'internal' req.hdf['error.message'] = escape(str(e)) req.hdf['error.traceback'] = escape(tb.getvalue()) req.display('error.cs', response=500) except RequestDone: pass except Exception, e2: if env and env.log: env.log.error('Failed to render pretty error page: %s', e2, exc_info=True) req.send_response(500) req.send_header('Content-Type', 'text/plain') req.end_headers() req.write('Oops...\n\nTrac detected an internal error:\n\n') req.write(str(e)) req.write('\n') req.write(tb.getvalue())
def test_default_links(self): env = EnvironmentStub() req = Mock(hdf=HDFWrapper(), cgi_location='/trac.cgi', path_info='') Chrome(env).populate_hdf(req, None) self.assertEqual('/trac.cgi/wiki', req.hdf['chrome.links.start.0.href']) self.assertEqual('/trac.cgi/search', req.hdf['chrome.links.search.0.href']) self.assertEqual('/trac.cgi/wiki/TracGuide', req.hdf['chrome.links.help.0.href']) self.assertEqual('/trac.cgi/chrome/common/css/trac.css', req.hdf['chrome.links.stylesheet.0.href'])
def test_nav_contributor_active(self): class TestNavigationContributor(Component): implements(INavigationContributor) def get_active_navigation_item(self, req): return 'test' def get_navigation_items(self, req): yield 'metanav', 'test', 'Test' env = EnvironmentStub(enable=[TestNavigationContributor]) req = Mock(hdf=HDFWrapper(), path_info='/', cgi_location='/trac.cgi') chrome = Chrome(env) chrome.populate_hdf(req, TestNavigationContributor(env)) self.assertEqual('Test', req.hdf['chrome.nav.metanav.test']) self.assertEqual('1', req.hdf['chrome.nav.metanav.test.active'])
def _test_import(self, env, filename, sheet=1): req = Request( { 'SERVER_PORT': 0, 'SERVER_NAME': 'any', 'wsgi.url_scheme': 'any', 'wsgi.input': 'any', 'REQUEST_METHOD': 'GET' }, lambda x, y: _printme) try: from trac.test import MockPerm req.perm = MockPerm() except ImportError: pass req.authname = 'testuser' req.hdf = HDFWrapper( [] ) # replace by this if you want to generate HTML: req.hdf = HDFWrapper(loadpaths=chrome.get_all_templates_dirs()) db = env.get_db_cnx() cursor = db.cursor() _exec(cursor, "select * from enum") enums_before = cursor.fetchall() _exec(cursor, "select * from component") components_before = cursor.fetchall() #print enums_before # when testing, always use the same time so that the results are comparable #print "importing " + filename + " with tickettime " + str(ImporterTestCase.TICKET_TIME) template, content_type = ImportModule(env)._do_import( filename, sheet, req, filename, ImporterTestCase.TICKET_TIME) #sys.stdout = tempstdout #req.display(template, content_type or 'text/html') #open('/tmp/out.html', 'w').write(req.hdf.render(template, None)) _exec(cursor, "select * from ticket") tickets = cursor.fetchall() _exec(cursor, "select * from ticket_custom") tickets_custom = cursor.fetchall() _exec(cursor, "select * from ticket_change") tickets_change = cursor.fetchall() _exec(cursor, "select * from enum") enums = [f for f in set(cursor.fetchall()) - set(enums_before)] _exec(cursor, "select * from component") components = [ f for f in set(cursor.fetchall()) - set(components_before) ] pp = pprint.PrettyPrinter(indent=4) return pp.pformat( [tickets, tickets_custom, tickets_change, enums, components])
def send_project_index(environ, start_response, parent_dir=None, env_paths=None): from trac.config import default_dir req = Request(environ, start_response) loadpaths = [default_dir('templates')] if req.environ.get('trac.env_index_template'): tmpl_path, template = os.path.split( req.environ['trac.env_index_template']) loadpaths.insert(0, tmpl_path) else: template = 'index.cs' req.hdf = HDFWrapper(loadpaths) tmpl_vars = {} if req.environ.get('trac.template_vars'): for pair in req.environ['trac.template_vars'].split(','): key, val = pair.split('=') req.hdf[key] = val if parent_dir and not env_paths: env_paths = dict([(filename, os.path.join(parent_dir, filename)) for filename in os.listdir(parent_dir)]) try: href = Href(req.base_path) projects = [] for env_name, env_path in get_environments(environ).items(): try: env = _open_environment(env_path, run_once=environ['wsgi.run_once']) proj = { 'name': env.project_name, 'description': env.project_description, 'href': href(env_name) } except Exception, e: proj = {'name': env_name, 'description': to_unicode(e)} projects.append(proj) projects.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) req.hdf['projects'] = projects req.display(template)
def dispatch(self, req): """Find a registered handler that matches the request and let it process it. In addition, this method initializes the HDF data set and adds the web site chrome. """ req.authname = self.authenticate(req) req.perm = PermissionCache(self.env, req.authname) chrome = Chrome(self.env) req.hdf = HDFWrapper(loadpaths=chrome.get_all_templates_dirs()) populate_hdf(req.hdf, self.env, req) newsession = req.args.has_key('newsession') req.session = Session(self.env, req, newsession) # Select the component that should handle the request chosen_handler = None default_handler = None if not req.path_info or req.path_info == '/': default_handler = self.config.get('trac', 'default_handler') for handler in self.handlers: if handler.match_request(req) or \ handler.__class__.__name__ == default_handler: chosen_handler = handler break chrome.populate_hdf(req, chosen_handler) if not chosen_handler: # FIXME: Should return '404 Not Found' to the client raise TracError, 'No handler matched request to %s' % req.path_info try: resp = chosen_handler.process_request(req) if resp: template, content_type = resp if not content_type: content_type = 'text/html' req.display(template, content_type or 'text/html') finally: # Give the session a chance to persist changes req.session.save()
def _test_preview(self, env, filename): req = Request( { 'SERVER_PORT': 0, 'SERVER_NAME': 'any', 'wsgi.url_scheme': 'any', 'wsgi.input': 'any', 'REQUEST_METHOD': 'GET' }, lambda x, y: _printme) try: from trac.test import MockPerm req.perm = MockPerm() except ImportError: pass req.authname = 'testuser' req.hdf = HDFWrapper( [] ) # replace by this if you want to generate HTML: req.hdf = HDFWrapper(loadpaths=chrome.get_all_templates_dirs()) template, content_type = ImportModule(env)._do_preview( filename, 1, req) #sys.stdout = tempstdout #req.display(template, content_type or 'text/html') #open('/tmp/out.html', 'w').write(req.hdf.render(template, None)) return str(req.hdf) + "\n"
def _get_hdf(self, req): hdf = HDFWrapper(loadpaths=Chrome(self.env).get_all_templates_dirs()) populate_hdf(hdf, self.env, req) return hdf
class CodeReviewNotifyEmail(NotifyEmail): template_name = "code_review_notify_email.cs" from_email = "codereview@localhost" ticket_pattern = re.compile('#([0-9]+)') def __init__(self, env): NotifyEmail.__init__(self, env) self.hdf = HDFWrapper(loadpaths=self.get_templates_dirs()) populate_hdf(self.hdf, env) def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] def notify(self, cr_dict): self.cr_dict = cr_dict cr = CodeReview(self.env, cr_dict['cr_id']) cursor = self.env.get_db_cnx().cursor() cursor.execute("SELECT author, message FROM revision WHERE rev='%s'" % cr_dict['cr_id']) recordset = cursor.fetchall() if not recordset: return cs_author = recordset[0][0] cs_message = recordset[0][1] if cs_author == "anonymous" and cr_dict['cr_author'] == "anonymous": return subject = "[TracNotify] ChangeSet r%s by %s reviewed by %s" % \ (cr_dict['cr_id'], cs_author, ','.join(cr.get_reviewers())) if cr_dict['priority'] == 'critical': subject = '[Critical]' + subject ticket_info = self.get_ticket_info(cs_message, cr_dict['cr_message']) self.hdf['trac_name'] = self.env.config.get('project', 'name') absurl = self.env.config.get('codereview', 'absurl') self.hdf['absurl'] = absurl self.hdf['r_content'] = wiki_to_html(cr_dict['cr_message'], self.env, cr_dict['req'], absurls = absurl) self.hdf['ticket_len'] = len(ticket_info) self.hdf['t_info'] = ticket_info self.hdf['cs_id'] = cr_dict['cr_id'] self.hdf['cs_author'] = cs_author self.hdf['cs_message'] = wiki_to_html(cs_message, self.env, cr_dict['req'], absurls = absurl, escape_newlines=True) self.hdf['r_author'] = ', '.join(cr.get_reviewers()) self.hdf['r_priority'] = cr_dict['priority'] self.subject = subject self.smtp_server = self.config['notification'].get('smtp_server') self.smtp_port = self.config['notification'].getint('smtp_port') self.from_email = self.config['notification'].get('smtp_from') self.replyto_email = self.config['notification'].get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: raise TracError(Markup('Unable to send email due to identity ' 'crisis.<p>Neither <b>notification.from</b> ' 'nor <b>notification.reply_to</b> are ' 'specified in the configuration.</p>'), 'SMTP Notification Error') # Authentication info (optional) self.user_name = self.config['notification'].get('smtp_user') self.password = self.config['notification'].get('smtp_password') Notify.notify(self, cr_dict['cr_id']) def get_reviewer_team(self): reviewer_team = self.env.config.get("codereview", "team_list", "") if reviewer_team: return [reviewer.strip() for reviewer in reviewer_team.split(',')] else: return [] def get_recipients(self, cr_id): cr = CodeReview(self.env, cr_id) reviewers = list(set(self.get_reviewer_team() + cr.get_reviewers())) cs_author = self.hdf.get('cs_author', None) if cs_author is None: cursor = self.env.get_db_cnx().cursor() cursor.execute("SELECT author FROM revision WHERE rev='%s'" % cr_id) cs_author = cursor.fetchone() if cs_author: cs_author = cs_author[0] else: cs_author = '' if cs_author in reviewers: reviewers.remove(cs_author) return ([cs_author,], reviewers) def get_ticket_info(self, cs_message, cr_message): cursor = self.env.get_db_cnx().cursor() ticket_ids = set(self.ticket_pattern.findall(cs_message or '') + self.ticket_pattern.findall(cr_message or '')) ticket_info = [] if(ticket_ids): cursor.execute('SELECT id, summary FROM ticket WHERE id in (%s) ORDER BY id' % ','.join(ticket_ids)) for id, summary in cursor.fetchall(): ticket_info.append({'id': id, 'summary': summary}) return ticket_info def send(self, torcpts, ccrcpts): from email.MIMEText import MIMEText from email.Utils import formatdate, formataddr body = self.hdf.render(self.template_name) projname = self.config.get('project', 'name') headers = {} headers['X-Mailer'] = 'Trac %s, by Edgewall Software' % __version__ headers['X-Trac-Version'] = __version__ headers['X-Trac-Project'] = projname headers['X-URL'] = self.config.get('project', 'url') headers['Subject'] = self.subject headers['From'] = (projname, self.from_email) headers['Sender'] = self.from_email headers['Reply-To'] = self.replyto_email def build_addresses(rcpts): """Format and remove invalid addresses""" return filter(lambda x: x, \ [self.get_smtp_address(addr) for addr in rcpts]) def remove_dup(rcpts, all): """Remove duplicates""" tmp = [] for rcpt in rcpts: if not rcpt in all: tmp.append(rcpt) all.append(rcpt) return (tmp, all) toaddrs = build_addresses(torcpts) ccaddrs = build_addresses(ccrcpts) recipients = [] (toaddrs, recipients) = remove_dup(toaddrs, recipients) (ccaddrs, recipients) = remove_dup(ccaddrs, recipients) if len(recipients) < 1: self.env.log.info('no recipient for a ticket notification') return headers['To'] = ', '.join(toaddrs) headers['Cc'] = ', '.join(ccaddrs) headers['Date'] = formatdate() if not self._charset.body_encoding: try: dummy = body.encode('ascii') except UnicodeDecodeError: raise TracError, "CodeReview contains non-Ascii chars. " \ "Please change encoding setting" msg = MIMEText(body) msg.set_type("text/html") del msg['Content-Transfer-Encoding'] msg.set_charset(self._charset) self.add_headers(msg, headers) self.env.log.debug("Sending SMTP notification to %s on port %d to %s" % (self.smtp_server, self.smtp_port, recipients)) msgtext = msg.as_string() # Ensure the message complies with RFC2822: use CRLF line endings recrlf = re.compile("\r?\n") msgtext = "\r\n".join(recrlf.split(msgtext)) self.server.sendmail(msg['From'], recipients, msgtext)
def __init__(self, env): NotifyEmail.__init__(self, env) self.hdf = HDFWrapper(loadpaths=self.get_templates_dirs()) populate_hdf(self.hdf, env)
def dispatch(self, req): """Find a registered handler that matches the request and let it process it. In addition, this method initializes the HDF data set and adds the web site chrome. """ # FIXME: For backwards compatibility, should be removed in 0.11 self.env.href = req.href # FIXME in 0.11: self.env.abs_href = Href(self.env.base_url) self.env.abs_href = req.abs_href # Select the component that should handle the request chosen_handler = None early_error = None req.authname = 'anonymous' req.perm = NoPermissionCache() try: if not req.path_info or req.path_info == '/': chosen_handler = self.default_handler else: for handler in self.handlers: if handler.match_request(req): chosen_handler = handler break # Attach user information to the request early, so that # the IRequestFilter can see it while preprocessing if not getattr(chosen_handler, 'anonymous_request', False): try: req.authname = self.authenticate(req) req.perm = PermissionCache(self.env, req.authname) req.session = Session(self.env, req) req.form_token = self._get_form_token(req) except: req.authname = 'anonymous' req.perm = NoPermissionCache() early_error = sys.exc_info() chosen_handler = self._pre_process_request(req, chosen_handler) except: early_error = sys.exc_info() if not chosen_handler and not early_error: early_error = (HTTPNotFound('No handler matched request to %s', req.path_info), None, None) # Prepare HDF for the clearsilver template try: use_template = getattr(chosen_handler, 'use_template', True) req.hdf = None if use_template: chrome = Chrome(self.env) req.hdf = HDFWrapper(loadpaths=chrome.get_all_templates_dirs()) populate_hdf(req.hdf, self.env, req) chrome.populate_hdf(req, chosen_handler) except: req.hdf = None # revert to sending plaintext error if not early_error: raise if early_error: try: self._post_process_request(req) except Exception, e: self.log.exception(e) raise early_error[0], early_error[1], early_error[2]
'to locate the Trac environment(s).') run_once = environ['wsgi.run_once'] env = env_error = None try: env = _open_environment(env_path, run_once=run_once) if env.base_url: environ['trac.base_url'] = env.base_url except TracError, e: env_error = e req = Request(environ, start_response) try: if not env and env_error: from trac.config import default_dir req.hdf = HDFWrapper([default_dir('templates')]) raise HTTPInternalError(env_error.message) try: try: dispatcher = RequestDispatcher(env) dispatcher.dispatch(req) except RequestDone: pass return req._response or [] finally: if not run_once: env.shutdown(threading._get_ident()) except HTTPException, e: if env: env.log.warn(e)
def render_summary(self, req, config, build, step, category): assert category == 'pylint' db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" SELECT MAX(lint_file.value) AS file, MAX(CAST(lint_line.value as INT)) AS line, MAX(lint_type.value) AS type, MAX(lint_tag.value) AS tag, MAX(lint_msg.value) AS msg, MAX(lint_category.value) as cat FROM bitten_report AS report LEFT OUTER JOIN bitten_report_item AS lint_file ON(lint_file.report=report.id AND lint_file.name='file') LEFT OUTER JOIN bitten_report_item AS lint_line ON(lint_line.report=report.id AND lint_line.item=lint_file.item AND lint_line.name='line') LEFT OUTER JOIN bitten_report_item AS lint_type ON(lint_type.report=report.id AND lint_type.item=lint_file.item AND lint_type.name='type') LEFT OUTER JOIN bitten_report_item AS lint_tag ON(lint_tag.report=report.id AND lint_tag.item=lint_file.item AND lint_tag.name='tag') LEFT OUTER JOIN bitten_report_item AS lint_msg ON(lint_msg.report=report.id AND lint_msg.item=lint_file.item AND lint_msg.name='msg') LEFT OUTER JOIN bitten_report_item AS lint_category ON(lint_category.report=report.id AND lint_category.item=lint_file.item AND lint_category.name='category') WHERE category=%s AND build=%s AND step=%s GROUP BY lint_file.value, lint_line.value, lint_type.value ORDER BY file, line, type""", (category, build.id, step.name)) data = [] totals = { 'error': 0, 'warning': 0, 'refactor': 0, 'fatal': 0, 'convention': 0, 'ignored': 0 } for fname, line, ltype, tag, msg, cat in cursor: #self.log.debug("%s, %s, %s, %s, %s, %s", fname, line, ltype, tag, msg, cat) #self.log.debug("CAT: %r", cat) if cat in ('error', 'warning', 'refactor', 'fatal', 'convention', 'ignored'): data.append( { 'href': self.env.href.browser(config.path, fname), 'file': fname, 'line': line, 'type': ltype, 'tag': tag, 'msg': msg, 'cat': cat } ) totals[cat] += 1 hdf = HDFWrapper(loadpaths=Chrome(self.env).get_all_templates_dirs()) hdf['data'] = data hdf['totals'] = totals return hdf.render('bittentrac_pylint.cs')
def test_htdocs_location(self): env = EnvironmentStub() req = Mock(hdf=HDFWrapper(), cgi_location='/trac.cgi', path_info='') Chrome(env).populate_hdf(req, None) self.assertEqual('/trac.cgi/chrome/common/', req.hdf['htdocs_location'])
def test_add_stylesheet(self): req = Mock(cgi_location='/trac.cgi', hdf=HDFWrapper()) add_stylesheet(req, 'common/css/trac.css') self.assertEqual('text/css', req.hdf['chrome.links.stylesheet.0.type']) self.assertEqual('/trac.cgi/chrome/common/css/trac.css', req.hdf['chrome.links.stylesheet.0.href'])
def render_summary(self, req, config, build, step, category): self.log.debug('Category: %s', category) assert category == 'coverage' db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" SELECT item_name.value AS unit, item_file.value AS file, MAX(item_lines.value) AS loc, MAX(exec_lines.value) AS exec, MAX(item_percentage.value) AS cov, MAX(miss_lines.value) AS miss FROM bitten_report AS report LEFT OUTER JOIN bitten_report_item AS item_name ON (item_name.report=report.id AND item_name.name='name') LEFT OUTER JOIN bitten_report_item AS item_file ON (item_file.report=report.id AND item_file.item=item_name.item AND item_file.name='file') LEFT OUTER JOIN bitten_report_item AS item_lines ON (item_lines.report=report.id AND item_lines.item=item_name.item AND item_lines.name='lines') LEFT OUTER JOIN bitten_report_item AS exec_lines ON (exec_lines.report=report.id AND exec_lines.item=item_name.item AND exec_lines.name='executed') LEFT OUTER JOIN bitten_report_item AS item_percentage ON (item_percentage.report=report.id AND item_percentage.item=item_name.item AND item_percentage.name='percentage') LEFT OUTER JOIN bitten_report_item AS miss_lines ON (miss_lines.report=report.id AND miss_lines.item=item_name.item AND miss_lines.name='miss') WHERE category='coverage' AND build=%s AND step=%s GROUP BY file, unit ORDER BY unit""", (build.id, step.name)) data = [] total_loc, total_cov, total_exe = 0, 0, 0 for unit, file, loc, exe, cov, miss in cursor: loc, cov, exe = int(loc), float(cov), int(exe) if loc: d = {'name': unit, 'loc': loc, 'cov': int(cov), 'exe': exe} #, 'miss': miss} if file: d['href'] = self.env.href.browser(config.path, file) if miss and file: missed = [] for lines in miss.split(): m = {'lines': lines} m['href'] = self.env.href.browser(config.path, file) + '#L%s' % \ lines.split('-')[0] missed.append(m) d['miss'] = missed else: d['miss'] = {'lines': miss} self.log.debug('DATA ROW:', d) data.append(d) total_loc += loc total_exe += exe total_cov += loc * cov hdf = HDFWrapper(loadpaths=Chrome(self.env).get_all_templates_dirs()) hdf['data'] = data hdf['totals'] = {'loc': total_loc, 'cov': int(total_cov / total_loc), 'exe': total_exe} return hdf.render('bittentrac_nosecoverage.cs')
def test_add_link_simple(self): req = Mock(hdf=HDFWrapper()) add_link(req, 'start', '/trac/wiki') self.assertEqual('/trac/wiki', req.hdf['chrome.links.start.0.href'])
class CodeReviewNotifyEmail(NotifyEmail): template_name = "code_review_notify_email.cs" from_email = "codereview@localhost" ticket_pattern = re.compile('#([0-9]+)') def __init__(self, env): NotifyEmail.__init__(self, env) self.hdf = HDFWrapper(loadpaths=self.get_templates_dirs()) populate_hdf(self.hdf, env) def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] def notify(self, cr_dict): self.cr_dict = cr_dict cr = CodeReview(self.env, cr_dict['cr_id']) cursor = self.env.get_db_cnx().cursor() cursor.execute("SELECT author, message FROM revision WHERE rev='%s'" % cr_dict['cr_id']) recordset = cursor.fetchall() if not recordset: return cs_author = recordset[0][0] cs_message = recordset[0][1] if cs_author == "anonymous" and cr_dict['cr_author'] == "anonymous": return subject = "[TracNotify] ChangeSet r%s by %s reviewed by %s" % \ (cr_dict['cr_id'], cs_author, ','.join(cr.get_reviewers())) if cr_dict['priority'] == 'critical': subject = '[Critical]' + subject ticket_info = self.get_ticket_info(cs_message, cr_dict['cr_message']) self.hdf['trac_name'] = self.env.config.get('project', 'name') absurl = self.env.config.get('codereview', 'absurl') self.hdf['absurl'] = absurl self.hdf['r_content'] = wiki_to_html(cr_dict['cr_message'], self.env, cr_dict['req'], absurls=absurl) self.hdf['ticket_len'] = len(ticket_info) self.hdf['t_info'] = ticket_info self.hdf['cs_id'] = cr_dict['cr_id'] self.hdf['cs_author'] = cs_author self.hdf['cs_message'] = wiki_to_html(cs_message, self.env, cr_dict['req'], absurls=absurl, escape_newlines=True) self.hdf['r_author'] = ', '.join(cr.get_reviewers()) self.hdf['r_priority'] = cr_dict['priority'] self.subject = subject self.smtp_server = self.config['notification'].get('smtp_server') self.smtp_port = self.config['notification'].getint('smtp_port') self.from_email = self.config['notification'].get('smtp_from') self.replyto_email = self.config['notification'].get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: raise TracError( Markup('Unable to send email due to identity ' 'crisis.<p>Neither <b>notification.from</b> ' 'nor <b>notification.reply_to</b> are ' 'specified in the configuration.</p>'), 'SMTP Notification Error') # Authentication info (optional) self.user_name = self.config['notification'].get('smtp_user') self.password = self.config['notification'].get('smtp_password') Notify.notify(self, cr_dict['cr_id']) def get_reviewer_team(self): reviewer_team = self.env.config.get("codereview", "team_list", "") if reviewer_team: return [reviewer.strip() for reviewer in reviewer_team.split(',')] else: return [] def get_recipients(self, cr_id): cr = CodeReview(self.env, cr_id) reviewers = list(set(self.get_reviewer_team() + cr.get_reviewers())) cs_author = self.hdf.get('cs_author', None) if cs_author is None: cursor = self.env.get_db_cnx().cursor() cursor.execute("SELECT author FROM revision WHERE rev='%s'" % cr_id) cs_author = cursor.fetchone() if cs_author: cs_author = cs_author[0] else: cs_author = '' if cs_author in reviewers: reviewers.remove(cs_author) return ([ cs_author, ], reviewers) def get_ticket_info(self, cs_message, cr_message): cursor = self.env.get_db_cnx().cursor() ticket_ids = set( self.ticket_pattern.findall(cs_message or '') + self.ticket_pattern.findall(cr_message or '')) ticket_info = [] if (ticket_ids): cursor.execute( 'SELECT id, summary FROM ticket WHERE id in (%s) ORDER BY id' % ','.join(ticket_ids)) for id, summary in cursor.fetchall(): ticket_info.append({'id': id, 'summary': summary}) return ticket_info def send(self, torcpts, ccrcpts): from email.MIMEText import MIMEText from email.Utils import formatdate, formataddr body = self.hdf.render(self.template_name) projname = self.config.get('project', 'name') headers = {} headers['X-Mailer'] = 'Trac %s, by Edgewall Software' % __version__ headers['X-Trac-Version'] = __version__ headers['X-Trac-Project'] = projname headers['X-URL'] = self.config.get('project', 'url') headers['Subject'] = self.subject headers['From'] = (projname, self.from_email) headers['Sender'] = self.from_email headers['Reply-To'] = self.replyto_email def build_addresses(rcpts): """Format and remove invalid addresses""" return filter(lambda x: x, \ [self.get_smtp_address(addr) for addr in rcpts]) def remove_dup(rcpts, all): """Remove duplicates""" tmp = [] for rcpt in rcpts: if not rcpt in all: tmp.append(rcpt) all.append(rcpt) return (tmp, all) toaddrs = build_addresses(torcpts) ccaddrs = build_addresses(ccrcpts) recipients = [] (toaddrs, recipients) = remove_dup(toaddrs, recipients) (ccaddrs, recipients) = remove_dup(ccaddrs, recipients) if len(recipients) < 1: self.env.log.info('no recipient for a ticket notification') return headers['To'] = ', '.join(toaddrs) headers['Cc'] = ', '.join(ccaddrs) headers['Date'] = formatdate() if not self._charset.body_encoding: try: dummy = body.encode('ascii') except UnicodeDecodeError: raise TracError, "CodeReview contains non-Ascii chars. " \ "Please change encoding setting" msg = MIMEText(body) msg.set_type("text/html") del msg['Content-Transfer-Encoding'] msg.set_charset(self._charset) self.add_headers(msg, headers) self.env.log.debug("Sending SMTP notification to %s on port %d to %s" % (self.smtp_server, self.smtp_port, recipients)) msgtext = msg.as_string() # Ensure the message complies with RFC2822: use CRLF line endings recrlf = re.compile("\r?\n") msgtext = "\r\n".join(recrlf.split(msgtext)) self.server.sendmail(msg['From'], recipients, msgtext)