def html_module_detail(filename, module_name, nav=None): """ Creates a module detail report based on coverage testing at the specified filename. If ``nav`` is specified, the nav template will be used as well. It uses `templates.default_module_detail` to create the page. The template contains the following sections which need to be rendered and assembled into the final HTML. TOP: Contains the HTML declaration and head information, as well as the inline stylesheet. It requires the following variable: * %(title)s The module name is probably fitting for this. CONTENT_HEADER: The header portion of the body. Requires the following variable: * %(title)s * %(source_file)s File path to the module * %(total_count)d * %(executed_count)d * %(excluded_count)d * %(ignored_count)d * %(percent_covered)0.1f * %(test_timestamp)s CONTENT_BODY: Annotated module source code listing. Requires the following variable: * ``%(source_lines)s`` The actual source listing which is generated by looping through each line and concatenanting together rendered ``SOURCE_LINE`` template (see below). BOTTOM: Just a closing ``</body></html>`` SOURCE_LINE: Used to assemble the content of ``%(source_lines)s`` for ``CONTENT_BODY``. Requires the following variables: * ``%(line_status)s`` (ignored, executed, missed, excluded) used as CSS class identifier to style the each source line. * ``%(source_line)s`` """ if not nav: nav = {} m_vars = ModuleVars(module_name) m_vars.source_lines = source_lines = list() i = 0 for i, source_line in enumerate([ cgi.escape(l.rstrip()) for l in open(m_vars.source_file, 'r').readlines() ]): line_status = 'ignored' if i + 1 in m_vars.executed: line_status = 'executed' if i + 1 in m_vars.excluded: line_status = 'excluded' if i + 1 in m_vars.missed: line_status = 'missed' source_lines.append(module_detail.SOURCE_LINE % vars()) m_vars.ignored_count = i + 1 - m_vars.total_count m_vars.source_lines = os.linesep.join(source_lines) if 'prev_link' in nav and 'next_link' in nav: nav_html = module_detail.NAV % nav elif 'prev_link' in nav: nav_html = module_detail.NAV_NO_NEXT % nav elif 'next_link' in nav: nav_html = module_detail.NAV_NO_PREV % nav else: nav_html = None fo = open(filename, 'w+') fo.write(module_detail.TOP % m_vars.__dict__) if nav and nav_html: fo.write(nav_html) fo.write(module_detail.CONTENT_HEADER % m_vars.__dict__) fo.write(module_detail.CONTENT_BODY % m_vars.__dict__) if nav and nav_html: fo.write(nav_html) fo.write(module_detail.BOTTOM) fo.close()
def html_module_detail(filename, module_name, nav=None): """ Creates a module detail report based on coverage testing at the specified filename. If ``nav`` is specified, the nav template will be used as well. It uses `templates.default_module_detail` to create the page. The template contains the following sections which need to be rendered and assembled into the final HTML. TOP: Contains the HTML declaration and head information, as well as the inline stylesheet. It requires the following variable: * %(title)s The module name is probably fitting for this. CONTENT_HEADER: The header portion of the body. Requires the following variable: * %(title)s * %(source_file)s File path to the module * %(total_count)d * %(executed_count)d * %(excluded_count)d * %(ignored_count)d * %(percent_covered)0.1f * %(test_timestamp)s CONTENT_BODY: Annotated module source code listing. Requires the following variable: * ``%(source_lines)s`` The actual source listing which is generated by looping through each line and concatenanting together rendered ``SOURCE_LINE`` template (see below). BOTTOM: Just a closing ``</body></html>`` SOURCE_LINE: Used to assemble the content of ``%(source_lines)s`` for ``CONTENT_BODY``. Requires the following variables: * ``%(line_status)s`` (ignored, executed, missed, excluded) used as CSS class identifier to style the each source line. * ``%(source_line)s`` """ if not nav: nav = {} m_vars = ModuleVars(module_name) m_vars.source_lines = source_lines = list() i = 0 for i, source_line in enumerate([cgi.escape(l.rstrip()) for l in open(m_vars.source_file, "r").readlines()]): line_status = "ignored" if i + 1 in m_vars.executed: line_status = "executed" if i + 1 in m_vars.excluded: line_status = "excluded" if i + 1 in m_vars.missed: line_status = "missed" source_lines.append(module_detail.SOURCE_LINE % vars()) m_vars.ignored_count = i + 1 - m_vars.total_count m_vars.source_lines = os.linesep.join(source_lines) if "prev_link" in nav and "next_link" in nav: nav_html = module_detail.NAV % nav elif "prev_link" in nav: nav_html = module_detail.NAV_NO_NEXT % nav elif "next_link" in nav: nav_html = module_detail.NAV_NO_PREV % nav else: nav_html = None fo = open(filename, "w+") fo.write(module_detail.TOP % m_vars.__dict__) if nav and nav_html: fo.write(nav_html) fo.write(module_detail.CONTENT_HEADER % m_vars.__dict__) fo.write(module_detail.CONTENT_BODY % m_vars.__dict__) if nav and nav_html: fo.write(nav_html) fo.write(module_detail.BOTTOM) fo.close()
def html_report(outdir, modules, excludes=None, errors=None): """ Creates an ``index.html`` in the specified ``outdir``. Also attempts to create a ``modules`` subdirectory to create module detail html pages, which are named `module.__name__` + '.html'. It uses `templates.default_module_index` to create the index page. The template contains the following sections which need to be rendered and assembled into `index.html`. TOP: Contains the HTML declaration and head information, as well as the inline stylesheet. It doesn't require any variables. CONTENT_HEADER: The header portion of the body. Requires the following variable: * ``%(test_timestamp)s`` CONTENT_BODY: A table of contents to the different module detail pages, with some basic stats. Requires the following variables: * ``%(module_stats)s`` This is the actual content of the table and is generated by looping through the modules we want to report on and concatenanting together rendered ``MODULE_STAT`` template (see below). * ``%(total_lines)d`` * ``%(total_executed)d`` * ``%(total_excluded)d`` * ``%(overall_covered)0.1f`` EXCEPTIONS_LINK: Link to the excludes and errors index page which shows packages and modules which were not part of the coverage analysis. Requires the following variable: * ``%(exceptions_link)s`` Link to the index page. * ``%(exceptions_desc)s`` Describe the exception. ERRORS_LINK: Link to the errors index page which shows packages and modules which had problems being imported. Requires the following variable: * ``%(errors_link)s`` Link to the index page. BOTTOM: Just a closing ``</body></html>`` MODULE_STAT: Used to assemble the content of ``%(module_stats)s`` for ``CONTENT_BODY``. Requires the following variables: * ``%(severity)s`` (normal, warning, critical) used as CSS class identifier to style the coverage percentage. * ``%(module_link)s`` * ``%(module_name)s`` * ``%(total_count)d`` * ``%(executed_count)d`` * ``%(excluded_count)d`` * ``%(percent_covered)0.1f`` """ test_timestamp = time.strftime('%a %Y-%m-%d %H:%M %Z') m_subdirname = 'modules' m_dir = os.path.join(outdir, m_subdirname) if not os.path.exists(m_dir): os.makedirs(m_dir) total_lines = 0 total_executed = 0 total_excluded = 0 total_stmts = 0 module_stats = list() m_names = list(modules.keys()) m_names.sort() for n in m_names: m_vars = ModuleVars(n, modules[n]) if not m_vars.total_count: excludes.append(m_vars.module_name) del modules[n] continue m_vars.module_link = p2url( os.path.join(m_subdirname, m_vars.module_name + '.html')) module_stats.append(module_index.MODULE_STAT % m_vars.__dict__) total_lines += m_vars.total_count total_executed += m_vars.executed_count total_excluded += m_vars.excluded_count total_stmts += len(m_vars.stmts) module_stats = os.linesep.join(module_stats) if total_stmts: overall_covered = float(total_executed) / total_stmts * 100 else: overall_covered = 0.0 m_names = list(modules.keys()) m_names.sort() i = 0 for i, n in enumerate(m_names): m_vars = ModuleVars(n) nav = dict(up_link=p2url(os.path.join('..', 'index.html')), up_label='index') if i > 0: m = ModuleVars(m_names[i - 1]) nav['prev_link'] = os.path.basename(m.module_link) nav['prev_label'] = m.module_name if i + 1 < len(modules): m = ModuleVars(m_names[i + 1]) nav['next_link'] = os.path.basename(m.module_link) nav['next_label'] = m.module_name html_module_detail(os.path.join(m_dir, m_vars.module_name + '.html'), n, nav) fo = open(os.path.join(outdir, 'index.html'), 'w+') fo.write(module_index.TOP) fo.write(module_index.CONTENT_HEADER % vars()) fo.write(module_index.CONTENT_BODY % vars()) if excludes: _file = 'excludes.html' exceptions_link = _file exception_desc = "Excluded packages and modules" fo.write(module_index.EXCEPTIONS_LINK % vars()) html_module_excludes(os.path.join(outdir, _file), excludes) if errors: _file = 'errors.html' exceptions_link = _file exception_desc = "Error packages and modules" fo.write(module_index.EXCEPTIONS_LINK % vars()) html_module_errors(os.path.join(outdir, _file), errors) fo.write(module_index.BOTTOM) fo.close() if settings.COVERAGE_BADGE_TYPE: badge = open( os.path.join(os.path.dirname(__file__), 'badges', settings.COVERAGE_BADGE_TYPE, '%s.png' % int(overall_covered)), 'rb').read() open(os.path.join(outdir, 'coverage_status.png'), 'wb').write(badge)
def html_report(outdir, modules, excludes=None, errors=None): """ Creates an ``index.html`` in the specified ``outdir``. Also attempts to create a ``modules`` subdirectory to create module detail html pages, which are named `module.__name__` + '.html'. It uses `templates.default_module_index` to create the index page. The template contains the following sections which need to be rendered and assembled into `index.html`. TOP: Contains the HTML declaration and head information, as well as the inline stylesheet. It doesn't require any variables. CONTENT_HEADER: The header portion of the body. Requires the following variable: * ``%(test_timestamp)s`` CONTENT_BODY: A table of contents to the different module detail pages, with some basic stats. Requires the following variables: * ``%(module_stats)s`` This is the actual content of the table and is generated by looping through the modules we want to report on and concatenanting together rendered ``MODULE_STAT`` template (see below). * ``%(total_lines)d`` * ``%(total_executed)d`` * ``%(total_excluded)d`` * ``%(overall_covered)0.1f`` EXCEPTIONS_LINK: Link to the excludes and errors index page which shows packages and modules which were not part of the coverage analysis. Requires the following variable: * ``%(exceptions_link)s`` Link to the index page. * ``%(exceptions_desc)s`` Describe the exception. ERRORS_LINK: Link to the errors index page which shows packages and modules which had problems being imported. Requires the following variable: * ``%(errors_link)s`` Link to the index page. BOTTOM: Just a closing ``</body></html>`` MODULE_STAT: Used to assemble the content of ``%(module_stats)s`` for ``CONTENT_BODY``. Requires the following variables: * ``%(severity)s`` (normal, warning, critical) used as CSS class identifier to style the coverage percentage. * ``%(module_link)s`` * ``%(module_name)s`` * ``%(total_count)d`` * ``%(executed_count)d`` * ``%(excluded_count)d`` * ``%(percent_covered)0.1f`` """ test_timestamp = time.strftime('%a %Y-%m-%d %H:%M %Z') m_subdirname = 'modules' m_dir = os.path.join(outdir, m_subdirname) if not os.path.exists(m_dir): os.makedirs(m_dir) total_lines = 0 total_executed = 0 total_excluded = 0 total_stmts = 0 module_stats = list() m_names = list(modules.keys()) m_names.sort() for n in m_names: m_vars = ModuleVars(n, modules[n]) if not m_vars.total_count: excludes.append(m_vars.module_name) del modules[n] continue m_vars.module_link = p2url(os.path.join(m_subdirname, m_vars.module_name + '.html')) module_stats.append(module_index.MODULE_STAT %m_vars.__dict__) total_lines += m_vars.total_count total_executed += m_vars.executed_count total_excluded += m_vars.excluded_count total_stmts += len(m_vars.stmts) module_stats = os.linesep.join(module_stats) if total_stmts: overall_covered = float(total_executed)/total_stmts*100 else: overall_covered = 0.0 m_names = list(modules.keys()) m_names.sort() i = 0 for i, n in enumerate(m_names): m_vars = ModuleVars(n) nav = dict(up_link=p2url(os.path.join('..', 'index.html')), up_label='index') if i > 0: m = ModuleVars(m_names[i-1]) nav['prev_link'] = os.path.basename(m.module_link) nav['prev_label'] = m.module_name if i+1 < len(modules): m = ModuleVars(m_names[i+1]) nav['next_link'] = os.path.basename(m.module_link) nav['next_label'] = m.module_name html_module_detail( os.path.join(m_dir, m_vars.module_name + '.html'), n, nav) fo = open(os.path.join(outdir, 'index.html'), 'w+') fo.write(module_index.TOP) fo.write(module_index.CONTENT_HEADER %vars()) fo.write(module_index.CONTENT_BODY %vars()) if excludes: _file = 'excludes.html' exceptions_link = _file exception_desc = "Excluded packages and modules" fo.write(module_index.EXCEPTIONS_LINK %vars()) html_module_excludes(os.path.join(outdir, _file), excludes) if errors: _file = 'errors.html' exceptions_link = _file exception_desc = "Error packages and modules" fo.write(module_index.EXCEPTIONS_LINK %vars()) html_module_errors(os.path.join(outdir, _file), errors) fo.write(module_index.BOTTOM) fo.close() if settings.COVERAGE_BADGE_TYPE: badge = open(os.path.join( os.path.dirname(__file__), 'badges', settings.COVERAGE_BADGE_TYPE, '%s.png' % int(overall_covered) ), 'rb').read() open(os.path.join(outdir, 'coverage_status.png'), 'wb').write(badge)