python-coverage-3.7.1+dfsg.1.orig/0000755000175000017500000000000012252501325015666 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/MANIFEST.in0000644000175000017500000000057012203272000017415 0ustar barrybarry# MANIFEST.in file for coverage.py recursive-include coverage/htmlfiles * recursive-include coverage/fullcoverage * include coverage.egg-info/*.* include setup.py include __main__.py include README.txt include CHANGES.txt include AUTHORS.txt include requirements.txt include igor.py include tox.ini recursive-include tests * recursive-include doc *.rst global-exclude *.pyc python-coverage-3.7.1+dfsg.1.orig/coverage/0000755000175000017500000000000012252501325017461 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/coverage/codeunit.py0000644000175000017500000001060712233013371021647 0ustar barrybarry"""Code unit (module) handling for Coverage.""" import glob, os from coverage.backward import open_source, string_class, StringIO from coverage.misc import CoverageException def code_unit_factory(morfs, file_locator): """Construct a list of CodeUnits from polymorphic inputs. `morfs` is a module or a filename, or a list of same. `file_locator` is a FileLocator that can help resolve filenames. Returns a list of CodeUnit objects. """ # Be sure we have a list. if not isinstance(morfs, (list, tuple)): morfs = [morfs] # On Windows, the shell doesn't expand wildcards. Do it here. globbed = [] for morf in morfs: if isinstance(morf, string_class) and ('?' in morf or '*' in morf): globbed.extend(glob.glob(morf)) else: globbed.append(morf) morfs = globbed code_units = [CodeUnit(morf, file_locator) for morf in morfs] return code_units class CodeUnit(object): """Code unit: a filename or module. Instance attributes: `name` is a human-readable name for this code unit. `filename` is the os path from which we can read the source. `relative` is a boolean. """ def __init__(self, morf, file_locator): self.file_locator = file_locator if hasattr(morf, '__file__'): f = morf.__file__ else: f = morf # .pyc files should always refer to a .py instead. if f.endswith('.pyc') or f.endswith('.pyo'): f = f[:-1] elif f.endswith('$py.class'): # Jython f = f[:-9] + ".py" self.filename = self.file_locator.canonical_filename(f) if hasattr(morf, '__name__'): n = modname = morf.__name__ self.relative = True else: n = os.path.splitext(morf)[0] rel = self.file_locator.relative_filename(n) if os.path.isabs(n): self.relative = (rel != n) else: self.relative = True n = rel modname = None self.name = n self.modname = modname def __repr__(self): return "" % (self.name, self.filename) # Annoying comparison operators. Py3k wants __lt__ etc, and Py2k needs all # of them defined. def __lt__(self, other): return self.name < other.name def __le__(self, other): return self.name <= other.name def __eq__(self, other): return self.name == other.name def __ne__(self, other): return self.name != other.name def __gt__(self, other): return self.name > other.name def __ge__(self, other): return self.name >= other.name def flat_rootname(self): """A base for a flat filename to correspond to this code unit. Useful for writing files about the code where you want all the files in the same directory, but need to differentiate same-named files from different directories. For example, the file a/b/c.py might return 'a_b_c' """ if self.modname: return self.modname.replace('.', '_') else: root = os.path.splitdrive(self.name)[1] return root.replace('\\', '_').replace('/', '_').replace('.', '_') def source_file(self): """Return an open file for reading the source of the code unit.""" if os.path.exists(self.filename): # A regular text file: open it. return open_source(self.filename) # Maybe it's in a zip file? source = self.file_locator.get_zip_data(self.filename) if source is not None: return StringIO(source) # Couldn't find source. raise CoverageException( "No source for code '%s'." % self.filename ) def should_be_python(self): """Does it seem like this file should contain Python? This is used to decide if a file reported as part of the exection of a program was really likely to have contained Python in the first place. """ # Get the file extension. _, ext = os.path.splitext(self.filename) # Anything named *.py* should be Python. if ext.startswith('.py'): return True # A file with no extension should be Python. if not ext: return True # Everything else is probably not Python. return False python-coverage-3.7.1+dfsg.1.orig/coverage/xmlreport.py0000644000175000017500000001326112233013371022070 0ustar barrybarry"""XML reporting for coverage.py""" import os, sys, time import xml.dom.minidom from coverage import __url__, __version__ from coverage.backward import sorted, rpartition # pylint: disable=W0622 from coverage.report import Reporter def rate(hit, num): """Return the fraction of `hit`/`num`, as a string.""" return "%.4g" % (float(hit) / (num or 1.0)) class XmlReporter(Reporter): """A reporter for writing Cobertura-style XML coverage results.""" def __init__(self, coverage, config): super(XmlReporter, self).__init__(coverage, config) self.packages = None self.xml_out = None self.arcs = coverage.data.has_arcs() def report(self, morfs, outfile=None): """Generate a Cobertura-compatible XML report for `morfs`. `morfs` is a list of modules or filenames. `outfile` is a file object to write the XML to. """ # Initial setup. outfile = outfile or sys.stdout # Create the DOM that will store the data. impl = xml.dom.minidom.getDOMImplementation() docType = impl.createDocumentType( "coverage", None, "http://cobertura.sourceforge.net/xml/coverage-03.dtd" ) self.xml_out = impl.createDocument(None, "coverage", docType) # Write header stuff. xcoverage = self.xml_out.documentElement xcoverage.setAttribute("version", __version__) xcoverage.setAttribute("timestamp", str(int(time.time()*1000))) xcoverage.appendChild(self.xml_out.createComment( " Generated by coverage.py: %s " % __url__ )) xpackages = self.xml_out.createElement("packages") xcoverage.appendChild(xpackages) # Call xml_file for each file in the data. self.packages = {} self.report_files(self.xml_file, morfs) lnum_tot, lhits_tot = 0, 0 bnum_tot, bhits_tot = 0, 0 # Populate the XML DOM with the package info. for pkg_name in sorted(self.packages.keys()): pkg_data = self.packages[pkg_name] class_elts, lhits, lnum, bhits, bnum = pkg_data xpackage = self.xml_out.createElement("package") xpackages.appendChild(xpackage) xclasses = self.xml_out.createElement("classes") xpackage.appendChild(xclasses) for class_name in sorted(class_elts.keys()): xclasses.appendChild(class_elts[class_name]) xpackage.setAttribute("name", pkg_name.replace(os.sep, '.')) xpackage.setAttribute("line-rate", rate(lhits, lnum)) xpackage.setAttribute("branch-rate", rate(bhits, bnum)) xpackage.setAttribute("complexity", "0") lnum_tot += lnum lhits_tot += lhits bnum_tot += bnum bhits_tot += bhits xcoverage.setAttribute("line-rate", rate(lhits_tot, lnum_tot)) xcoverage.setAttribute("branch-rate", rate(bhits_tot, bnum_tot)) # Use the DOM to write the output file. outfile.write(self.xml_out.toprettyxml()) # Return the total percentage. denom = lnum_tot + bnum_tot if denom == 0: pct = 0.0 else: pct = 100.0 * (lhits_tot + bhits_tot) / denom return pct def xml_file(self, cu, analysis): """Add to the XML report for a single file.""" # Create the 'lines' and 'package' XML elements, which # are populated later. Note that a package == a directory. package_name = rpartition(cu.name, ".")[0] className = cu.name package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0]) xclass = self.xml_out.createElement("class") xclass.appendChild(self.xml_out.createElement("methods")) xlines = self.xml_out.createElement("lines") xclass.appendChild(xlines) xclass.setAttribute("name", className) filename = cu.file_locator.relative_filename(cu.filename) xclass.setAttribute("filename", filename.replace("\\", "/")) xclass.setAttribute("complexity", "0") branch_stats = analysis.branch_stats() # For each statement, create an XML 'line' element. for line in sorted(analysis.statements): xline = self.xml_out.createElement("line") xline.setAttribute("number", str(line)) # Q: can we get info about the number of times a statement is # executed? If so, that should be recorded here. xline.setAttribute("hits", str(int(line not in analysis.missing))) if self.arcs: if line in branch_stats: total, taken = branch_stats[line] xline.setAttribute("branch", "true") xline.setAttribute("condition-coverage", "%d%% (%d/%d)" % (100*taken/total, taken, total) ) xlines.appendChild(xline) class_lines = len(analysis.statements) class_hits = class_lines - len(analysis.missing) if self.arcs: class_branches = sum([t for t,k in branch_stats.values()]) missing_branches = sum([t-k for t,k in branch_stats.values()]) class_br_hits = class_branches - missing_branches else: class_branches = 0.0 class_br_hits = 0.0 # Finalize the statistics that are collected in the XML DOM. xclass.setAttribute("line-rate", rate(class_hits, class_lines)) xclass.setAttribute("branch-rate", rate(class_br_hits, class_branches)) package[0][className] = xclass package[1] += class_hits package[2] += class_lines package[3] += class_br_hits package[4] += class_branches python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/0000755000175000017500000000000012306175240021453 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/keybd_open.png0000755000175000017500000000041312202156243024276 0ustar barrybarry‰PNG  IHDR# è#ºsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 3‘pb‹IDAT8˽“Aà ÇW¾‰ßßäî©Q5©­ÌÉHV»¶ð?F2%Òl–§GDxEQUTu©žsžÞâbîPkõ݉¥”SɈéCï};¯Ôû>€ÒZ»üpŒñHŒà r„¤Ç´ÍÌ/AŽ˜™¹öñ¢ûZíãÇOEã²2C;gÒ,´ÚÙF¼£Ÿ™óÅIEND®B`‚python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/jquery.hotkeys.js0000644000175000017500000000577112202156243025024 0ustar barrybarry/* * jQuery Hotkeys Plugin * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * * Based upon the plugin by Tzury Bar Yochay: * http://github.com/tzuryby/hotkeys * * Original idea by: * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ (function(jQuery){ jQuery.hotkeys = { version: "0.8", specialKeys: { 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" }, shiftNums: { "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", ".": ">", "/": "?", "\\": "|" } }; function keyHandler( handleObj ) { // Only care when a possible input has been specified if ( typeof handleObj.data !== "string" ) { return; } var origHandler = handleObj.handler, keys = handleObj.data.toLowerCase().split(" "); handleObj.handler = function( event ) { // Don't fire in text-accepting inputs that we didn't directly bind to if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) || event.target.type === "text") ) { return; } // Keypress represents characters, not special keys var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ], character = String.fromCharCode( event.which ).toLowerCase(), key, modif = "", possible = {}; // check combinations (alt|ctrl|shift+anything) if ( event.altKey && special !== "alt" ) { modif += "alt+"; } if ( event.ctrlKey && special !== "ctrl" ) { modif += "ctrl+"; } // TODO: Need to make sure this works consistently across platforms if ( event.metaKey && !event.ctrlKey && special !== "meta" ) { modif += "meta+"; } if ( event.shiftKey && special !== "shift" ) { modif += "shift+"; } if ( special ) { possible[ modif + special ] = true; } else { possible[ modif + character ] = true; possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true; // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" if ( modif === "shift+" ) { possible[ jQuery.hotkeys.shiftNums[ character ] ] = true; } } for ( var i = 0, l = keys.length; i < l; i++ ) { if ( possible[ keys[i] ] ) { return origHandler.apply( this, arguments ); } } }; } jQuery.each([ "keydown", "keyup", "keypress" ], function() { jQuery.event.special[ this ] = { add: keyHandler }; }); })( jQuery ); python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/pyfile.html0000644000175000017500000000700112224242247023630 0ustar barrybarry {# IE8 rounds line-height incorrectly, and adding this emulateIE7 line makes it right! #} {# http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/7684445e-f080-4d8f-8529-132763348e21 #} Coverage for {{cu.name|escape}}: {{nums.pc_covered_str}}% {% if extra_css %} {% endif %}

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

{% for line in lines %}

{{line.number}}

{% endfor %}
{% for line in lines %}

{% if line.annotate %}{{line.annotate}}{% endif %}{{line.html}} 

{% endfor %}
python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/style.css0000644000175000017500000001221012202156243023316 0ustar barrybarry/* CSS styles for Coverage. */ /* Page-wide styles */ html, body, h1, h2, h3, p, td, th { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } /* Set baseline grid to 16 pt. */ body { font-family: georgia, serif; font-size: 1em; } html>body { font-size: 16px; } /* Set base font size to 12/16 */ p { font-size: .75em; /* 12/16 */ line-height: 1.33333333em; /* 16/12 */ } table { border-collapse: collapse; } a.nav { text-decoration: none; color: inherit; } a.nav:hover { text-decoration: underline; color: inherit; } /* Page structure */ #header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; } #source { padding: 1em; font-family: "courier new", monospace; } #indexfile #footer { margin: 1em 3em; } #pyfile #footer { margin: 1em 1em; } #footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; } #index { margin: 1em 0 0 3em; } /* Header styles */ #header .content { padding: 1em 3em; } h1 { font-size: 1.25em; } h2.stats { margin-top: .5em; font-size: 1em; } .stats span { border: 1px solid; padding: .1em .25em; margin: 0 .1em; cursor: pointer; border-color: #999 #ccc #ccc #999; } .stats span.hide_run, .stats span.hide_exc, .stats span.hide_mis, .stats span.hide_par, .stats span.par.hide_run.hide_par { border-color: #ccc #999 #999 #ccc; } .stats span.par.hide_run { border-color: #999 #ccc #ccc #999; } .stats span.run { background: #ddffdd; } .stats span.exc { background: #eeeeee; } .stats span.mis { background: #ffdddd; } .stats span.hide_run { background: #eeffee; } .stats span.hide_exc { background: #f5f5f5; } .stats span.hide_mis { background: #ffeeee; } .stats span.par { background: #ffffaa; } .stats span.hide_par { background: #ffffcc; } /* Help panel */ #keyboard_icon { float: right; cursor: pointer; } .help_panel { position: absolute; background: #ffc; padding: .5em; border: 1px solid #883; display: none; } #indexfile .help_panel { width: 20em; height: 4em; } #pyfile .help_panel { width: 16em; height: 8em; } .help_panel .legend { font-style: italic; margin-bottom: 1em; } #panel_icon { float: right; cursor: pointer; } .keyhelp { margin: .75em; } .keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; } /* Source file styles */ .linenos p { text-align: right; margin: 0; padding: 0 .5em; color: #999999; font-family: verdana, sans-serif; font-size: .625em; /* 10/16 */ line-height: 1.6em; /* 16/10 */ } .linenos p.highlight { background: #ffdd00; } .linenos p a { text-decoration: none; color: #999999; } .linenos p a:hover { text-decoration: underline; color: #999999; } td.text { width: 100%; } .text p { margin: 0; padding: 0 0 0 .5em; border-left: 2px solid #ffffff; white-space: nowrap; } .text p.mis { background: #ffdddd; border-left: 2px solid #ff0000; } .text p.run, .text p.run.hide_par { background: #ddffdd; border-left: 2px solid #00ff00; } .text p.exc { background: #eeeeee; border-left: 2px solid #808080; } .text p.par, .text p.par.hide_run { background: #ffffaa; border-left: 2px solid #eeee99; } .text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, .text p.hide_run.hide_par { background: inherit; } .text span.annotate { font-family: georgia; font-style: italic; color: #666; float: right; padding-right: .5em; } .text p.hide_par span.annotate { display: none; } /* Syntax coloring */ .text .com { color: green; font-style: italic; line-height: 1px; } .text .key { font-weight: bold; line-height: 1px; } .text .str { color: #000080; } /* index styles */ #index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; } #index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; } #index th:hover { background: #eee; border-bottom: 1px solid #999; } #index td.left, #index th.left { padding-left: 0; } #index td.right, #index th.right { padding-right: 0; } #index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; } #index td.name, #index th.name { text-align: left; width: auto; } #index td.name a { text-decoration: none; color: #000; } #index td.name a:hover { text-decoration: underline; color: #000; } #index tr.total { } #index tr.total td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } #index tr.file:hover { background: #eeeeee; } python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/jquery.isonscreen.js0000644000175000017500000000273612202156243025504 0ustar barrybarry/* Copyright (c) 2010 * @author Laurence Wheway * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * @version 1.2.0 */ (function($) { jQuery.extend({ isOnScreen: function(box, container) { //ensure numbers come in as intgers (not strings) and remove 'px' is it's there for(var i in box){box[i] = parseFloat(box[i])}; for(var i in container){container[i] = parseFloat(container[i])}; if(!container){ container = { left: $(window).scrollLeft(), top: $(window).scrollTop(), width: $(window).width(), height: $(window).height() } } if( box.left+box.width-container.left > 0 && box.left < container.width+container.left && box.top+box.height-container.top > 0 && box.top < container.height+container.top ) return true; return false; } }) jQuery.fn.isOnScreen = function (container) { for(var i in container){container[i] = parseFloat(container[i])}; if(!container){ container = { left: $(window).scrollLeft(), top: $(window).scrollTop(), width: $(window).width(), height: $(window).height() } } if( $(this).offset().left+$(this).width()-container.left > 0 && $(this).offset().left < container.width+container.left && $(this).offset().top+$(this).height()-container.top > 0 && $(this).offset().top < container.height+container.top ) return true; return false; } })(jQuery); python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/coverage_html.js0000644000175000017500000002573512202156243024641 0ustar barrybarry// Coverage.py HTML report browser code. /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ /*global coverage: true, document, window, $ */ coverage = {}; // Find all the elements with shortkey_* class, and use them to assign a shotrtcut key. coverage.assign_shortkeys = function () { $("*[class*='shortkey_']").each(function (i, e) { $.each($(e).attr("class").split(" "), function (i, c) { if (/^shortkey_/.test(c)) { $(document).bind('keydown', c.substr(9), function () { $(e).click(); }); } }); }); }; // Create the events for the help panel. coverage.wire_up_help_panel = function () { $("#keyboard_icon").click(function () { // Show the help panel, and position it so the keyboard icon in the // panel is in the same place as the keyboard icon in the header. $(".help_panel").show(); var koff = $("#keyboard_icon").offset(); var poff = $("#panel_icon").position(); $(".help_panel").offset({ top: koff.top-poff.top, left: koff.left-poff.left }); }); $("#panel_icon").click(function () { $(".help_panel").hide(); }); }; // Loaded on index.html coverage.index_ready = function ($) { // Look for a cookie containing previous sort settings: var sort_list = []; var cookie_name = "COVERAGE_INDEX_SORT"; var i; // This almost makes it worth installing the jQuery cookie plugin: if (document.cookie.indexOf(cookie_name) > -1) { var cookies = document.cookie.split(";"); for (i = 0; i < cookies.length; i++) { var parts = cookies[i].split("="); if ($.trim(parts[0]) === cookie_name && parts[1]) { sort_list = eval("[[" + parts[1] + "]]"); break; } } } // Create a new widget which exists only to save and restore // the sort order: $.tablesorter.addWidget({ id: "persistentSort", // Format is called by the widget before displaying: format: function (table) { if (table.config.sortList.length === 0 && sort_list.length > 0) { // This table hasn't been sorted before - we'll use // our stored settings: $(table).trigger('sorton', [sort_list]); } else { // This is not the first load - something has // already defined sorting so we'll just update // our stored value to match: sort_list = table.config.sortList; } } }); // Configure our tablesorter to handle the variable number of // columns produced depending on report options: var headers = []; var col_count = $("table.index > thead > tr > th").length; headers[0] = { sorter: 'text' }; for (i = 1; i < col_count-1; i++) { headers[i] = { sorter: 'digit' }; } headers[col_count-1] = { sorter: 'percent' }; // Enable the table sorter: $("table.index").tablesorter({ widgets: ['persistentSort'], headers: headers }); coverage.assign_shortkeys(); coverage.wire_up_help_panel(); // Watch for page unload events so we can save the final sort settings: $(window).unload(function () { document.cookie = cookie_name + "=" + sort_list.toString() + "; path=/"; }); }; // -- pyfile stuff -- coverage.pyfile_ready = function ($) { // If we're directed to a particular line number, highlight the line. var frag = location.hash; if (frag.length > 2 && frag[1] === 'n') { $(frag).addClass('highlight'); coverage.set_sel(parseInt(frag.substr(2), 10)); } else { coverage.set_sel(0); } $(document) .bind('keydown', 'j', coverage.to_next_chunk_nicely) .bind('keydown', 'k', coverage.to_prev_chunk_nicely) .bind('keydown', '0', coverage.to_top) .bind('keydown', '1', coverage.to_first_chunk) ; $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.target, "run");}); $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.target, "exc");}); $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.target, "mis");}); $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.target, "par");}); coverage.assign_shortkeys(); coverage.wire_up_help_panel(); }; coverage.toggle_lines = function (btn, cls) { btn = $(btn); var hide = "hide_"+cls; if (btn.hasClass(hide)) { $("#source ."+cls).removeClass(hide); btn.removeClass(hide); } else { $("#source ."+cls).addClass(hide); btn.addClass(hide); } }; // Return the nth line div. coverage.line_elt = function (n) { return $("#t" + n); }; // Return the nth line number div. coverage.num_elt = function (n) { return $("#n" + n); }; // Return the container of all the code. coverage.code_container = function () { return $(".linenos"); }; // Set the selection. b and e are line numbers. coverage.set_sel = function (b, e) { // The first line selected. coverage.sel_begin = b; // The next line not selected. coverage.sel_end = (e === undefined) ? b+1 : e; }; coverage.to_top = function () { coverage.set_sel(0, 1); coverage.scroll_window(0); }; coverage.to_first_chunk = function () { coverage.set_sel(0, 1); coverage.to_next_chunk(); }; coverage.is_transparent = function (color) { // Different browsers return different colors for "none". return color === "transparent" || color === "rgba(0, 0, 0, 0)"; }; coverage.to_next_chunk = function () { var c = coverage; // Find the start of the next colored chunk. var probe = c.sel_end; while (true) { var probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } var color = probe_line.css("background-color"); if (!c.is_transparent(color)) { break; } probe++; } // There's a next chunk, `probe` points to it. var begin = probe; // Find the end of this chunk. var next_color = color; while (next_color === color) { probe++; probe_line = c.line_elt(probe); next_color = probe_line.css("background-color"); } c.set_sel(begin, probe); c.show_selection(); }; coverage.to_prev_chunk = function () { var c = coverage; // Find the end of the prev colored chunk. var probe = c.sel_begin-1; var probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } var color = probe_line.css("background-color"); while (probe > 0 && c.is_transparent(color)) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } color = probe_line.css("background-color"); } // There's a prev chunk, `probe` points to its last line. var end = probe+1; // Find the beginning of this chunk. var prev_color = color; while (prev_color === color) { probe--; probe_line = c.line_elt(probe); prev_color = probe_line.css("background-color"); } c.set_sel(probe+1, end); c.show_selection(); }; // Return the line number of the line nearest pixel position pos coverage.line_at_pos = function (pos) { var l1 = coverage.line_elt(1), l2 = coverage.line_elt(2), result; if (l1.length && l2.length) { var l1_top = l1.offset().top, line_height = l2.offset().top - l1_top, nlines = (pos - l1_top) / line_height; if (nlines < 1) { result = 1; } else { result = Math.ceil(nlines); } } else { result = 1; } return result; }; // Returns 0, 1, or 2: how many of the two ends of the selection are on // the screen right now? coverage.selection_ends_on_screen = function () { if (coverage.sel_begin === 0) { return 0; } var top = coverage.line_elt(coverage.sel_begin); var next = coverage.line_elt(coverage.sel_end-1); return ( (top.isOnScreen() ? 1 : 0) + (next.isOnScreen() ? 1 : 0) ); }; coverage.to_next_chunk_nicely = function () { coverage.finish_scrolling(); if (coverage.selection_ends_on_screen() === 0) { // The selection is entirely off the screen: select the top line on // the screen. var win = $(window); coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); } coverage.to_next_chunk(); }; coverage.to_prev_chunk_nicely = function () { coverage.finish_scrolling(); if (coverage.selection_ends_on_screen() === 0) { var win = $(window); coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height())); } coverage.to_prev_chunk(); }; // Select line number lineno, or if it is in a colored chunk, select the // entire chunk coverage.select_line_or_chunk = function (lineno) { var c = coverage; var probe_line = c.line_elt(lineno); if (probe_line.length === 0) { return; } var the_color = probe_line.css("background-color"); if (!c.is_transparent(the_color)) { // The line is in a highlighted chunk. // Search backward for the first line. var probe = lineno; var color = the_color; while (probe > 0 && color === the_color) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { break; } color = probe_line.css("background-color"); } var begin = probe + 1; // Search forward for the last line. probe = lineno; color = the_color; while (color === the_color) { probe++; probe_line = c.line_elt(probe); color = probe_line.css("background-color"); } coverage.set_sel(begin, probe); } else { coverage.set_sel(lineno); } }; coverage.show_selection = function () { var c = coverage; // Highlight the lines in the chunk c.code_container().find(".highlight").removeClass("highlight"); for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { c.num_elt(probe).addClass("highlight"); } c.scroll_to_selection(); }; coverage.scroll_to_selection = function () { // Scroll the page if the chunk isn't fully visible. if (coverage.selection_ends_on_screen() < 2) { // Need to move the page. The html,body trick makes it scroll in all // browsers, got it from http://stackoverflow.com/questions/3042651 var top = coverage.line_elt(coverage.sel_begin); var top_pos = parseInt(top.offset().top, 10); coverage.scroll_window(top_pos - 30); } }; coverage.scroll_window = function (to_pos) { $("html,body").animate({scrollTop: to_pos}, 200); }; coverage.finish_scrolling = function () { $("html,body").stop(true, true); }; python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/keybd_closed.png0000755000175000017500000000041012202156243024603 0ustar barrybarry‰PNG  IHDR# è#ºsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ ÚòÕWˆIDAT8ËÍ•K€ D§Æ-×lÏ×äug¥|Dâ¬JCÉd^ãRLÖþfXuž"–7™¹ëˆ4Õ1Æâw3#†Z圳ӱŒ„*”æb2w†™k†.1{ïÏsKÎ1­@Ö©‚j-¦¢ÓSü¹,t&¦#Ÿ«cGt¦(ýé;8Õ¶˜§f·AIEND®B`‚python-coverage-3.7.1+dfsg.1.orig/coverage/htmlfiles/index.html0000644000175000017500000000701312224242237023451 0ustar barrybarry {{ title|escape }} {% if extra_css %} {% endif %}

Hot-keys on this page

n s m x {% if arcs %} b p {% endif %} c   change column sorting

{# The title='' attr doesn't work in Safari. #} {% if arcs %} {% endif %} {# HTML syntax requires thead, tfoot, tbody #} {% if arcs %} {% endif %} {% for file in files %} {% if arcs %} {% endif %} {% endfor %}
Module statements missing excludedbranches partialcoverage
Total {{totals.n_statements}} {{totals.n_missing}} {{totals.n_excluded}}{{totals.n_branches}} {{totals.n_partial_branches}}{{totals.pc_covered_str}}%
{{file.name}} {{file.nums.n_statements}} {{file.nums.n_missing}} {{file.nums.n_excluded}}{{file.nums.n_branches}} {{file.nums.n_partial_branches}}{{file.nums.pc_covered_str}}%
python-coverage-3.7.1+dfsg.1.orig/coverage/results.py0000644000175000017500000002342512233077601021546 0ustar barrybarry"""Results of coverage measurement.""" import os from coverage.backward import iitems, set, sorted # pylint: disable=W0622 from coverage.misc import format_lines, join_regex, NoSource from coverage.parser import CodeParser class Analysis(object): """The results of analyzing a code unit.""" def __init__(self, cov, code_unit): self.coverage = cov self.code_unit = code_unit self.filename = self.code_unit.filename actual_filename, source = self.find_source(self.filename) self.parser = CodeParser( text=source, filename=actual_filename, exclude=self.coverage._exclude_regex('exclude') ) self.statements, self.excluded = self.parser.parse_source() # Identify missing statements. executed = self.coverage.data.executed_lines(self.filename) exec1 = self.parser.first_lines(executed) self.missing = self.statements - exec1 if self.coverage.data.has_arcs(): self.no_branch = self.parser.lines_matching( join_regex(self.coverage.config.partial_list), join_regex(self.coverage.config.partial_always_list) ) n_branches = self.total_branches() mba = self.missing_branch_arcs() n_partial_branches = sum( [len(v) for k,v in iitems(mba) if k not in self.missing] ) n_missing_branches = sum([len(v) for k,v in iitems(mba)]) else: n_branches = n_partial_branches = n_missing_branches = 0 self.no_branch = set() self.numbers = Numbers( n_files=1, n_statements=len(self.statements), n_excluded=len(self.excluded), n_missing=len(self.missing), n_branches=n_branches, n_partial_branches=n_partial_branches, n_missing_branches=n_missing_branches, ) def find_source(self, filename): """Find the source for `filename`. Returns two values: the actual filename, and the source. The source returned depends on which of these cases holds: * The filename seems to be a non-source file: returns None * The filename is a source file, and actually exists: returns None. * The filename is a source file, and is in a zip file or egg: returns the source. * The filename is a source file, but couldn't be found: raises `NoSource`. """ source = None base, ext = os.path.splitext(filename) TRY_EXTS = { '.py': ['.py', '.pyw'], '.pyw': ['.pyw'], } try_exts = TRY_EXTS.get(ext) if not try_exts: return filename, None for try_ext in try_exts: try_filename = base + try_ext if os.path.exists(try_filename): return try_filename, None source = self.coverage.file_locator.get_zip_data(try_filename) if source: return try_filename, source raise NoSource("No source for code: '%s'" % filename) def missing_formatted(self): """The missing line numbers, formatted nicely. Returns a string like "1-2, 5-11, 13-14". """ return format_lines(self.statements, self.missing) def has_arcs(self): """Were arcs measured in this result?""" return self.coverage.data.has_arcs() def arc_possibilities(self): """Returns a sorted list of the arcs in the code.""" arcs = self.parser.arcs() return arcs def arcs_executed(self): """Returns a sorted list of the arcs actually executed in the code.""" executed = self.coverage.data.executed_arcs(self.filename) m2fl = self.parser.first_line executed = [(m2fl(l1), m2fl(l2)) for (l1,l2) in executed] return sorted(executed) def arcs_missing(self): """Returns a sorted list of the arcs in the code not executed.""" possible = self.arc_possibilities() executed = self.arcs_executed() missing = [ p for p in possible if p not in executed and p[0] not in self.no_branch ] return sorted(missing) def arcs_unpredicted(self): """Returns a sorted list of the executed arcs missing from the code.""" possible = self.arc_possibilities() executed = self.arcs_executed() # Exclude arcs here which connect a line to itself. They can occur # in executed data in some cases. This is where they can cause # trouble, and here is where it's the least burden to remove them. unpredicted = [ e for e in executed if e not in possible and e[0] != e[1] ] return sorted(unpredicted) def branch_lines(self): """Returns a list of line numbers that have more than one exit.""" exit_counts = self.parser.exit_counts() return [l1 for l1,count in iitems(exit_counts) if count > 1] def total_branches(self): """How many total branches are there?""" exit_counts = self.parser.exit_counts() return sum([count for count in exit_counts.values() if count > 1]) def missing_branch_arcs(self): """Return arcs that weren't executed from branch lines. Returns {l1:[l2a,l2b,...], ...} """ missing = self.arcs_missing() branch_lines = set(self.branch_lines()) mba = {} for l1, l2 in missing: if l1 in branch_lines: if l1 not in mba: mba[l1] = [] mba[l1].append(l2) return mba def branch_stats(self): """Get stats about branches. Returns a dict mapping line numbers to a tuple: (total_exits, taken_exits). """ exit_counts = self.parser.exit_counts() missing_arcs = self.missing_branch_arcs() stats = {} for lnum in self.branch_lines(): exits = exit_counts[lnum] try: missing = len(missing_arcs[lnum]) except KeyError: missing = 0 stats[lnum] = (exits, exits - missing) return stats class Numbers(object): """The numerical results of measuring coverage. This holds the basic statistics from `Analysis`, and is used to roll up statistics across files. """ # A global to determine the precision on coverage percentages, the number # of decimal places. _precision = 0 _near0 = 1.0 # These will change when _precision is changed. _near100 = 99.0 def __init__(self, n_files=0, n_statements=0, n_excluded=0, n_missing=0, n_branches=0, n_partial_branches=0, n_missing_branches=0 ): self.n_files = n_files self.n_statements = n_statements self.n_excluded = n_excluded self.n_missing = n_missing self.n_branches = n_branches self.n_partial_branches = n_partial_branches self.n_missing_branches = n_missing_branches def set_precision(cls, precision): """Set the number of decimal places used to report percentages.""" assert 0 <= precision < 10 cls._precision = precision cls._near0 = 1.0 / 10**precision cls._near100 = 100.0 - cls._near0 set_precision = classmethod(set_precision) def _get_n_executed(self): """Returns the number of executed statements.""" return self.n_statements - self.n_missing n_executed = property(_get_n_executed) def _get_n_executed_branches(self): """Returns the number of executed branches.""" return self.n_branches - self.n_missing_branches n_executed_branches = property(_get_n_executed_branches) def _get_pc_covered(self): """Returns a single percentage value for coverage.""" if self.n_statements > 0: pc_cov = (100.0 * (self.n_executed + self.n_executed_branches) / (self.n_statements + self.n_branches)) else: pc_cov = 100.0 return pc_cov pc_covered = property(_get_pc_covered) def _get_pc_covered_str(self): """Returns the percent covered, as a string, without a percent sign. Note that "0" is only returned when the value is truly zero, and "100" is only returned when the value is truly 100. Rounding can never result in either "0" or "100". """ pc = self.pc_covered if 0 < pc < self._near0: pc = self._near0 elif self._near100 < pc < 100: pc = self._near100 else: pc = round(pc, self._precision) return "%.*f" % (self._precision, pc) pc_covered_str = property(_get_pc_covered_str) def pc_str_width(cls): """How many characters wide can pc_covered_str be?""" width = 3 # "100" if cls._precision > 0: width += 1 + cls._precision return width pc_str_width = classmethod(pc_str_width) def __add__(self, other): nums = Numbers() nums.n_files = self.n_files + other.n_files nums.n_statements = self.n_statements + other.n_statements nums.n_excluded = self.n_excluded + other.n_excluded nums.n_missing = self.n_missing + other.n_missing nums.n_branches = self.n_branches + other.n_branches nums.n_partial_branches = ( self.n_partial_branches + other.n_partial_branches ) nums.n_missing_branches = ( self.n_missing_branches + other.n_missing_branches ) return nums def __radd__(self, other): # Implementing 0+Numbers allows us to sum() a list of Numbers. if other == 0: return self return NotImplemented python-coverage-3.7.1+dfsg.1.orig/coverage/summary.py0000644000175000017500000000563412230634542021544 0ustar barrybarry"""Summary reporting""" import sys from coverage.report import Reporter from coverage.results import Numbers from coverage.misc import NotPython class SummaryReporter(Reporter): """A reporter for writing the summary report.""" def __init__(self, coverage, config): super(SummaryReporter, self).__init__(coverage, config) self.branches = coverage.data.has_arcs() def report(self, morfs, outfile=None): """Writes a report summarizing coverage statistics per module. `outfile` is a file object to write the summary to. """ self.find_code_units(morfs) # Prepare the formatting strings max_name = max([len(cu.name) for cu in self.code_units] + [5]) fmt_name = "%%- %ds " % max_name fmt_err = "%s %s: %s\n" header = (fmt_name % "Name") + " Stmts Miss" fmt_coverage = fmt_name + "%6d %6d" if self.branches: header += " Branch BrMiss" fmt_coverage += " %6d %6d" width100 = Numbers.pc_str_width() header += "%*s" % (width100+4, "Cover") fmt_coverage += "%%%ds%%%%" % (width100+3,) if self.config.show_missing: header += " Missing" fmt_coverage += " %s" rule = "-" * len(header) + "\n" header += "\n" fmt_coverage += "\n" if not outfile: outfile = sys.stdout # Write the header outfile.write(header) outfile.write(rule) total = Numbers() for cu in self.code_units: try: analysis = self.coverage._analyze(cu) nums = analysis.numbers args = (cu.name, nums.n_statements, nums.n_missing) if self.branches: args += (nums.n_branches, nums.n_missing_branches) args += (nums.pc_covered_str,) if self.config.show_missing: args += (analysis.missing_formatted(),) outfile.write(fmt_coverage % args) total += nums except KeyboardInterrupt: # pragma: not covered raise except: report_it = not self.config.ignore_errors if report_it: typ, msg = sys.exc_info()[:2] if typ is NotPython and not cu.should_be_python(): report_it = False if report_it: outfile.write(fmt_err % (cu.name, typ.__name__, msg)) if total.n_files > 1: outfile.write(rule) args = ("TOTAL", total.n_statements, total.n_missing) if self.branches: args += (total.n_branches, total.n_missing_branches) args += (total.pc_covered_str,) if self.config.show_missing: args += ("",) outfile.write(fmt_coverage % args) return total.pc_covered python-coverage-3.7.1+dfsg.1.orig/coverage/html.py0000644000175000017500000003145112233327133021005 0ustar barrybarry"""HTML reporting for Coverage.""" import os, re, shutil, sys import coverage from coverage.backward import pickle from coverage.misc import CoverageException, Hasher from coverage.phystokens import source_token_lines, source_encoding from coverage.report import Reporter from coverage.results import Numbers from coverage.templite import Templite # Static files are looked for in a list of places. STATIC_PATH = [ # The place Debian puts system Javascript libraries. "/usr/share/javascript", # Our htmlfiles directory. os.path.join(os.path.dirname(__file__), "htmlfiles"), ] def data_filename(fname, pkgdir=""): """Return the path to a data file of ours. The file is searched for on `STATIC_PATH`, and the first place it's found, is returned. Each directory in `STATIC_PATH` is searched as-is, and also, if `pkgdir` is provided, at that subdirectory. """ for static_dir in STATIC_PATH: static_filename = os.path.join(static_dir, fname) if os.path.exists(static_filename): return static_filename if pkgdir: static_filename = os.path.join(static_dir, pkgdir, fname) if os.path.exists(static_filename): return static_filename raise CoverageException("Couldn't find static file %r" % fname) def data(fname): """Return the contents of a data file of ours.""" data_file = open(data_filename(fname)) try: return data_file.read() finally: data_file.close() class HtmlReporter(Reporter): """HTML reporting.""" # These files will be copied from the htmlfiles dir to the output dir. STATIC_FILES = [ ("style.css", ""), ("jquery.min.js", "jquery"), ("jquery.hotkeys.js", "jquery-hotkeys"), ("jquery.isonscreen.js", "jquery-isonscreen"), ("jquery.tablesorter.min.js", "jquery-tablesorter"), ("coverage_html.js", ""), ("keybd_closed.png", ""), ("keybd_open.png", ""), ] def __init__(self, cov, config): super(HtmlReporter, self).__init__(cov, config) self.directory = None self.template_globals = { 'escape': escape, 'title': self.config.html_title, '__url__': coverage.__url__, '__version__': coverage.__version__, } self.source_tmpl = Templite( data("pyfile.html"), self.template_globals ) self.coverage = cov self.files = [] self.arcs = self.coverage.data.has_arcs() self.status = HtmlStatus() self.extra_css = None self.totals = Numbers() def report(self, morfs): """Generate an HTML report for `morfs`. `morfs` is a list of modules or filenames. """ assert self.config.html_dir, "must give a directory for html reporting" # Read the status data. self.status.read(self.config.html_dir) # Check that this run used the same settings as the last run. m = Hasher() m.update(self.config) these_settings = m.digest() if self.status.settings_hash() != these_settings: self.status.reset() self.status.set_settings_hash(these_settings) # The user may have extra CSS they want copied. if self.config.extra_css: self.extra_css = os.path.basename(self.config.extra_css) # Process all the files. self.report_files(self.html_file, morfs, self.config.html_dir) if not self.files: raise CoverageException("No data to report.") # Write the index file. self.index_file() self.make_local_static_report_files() return self.totals.pc_covered def make_local_static_report_files(self): """Make local instances of static files for HTML report.""" # The files we provide must always be copied. for static, pkgdir in self.STATIC_FILES: shutil.copyfile( data_filename(static, pkgdir), os.path.join(self.directory, static) ) # The user may have extra CSS they want copied. if self.extra_css: shutil.copyfile( self.config.extra_css, os.path.join(self.directory, self.extra_css) ) def write_html(self, fname, html): """Write `html` to `fname`, properly encoded.""" fout = open(fname, "wb") try: fout.write(html.encode('ascii', 'xmlcharrefreplace')) finally: fout.close() def file_hash(self, source, cu): """Compute a hash that changes if the file needs to be re-reported.""" m = Hasher() m.update(source) self.coverage.data.add_to_hash(cu.filename, m) return m.digest() def html_file(self, cu, analysis): """Generate an HTML file for one source file.""" source_file = cu.source_file() try: source = source_file.read() finally: source_file.close() # Find out if the file on disk is already correct. flat_rootname = cu.flat_rootname() this_hash = self.file_hash(source, cu) that_hash = self.status.file_hash(flat_rootname) if this_hash == that_hash: # Nothing has changed to require the file to be reported again. self.files.append(self.status.index_info(flat_rootname)) return self.status.set_file_hash(flat_rootname, this_hash) # If need be, determine the encoding of the source file. We use it # later to properly write the HTML. if sys.version_info < (3, 0): encoding = source_encoding(source) # Some UTF8 files have the dreaded UTF8 BOM. If so, junk it. if encoding.startswith("utf-8") and source[:3] == "\xef\xbb\xbf": source = source[3:] encoding = "utf-8" # Get the numbers for this file. nums = analysis.numbers if self.arcs: missing_branch_arcs = analysis.missing_branch_arcs() # These classes determine which lines are highlighted by default. c_run = "run hide_run" c_exc = "exc" c_mis = "mis" c_par = "par " + c_run lines = [] for lineno, line in enumerate(source_token_lines(source)): lineno += 1 # 1-based line numbers. # Figure out how to mark this line. line_class = [] annotate_html = "" annotate_title = "" if lineno in analysis.statements: line_class.append("stm") if lineno in analysis.excluded: line_class.append(c_exc) elif lineno in analysis.missing: line_class.append(c_mis) elif self.arcs and lineno in missing_branch_arcs: line_class.append(c_par) annlines = [] for b in missing_branch_arcs[lineno]: if b < 0: annlines.append("exit") else: annlines.append(str(b)) annotate_html = "   ".join(annlines) if len(annlines) > 1: annotate_title = "no jumps to these line numbers" elif len(annlines) == 1: annotate_title = "no jump to this line number" elif lineno in analysis.statements: line_class.append(c_run) # Build the HTML for the line html = [] for tok_type, tok_text in line: if tok_type == "ws": html.append(escape(tok_text)) else: tok_html = escape(tok_text) or ' ' html.append( "%s" % (tok_type, tok_html) ) lines.append({ 'html': ''.join(html), 'number': lineno, 'class': ' '.join(line_class) or "pln", 'annotate': annotate_html, 'annotate_title': annotate_title, }) # Write the HTML page for this file. html = spaceless(self.source_tmpl.render({ 'c_exc': c_exc, 'c_mis': c_mis, 'c_par': c_par, 'c_run': c_run, 'arcs': self.arcs, 'extra_css': self.extra_css, 'cu': cu, 'nums': nums, 'lines': lines, })) if sys.version_info < (3, 0): html = html.decode(encoding) html_filename = flat_rootname + ".html" html_path = os.path.join(self.directory, html_filename) self.write_html(html_path, html) # Save this file's information for the index file. index_info = { 'nums': nums, 'html_filename': html_filename, 'name': cu.name, } self.files.append(index_info) self.status.set_index_info(flat_rootname, index_info) def index_file(self): """Write the index.html file for this report.""" index_tmpl = Templite( data("index.html"), self.template_globals ) self.totals = sum([f['nums'] for f in self.files]) html = index_tmpl.render({ 'arcs': self.arcs, 'extra_css': self.extra_css, 'files': self.files, 'totals': self.totals, }) if sys.version_info < (3, 0): html = html.decode("utf-8") self.write_html( os.path.join(self.directory, "index.html"), html ) # Write the latest hashes for next time. self.status.write(self.directory) class HtmlStatus(object): """The status information we keep to support incremental reporting.""" STATUS_FILE = "status.dat" STATUS_FORMAT = 1 def __init__(self): self.reset() def reset(self): """Initialize to empty.""" self.settings = '' self.files = {} def read(self, directory): """Read the last status in `directory`.""" usable = False try: status_file = os.path.join(directory, self.STATUS_FILE) fstatus = open(status_file, "rb") try: status = pickle.load(fstatus) finally: fstatus.close() except (IOError, ValueError): usable = False else: usable = True if status['format'] != self.STATUS_FORMAT: usable = False elif status['version'] != coverage.__version__: usable = False if usable: self.files = status['files'] self.settings = status['settings'] else: self.reset() def write(self, directory): """Write the current status to `directory`.""" status_file = os.path.join(directory, self.STATUS_FILE) status = { 'format': self.STATUS_FORMAT, 'version': coverage.__version__, 'settings': self.settings, 'files': self.files, } fout = open(status_file, "wb") try: pickle.dump(status, fout) finally: fout.close() def settings_hash(self): """Get the hash of the coverage.py settings.""" return self.settings def set_settings_hash(self, settings): """Set the hash of the coverage.py settings.""" self.settings = settings def file_hash(self, fname): """Get the hash of `fname`'s contents.""" return self.files.get(fname, {}).get('hash', '') def set_file_hash(self, fname, val): """Set the hash of `fname`'s contents.""" self.files.setdefault(fname, {})['hash'] = val def index_info(self, fname): """Get the information for index.html for `fname`.""" return self.files.get(fname, {}).get('index', {}) def set_index_info(self, fname, info): """Set the information for index.html for `fname`.""" self.files.setdefault(fname, {})['index'] = info # Helpers for templates and generating HTML def escape(t): """HTML-escape the text in `t`.""" return (t # Convert HTML special chars into HTML entities. .replace("&", "&").replace("<", "<").replace(">", ">") .replace("'", "'").replace('"', """) # Convert runs of spaces: "......" -> " . . ." .replace(" ", "  ") # To deal with odd-length runs, convert the final pair of spaces # so that "....." -> " .  ." .replace(" ", "  ") ) def spaceless(html): """Squeeze out some annoying extra space from an HTML string. Nicely-formatted templates mean lots of extra space in the result. Get rid of some. """ html = re.sub(r">\s+

\n

col: line.append(("ws", " " * (scol - col))) mark_start = False tok_class = tokenize.tok_name.get(ttype, 'xx').lower()[:3] if ttype == token.NAME and keyword.iskeyword(ttext): tok_class = "key" line.append((tok_class, part)) mark_end = True scol = 0 if mark_end: col = ecol if line: yield line def source_encoding(source): """Determine the encoding for `source` (a string), according to PEP 263. Returns a string, the name of the encoding. """ # Note: this function should never be called on Python 3, since py3 has # built-in tools to do this. assert sys.version_info < (3, 0) # This is mostly code adapted from Py3.2's tokenize module. cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") # Do this so the detect_encode code we copied will work. readline = iter(source.splitlines(True)).next def _get_normal_name(orig_enc): """Imitates get_normal_name in tokenizer.c.""" # Only care about the first 12 characters. enc = orig_enc[:12].lower().replace("_", "-") if re.match(r"^utf-8($|-)", enc): return "utf-8" if re.match(r"^(latin-1|iso-8859-1|iso-latin-1)($|-)", enc): return "iso-8859-1" return orig_enc # From detect_encode(): # It detects the encoding from the presence of a utf-8 bom or an encoding # cookie as specified in pep-0263. If both a bom and a cookie are present, # but disagree, a SyntaxError will be raised. If the encoding cookie is an # invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, # 'utf-8-sig' is returned. # If no encoding is specified, then the default will be returned. The # default varied with version. if sys.version_info <= (2, 4): default = 'iso-8859-1' else: default = 'ascii' bom_found = False encoding = None def read_or_stop(): """Get the next source line, or ''.""" try: return readline() except StopIteration: return '' def find_cookie(line): """Find an encoding cookie in `line`.""" try: line_string = line.decode('ascii') except UnicodeDecodeError: return None matches = cookie_re.findall(line_string) if not matches: return None encoding = _get_normal_name(matches[0]) try: codec = codecs.lookup(encoding) except LookupError: # This behaviour mimics the Python interpreter raise SyntaxError("unknown encoding: " + encoding) if bom_found: # codecs in 2.3 were raw tuples of functions, assume the best. codec_name = getattr(codec, 'name', encoding) if codec_name != 'utf-8': # This behaviour mimics the Python interpreter raise SyntaxError('encoding problem: utf-8') encoding += '-sig' return encoding first = read_or_stop() if first.startswith(codecs.BOM_UTF8): bom_found = True first = first[3:] default = 'utf-8-sig' if not first: return default encoding = find_cookie(first) if encoding: return encoding second = read_or_stop() if not second: return default encoding = find_cookie(second) if encoding: return encoding return default python-coverage-3.7.1+dfsg.1.orig/coverage/files.py0000644000175000017500000002474412233013371021146 0ustar barrybarry"""File wrangling.""" from coverage.backward import to_string from coverage.misc import CoverageException import fnmatch, os, os.path, re, sys import ntpath, posixpath class FileLocator(object): """Understand how filenames work.""" def __init__(self): # The absolute path to our current directory. self.relative_dir = os.path.normcase(abs_file(os.curdir) + os.sep) # Cache of results of calling the canonical_filename() method, to # avoid duplicating work. self.canonical_filename_cache = {} def relative_filename(self, filename): """Return the relative form of `filename`. The filename will be relative to the current directory when the `FileLocator` was constructed. """ fnorm = os.path.normcase(filename) if fnorm.startswith(self.relative_dir): filename = filename[len(self.relative_dir):] return filename def canonical_filename(self, filename): """Return a canonical filename for `filename`. An absolute path with no redundant components and normalized case. """ if filename not in self.canonical_filename_cache: if not os.path.isabs(filename): for path in [os.curdir] + sys.path: if path is None: continue f = os.path.join(path, filename) if os.path.exists(f): filename = f break cf = abs_file(filename) self.canonical_filename_cache[filename] = cf return self.canonical_filename_cache[filename] def get_zip_data(self, filename): """Get data from `filename` if it is a zip file path. Returns the string data read from the zip file, or None if no zip file could be found or `filename` isn't in it. The data returned will be an empty string if the file is empty. """ import zipimport markers = ['.zip'+os.sep, '.egg'+os.sep] for marker in markers: if marker in filename: parts = filename.split(marker) try: zi = zipimport.zipimporter(parts[0]+marker[:-1]) except zipimport.ZipImportError: continue try: data = zi.get_data(parts[1]) except IOError: continue return to_string(data) return None if sys.platform == 'win32': def actual_path(path): """Get the actual path of `path`, including the correct case.""" if path in actual_path.cache: return actual_path.cache[path] head, tail = os.path.split(path) if not tail: actpath = head elif not head: actpath = tail else: head = actual_path(head) if head in actual_path.list_cache: files = actual_path.list_cache[head] else: try: files = os.listdir(head) except OSError: files = [] actual_path.list_cache[head] = files normtail = os.path.normcase(tail) for f in files: if os.path.normcase(f) == normtail: tail = f break actpath = os.path.join(head, tail) actual_path.cache[path] = actpath return actpath actual_path.cache = {} actual_path.list_cache = {} else: def actual_path(filename): """The actual path for non-Windows platforms.""" return filename def abs_file(filename): """Return the absolute normalized form of `filename`.""" path = os.path.expandvars(os.path.expanduser(filename)) path = os.path.abspath(os.path.realpath(path)) path = actual_path(path) return path def isabs_anywhere(filename): """Is `filename` an absolute path on any OS?""" return ntpath.isabs(filename) or posixpath.isabs(filename) def prep_patterns(patterns): """Prepare the file patterns for use in a `FnmatchMatcher`. If a pattern starts with a wildcard, it is used as a pattern as-is. If it does not start with a wildcard, then it is made absolute with the current directory. If `patterns` is None, an empty list is returned. """ prepped = [] for p in patterns or []: if p.startswith("*") or p.startswith("?"): prepped.append(p) else: prepped.append(abs_file(p)) return prepped class TreeMatcher(object): """A matcher for files in a tree.""" def __init__(self, directories): self.dirs = directories[:] def __repr__(self): return "" % self.dirs def info(self): """A list of strings for displaying when dumping state.""" return self.dirs def add(self, directory): """Add another directory to the list we match for.""" self.dirs.append(directory) def match(self, fpath): """Does `fpath` indicate a file in one of our trees?""" for d in self.dirs: if fpath.startswith(d): if fpath == d: # This is the same file! return True if fpath[len(d)] == os.sep: # This is a file in the directory return True return False class FnmatchMatcher(object): """A matcher for files by filename pattern.""" def __init__(self, pats): self.pats = pats[:] def __repr__(self): return "" % self.pats def info(self): """A list of strings for displaying when dumping state.""" return self.pats def match(self, fpath): """Does `fpath` match one of our filename patterns?""" for pat in self.pats: if fnmatch.fnmatch(fpath, pat): return True return False def sep(s): """Find the path separator used in this string, or os.sep if none.""" sep_match = re.search(r"[\\/]", s) if sep_match: the_sep = sep_match.group(0) else: the_sep = os.sep return the_sep class PathAliases(object): """A collection of aliases for paths. When combining data files from remote machines, often the paths to source code are different, for example, due to OS differences, or because of serialized checkouts on continuous integration machines. A `PathAliases` object tracks a list of pattern/result pairs, and can map a path through those aliases to produce a unified path. `locator` is a FileLocator that is used to canonicalize the results. """ def __init__(self, locator=None): self.aliases = [] self.locator = locator def add(self, pattern, result): """Add the `pattern`/`result` pair to the list of aliases. `pattern` is an `fnmatch`-style pattern. `result` is a simple string. When mapping paths, if a path starts with a match against `pattern`, then that match is replaced with `result`. This models isomorphic source trees being rooted at different places on two different machines. `pattern` can't end with a wildcard component, since that would match an entire tree, and not just its root. """ # The pattern can't end with a wildcard component. pattern = pattern.rstrip(r"\/") if pattern.endswith("*"): raise CoverageException("Pattern must not end with wildcards.") pattern_sep = sep(pattern) # The pattern is meant to match a filepath. Let's make it absolute # unless it already is, or is meant to match any prefix. if not pattern.startswith('*') and not isabs_anywhere(pattern): pattern = abs_file(pattern) pattern += pattern_sep # Make a regex from the pattern. fnmatch always adds a \Z or $ to # match the whole string, which we don't want. regex_pat = fnmatch.translate(pattern).replace(r'\Z(', '(') if regex_pat.endswith("$"): regex_pat = regex_pat[:-1] # We want */a/b.py to match on Windows too, so change slash to match # either separator. regex_pat = regex_pat.replace(r"\/", r"[\\/]") # We want case-insensitive matching, so add that flag. regex = re.compile(r"(?i)" + regex_pat) # Normalize the result: it must end with a path separator. result_sep = sep(result) result = result.rstrip(r"\/") + result_sep self.aliases.append((regex, result, pattern_sep, result_sep)) def map(self, path): """Map `path` through the aliases. `path` is checked against all of the patterns. The first pattern to match is used to replace the root of the path with the result root. Only one pattern is ever used. If no patterns match, `path` is returned unchanged. The separator style in the result is made to match that of the result in the alias. """ for regex, result, pattern_sep, result_sep in self.aliases: m = regex.match(path) if m: new = path.replace(m.group(0), result) if pattern_sep != result_sep: new = new.replace(pattern_sep, result_sep) if self.locator: new = self.locator.canonical_filename(new) return new return path def find_python_files(dirname): """Yield all of the importable Python files in `dirname`, recursively. To be importable, the files have to be in a directory with a __init__.py, except for `dirname` itself, which isn't required to have one. The assumption is that `dirname` was specified directly, so the user knows best, but subdirectories are checked for a __init__.py to be sure we only find the importable files. """ for i, (dirpath, dirnames, filenames) in enumerate(os.walk(dirname)): if i > 0 and '__init__.py' not in filenames: # If a directory doesn't have __init__.py, then it isn't # importable and neither are its files del dirnames[:] continue for filename in filenames: # We're only interested in files that look like reasonable Python # files: Must end with .py or .pyw, and must not have certain funny # characters that probably mean they are editor junk. if re.match(r"^[^.#~!$@%^&*()+=,]+\.pyw?$", filename): yield os.path.join(dirpath, filename) python-coverage-3.7.1+dfsg.1.orig/coverage/execfile.py0000644000175000017500000001335112233013371021620 0ustar barrybarry"""Execute files of Python code.""" import imp, marshal, os, sys from coverage.backward import exec_code_object, open_source from coverage.misc import ExceptionDuringRun, NoCode, NoSource try: # In Py 2.x, the builtins were in __builtin__ BUILTINS = sys.modules['__builtin__'] except KeyError: # In Py 3.x, they're in builtins BUILTINS = sys.modules['builtins'] def rsplit1(s, sep): """The same as s.rsplit(sep, 1), but works in 2.3""" parts = s.split(sep) return sep.join(parts[:-1]), parts[-1] def run_python_module(modulename, args): """Run a python module, as though with ``python -m name args...``. `modulename` is the name of the module, possibly a dot-separated name. `args` is the argument array to present as sys.argv, including the first element naming the module being executed. """ openfile = None glo, loc = globals(), locals() try: try: # Search for the module - inside its parent package, if any - using # standard import mechanics. if '.' in modulename: packagename, name = rsplit1(modulename, '.') package = __import__(packagename, glo, loc, ['__path__']) searchpath = package.__path__ else: packagename, name = None, modulename searchpath = None # "top-level search" in imp.find_module() openfile, pathname, _ = imp.find_module(name, searchpath) # Complain if this is a magic non-file module. if openfile is None and pathname is None: raise NoSource( "module does not live in a file: %r" % modulename ) # If `modulename` is actually a package, not a mere module, then we # pretend to be Python 2.7 and try running its __main__.py script. if openfile is None: packagename = modulename name = '__main__' package = __import__(packagename, glo, loc, ['__path__']) searchpath = package.__path__ openfile, pathname, _ = imp.find_module(name, searchpath) except ImportError: _, err, _ = sys.exc_info() raise NoSource(str(err)) finally: if openfile: openfile.close() # Finally, hand the file off to run_python_file for execution. pathname = os.path.abspath(pathname) args[0] = pathname run_python_file(pathname, args, package=packagename) def run_python_file(filename, args, package=None): """Run a python file as if it were the main program on the command line. `filename` is the path to the file to execute, it need not be a .py file. `args` is the argument array to present as sys.argv, including the first element naming the file being executed. `package` is the name of the enclosing package, if any. """ # Create a module to serve as __main__ old_main_mod = sys.modules['__main__'] main_mod = imp.new_module('__main__') sys.modules['__main__'] = main_mod main_mod.__file__ = filename if package: main_mod.__package__ = package main_mod.__builtins__ = BUILTINS # Set sys.argv properly. old_argv = sys.argv sys.argv = args try: # Make a code object somehow. if filename.endswith(".pyc") or filename.endswith(".pyo"): code = make_code_from_pyc(filename) else: code = make_code_from_py(filename) # Execute the code object. try: exec_code_object(code, main_mod.__dict__) except SystemExit: # The user called sys.exit(). Just pass it along to the upper # layers, where it will be handled. raise except: # Something went wrong while executing the user code. # Get the exc_info, and pack them into an exception that we can # throw up to the outer loop. We peel two layers off the traceback # so that the coverage.py code doesn't appear in the final printed # traceback. typ, err, tb = sys.exc_info() raise ExceptionDuringRun(typ, err, tb.tb_next.tb_next) finally: # Restore the old __main__ sys.modules['__main__'] = old_main_mod # Restore the old argv and path sys.argv = old_argv def make_code_from_py(filename): """Get source from `filename` and make a code object of it.""" # Open the source file. try: source_file = open_source(filename) except IOError: raise NoSource("No file to run: %r" % filename) try: source = source_file.read() finally: source_file.close() # We have the source. `compile` still needs the last line to be clean, # so make sure it is, then compile a code object from it. if not source or source[-1] != '\n': source += '\n' code = compile(source, filename, "exec") return code def make_code_from_pyc(filename): """Get a code object from a .pyc file.""" try: fpyc = open(filename, "rb") except IOError: raise NoCode("No file to run: %r" % filename) try: # First four bytes are a version-specific magic number. It has to # match or we won't run the file. magic = fpyc.read(4) if magic != imp.get_magic(): raise NoCode("Bad magic number in .pyc file") # Skip the junk in the header that we don't need. fpyc.read(4) # Skip the moddate. if sys.version_info >= (3, 3): # 3.3 added another long to the header (size), skip it. fpyc.read(4) # The rest of the file is the code object we want. code = marshal.load(fpyc) finally: fpyc.close() return code python-coverage-3.7.1+dfsg.1.orig/coverage/__init__.py0000644000175000017500000001063112216170233021573 0ustar barrybarry"""Code coverage measurement for Python. Ned Batchelder http://nedbatchelder.com/code/coverage """ from coverage.version import __version__, __url__ from coverage.control import coverage, process_startup from coverage.data import CoverageData from coverage.cmdline import main, CoverageScript from coverage.misc import CoverageException # Module-level functions. The original API to this module was based on # functions defined directly in the module, with a singleton of the coverage() # class. That design hampered programmability, so the current api uses # explicitly-created coverage objects. But for backward compatibility, here we # define the top-level functions to create the singleton when they are first # called. # Singleton object for use with module-level functions. The singleton is # created as needed when one of the module-level functions is called. _the_coverage = None def _singleton_method(name): """Return a function to the `name` method on a singleton `coverage` object. The singleton object is created the first time one of these functions is called. """ # Disable pylint msg W0612, because a bunch of variables look unused, but # they're accessed via locals(). # pylint: disable=W0612 def wrapper(*args, **kwargs): """Singleton wrapper around a coverage method.""" global _the_coverage if not _the_coverage: _the_coverage = coverage(auto_data=True) return getattr(_the_coverage, name)(*args, **kwargs) import inspect meth = getattr(coverage, name) args, varargs, kw, defaults = inspect.getargspec(meth) argspec = inspect.formatargspec(args[1:], varargs, kw, defaults) docstring = meth.__doc__ wrapper.__doc__ = ("""\ A first-use-singleton wrapper around coverage.%(name)s. This wrapper is provided for backward compatibility with legacy code. New code should use coverage.%(name)s directly. %(name)s%(argspec)s: %(docstring)s """ % locals() ) return wrapper # Define the module-level functions. use_cache = _singleton_method('use_cache') start = _singleton_method('start') stop = _singleton_method('stop') erase = _singleton_method('erase') exclude = _singleton_method('exclude') analysis = _singleton_method('analysis') analysis2 = _singleton_method('analysis2') report = _singleton_method('report') annotate = _singleton_method('annotate') # On Windows, we encode and decode deep enough that something goes wrong and # the encodings.utf_8 module is loaded and then unloaded, I don't know why. # Adding a reference here prevents it from being unloaded. Yuk. import encodings.utf_8 # Because of the "from coverage.control import fooey" lines at the top of the # file, there's an entry for coverage.coverage in sys.modules, mapped to None. # This makes some inspection tools (like pydoc) unable to find the class # coverage.coverage. So remove that entry. import sys try: del sys.modules['coverage.coverage'] except KeyError: pass # COPYRIGHT AND LICENSE # # Copyright 2001 Gareth Rees. All rights reserved. # Copyright 2004-2013 Ned Batchelder. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. python-coverage-3.7.1+dfsg.1.orig/coverage/templite.py0000644000175000017500000001532412233336266021674 0ustar barrybarry"""A simple Python template renderer, for a nano-subset of Django syntax.""" # Coincidentally named the same as http://code.activestate.com/recipes/496702/ import re from coverage.backward import set # pylint: disable=W0622 class CodeBuilder(object): """Build source code conveniently.""" def __init__(self, indent=0): self.code = [] self.indent_amount = indent def add_line(self, line): """Add a line of source to the code. Don't include indentations or newlines. """ self.code.append(" " * self.indent_amount) self.code.append(line) self.code.append("\n") def add_section(self): """Add a section, a sub-CodeBuilder.""" sect = CodeBuilder(self.indent_amount) self.code.append(sect) return sect def indent(self): """Increase the current indent for following lines.""" self.indent_amount += 4 def dedent(self): """Decrease the current indent for following lines.""" self.indent_amount -= 4 def __str__(self): return "".join([str(c) for c in self.code]) def get_function(self, fn_name): """Compile the code, and return the function `fn_name`.""" assert self.indent_amount == 0 g = {} code_text = str(self) exec(code_text, g) return g[fn_name] class Templite(object): """A simple template renderer, for a nano-subset of Django syntax. Supported constructs are extended variable access:: {{var.modifer.modifier|filter|filter}} loops:: {% for var in list %}...{% endfor %} and ifs:: {% if var %}...{% endif %} Comments are within curly-hash markers:: {# This will be ignored #} Construct a Templite with the template text, then use `render` against a dictionary context to create a finished string. """ def __init__(self, text, *contexts): """Construct a Templite with the given `text`. `contexts` are dictionaries of values to use for future renderings. These are good for filters and global values. """ self.text = text self.context = {} for context in contexts: self.context.update(context) # We construct a function in source form, then compile it and hold onto # it, and execute it to render the template. code = CodeBuilder() code.add_line("def render(ctx, dot):") code.indent() vars_code = code.add_section() self.all_vars = set() self.loop_vars = set() code.add_line("result = []") code.add_line("a = result.append") code.add_line("e = result.extend") code.add_line("s = str") buffered = [] def flush_output(): """Force `buffered` to the code builder.""" if len(buffered) == 1: code.add_line("a(%s)" % buffered[0]) elif len(buffered) > 1: code.add_line("e([%s])" % ",".join(buffered)) del buffered[:] # Split the text to form a list of tokens. toks = re.split(r"(?s)({{.*?}}|{%.*?%}|{#.*?#})", text) ops_stack = [] for tok in toks: if tok.startswith('{{'): # An expression to evaluate. buffered.append("s(%s)" % self.expr_code(tok[2:-2].strip())) elif tok.startswith('{#'): # Comment: ignore it and move on. continue elif tok.startswith('{%'): # Action tag: split into words and parse further. flush_output() words = tok[2:-2].strip().split() if words[0] == 'if': # An if statement: evaluate the expression to determine if. assert len(words) == 2 ops_stack.append('if') code.add_line("if %s:" % self.expr_code(words[1])) code.indent() elif words[0] == 'for': # A loop: iterate over expression result. assert len(words) == 4 and words[2] == 'in' ops_stack.append('for') self.loop_vars.add(words[1]) code.add_line( "for c_%s in %s:" % ( words[1], self.expr_code(words[3]) ) ) code.indent() elif words[0].startswith('end'): # Endsomething. Pop the ops stack end_what = words[0][3:] if ops_stack[-1] != end_what: raise SyntaxError("Mismatched end tag: %r" % end_what) ops_stack.pop() code.dedent() else: raise SyntaxError("Don't understand tag: %r" % words[0]) else: # Literal content. If it isn't empty, output it. if tok: buffered.append("%r" % tok) flush_output() for var_name in self.all_vars - self.loop_vars: vars_code.add_line("c_%s = ctx[%r]" % (var_name, var_name)) if ops_stack: raise SyntaxError("Unmatched action tag: %r" % ops_stack[-1]) code.add_line("return ''.join(result)") code.dedent() self.render_function = code.get_function('render') def expr_code(self, expr): """Generate a Python expression for `expr`.""" if "|" in expr: pipes = expr.split("|") code = self.expr_code(pipes[0]) for func in pipes[1:]: self.all_vars.add(func) code = "c_%s(%s)" % (func, code) elif "." in expr: dots = expr.split(".") code = self.expr_code(dots[0]) args = [repr(d) for d in dots[1:]] code = "dot(%s, %s)" % (code, ", ".join(args)) else: self.all_vars.add(expr) code = "c_%s" % expr return code def render(self, context=None): """Render this template by applying it to `context`. `context` is a dictionary of values to use in this rendering. """ # Make the complete context we'll use. ctx = dict(self.context) if context: ctx.update(context) return self.render_function(ctx, self.do_dots) def do_dots(self, value, *dots): """Evaluate dotted expressions at runtime.""" for dot in dots: try: value = getattr(value, dot) except AttributeError: value = value[dot] if hasattr(value, '__call__'): value = value() return value python-coverage-3.7.1+dfsg.1.orig/coverage/version.py0000644000175000017500000000053412233013371021520 0ustar barrybarry"""The version and URL for coverage.py""" # This file is exec'ed in setup.py, don't import anything! __version__ = "3.7.1" # see detailed history in CHANGES.txt __url__ = "http://nedbatchelder.com/code/coverage" if max(__version__).isalpha(): # For pre-releases, use a version-specific URL. __url__ += "/" + __version__ python-coverage-3.7.1+dfsg.1.orig/coverage/misc.py0000644000175000017500000001043012233220425020762 0ustar barrybarry"""Miscellaneous stuff for Coverage.""" import errno import inspect import os import sys from coverage.backward import md5, sorted # pylint: disable=W0622 from coverage.backward import string_class, to_bytes def nice_pair(pair): """Make a nice string representation of a pair of numbers. If the numbers are equal, just return the number, otherwise return the pair with a dash between them, indicating the range. """ start, end = pair if start == end: return "%d" % start else: return "%d-%d" % (start, end) def format_lines(statements, lines): """Nicely format a list of line numbers. Format a list of line numbers for printing by coalescing groups of lines as long as the lines represent consecutive statements. This will coalesce even if there are gaps between statements. For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". """ pairs = [] i = 0 j = 0 start = None statements = sorted(statements) lines = sorted(lines) while i < len(statements) and j < len(lines): if statements[i] == lines[j]: if start == None: start = lines[j] end = lines[j] j += 1 elif start: pairs.append((start, end)) start = None i += 1 if start: pairs.append((start, end)) ret = ', '.join(map(nice_pair, pairs)) return ret def short_stack(): """Return a string summarizing the call stack.""" stack = inspect.stack()[:0:-1] return "\n".join(["%30s : %s @%d" % (t[3],t[1],t[2]) for t in stack]) def expensive(fn): """A decorator to cache the result of an expensive operation. Only applies to methods with no arguments. """ attr = "_cache_" + fn.__name__ def _wrapped(self): """Inner fn that checks the cache.""" if not hasattr(self, attr): setattr(self, attr, fn(self)) return getattr(self, attr) return _wrapped def bool_or_none(b): """Return bool(b), but preserve None.""" if b is None: return None else: return bool(b) def join_regex(regexes): """Combine a list of regexes into one that matches any of them.""" if len(regexes) > 1: return "|".join(["(%s)" % r for r in regexes]) elif regexes: return regexes[0] else: return "" def file_be_gone(path): """Remove a file, and don't get annoyed if it doesn't exist.""" try: os.remove(path) except OSError: _, e, _ = sys.exc_info() if e.errno != errno.ENOENT: raise class Hasher(object): """Hashes Python data into md5.""" def __init__(self): self.md5 = md5() def update(self, v): """Add `v` to the hash, recursively if needed.""" self.md5.update(to_bytes(str(type(v)))) if isinstance(v, string_class): self.md5.update(to_bytes(v)) elif v is None: pass elif isinstance(v, (int, float)): self.md5.update(to_bytes(str(v))) elif isinstance(v, (tuple, list)): for e in v: self.update(e) elif isinstance(v, dict): keys = v.keys() for k in sorted(keys): self.update(k) self.update(v[k]) else: for k in dir(v): if k.startswith('__'): continue a = getattr(v, k) if inspect.isroutine(a): continue self.update(k) self.update(a) def digest(self): """Retrieve the digest of the hash.""" return self.md5.digest() class CoverageException(Exception): """An exception specific to Coverage.""" pass class NoSource(CoverageException): """We couldn't find the source for a module.""" pass class NoCode(NoSource): """We couldn't find any code at all.""" pass class NotPython(CoverageException): """A source file turned out not to be parsable Python.""" pass class ExceptionDuringRun(CoverageException): """An exception happened while running customer code. Construct it with three arguments, the values from `sys.exc_info`. """ pass python-coverage-3.7.1+dfsg.1.orig/coverage/tracer.c0000644000175000017500000005511612202156243021115 0ustar barrybarry/* C-based Tracer for Coverage. */ #include "Python.h" #include "compile.h" /* in 2.3, this wasn't part of Python.h */ #include "eval.h" /* or this. */ #include "structmember.h" #include "frameobject.h" /* Compile-time debugging helpers */ #undef WHAT_LOG /* Define to log the WHAT params in the trace function. */ #undef TRACE_LOG /* Define to log our bookkeeping. */ #undef COLLECT_STATS /* Collect counters: stats are printed when tracer is stopped. */ #if COLLECT_STATS #define STATS(x) x #else #define STATS(x) #endif /* Py 2.x and 3.x compatibility */ #ifndef Py_TYPE #define Py_TYPE(o) (((PyObject*)(o))->ob_type) #endif #if PY_MAJOR_VERSION >= 3 #define MyText_Type PyUnicode_Type #define MyText_Check(o) PyUnicode_Check(o) #define MyText_AS_BYTES(o) PyUnicode_AsASCIIString(o) #define MyText_AS_STRING(o) PyBytes_AS_STRING(o) #define MyInt_FromLong(l) PyLong_FromLong(l) #define MyType_HEAD_INIT PyVarObject_HEAD_INIT(NULL, 0) #else #define MyText_Type PyString_Type #define MyText_Check(o) PyString_Check(o) #define MyText_AS_BYTES(o) (Py_INCREF(o), o) #define MyText_AS_STRING(o) PyString_AS_STRING(o) #define MyInt_FromLong(l) PyInt_FromLong(l) #define MyType_HEAD_INIT PyObject_HEAD_INIT(NULL) 0, #endif /* Py3k */ /* The values returned to indicate ok or error. */ #define RET_OK 0 #define RET_ERROR -1 /* An entry on the data stack. For each call frame, we need to record the dictionary to capture data, and the last line number executed in that frame. */ typedef struct { PyObject * file_data; /* PyMem_Malloc'ed, a borrowed ref. */ int last_line; } DataStackEntry; /* The CTracer type. */ typedef struct { PyObject_HEAD /* Python objects manipulated directly by the Collector class. */ PyObject * should_trace; PyObject * warn; PyObject * data; PyObject * should_trace_cache; PyObject * arcs; /* Has the tracer been started? */ int started; /* Are we tracing arcs, or just lines? */ int tracing_arcs; /* The data stack is a stack of dictionaries. Each dictionary collects data for a single source file. The data stack parallels the call stack: each call pushes the new frame's file data onto the data stack, and each return pops file data off. The file data is a dictionary whose form depends on the tracing options. If tracing arcs, the keys are line number pairs. If not tracing arcs, the keys are line numbers. In both cases, the value is irrelevant (None). */ /* The index of the last-used entry in data_stack. */ int depth; /* The file data at each level, or NULL if not recording. */ DataStackEntry * data_stack; int data_stack_alloc; /* number of entries allocated at data_stack. */ /* The current file_data dictionary. Borrowed. */ PyObject * cur_file_data; /* The line number of the last line recorded, for tracing arcs. -1 means there was no previous line, as when entering a code object. */ int last_line; /* The parent frame for the last exception event, to fix missing returns. */ PyFrameObject * last_exc_back; int last_exc_firstlineno; #if COLLECT_STATS struct { unsigned int calls; unsigned int lines; unsigned int returns; unsigned int exceptions; unsigned int others; unsigned int new_files; unsigned int missed_returns; unsigned int stack_reallocs; unsigned int errors; } stats; #endif /* COLLECT_STATS */ } CTracer; #define STACK_DELTA 100 static int CTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused) { #if COLLECT_STATS self->stats.calls = 0; self->stats.lines = 0; self->stats.returns = 0; self->stats.exceptions = 0; self->stats.others = 0; self->stats.new_files = 0; self->stats.missed_returns = 0; self->stats.stack_reallocs = 0; self->stats.errors = 0; #endif /* COLLECT_STATS */ self->should_trace = NULL; self->warn = NULL; self->data = NULL; self->should_trace_cache = NULL; self->arcs = NULL; self->started = 0; self->tracing_arcs = 0; self->depth = -1; self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry)); if (self->data_stack == NULL) { STATS( self->stats.errors++; ) PyErr_NoMemory(); return RET_ERROR; } self->data_stack_alloc = STACK_DELTA; self->cur_file_data = NULL; self->last_line = -1; self->last_exc_back = NULL; return RET_OK; } static void CTracer_dealloc(CTracer *self) { if (self->started) { PyEval_SetTrace(NULL, NULL); } Py_XDECREF(self->should_trace); Py_XDECREF(self->warn); Py_XDECREF(self->data); Py_XDECREF(self->should_trace_cache); PyMem_Free(self->data_stack); Py_TYPE(self)->tp_free((PyObject*)self); } #if TRACE_LOG static const char * indent(int n) { static const char * spaces = " " " " " " " " ; return spaces + strlen(spaces) - n*2; } static int logging = 0; /* Set these constants to be a file substring and line number to start logging. */ static const char * start_file = "tests/views"; static int start_line = 27; static void showlog(int depth, int lineno, PyObject * filename, const char * msg) { if (logging) { printf("%s%3d ", indent(depth), depth); if (lineno) { printf("%4d", lineno); } else { printf(" "); } if (filename) { PyObject *ascii = MyText_AS_BYTES(filename); printf(" %s", MyText_AS_STRING(ascii)); Py_DECREF(ascii); } if (msg) { printf(" %s", msg); } printf("\n"); } } #define SHOWLOG(a,b,c,d) showlog(a,b,c,d) #else #define SHOWLOG(a,b,c,d) #endif /* TRACE_LOG */ #if WHAT_LOG static const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "}; #endif /* Record a pair of integers in self->cur_file_data. */ static int CTracer_record_pair(CTracer *self, int l1, int l2) { int ret = RET_OK; PyObject * t = Py_BuildValue("(ii)", l1, l2); if (t != NULL) { if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) { STATS( self->stats.errors++; ) ret = RET_ERROR; } Py_DECREF(t); } else { STATS( self->stats.errors++; ) ret = RET_ERROR; } return ret; } /* * The Trace Function */ static int CTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) { int ret = RET_OK; PyObject * filename = NULL; PyObject * tracename = NULL; #if WHAT_LOG || TRACE_LOG PyObject * ascii = NULL; #endif #if WHAT_LOG if (what <= sizeof(what_sym)/sizeof(const char *)) { ascii = MyText_AS_BYTES(frame->f_code->co_filename); printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(ascii), frame->f_lineno); Py_DECREF(ascii); } #endif #if TRACE_LOG ascii = MyText_AS_BYTES(frame->f_code->co_filename); if (strstr(MyText_AS_STRING(ascii), start_file) && frame->f_lineno == start_line) { logging = 1; } Py_DECREF(ascii); #endif /* See below for details on missing-return detection. */ if (self->last_exc_back) { if (frame == self->last_exc_back) { /* Looks like someone forgot to send a return event. We'll clear the exception state and do the RETURN code here. Notice that the frame we have in hand here is not the correct frame for the RETURN, that frame is gone. Our handling for RETURN doesn't need the actual frame, but we do log it, so that will look a little off if you're looking at the detailed log. If someday we need to examine the frame when doing RETURN, then we'll need to keep more of the missed frame's state. */ STATS( self->stats.missed_returns++; ) if (self->depth >= 0) { if (self->tracing_arcs && self->cur_file_data) { if (CTracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) { return RET_ERROR; } } SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn"); self->cur_file_data = self->data_stack[self->depth].file_data; self->last_line = self->data_stack[self->depth].last_line; self->depth--; } } self->last_exc_back = NULL; } switch (what) { case PyTrace_CALL: /* 0 */ STATS( self->stats.calls++; ) /* Grow the stack. */ self->depth++; if (self->depth >= self->data_stack_alloc) { STATS( self->stats.stack_reallocs++; ) /* We've outgrown our data_stack array: make it bigger. */ int bigger = self->data_stack_alloc + STACK_DELTA; DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry)); if (bigger_data_stack == NULL) { STATS( self->stats.errors++; ) PyErr_NoMemory(); self->depth--; return RET_ERROR; } self->data_stack = bigger_data_stack; self->data_stack_alloc = bigger; } /* Push the current state on the stack. */ self->data_stack[self->depth].file_data = self->cur_file_data; self->data_stack[self->depth].last_line = self->last_line; /* Check if we should trace this line. */ filename = frame->f_code->co_filename; tracename = PyDict_GetItem(self->should_trace_cache, filename); if (tracename == NULL) { STATS( self->stats.new_files++; ) /* We've never considered this file before. */ /* Ask should_trace about it. */ PyObject * args = Py_BuildValue("(OO)", filename, frame); tracename = PyObject_Call(self->should_trace, args, NULL); Py_DECREF(args); if (tracename == NULL) { /* An error occurred inside should_trace. */ STATS( self->stats.errors++; ) return RET_ERROR; } if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) { STATS( self->stats.errors++; ) return RET_ERROR; } } else { Py_INCREF(tracename); } /* If tracename is a string, then we're supposed to trace. */ if (MyText_Check(tracename)) { PyObject * file_data = PyDict_GetItem(self->data, tracename); if (file_data == NULL) { file_data = PyDict_New(); if (file_data == NULL) { STATS( self->stats.errors++; ) return RET_ERROR; } ret = PyDict_SetItem(self->data, tracename, file_data); Py_DECREF(file_data); if (ret < 0) { STATS( self->stats.errors++; ) return RET_ERROR; } } self->cur_file_data = file_data; /* Make the frame right in case settrace(gettrace()) happens. */ Py_INCREF(self); frame->f_trace = (PyObject*)self; SHOWLOG(self->depth, frame->f_lineno, filename, "traced"); } else { self->cur_file_data = NULL; SHOWLOG(self->depth, frame->f_lineno, filename, "skipped"); } Py_DECREF(tracename); self->last_line = -1; break; case PyTrace_RETURN: /* 3 */ STATS( self->stats.returns++; ) /* A near-copy of this code is above in the missing-return handler. */ if (self->depth >= 0) { if (self->tracing_arcs && self->cur_file_data) { int first = frame->f_code->co_firstlineno; if (CTracer_record_pair(self, self->last_line, -first) < 0) { return RET_ERROR; } } SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return"); self->cur_file_data = self->data_stack[self->depth].file_data; self->last_line = self->data_stack[self->depth].last_line; self->depth--; } break; case PyTrace_LINE: /* 2 */ STATS( self->stats.lines++; ) if (self->depth >= 0) { SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line"); if (self->cur_file_data) { /* We're tracing in this frame: record something. */ if (self->tracing_arcs) { /* Tracing arcs: key is (last_line,this_line). */ if (CTracer_record_pair(self, self->last_line, frame->f_lineno) < 0) { return RET_ERROR; } } else { /* Tracing lines: key is simply this_line. */ PyObject * this_line = MyInt_FromLong(frame->f_lineno); if (this_line == NULL) { STATS( self->stats.errors++; ) return RET_ERROR; } ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None); Py_DECREF(this_line); if (ret < 0) { STATS( self->stats.errors++; ) return RET_ERROR; } } } self->last_line = frame->f_lineno; } break; case PyTrace_EXCEPTION: /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event without a return event. To detect that, we'll keep a copy of the parent frame for an exception event. If the next event is in that frame, then we must have returned without a return event. We can synthesize the missing event then. Python itself fixed this problem in 2.4. Pyexpat still has the bug. I've reported the problem with pyexpat as http://bugs.python.org/issue6359 . If it gets fixed, this code should still work properly. Maybe some day the bug will be fixed everywhere coverage.py is supported, and we can remove this missing-return detection. More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html */ STATS( self->stats.exceptions++; ) self->last_exc_back = frame->f_back; self->last_exc_firstlineno = frame->f_code->co_firstlineno; break; default: STATS( self->stats.others++; ) break; } return RET_OK; } /* * Python has two ways to set the trace function: sys.settrace(fn), which * takes a Python callable, and PyEval_SetTrace(func, obj), which takes * a C function and a Python object. The way these work together is that * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the * Python callable as the object in PyEval_SetTrace. So sys.gettrace() * simply returns the Python object used as the second argument to * PyEval_SetTrace. So sys.gettrace() will return our self parameter, which * means it must be callable to be used in sys.settrace(). * * So we make our self callable, equivalent to invoking our trace function. * * To help with the process of replaying stored frames, this function has an * optional keyword argument: * * def CTracer_call(frame, event, arg, lineno=0) * * If provided, the lineno argument is used as the line number, and the * frame's f_lineno member is ignored. */ static PyObject * CTracer_call(CTracer *self, PyObject *args, PyObject *kwds) { PyFrameObject *frame; PyObject *what_str; PyObject *arg; int lineno = 0; int what; int orig_lineno; PyObject *ret = NULL; static char *what_names[] = { "call", "exception", "line", "return", "c_call", "c_exception", "c_return", NULL }; #if WHAT_LOG printf("pytrace\n"); #endif static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist, &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) { goto done; } /* In Python, the what argument is a string, we need to find an int for the C function. */ for (what = 0; what_names[what]; what++) { PyObject *ascii = MyText_AS_BYTES(what_str); int should_break = !strcmp(MyText_AS_STRING(ascii), what_names[what]); Py_DECREF(ascii); if (should_break) { break; } } /* Save off the frame's lineno, and use the forced one, if provided. */ orig_lineno = frame->f_lineno; if (lineno > 0) { frame->f_lineno = lineno; } /* Invoke the C function, and return ourselves. */ if (CTracer_trace(self, frame, what, arg) == RET_OK) { Py_INCREF(self); ret = (PyObject *)self; } /* Clean up. */ frame->f_lineno = orig_lineno; done: return ret; } static PyObject * CTracer_start(CTracer *self, PyObject *args_unused) { PyEval_SetTrace((Py_tracefunc)CTracer_trace, (PyObject*)self); self->started = 1; self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs); self->last_line = -1; /* start() returns a trace function usable with sys.settrace() */ Py_INCREF(self); return (PyObject *)self; } static PyObject * CTracer_stop(CTracer *self, PyObject *args_unused) { if (self->started) { PyEval_SetTrace(NULL, NULL); self->started = 0; } return Py_BuildValue(""); } static PyObject * CTracer_get_stats(CTracer *self) { #if COLLECT_STATS return Py_BuildValue( "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}", "calls", self->stats.calls, "lines", self->stats.lines, "returns", self->stats.returns, "exceptions", self->stats.exceptions, "others", self->stats.others, "new_files", self->stats.new_files, "missed_returns", self->stats.missed_returns, "stack_reallocs", self->stats.stack_reallocs, "stack_alloc", self->data_stack_alloc, "errors", self->stats.errors ); #else return Py_BuildValue(""); #endif /* COLLECT_STATS */ } static PyMemberDef CTracer_members[] = { { "should_trace", T_OBJECT, offsetof(CTracer, should_trace), 0, PyDoc_STR("Function indicating whether to trace a file.") }, { "warn", T_OBJECT, offsetof(CTracer, warn), 0, PyDoc_STR("Function for issuing warnings.") }, { "data", T_OBJECT, offsetof(CTracer, data), 0, PyDoc_STR("The raw dictionary of trace data.") }, { "should_trace_cache", T_OBJECT, offsetof(CTracer, should_trace_cache), 0, PyDoc_STR("Dictionary caching should_trace results.") }, { "arcs", T_OBJECT, offsetof(CTracer, arcs), 0, PyDoc_STR("Should we trace arcs, or just lines?") }, { NULL } }; static PyMethodDef CTracer_methods[] = { { "start", (PyCFunction) CTracer_start, METH_VARARGS, PyDoc_STR("Start the tracer") }, { "stop", (PyCFunction) CTracer_stop, METH_VARARGS, PyDoc_STR("Stop the tracer") }, { "get_stats", (PyCFunction) CTracer_get_stats, METH_VARARGS, PyDoc_STR("Get statistics about the tracing") }, { NULL } }; static PyTypeObject CTracerType = { MyType_HEAD_INIT "coverage.CTracer", /*tp_name*/ sizeof(CTracer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CTracer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ (ternaryfunc)CTracer_call, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "CTracer objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CTracer_methods, /* tp_methods */ CTracer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)CTracer_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; /* Module definition */ #define MODULE_DOC PyDoc_STR("Fast coverage tracer.") #if PY_MAJOR_VERSION >= 3 static PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "coverage.tracer", MODULE_DOC, -1, NULL, /* methods */ NULL, NULL, /* traverse */ NULL, /* clear */ NULL }; PyObject * PyInit_tracer(void) { PyObject * mod = PyModule_Create(&moduledef); if (mod == NULL) { return NULL; } CTracerType.tp_new = PyType_GenericNew; if (PyType_Ready(&CTracerType) < 0) { Py_DECREF(mod); return NULL; } Py_INCREF(&CTracerType); PyModule_AddObject(mod, "CTracer", (PyObject *)&CTracerType); return mod; } #else void inittracer(void) { PyObject * mod; mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC); if (mod == NULL) { return; } CTracerType.tp_new = PyType_GenericNew; if (PyType_Ready(&CTracerType) < 0) { return; } Py_INCREF(&CTracerType); PyModule_AddObject(mod, "CTracer", (PyObject *)&CTracerType); } #endif /* Py3k */ python-coverage-3.7.1+dfsg.1.orig/coverage/annotate.py0000644000175000017500000000603112233013371021642 0ustar barrybarry"""Source file annotation for Coverage.""" import os, re from coverage.backward import sorted # pylint: disable=W0622 from coverage.report import Reporter class AnnotateReporter(Reporter): """Generate annotated source files showing line coverage. This reporter creates annotated copies of the measured source files. Each .py file is copied as a .py,cover file, with a left-hand margin annotating each line:: > def h(x): - if 0: #pragma: no cover - pass > if x == 1: ! a = 1 > else: > a = 2 > h(2) Executed lines use '>', lines not executed use '!', lines excluded from consideration use '-'. """ def __init__(self, coverage, config): super(AnnotateReporter, self).__init__(coverage, config) self.directory = None blank_re = re.compile(r"\s*(#|$)") else_re = re.compile(r"\s*else\s*:\s*(#|$)") def report(self, morfs, directory=None): """Run the report. See `coverage.report()` for arguments. """ self.report_files(self.annotate_file, morfs, directory) def annotate_file(self, cu, analysis): """Annotate a single file. `cu` is the CodeUnit for the file to annotate. """ if not cu.relative: return filename = cu.filename source = cu.source_file() if self.directory: dest_file = os.path.join(self.directory, cu.flat_rootname()) dest_file += ".py,cover" else: dest_file = filename + ",cover" dest = open(dest_file, 'w') statements = sorted(analysis.statements) missing = sorted(analysis.missing) excluded = sorted(analysis.excluded) lineno = 0 i = 0 j = 0 covered = True while True: line = source.readline() if line == '': break lineno += 1 while i < len(statements) and statements[i] < lineno: i += 1 while j < len(missing) and missing[j] < lineno: j += 1 if i < len(statements) and statements[i] == lineno: covered = j >= len(missing) or missing[j] > lineno if self.blank_re.match(line): dest.write(' ') elif self.else_re.match(line): # Special logic for lines containing only 'else:'. if i >= len(statements) and j >= len(missing): dest.write('! ') elif i >= len(statements) or j >= len(missing): dest.write('> ') elif statements[i] == missing[j]: dest.write('! ') else: dest.write('> ') elif lineno in excluded: dest.write('- ') elif covered: dest.write('> ') else: dest.write('! ') dest.write(line) source.close() dest.close() python-coverage-3.7.1+dfsg.1.orig/coverage/__main__.py0000644000175000017500000000014412202156243021552 0ustar barrybarry"""Coverage.py's main entry point.""" import sys from coverage.cmdline import main sys.exit(main()) python-coverage-3.7.1+dfsg.1.orig/coverage/backward.py0000644000175000017500000001210312233013371021604 0ustar barrybarry"""Add things to old Pythons so I can pretend they are newer.""" # This file does lots of tricky stuff, so disable a bunch of lintisms. # pylint: disable=F0401,W0611,W0622 # F0401: Unable to import blah # W0611: Unused import blah # W0622: Redefining built-in blah import os, re, sys # Python 2.3 doesn't have `set` try: set = set # new in 2.4 except NameError: from sets import Set as set # Python 2.3 doesn't have `sorted`. try: sorted = sorted except NameError: def sorted(iterable): """A 2.3-compatible implementation of `sorted`.""" lst = list(iterable) lst.sort() return lst # Python 2.3 doesn't have `reversed`. try: reversed = reversed except NameError: def reversed(iterable): """A 2.3-compatible implementation of `reversed`.""" lst = list(iterable) return lst[::-1] # rpartition is new in 2.5 try: "".rpartition except AttributeError: def rpartition(s, sep): """Implement s.rpartition(sep) for old Pythons.""" i = s.rfind(sep) if i == -1: return ('', '', s) else: return (s[:i], sep, s[i+len(sep):]) else: def rpartition(s, sep): """A common interface for new Pythons.""" return s.rpartition(sep) # Pythons 2 and 3 differ on where to get StringIO try: from cStringIO import StringIO BytesIO = StringIO except ImportError: from io import StringIO, BytesIO # What's a string called? try: string_class = basestring except NameError: string_class = str # Where do pickles come from? try: import cPickle as pickle except ImportError: import pickle # range or xrange? try: range = xrange except NameError: range = range # A function to iterate listlessly over a dict's items. try: {}.iteritems except AttributeError: def iitems(d): """Produce the items from dict `d`.""" return d.items() else: def iitems(d): """Produce the items from dict `d`.""" return d.iteritems() # Exec is a statement in Py2, a function in Py3 if sys.version_info >= (3, 0): def exec_code_object(code, global_map): """A wrapper around exec().""" exec(code, global_map) else: # OK, this is pretty gross. In Py2, exec was a statement, but that will # be a syntax error if we try to put it in a Py3 file, even if it is never # executed. So hide it inside an evaluated string literal instead. eval( compile( "def exec_code_object(code, global_map):\n" " exec code in global_map\n", "", "exec" ) ) # Reading Python source and interpreting the coding comment is a big deal. if sys.version_info >= (3, 0): # Python 3.2 provides `tokenize.open`, the best way to open source files. import tokenize try: open_source = tokenize.open # pylint: disable=E1101 except AttributeError: from io import TextIOWrapper detect_encoding = tokenize.detect_encoding # pylint: disable=E1101 # Copied from the 3.2 stdlib: def open_source(fname): """Open a file in read only mode using the encoding detected by detect_encoding(). """ buffer = open(fname, 'rb') encoding, _ = detect_encoding(buffer.readline) buffer.seek(0) text = TextIOWrapper(buffer, encoding, line_buffering=True) text.mode = 'r' return text else: def open_source(fname): """Open a source file the best way.""" return open(fname, "rU") # Python 3.x is picky about bytes and strings, so provide methods to # get them right, and make them no-ops in 2.x if sys.version_info >= (3, 0): def to_bytes(s): """Convert string `s` to bytes.""" return s.encode('utf8') def to_string(b): """Convert bytes `b` to a string.""" return b.decode('utf8') def binary_bytes(byte_values): """Produce a byte string with the ints from `byte_values`.""" return bytes(byte_values) def byte_to_int(byte_value): """Turn an element of a bytes object into an int.""" return byte_value def bytes_to_ints(bytes_value): """Turn a bytes object into a sequence of ints.""" # In Py3, iterating bytes gives ints. return bytes_value else: def to_bytes(s): """Convert string `s` to bytes (no-op in 2.x).""" return s def to_string(b): """Convert bytes `b` to a string (no-op in 2.x).""" return b def binary_bytes(byte_values): """Produce a byte string with the ints from `byte_values`.""" return "".join([chr(b) for b in byte_values]) def byte_to_int(byte_value): """Turn an element of a bytes object into an int.""" return ord(byte_value) def bytes_to_ints(bytes_value): """Turn a bytes object into a sequence of ints.""" for byte in bytes_value: yield ord(byte) # Md5 is available in different places. try: import hashlib md5 = hashlib.md5 except ImportError: import md5 md5 = md5.new python-coverage-3.7.1+dfsg.1.orig/coverage/cmdline.py0000644000175000017500000006106012233013371021447 0ustar barrybarry"""Command-line support for Coverage.""" import optparse, os, sys, time, traceback from coverage.backward import sorted # pylint: disable=W0622 from coverage.execfile import run_python_file, run_python_module from coverage.misc import CoverageException, ExceptionDuringRun, NoSource from coverage.debug import info_formatter class Opts(object): """A namespace class for individual options we'll build parsers from.""" append = optparse.make_option( '-a', '--append', action='store_false', dest="erase_first", help="Append coverage data to .coverage, otherwise it is started " "clean with each run." ) branch = optparse.make_option( '', '--branch', action='store_true', help="Measure branch coverage in addition to statement coverage." ) debug = optparse.make_option( '', '--debug', action='store', metavar="OPTS", help="Debug options, separated by commas" ) directory = optparse.make_option( '-d', '--directory', action='store', metavar="DIR", help="Write the output files to DIR." ) fail_under = optparse.make_option( '', '--fail-under', action='store', metavar="MIN", type="int", help="Exit with a status of 2 if the total coverage is less than MIN." ) help = optparse.make_option( '-h', '--help', action='store_true', help="Get help on this command." ) ignore_errors = optparse.make_option( '-i', '--ignore-errors', action='store_true', help="Ignore errors while reading source files." ) include = optparse.make_option( '', '--include', action='store', metavar="PAT1,PAT2,...", help="Include files only when their filename path matches one of " "these patterns. Usually needs quoting on the command line." ) pylib = optparse.make_option( '-L', '--pylib', action='store_true', help="Measure coverage even inside the Python installed library, " "which isn't done by default." ) show_missing = optparse.make_option( '-m', '--show-missing', action='store_true', help="Show line numbers of statements in each module that weren't " "executed." ) old_omit = optparse.make_option( '-o', '--omit', action='store', metavar="PAT1,PAT2,...", help="Omit files when their filename matches one of these patterns. " "Usually needs quoting on the command line." ) omit = optparse.make_option( '', '--omit', action='store', metavar="PAT1,PAT2,...", help="Omit files when their filename matches one of these patterns. " "Usually needs quoting on the command line." ) output_xml = optparse.make_option( '-o', '', action='store', dest="outfile", metavar="OUTFILE", help="Write the XML report to this file. Defaults to 'coverage.xml'" ) parallel_mode = optparse.make_option( '-p', '--parallel-mode', action='store_true', help="Append the machine name, process id and random number to the " ".coverage data file name to simplify collecting data from " "many processes." ) module = optparse.make_option( '-m', '--module', action='store_true', help=" is an importable Python module, not a script path, " "to be run as 'python -m' would run it." ) rcfile = optparse.make_option( '', '--rcfile', action='store', help="Specify configuration file. Defaults to '.coveragerc'" ) source = optparse.make_option( '', '--source', action='store', metavar="SRC1,SRC2,...", help="A list of packages or directories of code to be measured." ) timid = optparse.make_option( '', '--timid', action='store_true', help="Use a simpler but slower trace method. Try this if you get " "seemingly impossible results!" ) title = optparse.make_option( '', '--title', action='store', metavar="TITLE", help="A text string to use as the title on the HTML." ) version = optparse.make_option( '', '--version', action='store_true', help="Display version information and exit." ) class CoverageOptionParser(optparse.OptionParser, object): """Base OptionParser for coverage. Problems don't exit the program. Defaults are initialized for all options. """ def __init__(self, *args, **kwargs): super(CoverageOptionParser, self).__init__( add_help_option=False, *args, **kwargs ) self.set_defaults( actions=[], branch=None, debug=None, directory=None, fail_under=None, help=None, ignore_errors=None, include=None, omit=None, parallel_mode=None, module=None, pylib=None, rcfile=True, show_missing=None, source=None, timid=None, title=None, erase_first=None, version=None, ) self.disable_interspersed_args() self.help_fn = self.help_noop def help_noop(self, error=None, topic=None, parser=None): """No-op help function.""" pass class OptionParserError(Exception): """Used to stop the optparse error handler ending the process.""" pass def parse_args(self, args=None, options=None): """Call optparse.parse_args, but return a triple: (ok, options, args) """ try: options, args = \ super(CoverageOptionParser, self).parse_args(args, options) except self.OptionParserError: return False, None, None return True, options, args def error(self, msg): """Override optparse.error so sys.exit doesn't get called.""" self.help_fn(msg) raise self.OptionParserError class ClassicOptionParser(CoverageOptionParser): """Command-line parser for coverage.py classic arguments.""" def __init__(self): super(ClassicOptionParser, self).__init__() self.add_action('-a', '--annotate', 'annotate') self.add_action('-b', '--html', 'html') self.add_action('-c', '--combine', 'combine') self.add_action('-e', '--erase', 'erase') self.add_action('-r', '--report', 'report') self.add_action('-x', '--execute', 'execute') self.add_options([ Opts.directory, Opts.help, Opts.ignore_errors, Opts.pylib, Opts.show_missing, Opts.old_omit, Opts.parallel_mode, Opts.timid, Opts.version, ]) def add_action(self, dash, dashdash, action_code): """Add a specialized option that is the action to execute.""" option = self.add_option(dash, dashdash, action='callback', callback=self._append_action ) option.action_code = action_code def _append_action(self, option, opt_unused, value_unused, parser): """Callback for an option that adds to the `actions` list.""" parser.values.actions.append(option.action_code) class CmdOptionParser(CoverageOptionParser): """Parse one of the new-style commands for coverage.py.""" def __init__(self, action, options=None, defaults=None, usage=None, cmd=None, description=None ): """Create an OptionParser for a coverage command. `action` is the slug to put into `options.actions`. `options` is a list of Option's for the command. `defaults` is a dict of default value for options. `usage` is the usage string to display in help. `cmd` is the command name, if different than `action`. `description` is the description of the command, for the help text. """ if usage: usage = "%prog " + usage super(CmdOptionParser, self).__init__( prog="coverage %s" % (cmd or action), usage=usage, description=description, ) self.set_defaults(actions=[action], **(defaults or {})) if options: self.add_options(options) self.cmd = cmd or action def __eq__(self, other): # A convenience equality, so that I can put strings in unit test # results, and they will compare equal to objects. return (other == "" % self.cmd) GLOBAL_ARGS = [ Opts.rcfile, Opts.help, ] CMDS = { 'annotate': CmdOptionParser("annotate", [ Opts.directory, Opts.ignore_errors, Opts.omit, Opts.include, ] + GLOBAL_ARGS, usage = "[options] [modules]", description = "Make annotated copies of the given files, marking " "statements that are executed with > and statements that are " "missed with !." ), 'combine': CmdOptionParser("combine", GLOBAL_ARGS, usage = " ", description = "Combine data from multiple coverage files collected " "with 'run -p'. The combined results are written to a single " "file representing the union of the data." ), 'debug': CmdOptionParser("debug", GLOBAL_ARGS, usage = "", description = "Display information on the internals of coverage.py, " "for diagnosing problems. " "Topics are 'data' to show a summary of the collected data, " "or 'sys' to show installation information." ), 'erase': CmdOptionParser("erase", GLOBAL_ARGS, usage = " ", description = "Erase previously collected coverage data." ), 'help': CmdOptionParser("help", GLOBAL_ARGS, usage = "[command]", description = "Describe how to use coverage.py" ), 'html': CmdOptionParser("html", [ Opts.directory, Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, Opts.title, ] + GLOBAL_ARGS, usage = "[options] [modules]", description = "Create an HTML report of the coverage of the files. " "Each file gets its own page, with the source decorated to show " "executed, excluded, and missed lines." ), 'report': CmdOptionParser("report", [ Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, Opts.show_missing, ] + GLOBAL_ARGS, usage = "[options] [modules]", description = "Report coverage statistics on modules." ), 'run': CmdOptionParser("execute", [ Opts.append, Opts.branch, Opts.debug, Opts.pylib, Opts.parallel_mode, Opts.module, Opts.timid, Opts.source, Opts.omit, Opts.include, ] + GLOBAL_ARGS, defaults = {'erase_first': True}, cmd = "run", usage = "[options] [program options]", description = "Run a Python program, measuring code execution." ), 'xml': CmdOptionParser("xml", [ Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, Opts.output_xml, ] + GLOBAL_ARGS, cmd = "xml", usage = "[options] [modules]", description = "Generate an XML report of coverage results." ), } OK, ERR, FAIL_UNDER = 0, 1, 2 class CoverageScript(object): """The command-line interface to Coverage.""" def __init__(self, _covpkg=None, _run_python_file=None, _run_python_module=None, _help_fn=None): # _covpkg is for dependency injection, so we can test this code. if _covpkg: self.covpkg = _covpkg else: import coverage self.covpkg = coverage # For dependency injection: self.run_python_file = _run_python_file or run_python_file self.run_python_module = _run_python_module or run_python_module self.help_fn = _help_fn or self.help self.classic = False self.coverage = None def command_line(self, argv): """The bulk of the command line interface to Coverage. `argv` is the argument list to process. Returns 0 if all is well, 1 if something went wrong. """ # Collect the command-line options. if not argv: self.help_fn(topic='minimum_help') return OK # The command syntax we parse depends on the first argument. Classic # syntax always starts with an option. self.classic = argv[0].startswith('-') if self.classic: parser = ClassicOptionParser() else: parser = CMDS.get(argv[0]) if not parser: self.help_fn("Unknown command: '%s'" % argv[0]) return ERR argv = argv[1:] parser.help_fn = self.help_fn ok, options, args = parser.parse_args(argv) if not ok: return ERR # Handle help and version. if self.do_help(options, args, parser): return OK # Check for conflicts and problems in the options. if not self.args_ok(options, args): return ERR # Listify the list options. source = unshell_list(options.source) omit = unshell_list(options.omit) include = unshell_list(options.include) debug = unshell_list(options.debug) # Do something. self.coverage = self.covpkg.coverage( data_suffix = options.parallel_mode, cover_pylib = options.pylib, timid = options.timid, branch = options.branch, config_file = options.rcfile, source = source, omit = omit, include = include, debug = debug, ) if 'debug' in options.actions: return self.do_debug(args) if 'erase' in options.actions or options.erase_first: self.coverage.erase() else: self.coverage.load() if 'execute' in options.actions: self.do_execute(options, args) if 'combine' in options.actions: self.coverage.combine() self.coverage.save() # Remaining actions are reporting, with some common options. report_args = dict( morfs = args, ignore_errors = options.ignore_errors, omit = omit, include = include, ) if 'report' in options.actions: total = self.coverage.report( show_missing=options.show_missing, **report_args) if 'annotate' in options.actions: self.coverage.annotate( directory=options.directory, **report_args) if 'html' in options.actions: total = self.coverage.html_report( directory=options.directory, title=options.title, **report_args) if 'xml' in options.actions: outfile = options.outfile total = self.coverage.xml_report(outfile=outfile, **report_args) if options.fail_under is not None: if total >= options.fail_under: return OK else: return FAIL_UNDER else: return OK def help(self, error=None, topic=None, parser=None): """Display an error message, or the named topic.""" assert error or topic or parser if error: print(error) print("Use 'coverage help' for help.") elif parser: print(parser.format_help().strip()) else: help_msg = HELP_TOPICS.get(topic, '').strip() if help_msg: print(help_msg % self.covpkg.__dict__) else: print("Don't know topic %r" % topic) def do_help(self, options, args, parser): """Deal with help requests. Return True if it handled the request, False if not. """ # Handle help. if options.help: if self.classic: self.help_fn(topic='help') else: self.help_fn(parser=parser) return True if "help" in options.actions: if args: for a in args: parser = CMDS.get(a) if parser: self.help_fn(parser=parser) else: self.help_fn(topic=a) else: self.help_fn(topic='help') return True # Handle version. if options.version: self.help_fn(topic='version') return True return False def args_ok(self, options, args): """Check for conflicts and problems in the options. Returns True if everything is ok, or False if not. """ for i in ['erase', 'execute']: for j in ['annotate', 'html', 'report', 'combine']: if (i in options.actions) and (j in options.actions): self.help_fn("You can't specify the '%s' and '%s' " "options at the same time." % (i, j)) return False if not options.actions: self.help_fn( "You must specify at least one of -e, -x, -c, -r, -a, or -b." ) return False args_allowed = ( 'execute' in options.actions or 'annotate' in options.actions or 'html' in options.actions or 'debug' in options.actions or 'report' in options.actions or 'xml' in options.actions ) if not args_allowed and args: self.help_fn("Unexpected arguments: %s" % " ".join(args)) return False if 'execute' in options.actions and not args: self.help_fn("Nothing to do.") return False return True def do_execute(self, options, args): """Implementation of 'coverage run'.""" # Set the first path element properly. old_path0 = sys.path[0] # Run the script. self.coverage.start() code_ran = True try: try: if options.module: sys.path[0] = '' self.run_python_module(args[0], args) else: filename = args[0] sys.path[0] = os.path.abspath(os.path.dirname(filename)) self.run_python_file(filename, args) except NoSource: code_ran = False raise finally: self.coverage.stop() if code_ran: self.coverage.save() # Restore the old path sys.path[0] = old_path0 def do_debug(self, args): """Implementation of 'coverage debug'.""" if not args: self.help_fn("What information would you like: data, sys?") return ERR for info in args: if info == 'sys': print("-- sys ----------------------------------------") for line in info_formatter(self.coverage.sysinfo()): print(" %s" % line) elif info == 'data': print("-- data ---------------------------------------") self.coverage.load() print("path: %s" % self.coverage.data.filename) print("has_arcs: %r" % self.coverage.data.has_arcs()) summary = self.coverage.data.summary(fullpath=True) if summary: filenames = sorted(summary.keys()) print("\n%d files:" % len(filenames)) for f in filenames: print("%s: %d lines" % (f, summary[f])) else: print("No data collected") else: self.help_fn("Don't know what you mean by %r" % info) return ERR return OK def unshell_list(s): """Turn a command-line argument into a list.""" if not s: return None if sys.platform == 'win32': # When running coverage as coverage.exe, some of the behavior # of the shell is emulated: wildcards are expanded into a list of # filenames. So you have to single-quote patterns on the command # line, but (not) helpfully, the single quotes are included in the # argument, so we have to strip them off here. s = s.strip("'") return s.split(',') HELP_TOPICS = { # ------------------------- 'classic': r"""Coverage.py version %(__version__)s Measure, collect, and report on code coverage in Python programs. Usage: coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] Execute the module, passing the given command-line arguments, collecting coverage data. With the -p option, include the machine name and process id in the .coverage file name. With -L, measure coverage even inside the Python installed library, which isn't done by default. With --timid, use a simpler but slower trace method. coverage -e Erase collected coverage data. coverage -c Combine data from multiple coverage files (as created by -p option above) and store it into a single file representing the union of the coverage. coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] Report on the statement coverage for the given files. With the -m option, show line numbers of the statements that weren't executed. coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] Create an HTML report of the coverage of the given files. Each file gets its own page, with the file listing decorated to show executed, excluded, and missed lines. coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] Make annotated copies of the given files, marking statements that are executed with > and statements that are missed with !. -d DIR Write output files for -b or -a to this directory. -i Ignore errors while reporting or annotating. -o DIR,... Omit reporting or annotating files when their filename path starts with a directory listed in the omit list. e.g. coverage -i -r -o c:\python25,lib\enthought\traits Coverage data is saved in the file .coverage by default. Set the COVERAGE_FILE environment variable to save it somewhere else. """, # ------------------------- 'help': """\ Coverage.py, version %(__version__)s Measure, collect, and report on code coverage in Python programs. usage: coverage [options] [args] Commands: annotate Annotate source files with execution information. combine Combine a number of data files. erase Erase previously collected coverage data. help Get help on using coverage.py. html Create an HTML report. report Report coverage stats on modules. run Run a Python program and measure code execution. xml Create an XML report of coverage results. Use "coverage help " for detailed help on any command. Use "coverage help classic" for help on older command syntax. For more information, see %(__url__)s """, # ------------------------- 'minimum_help': """\ Code coverage for Python. Use 'coverage help' for help. """, # ------------------------- 'version': """\ Coverage.py, version %(__version__)s. %(__url__)s """, } def main(argv=None): """The main entry point to Coverage. This is installed as the script entry point. """ if argv is None: argv = sys.argv[1:] try: start = time.clock() status = CoverageScript().command_line(argv) end = time.clock() if 0: print("time: %.3fs" % (end - start)) except ExceptionDuringRun: # An exception was caught while running the product code. The # sys.exc_info() return tuple is packed into an ExceptionDuringRun # exception. _, err, _ = sys.exc_info() traceback.print_exception(*err.args) status = ERR except CoverageException: # A controlled error inside coverage.py: print the message to the user. _, err, _ = sys.exc_info() print(err) status = ERR except SystemExit: # The user called `sys.exit()`. Exit with their argument, if any. _, err, _ = sys.exc_info() if err.args: status = err.args[0] else: status = None return status python-coverage-3.7.1+dfsg.1.orig/coverage/bytecode.py0000644000175000017500000000376412221560501021640 0ustar barrybarry"""Bytecode manipulation for coverage.py""" import opcode, types from coverage.backward import byte_to_int class ByteCode(object): """A single bytecode.""" def __init__(self): # The offset of this bytecode in the code object. self.offset = -1 # The opcode, defined in the `opcode` module. self.op = -1 # The argument, a small integer, whose meaning depends on the opcode. self.arg = -1 # The offset in the code object of the next bytecode. self.next_offset = -1 # The offset to jump to. self.jump_to = -1 class ByteCodes(object): """Iterator over byte codes in `code`. Returns `ByteCode` objects. """ # pylint: disable=R0924 def __init__(self, code): self.code = code def __getitem__(self, i): return byte_to_int(self.code[i]) def __iter__(self): offset = 0 while offset < len(self.code): bc = ByteCode() bc.op = self[offset] bc.offset = offset next_offset = offset+1 if bc.op >= opcode.HAVE_ARGUMENT: bc.arg = self[offset+1] + 256*self[offset+2] next_offset += 2 label = -1 if bc.op in opcode.hasjrel: label = next_offset + bc.arg elif bc.op in opcode.hasjabs: label = bc.arg bc.jump_to = label bc.next_offset = offset = next_offset yield bc class CodeObjects(object): """Iterate over all the code objects in `code`.""" def __init__(self, code): self.stack = [code] def __iter__(self): while self.stack: # We're going to return the code object on the stack, but first # push its children for later returning. code = self.stack.pop() for c in code.co_consts: if isinstance(c, types.CodeType): self.stack.append(c) yield code python-coverage-3.7.1+dfsg.1.orig/coverage/control.py0000644000175000017500000007171612251732652021537 0ustar barrybarry"""Core control stuff for Coverage.""" import atexit, os, random, socket, sys from coverage.annotate import AnnotateReporter from coverage.backward import string_class, iitems, sorted # pylint: disable=W0622 from coverage.codeunit import code_unit_factory, CodeUnit from coverage.collector import Collector from coverage.config import CoverageConfig from coverage.data import CoverageData from coverage.debug import DebugControl from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher from coverage.files import PathAliases, find_python_files, prep_patterns from coverage.html import HtmlReporter from coverage.misc import CoverageException, bool_or_none, join_regex from coverage.misc import file_be_gone from coverage.results import Analysis, Numbers from coverage.summary import SummaryReporter from coverage.xmlreport import XmlReporter # Pypy has some unusual stuff in the "stdlib". Consider those locations # when deciding where the stdlib is. try: import _structseq # pylint: disable=F0401 except ImportError: _structseq = None class coverage(object): """Programmatic access to coverage.py. To use:: from coverage import coverage cov = coverage() cov.start() #.. call your code .. cov.stop() cov.html_report(directory='covhtml') """ def __init__(self, data_file=None, data_suffix=None, cover_pylib=None, auto_data=False, timid=None, branch=None, config_file=True, source=None, omit=None, include=None, debug=None, debug_file=None): """ `data_file` is the base name of the data file to use, defaulting to ".coverage". `data_suffix` is appended (with a dot) to `data_file` to create the final file name. If `data_suffix` is simply True, then a suffix is created with the machine and process identity included. `cover_pylib` is a boolean determining whether Python code installed with the Python interpreter is measured. This includes the Python standard library and any packages installed with the interpreter. If `auto_data` is true, then any existing data file will be read when coverage measurement starts, and data will be saved automatically when measurement stops. If `timid` is true, then a slower and simpler trace function will be used. This is important for some environments where manipulation of tracing functions breaks the faster trace function. If `branch` is true, then branch coverage will be measured in addition to the usual statement coverage. `config_file` determines what config file to read. If it is a string, it is the name of the config file to read. If it is True, then a standard file is read (".coveragerc"). If it is False, then no file is read. `source` is a list of file paths or package names. Only code located in the trees indicated by the file paths or package names will be measured. `include` and `omit` are lists of filename patterns. Files that match `include` will be measured, files that match `omit` will not. Each will also accept a single string argument. `debug` is a list of strings indicating what debugging information is desired. `debug_file` is the file to write debug messages to, defaulting to stderr. """ from coverage import __version__ # A record of all the warnings that have been issued. self._warnings = [] # Build our configuration from a number of sources: # 1: defaults: self.config = CoverageConfig() # 2: from the coveragerc file: if config_file: if config_file is True: config_file = ".coveragerc" try: self.config.from_file(config_file) except ValueError: _, err, _ = sys.exc_info() raise CoverageException( "Couldn't read config file %s: %s" % (config_file, err) ) # 3: from environment variables: self.config.from_environment('COVERAGE_OPTIONS') env_data_file = os.environ.get('COVERAGE_FILE') if env_data_file: self.config.data_file = env_data_file # 4: from constructor arguments: self.config.from_args( data_file=data_file, cover_pylib=cover_pylib, timid=timid, branch=branch, parallel=bool_or_none(data_suffix), source=source, omit=omit, include=include, debug=debug, ) # Create and configure the debugging controller. self.debug = DebugControl(self.config.debug, debug_file or sys.stderr) self.auto_data = auto_data # _exclude_re is a dict mapping exclusion list names to compiled # regexes. self._exclude_re = {} self._exclude_regex_stale() self.file_locator = FileLocator() # The source argument can be directories or package names. self.source = [] self.source_pkgs = [] for src in self.config.source or []: if os.path.exists(src): self.source.append(self.file_locator.canonical_filename(src)) else: self.source_pkgs.append(src) self.omit = prep_patterns(self.config.omit) self.include = prep_patterns(self.config.include) self.collector = Collector( self._should_trace, timid=self.config.timid, branch=self.config.branch, warn=self._warn ) # Suffixes are a bit tricky. We want to use the data suffix only when # collecting data, not when combining data. So we save it as # `self.run_suffix` now, and promote it to `self.data_suffix` if we # find that we are collecting data later. if data_suffix or self.config.parallel: if not isinstance(data_suffix, string_class): # if data_suffix=True, use .machinename.pid.random data_suffix = True else: data_suffix = None self.data_suffix = None self.run_suffix = data_suffix # Create the data file. We do this at construction time so that the # data file will be written into the directory where the process # started rather than wherever the process eventually chdir'd to. self.data = CoverageData( basename=self.config.data_file, collector="coverage v%s" % __version__, debug=self.debug, ) # The dirs for files considered "installed with the interpreter". self.pylib_dirs = [] if not self.config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. for m in (atexit, os, random, socket, _structseq): if m is not None and hasattr(m, "__file__"): m_dir = self._canonical_dir(m) if m_dir not in self.pylib_dirs: self.pylib_dirs.append(m_dir) # To avoid tracing the coverage code itself, we skip anything located # where we are. self.cover_dir = self._canonical_dir(__file__) # The matchers for _should_trace. self.source_match = None self.pylib_match = self.cover_match = None self.include_match = self.omit_match = None # Set the reporting precision. Numbers.set_precision(self.config.precision) # Is it ok for no data to be collected? self._warn_no_data = True self._warn_unimported_source = True # State machine variables: # Have we started collecting and not stopped it? self._started = False # Have we measured some data and not harvested it? self._measured = False atexit.register(self._atexit) def _canonical_dir(self, morf): """Return the canonical directory of the module or file `morf`.""" return os.path.split(CodeUnit(morf, self.file_locator).filename)[0] def _source_for_file(self, filename): """Return the source file for `filename`.""" if not filename.endswith(".py"): if filename[-4:-1] == ".py": filename = filename[:-1] elif filename.endswith("$py.class"): # jython filename = filename[:-9] + ".py" return filename def _should_trace_with_reason(self, filename, frame): """Decide whether to trace execution in `filename`, with a reason. This function is called from the trace function. As each new file name is encountered, this function determines whether it is traced or not. Returns a pair of values: the first indicates whether the file should be traced: it's a canonicalized filename if it should be traced, None if it should not. The second value is a string, the resason for the decision. """ if not filename: # Empty string is pretty useless return None, "empty string isn't a filename" if filename.startswith('<'): # Lots of non-file execution is represented with artificial # filenames like "", "", or # "". Don't ever trace these executions, since we # can't do anything with the data later anyway. return None, "not a real filename" self._check_for_packages() # Compiled Python files have two filenames: frame.f_code.co_filename is # the filename at the time the .pyc was compiled. The second name is # __file__, which is where the .pyc was actually loaded from. Since # .pyc files can be moved after compilation (for example, by being # installed), we look for __file__ in the frame and prefer it to the # co_filename value. dunder_file = frame.f_globals.get('__file__') if dunder_file: filename = self._source_for_file(dunder_file) # Jython reports the .class file to the tracer, use the source file. if filename.endswith("$py.class"): filename = filename[:-9] + ".py" canonical = self.file_locator.canonical_filename(filename) # If the user specified source or include, then that's authoritative # about the outer bound of what to measure and we don't have to apply # any canned exclusions. If they didn't, then we have to exclude the # stdlib and coverage.py directories. if self.source_match: if not self.source_match.match(canonical): return None, "falls outside the --source trees" elif self.include_match: if not self.include_match.match(canonical): return None, "falls outside the --include trees" else: # If we aren't supposed to trace installed code, then check if this # is near the Python standard library and skip it if so. if self.pylib_match and self.pylib_match.match(canonical): return None, "is in the stdlib" # We exclude the coverage code itself, since a little of it will be # measured otherwise. if self.cover_match and self.cover_match.match(canonical): return None, "is part of coverage.py" # Check the file against the omit pattern. if self.omit_match and self.omit_match.match(canonical): return None, "is inside an --omit pattern" return canonical, "because we love you" def _should_trace(self, filename, frame): """Decide whether to trace execution in `filename`. Calls `_should_trace_with_reason`, and returns just the decision. """ canonical, reason = self._should_trace_with_reason(filename, frame) if self.debug.should('trace'): if not canonical: msg = "Not tracing %r: %s" % (filename, reason) else: msg = "Tracing %r" % (filename,) self.debug.write(msg) return canonical def _warn(self, msg): """Use `msg` as a warning.""" self._warnings.append(msg) sys.stderr.write("Coverage.py warning: %s\n" % msg) def _check_for_packages(self): """Update the source_match matcher with latest imported packages.""" # Our self.source_pkgs attribute is a list of package names we want to # measure. Each time through here, we see if we've imported any of # them yet. If so, we add its file to source_match, and we don't have # to look for that package any more. if self.source_pkgs: found = [] for pkg in self.source_pkgs: try: mod = sys.modules[pkg] except KeyError: continue found.append(pkg) try: pkg_file = mod.__file__ except AttributeError: pkg_file = None else: d, f = os.path.split(pkg_file) if f.startswith('__init__'): # This is actually a package, return the directory. pkg_file = d else: pkg_file = self._source_for_file(pkg_file) pkg_file = self.file_locator.canonical_filename(pkg_file) if not os.path.exists(pkg_file): pkg_file = None if pkg_file: self.source.append(pkg_file) self.source_match.add(pkg_file) else: self._warn("Module %s has no Python source." % pkg) for pkg in found: self.source_pkgs.remove(pkg) def use_cache(self, usecache): """Control the use of a data file (incorrectly called a cache). `usecache` is true or false, whether to read and write data on disk. """ self.data.usefile(usecache) def load(self): """Load previously-collected coverage data from the data file.""" self.collector.reset() self.data.read() def start(self): """Start measuring code coverage. Coverage measurement actually occurs in functions called after `start` is invoked. Statements in the same scope as `start` won't be measured. Once you invoke `start`, you must also call `stop` eventually, or your process might not shut down cleanly. """ if self.run_suffix: # Calling start() means we're running code, so use the run_suffix # as the data_suffix when we eventually save the data. self.data_suffix = self.run_suffix if self.auto_data: self.load() # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) # The user may want to debug things, show info if desired. if self.debug.should('config'): self.debug.write("Configuration values:") config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info(config_info) if self.debug.should('sys'): self.debug.write("Debugging info:") self.debug.write_formatted_info(self.sysinfo()) self.collector.start() self._started = True self._measured = True def stop(self): """Stop measuring code coverage.""" self._started = False self.collector.stop() def _atexit(self): """Clean up on process shutdown.""" if self._started: self.stop() if self.auto_data: self.save() def erase(self): """Erase previously-collected coverage data. This removes the in-memory data collected in this session as well as discarding the data file. """ self.collector.reset() self.data.erase() def clear_exclude(self, which='exclude'): """Clear the exclude list.""" setattr(self.config, which + "_list", []) self._exclude_regex_stale() def exclude(self, regex, which='exclude'): """Exclude source lines from execution consideration. A number of lists of regular expressions are maintained. Each list selects lines that are treated differently during reporting. `which` determines which list is modified. The "exclude" list selects lines that are not considered executable at all. The "partial" list indicates lines with branches that are not taken. `regex` is a regular expression. The regex is added to the specified list. If any of the regexes in the list is found in a line, the line is marked for special treatment during reporting. """ excl_list = getattr(self.config, which + "_list") excl_list.append(regex) self._exclude_regex_stale() def _exclude_regex_stale(self): """Drop all the compiled exclusion regexes, a list was modified.""" self._exclude_re.clear() def _exclude_regex(self, which): """Return a compiled regex for the given exclusion list.""" if which not in self._exclude_re: excl_list = getattr(self.config, which + "_list") self._exclude_re[which] = join_regex(excl_list) return self._exclude_re[which] def get_exclude_list(self, which='exclude'): """Return a list of excluded regex patterns. `which` indicates which list is desired. See `exclude` for the lists that are available, and their meaning. """ return getattr(self.config, which + "_list") def save(self): """Save the collected coverage data to the data file.""" data_suffix = self.data_suffix if data_suffix is True: # If data_suffix was a simple true value, then make a suffix with # plenty of distinguishing information. We do this here in # `save()` at the last minute so that the pid will be correct even # if the process forks. extra = "" if _TEST_NAME_FILE: f = open(_TEST_NAME_FILE) test_name = f.read() f.close() extra = "." + test_name data_suffix = "%s%s.%s.%06d" % ( socket.gethostname(), extra, os.getpid(), random.randint(0, 999999) ) self._harvest_data() self.data.write(suffix=data_suffix) def combine(self): """Combine together a number of similarly-named coverage data files. All coverage data files whose name starts with `data_file` (from the coverage() constructor) will be read, and combined together into the current measurements. """ aliases = None if self.config.paths: aliases = PathAliases(self.file_locator) for paths in self.config.paths.values(): result = paths[0] for pattern in paths[1:]: aliases.add(pattern, result) self.data.combine_parallel_data(aliases=aliases) def _harvest_data(self): """Get the collected data and reset the collector. Also warn about various problems collecting data. """ if not self._measured: return self.data.add_line_data(self.collector.get_line_data()) self.data.add_arc_data(self.collector.get_arc_data()) self.collector.reset() # If there are still entries in the source_pkgs list, then we never # encountered those packages. if self._warn_unimported_source: for pkg in self.source_pkgs: self._warn("Module %s was never imported." % pkg) # Find out if we got any data. summary = self.data.summary() if not summary and self._warn_no_data: self._warn("No data was collected.") # Find files that were never executed at all. for src in self.source: for py_file in find_python_files(src): py_file = self.file_locator.canonical_filename(py_file) if self.omit_match and self.omit_match.match(py_file): # Turns out this file was omitted, so don't pull it back # in as unexecuted. continue self.data.touch_file(py_file) self._measured = False # Backward compatibility with version 1. def analysis(self, morf): """Like `analysis2` but doesn't return excluded line numbers.""" f, s, _, m, mf = self.analysis2(morf) return f, s, m, mf def analysis2(self, morf): """Analyze a module. `morf` is a module or a filename. It will be analyzed to determine its coverage statistics. The return value is a 5-tuple: * The filename for the module. * A list of line numbers of executable statements. * A list of line numbers of excluded statements. * A list of line numbers of statements not run (missing from execution). * A readable formatted string of the missing line numbers. The analysis uses the source file itself and the current measured coverage data. """ analysis = self._analyze(morf) return ( analysis.filename, sorted(analysis.statements), sorted(analysis.excluded), sorted(analysis.missing), analysis.missing_formatted(), ) def _analyze(self, it): """Analyze a single morf or code unit. Returns an `Analysis` object. """ self._harvest_data() if not isinstance(it, CodeUnit): it = code_unit_factory(it, self.file_locator)[0] return Analysis(self, it) def report(self, morfs=None, show_missing=True, ignore_errors=None, file=None, # pylint: disable=W0622 omit=None, include=None ): """Write a summary report to `file`. Each module in `morfs` is listed, with counts of statements, executed statements, missing statements, and a list of lines missed. `include` is a list of filename patterns. Modules whose filenames match those patterns will be included in the report. Modules matching `omit` will not be included in the report. Returns a float, the total percentage covered. """ self._harvest_data() self.config.from_args( ignore_errors=ignore_errors, omit=omit, include=include, show_missing=show_missing, ) reporter = SummaryReporter(self, self.config) return reporter.report(morfs, outfile=file) def annotate(self, morfs=None, directory=None, ignore_errors=None, omit=None, include=None): """Annotate a list of modules. Each module in `morfs` is annotated. The source is written to a new file, named with a ",cover" suffix, with each line prefixed with a marker to indicate the coverage of the line. Covered lines have ">", excluded lines have "-", and missing lines have "!". See `coverage.report()` for other arguments. """ self._harvest_data() self.config.from_args( ignore_errors=ignore_errors, omit=omit, include=include ) reporter = AnnotateReporter(self, self.config) reporter.report(morfs, directory=directory) def html_report(self, morfs=None, directory=None, ignore_errors=None, omit=None, include=None, extra_css=None, title=None): """Generate an HTML report. The HTML is written to `directory`. The file "index.html" is the overview starting point, with links to more detailed pages for individual modules. `extra_css` is a path to a file of other CSS to apply on the page. It will be copied into the HTML directory. `title` is a text string (not HTML) to use as the title of the HTML report. See `coverage.report()` for other arguments. Returns a float, the total percentage covered. """ self._harvest_data() self.config.from_args( ignore_errors=ignore_errors, omit=omit, include=include, html_dir=directory, extra_css=extra_css, html_title=title, ) reporter = HtmlReporter(self, self.config) return reporter.report(morfs) def xml_report(self, morfs=None, outfile=None, ignore_errors=None, omit=None, include=None): """Generate an XML report of coverage results. The report is compatible with Cobertura reports. Each module in `morfs` is included in the report. `outfile` is the path to write the file to, "-" will write to stdout. See `coverage.report()` for other arguments. Returns a float, the total percentage covered. """ self._harvest_data() self.config.from_args( ignore_errors=ignore_errors, omit=omit, include=include, xml_output=outfile, ) file_to_close = None delete_file = False if self.config.xml_output: if self.config.xml_output == '-': outfile = sys.stdout else: outfile = open(self.config.xml_output, "w") file_to_close = outfile try: try: reporter = XmlReporter(self, self.config) return reporter.report(morfs, outfile=outfile) except CoverageException: delete_file = True raise finally: if file_to_close: file_to_close.close() if delete_file: file_be_gone(self.config.xml_output) def sysinfo(self): """Return a list of (key, value) pairs showing internal information.""" import coverage as covmod import platform, re try: implementation = platform.python_implementation() except AttributeError: implementation = "unknown" info = [ ('version', covmod.__version__), ('coverage', covmod.__file__), ('cover_dir', self.cover_dir), ('pylib_dirs', self.pylib_dirs), ('tracer', self.collector.tracer_name()), ('config_files', self.config.attempted_config_files), ('configs_read', self.config.config_files), ('data_path', self.data.filename), ('python', sys.version.replace('\n', '')), ('platform', platform.platform()), ('implementation', implementation), ('executable', sys.executable), ('cwd', os.getcwd()), ('path', sys.path), ('environment', sorted([ ("%s = %s" % (k, v)) for k, v in iitems(os.environ) if re.search(r"^COV|^PY", k) ])), ('command_line', " ".join(getattr(sys, 'argv', ['???']))), ] if self.source_match: info.append(('source_match', self.source_match.info())) if self.include_match: info.append(('include_match', self.include_match.info())) if self.omit_match: info.append(('omit_match', self.omit_match.info())) if self.cover_match: info.append(('cover_match', self.cover_match.info())) if self.pylib_match: info.append(('pylib_match', self.pylib_match.info())) return info def process_startup(): """Call this at Python startup to perhaps measure coverage. If the environment variable COVERAGE_PROCESS_START is defined, coverage measurement is started. The value of the variable is the config file to use. There are two ways to configure your Python installation to invoke this function when Python starts: #. Create or append to sitecustomize.py to add these lines:: import coverage coverage.process_startup() #. Create a .pth file in your Python installation containing:: import coverage; coverage.process_startup() """ cps = os.environ.get("COVERAGE_PROCESS_START") if cps: cov = coverage(config_file=cps, auto_data=True) cov.start() cov._warn_no_data = False cov._warn_unimported_source = False # A hack for debugging testing in subprocesses. _TEST_NAME_FILE = "" #"/tmp/covtest.txt" python-coverage-3.7.1+dfsg.1.orig/coverage/parser.py0000644000175000017500000006212412233207633021340 0ustar barrybarry"""Code parsing for Coverage.""" import dis, re, sys, token, tokenize from coverage.backward import set, sorted, StringIO # pylint: disable=W0622 from coverage.backward import open_source, range # pylint: disable=W0622 from coverage.backward import reversed # pylint: disable=W0622 from coverage.backward import bytes_to_ints from coverage.bytecode import ByteCodes, CodeObjects from coverage.misc import nice_pair, expensive, join_regex from coverage.misc import CoverageException, NoSource, NotPython class CodeParser(object): """Parse code to find executable lines, excluded lines, etc.""" def __init__(self, text=None, filename=None, exclude=None): """ Source can be provided as `text`, the text itself, or `filename`, from which the text will be read. Excluded lines are those that match `exclude`, a regex. """ assert text or filename, "CodeParser needs either text or filename" self.filename = filename or "" self.text = text if not self.text: try: sourcef = open_source(self.filename) try: self.text = sourcef.read() finally: sourcef.close() except IOError: _, err, _ = sys.exc_info() raise NoSource( "No source for code: '%s': %s" % (self.filename, err) ) # Scrap the BOM if it exists. if self.text and ord(self.text[0]) == 0xfeff: self.text = self.text[1:] self.exclude = exclude self.show_tokens = False # The text lines of the parsed code. self.lines = self.text.split('\n') # The line numbers of excluded lines of code. self.excluded = set() # The line numbers of docstring lines. self.docstrings = set() # The line numbers of class definitions. self.classdefs = set() # A dict mapping line numbers to (lo,hi) for multi-line statements. self.multiline = {} # The line numbers that start statements. self.statement_starts = set() # Lazily-created ByteParser self._byte_parser = None def _get_byte_parser(self): """Create a ByteParser on demand.""" if not self._byte_parser: self._byte_parser = \ ByteParser(text=self.text, filename=self.filename) return self._byte_parser byte_parser = property(_get_byte_parser) def lines_matching(self, *regexes): """Find the lines matching one of a list of regexes. Returns a set of line numbers, the lines that contain a match for one of the regexes in `regexes`. The entire line needn't match, just a part of it. """ regex_c = re.compile(join_regex(regexes)) matches = set() for i, ltext in enumerate(self.lines): if regex_c.search(ltext): matches.add(i+1) return matches def _raw_parse(self): """Parse the source to find the interesting facts about its lines. A handful of member fields are updated. """ # Find lines which match an exclusion pattern. if self.exclude: self.excluded = self.lines_matching(self.exclude) # Tokenize, to find excluded suites, to find docstrings, and to find # multi-line statements. indent = 0 exclude_indent = 0 excluding = False prev_toktype = token.INDENT first_line = None empty = True tokgen = generate_tokens(self.text) for toktype, ttext, (slineno, _), (elineno, _), ltext in tokgen: if self.show_tokens: # pragma: not covered print("%10s %5s %-20r %r" % ( tokenize.tok_name.get(toktype, toktype), nice_pair((slineno, elineno)), ttext, ltext )) if toktype == token.INDENT: indent += 1 elif toktype == token.DEDENT: indent -= 1 elif toktype == token.NAME and ttext == 'class': # Class definitions look like branches in the byte code, so # we need to exclude them. The simplest way is to note the # lines with the 'class' keyword. self.classdefs.add(slineno) elif toktype == token.OP and ttext == ':': if not excluding and elineno in self.excluded: # Start excluding a suite. We trigger off of the colon # token so that the #pragma comment will be recognized on # the same line as the colon. exclude_indent = indent excluding = True elif toktype == token.STRING and prev_toktype == token.INDENT: # Strings that are first on an indented line are docstrings. # (a trick from trace.py in the stdlib.) This works for # 99.9999% of cases. For the rest (!) see: # http://stackoverflow.com/questions/1769332/x/1769794#1769794 self.docstrings.update(range(slineno, elineno+1)) elif toktype == token.NEWLINE: if first_line is not None and elineno != first_line: # We're at the end of a line, and we've ended on a # different line than the first line of the statement, # so record a multi-line range. rng = (first_line, elineno) for l in range(first_line, elineno+1): self.multiline[l] = rng first_line = None if ttext.strip() and toktype != tokenize.COMMENT: # A non-whitespace token. empty = False if first_line is None: # The token is not whitespace, and is the first in a # statement. first_line = slineno # Check whether to end an excluded suite. if excluding and indent <= exclude_indent: excluding = False if excluding: self.excluded.add(elineno) prev_toktype = toktype # Find the starts of the executable statements. if not empty: self.statement_starts.update(self.byte_parser._find_statements()) def first_line(self, line): """Return the first line number of the statement including `line`.""" rng = self.multiline.get(line) if rng: first_line = rng[0] else: first_line = line return first_line def first_lines(self, lines, *ignores): """Map the line numbers in `lines` to the correct first line of the statement. Skip any line mentioned in any of the sequences in `ignores`. Returns a set of the first lines. """ ignore = set() for ign in ignores: ignore.update(ign) lset = set() for l in lines: if l in ignore: continue new_l = self.first_line(l) if new_l not in ignore: lset.add(new_l) return lset def parse_source(self): """Parse source text to find executable lines, excluded lines, etc. Return values are 1) a set of executable line numbers, and 2) a set of excluded line numbers. Reported line numbers are normalized to the first line of multi-line statements. """ try: self._raw_parse() except (tokenize.TokenError, IndentationError): _, tokerr, _ = sys.exc_info() msg, lineno = tokerr.args raise NotPython( "Couldn't parse '%s' as Python source: '%s' at %s" % (self.filename, msg, lineno) ) excluded_lines = self.first_lines(self.excluded) lines = self.first_lines( self.statement_starts, excluded_lines, self.docstrings ) return lines, excluded_lines def arcs(self): """Get information about the arcs available in the code. Returns a sorted list of line number pairs. Line numbers have been normalized to the first line of multiline statements. """ all_arcs = [] for l1, l2 in self.byte_parser._all_arcs(): fl1 = self.first_line(l1) fl2 = self.first_line(l2) if fl1 != fl2: all_arcs.append((fl1, fl2)) return sorted(all_arcs) arcs = expensive(arcs) def exit_counts(self): """Get a mapping from line numbers to count of exits from that line. Excluded lines are excluded. """ excluded_lines = self.first_lines(self.excluded) exit_counts = {} for l1, l2 in self.arcs(): if l1 < 0: # Don't ever report -1 as a line number continue if l1 in excluded_lines: # Don't report excluded lines as line numbers. continue if l2 in excluded_lines: # Arcs to excluded lines shouldn't count. continue if l1 not in exit_counts: exit_counts[l1] = 0 exit_counts[l1] += 1 # Class definitions have one extra exit, so remove one for each: for l in self.classdefs: # Ensure key is there: classdefs can include excluded lines. if l in exit_counts: exit_counts[l] -= 1 return exit_counts exit_counts = expensive(exit_counts) ## Opcodes that guide the ByteParser. def _opcode(name): """Return the opcode by name from the dis module.""" return dis.opmap[name] def _opcode_set(*names): """Return a set of opcodes by the names in `names`.""" s = set() for name in names: try: s.add(_opcode(name)) except KeyError: pass return s # Opcodes that leave the code object. OPS_CODE_END = _opcode_set('RETURN_VALUE') # Opcodes that unconditionally end the code chunk. OPS_CHUNK_END = _opcode_set( 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'RETURN_VALUE', 'RAISE_VARARGS', 'BREAK_LOOP', 'CONTINUE_LOOP', ) # Opcodes that unconditionally begin a new code chunk. By starting new chunks # with unconditional jump instructions, we neatly deal with jumps to jumps # properly. OPS_CHUNK_BEGIN = _opcode_set('JUMP_ABSOLUTE', 'JUMP_FORWARD') # Opcodes that push a block on the block stack. OPS_PUSH_BLOCK = _opcode_set( 'SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'SETUP_WITH' ) # Block types for exception handling. OPS_EXCEPT_BLOCKS = _opcode_set('SETUP_EXCEPT', 'SETUP_FINALLY') # Opcodes that pop a block from the block stack. OPS_POP_BLOCK = _opcode_set('POP_BLOCK') # Opcodes that have a jump destination, but aren't really a jump. OPS_NO_JUMP = OPS_PUSH_BLOCK # Individual opcodes we need below. OP_BREAK_LOOP = _opcode('BREAK_LOOP') OP_END_FINALLY = _opcode('END_FINALLY') OP_COMPARE_OP = _opcode('COMPARE_OP') COMPARE_EXCEPTION = 10 # just have to get this const from the code. OP_LOAD_CONST = _opcode('LOAD_CONST') OP_RETURN_VALUE = _opcode('RETURN_VALUE') class ByteParser(object): """Parse byte codes to understand the structure of code.""" def __init__(self, code=None, text=None, filename=None): if code: self.code = code self.text = text else: if not text: assert filename, "If no code or text, need a filename" sourcef = open_source(filename) try: text = sourcef.read() finally: sourcef.close() self.text = text try: # Python 2.3 and 2.4 don't like partial last lines, so be sure # the text ends nicely for them. self.code = compile(text + '\n', filename, "exec") except SyntaxError: _, synerr, _ = sys.exc_info() raise NotPython( "Couldn't parse '%s' as Python source: '%s' at line %d" % (filename, synerr.msg, synerr.lineno) ) # Alternative Python implementations don't always provide all the # attributes on code objects that we need to do the analysis. for attr in ['co_lnotab', 'co_firstlineno', 'co_consts', 'co_code']: if not hasattr(self.code, attr): raise CoverageException( "This implementation of Python doesn't support code " "analysis.\n" "Run coverage.py under CPython for this command." ) def child_parsers(self): """Iterate over all the code objects nested within this one. The iteration includes `self` as its first value. """ children = CodeObjects(self.code) return [ByteParser(code=c, text=self.text) for c in children] def _bytes_lines(self): """Map byte offsets to line numbers in `code`. Uses co_lnotab described in Python/compile.c to map byte offsets to line numbers. Produces a sequence: (b0, l0), (b1, l1), ... Only byte offsets that correspond to line numbers are included in the results. """ # Adapted from dis.py in the standard library. byte_increments = bytes_to_ints(self.code.co_lnotab[0::2]) line_increments = bytes_to_ints(self.code.co_lnotab[1::2]) last_line_num = None line_num = self.code.co_firstlineno byte_num = 0 for byte_incr, line_incr in zip(byte_increments, line_increments): if byte_incr: if line_num != last_line_num: yield (byte_num, line_num) last_line_num = line_num byte_num += byte_incr line_num += line_incr if line_num != last_line_num: yield (byte_num, line_num) def _find_statements(self): """Find the statements in `self.code`. Produce a sequence of line numbers that start statements. Recurses into all code objects reachable from `self.code`. """ for bp in self.child_parsers(): # Get all of the lineno information from this code. for _, l in bp._bytes_lines(): yield l def _block_stack_repr(self, block_stack): """Get a string version of `block_stack`, for debugging.""" blocks = ", ".join( ["(%s, %r)" % (dis.opname[b[0]], b[1]) for b in block_stack] ) return "[" + blocks + "]" def _split_into_chunks(self): """Split the code object into a list of `Chunk` objects. Each chunk is only entered at its first instruction, though there can be many exits from a chunk. Returns a list of `Chunk` objects. """ # The list of chunks so far, and the one we're working on. chunks = [] chunk = None # A dict mapping byte offsets of line starts to the line numbers. bytes_lines_map = dict(self._bytes_lines()) # The block stack: loops and try blocks get pushed here for the # implicit jumps that can occur. # Each entry is a tuple: (block type, destination) block_stack = [] # Some op codes are followed by branches that should be ignored. This # is a count of how many ignores are left. ignore_branch = 0 # We have to handle the last two bytecodes specially. ult = penult = None # Get a set of all of the jump-to points. jump_to = set() bytecodes = list(ByteCodes(self.code.co_code)) for bc in bytecodes: if bc.jump_to >= 0: jump_to.add(bc.jump_to) chunk_lineno = 0 # Walk the byte codes building chunks. for bc in bytecodes: # Maybe have to start a new chunk start_new_chunk = False first_chunk = False if bc.offset in bytes_lines_map: # Start a new chunk for each source line number. start_new_chunk = True chunk_lineno = bytes_lines_map[bc.offset] first_chunk = True elif bc.offset in jump_to: # To make chunks have a single entrance, we have to make a new # chunk when we get to a place some bytecode jumps to. start_new_chunk = True elif bc.op in OPS_CHUNK_BEGIN: # Jumps deserve their own unnumbered chunk. This fixes # problems with jumps to jumps getting confused. start_new_chunk = True if not chunk or start_new_chunk: if chunk: chunk.exits.add(bc.offset) chunk = Chunk(bc.offset, chunk_lineno, first_chunk) chunks.append(chunk) # Look at the opcode if bc.jump_to >= 0 and bc.op not in OPS_NO_JUMP: if ignore_branch: # Someone earlier wanted us to ignore this branch. ignore_branch -= 1 else: # The opcode has a jump, it's an exit for this chunk. chunk.exits.add(bc.jump_to) if bc.op in OPS_CODE_END: # The opcode can exit the code object. chunk.exits.add(-self.code.co_firstlineno) if bc.op in OPS_PUSH_BLOCK: # The opcode adds a block to the block_stack. block_stack.append((bc.op, bc.jump_to)) if bc.op in OPS_POP_BLOCK: # The opcode pops a block from the block stack. block_stack.pop() if bc.op in OPS_CHUNK_END: # This opcode forces the end of the chunk. if bc.op == OP_BREAK_LOOP: # A break is implicit: jump where the top of the # block_stack points. chunk.exits.add(block_stack[-1][1]) chunk = None if bc.op == OP_END_FINALLY: # For the finally clause we need to find the closest exception # block, and use its jump target as an exit. for block in reversed(block_stack): if block[0] in OPS_EXCEPT_BLOCKS: chunk.exits.add(block[1]) break if bc.op == OP_COMPARE_OP and bc.arg == COMPARE_EXCEPTION: # This is an except clause. We want to overlook the next # branch, so that except's don't count as branches. ignore_branch += 1 penult = ult ult = bc if chunks: # The last two bytecodes could be a dummy "return None" that # shouldn't be counted as real code. Every Python code object seems # to end with a return, and a "return None" is inserted if there # isn't an explicit return in the source. if ult and penult: if penult.op == OP_LOAD_CONST and ult.op == OP_RETURN_VALUE: if self.code.co_consts[penult.arg] is None: # This is "return None", but is it dummy? A real line # would be a last chunk all by itself. if chunks[-1].byte != penult.offset: ex = -self.code.co_firstlineno # Split the last chunk last_chunk = chunks[-1] last_chunk.exits.remove(ex) last_chunk.exits.add(penult.offset) chunk = Chunk( penult.offset, last_chunk.line, False ) chunk.exits.add(ex) chunks.append(chunk) # Give all the chunks a length. chunks[-1].length = bc.next_offset - chunks[-1].byte # pylint: disable=W0631,C0301 for i in range(len(chunks)-1): chunks[i].length = chunks[i+1].byte - chunks[i].byte #self.validate_chunks(chunks) return chunks def validate_chunks(self, chunks): """Validate the rule that chunks have a single entrance.""" # starts is the entrances to the chunks starts = set([ch.byte for ch in chunks]) for ch in chunks: assert all([(ex in starts or ex < 0) for ex in ch.exits]) def _arcs(self): """Find the executable arcs in the code. Yields pairs: (from,to). From and to are integer line numbers. If from is < 0, then the arc is an entrance into the code object. If to is < 0, the arc is an exit from the code object. """ chunks = self._split_into_chunks() # A map from byte offsets to chunks jumped into. byte_chunks = dict([(c.byte, c) for c in chunks]) # There's always an entrance at the first chunk. yield (-1, byte_chunks[0].line) # Traverse from the first chunk in each line, and yield arcs where # the trace function will be invoked. for chunk in chunks: if not chunk.first: continue chunks_considered = set() chunks_to_consider = [chunk] while chunks_to_consider: # Get the chunk we're considering, and make sure we don't # consider it again this_chunk = chunks_to_consider.pop() chunks_considered.add(this_chunk) # For each exit, add the line number if the trace function # would be triggered, or add the chunk to those being # considered if not. for ex in this_chunk.exits: if ex < 0: yield (chunk.line, ex) else: next_chunk = byte_chunks[ex] if next_chunk in chunks_considered: continue # The trace function is invoked if visiting the first # bytecode in a line, or if the transition is a # backward jump. backward_jump = next_chunk.byte < this_chunk.byte if next_chunk.first or backward_jump: if next_chunk.line != chunk.line: yield (chunk.line, next_chunk.line) else: chunks_to_consider.append(next_chunk) def _all_chunks(self): """Returns a list of `Chunk` objects for this code and its children. See `_split_into_chunks` for details. """ chunks = [] for bp in self.child_parsers(): chunks.extend(bp._split_into_chunks()) return chunks def _all_arcs(self): """Get the set of all arcs in this code object and its children. See `_arcs` for details. """ arcs = set() for bp in self.child_parsers(): arcs.update(bp._arcs()) return arcs class Chunk(object): """A sequence of byte codes with a single entrance. To analyze byte code, we have to divide it into chunks, sequences of byte codes such that each chunk has only one entrance, the first instruction in the block. This is almost the CS concept of `basic block`_, except that we're willing to have many exits from a chunk, and "basic block" is a more cumbersome term. .. _basic block: http://en.wikipedia.org/wiki/Basic_block `line` is the source line number containing this chunk. `first` is true if this is the first chunk in the source line. An exit < 0 means the chunk can leave the code (return). The exit is the negative of the starting line number of the code block. """ def __init__(self, byte, line, first): self.byte = byte self.line = line self.first = first self.length = 0 self.exits = set() def __repr__(self): if self.first: bang = "!" else: bang = "" return "<%d+%d @%d%s %r>" % ( self.byte, self.length, self.line, bang, list(self.exits) ) class CachedTokenizer(object): """A one-element cache around tokenize.generate_tokens. When reporting, coverage.py tokenizes files twice, once to find the structure of the file, and once to syntax-color it. Tokenizing is expensive, and easily cached. This is a one-element cache so that our twice-in-a-row tokenizing doesn't actually tokenize twice. """ def __init__(self): self.last_text = None self.last_tokens = None def generate_tokens(self, text): """A stand-in for `tokenize.generate_tokens`.""" if text != self.last_text: self.last_text = text self.last_tokens = list( tokenize.generate_tokens(StringIO(text).readline) ) return self.last_tokens # Create our generate_tokens cache as a callable replacement function. generate_tokens = CachedTokenizer().generate_tokens python-coverage-3.7.1+dfsg.1.orig/coverage/config.py0000644000175000017500000001567312233013371021312 0ustar barrybarry"""Config file for coverage.py""" import os, re, sys from coverage.backward import string_class, iitems # In py3, # ConfigParser was renamed to the more-standard configparser try: import configparser # pylint: disable=F0401 except ImportError: import ConfigParser as configparser class HandyConfigParser(configparser.RawConfigParser): """Our specialization of ConfigParser.""" def read(self, filename): """Read a filename as UTF-8 configuration data.""" kwargs = {} if sys.version_info >= (3, 2): kwargs['encoding'] = "utf-8" return configparser.RawConfigParser.read(self, filename, **kwargs) def get(self, *args, **kwargs): v = configparser.RawConfigParser.get(self, *args, **kwargs) def dollar_replace(m): """Called for each $replacement.""" # Only one of the groups will have matched, just get its text. word = [w for w in m.groups() if w is not None][0] if word == "$": return "$" else: return os.environ.get(word, '') dollar_pattern = r"""(?x) # Use extended regex syntax \$(?: # A dollar sign, then (?P\w+) | # a plain word, {(?P\w+)} | # or a {-wrapped word, (?P[$]) # or a dollar sign. ) """ v = re.sub(dollar_pattern, dollar_replace, v) return v def getlist(self, section, option): """Read a list of strings. The value of `section` and `option` is treated as a comma- and newline- separated list of strings. Each value is stripped of whitespace. Returns the list of strings. """ value_list = self.get(section, option) values = [] for value_line in value_list.split('\n'): for value in value_line.split(','): value = value.strip() if value: values.append(value) return values def getlinelist(self, section, option): """Read a list of full-line strings. The value of `section` and `option` is treated as a newline-separated list of strings. Each value is stripped of whitespace. Returns the list of strings. """ value_list = self.get(section, option) return list(filter(None, value_list.split('\n'))) # The default line exclusion regexes DEFAULT_EXCLUDE = [ '(?i)# *pragma[: ]*no *cover', ] # The default partial branch regexes, to be modified by the user. DEFAULT_PARTIAL = [ '(?i)# *pragma[: ]*no *branch', ] # The default partial branch regexes, based on Python semantics. # These are any Python branching constructs that can't actually execute all # their branches. DEFAULT_PARTIAL_ALWAYS = [ 'while (True|1|False|0):', 'if (True|1|False|0):', ] class CoverageConfig(object): """Coverage.py configuration. The attributes of this class are the various settings that control the operation of coverage.py. """ def __init__(self): """Initialize the configuration attributes to their defaults.""" # Metadata about the config. self.attempted_config_files = [] self.config_files = [] # Defaults for [run] self.branch = False self.cover_pylib = False self.data_file = ".coverage" self.parallel = False self.timid = False self.source = None self.debug = [] # Defaults for [report] self.exclude_list = DEFAULT_EXCLUDE[:] self.ignore_errors = False self.include = None self.omit = None self.partial_list = DEFAULT_PARTIAL[:] self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:] self.precision = 0 self.show_missing = False # Defaults for [html] self.html_dir = "htmlcov" self.extra_css = None self.html_title = "Coverage report" # Defaults for [xml] self.xml_output = "coverage.xml" # Defaults for [paths] self.paths = {} def from_environment(self, env_var): """Read configuration from the `env_var` environment variable.""" # Timidity: for nose users, read an environment variable. This is a # cheap hack, since the rest of the command line arguments aren't # recognized, but it solves some users' problems. env = os.environ.get(env_var, '') if env: self.timid = ('--timid' in env) MUST_BE_LIST = ["omit", "include", "debug"] def from_args(self, **kwargs): """Read config values from `kwargs`.""" for k, v in iitems(kwargs): if v is not None: if k in self.MUST_BE_LIST and isinstance(v, string_class): v = [v] setattr(self, k, v) def from_file(self, filename): """Read configuration from a .rc file. `filename` is a file name to read. """ self.attempted_config_files.append(filename) cp = HandyConfigParser() files_read = cp.read(filename) if files_read is not None: # return value changed in 2.4 self.config_files.extend(files_read) for option_spec in self.CONFIG_FILE_OPTIONS: self.set_attr_from_config_option(cp, *option_spec) # [paths] is special if cp.has_section('paths'): for option in cp.options('paths'): self.paths[option] = cp.getlist('paths', option) CONFIG_FILE_OPTIONS = [ # [run] ('branch', 'run:branch', 'boolean'), ('cover_pylib', 'run:cover_pylib', 'boolean'), ('data_file', 'run:data_file'), ('debug', 'run:debug', 'list'), ('include', 'run:include', 'list'), ('omit', 'run:omit', 'list'), ('parallel', 'run:parallel', 'boolean'), ('source', 'run:source', 'list'), ('timid', 'run:timid', 'boolean'), # [report] ('exclude_list', 'report:exclude_lines', 'linelist'), ('ignore_errors', 'report:ignore_errors', 'boolean'), ('include', 'report:include', 'list'), ('omit', 'report:omit', 'list'), ('partial_list', 'report:partial_branches', 'linelist'), ('partial_always_list', 'report:partial_branches_always', 'linelist'), ('precision', 'report:precision', 'int'), ('show_missing', 'report:show_missing', 'boolean'), # [html] ('html_dir', 'html:directory'), ('extra_css', 'html:extra_css'), ('html_title', 'html:title'), # [xml] ('xml_output', 'xml:output'), ] def set_attr_from_config_option(self, cp, attr, where, type_=''): """Set an attribute on self if it exists in the ConfigParser.""" section, option = where.split(":") if cp.has_option(section, option): method = getattr(cp, 'get'+type_) setattr(self, attr, method(section, option)) python-coverage-3.7.1+dfsg.1.orig/coverage/collector.py0000644000175000017500000003214412215727524022037 0ustar barrybarry"""Raw data collector for Coverage.""" import os, sys, threading try: # Use the C extension code when we can, for speed. from coverage.tracer import CTracer # pylint: disable=F0401,E0611 except ImportError: # Couldn't import the C extension, maybe it isn't built. if os.getenv('COVERAGE_TEST_TRACER') == 'c': # During testing, we use the COVERAGE_TEST_TRACER env var to indicate # that we've fiddled with the environment to test this fallback code. # If we thought we had a C tracer, but couldn't import it, then exit # quickly and clearly instead of dribbling confusing errors. I'm using # sys.exit here instead of an exception because an exception here # causes all sorts of other noise in unittest. sys.stderr.write( "*** COVERAGE_TEST_TRACER is 'c' but can't import CTracer!\n" ) sys.exit(1) CTracer = None class PyTracer(object): """Python implementation of the raw data tracer.""" # Because of poor implementations of trace-function-manipulating tools, # the Python trace function must be kept very simple. In particular, there # must be only one function ever set as the trace function, both through # sys.settrace, and as the return value from the trace function. Put # another way, the trace function must always return itself. It cannot # swap in other functions, or return None to avoid tracing a particular # frame. # # The trace manipulator that introduced this restriction is DecoratorTools, # which sets a trace function, and then later restores the pre-existing one # by calling sys.settrace with a function it found in the current frame. # # Systems that use DecoratorTools (or similar trace manipulations) must use # PyTracer to get accurate results. The command-line --timid argument is # used to force the use of this tracer. def __init__(self): self.data = None self.should_trace = None self.should_trace_cache = None self.warn = None self.cur_file_data = None self.last_line = 0 self.data_stack = [] self.last_exc_back = None self.last_exc_firstlineno = 0 self.arcs = False self.thread = None self.stopped = False def _trace(self, frame, event, arg_unused): """The trace function passed to sys.settrace.""" if self.stopped: return if 0: sys.stderr.write("trace event: %s %r @%d\n" % ( event, frame.f_code.co_filename, frame.f_lineno )) if self.last_exc_back: if frame == self.last_exc_back: # Someone forgot a return event. if self.arcs and self.cur_file_data: pair = (self.last_line, -self.last_exc_firstlineno) self.cur_file_data[pair] = None self.cur_file_data, self.last_line = self.data_stack.pop() self.last_exc_back = None if event == 'call': # Entering a new function context. Decide if we should trace # in this file. self.data_stack.append((self.cur_file_data, self.last_line)) filename = frame.f_code.co_filename if filename not in self.should_trace_cache: tracename = self.should_trace(filename, frame) self.should_trace_cache[filename] = tracename else: tracename = self.should_trace_cache[filename] #print("called, stack is %d deep, tracename is %r" % ( # len(self.data_stack), tracename)) if tracename: if tracename not in self.data: self.data[tracename] = {} self.cur_file_data = self.data[tracename] else: self.cur_file_data = None # Set the last_line to -1 because the next arc will be entering a # code block, indicated by (-1, n). self.last_line = -1 elif event == 'line': # Record an executed line. if self.cur_file_data is not None: if self.arcs: #print("lin", self.last_line, frame.f_lineno) self.cur_file_data[(self.last_line, frame.f_lineno)] = None else: #print("lin", frame.f_lineno) self.cur_file_data[frame.f_lineno] = None self.last_line = frame.f_lineno elif event == 'return': if self.arcs and self.cur_file_data: first = frame.f_code.co_firstlineno self.cur_file_data[(self.last_line, -first)] = None # Leaving this function, pop the filename stack. self.cur_file_data, self.last_line = self.data_stack.pop() #print("returned, stack is %d deep" % (len(self.data_stack))) elif event == 'exception': #print("exc", self.last_line, frame.f_lineno) self.last_exc_back = frame.f_back self.last_exc_firstlineno = frame.f_code.co_firstlineno return self._trace def start(self): """Start this Tracer. Return a Python function suitable for use with sys.settrace(). """ self.thread = threading.currentThread() sys.settrace(self._trace) return self._trace def stop(self): """Stop this Tracer.""" self.stopped = True if self.thread != threading.currentThread(): # Called on a different thread than started us: we can't unhook # ourseves, but we've set the flag that we should stop, so we won't # do any more tracing. return if hasattr(sys, "gettrace") and self.warn: if sys.gettrace() != self._trace: msg = "Trace function changed, measurement is likely wrong: %r" self.warn(msg % (sys.gettrace(),)) #print("Stopping tracer on %s" % threading.current_thread().ident) sys.settrace(None) def get_stats(self): """Return a dictionary of statistics, or None.""" return None class Collector(object): """Collects trace data. Creates a Tracer object for each thread, since they track stack information. Each Tracer points to the same shared data, contributing traced data points. When the Collector is started, it creates a Tracer for the current thread, and installs a function to create Tracers for each new thread started. When the Collector is stopped, all active Tracers are stopped. Threads started while the Collector is stopped will never have Tracers associated with them. """ # The stack of active Collectors. Collectors are added here when started, # and popped when stopped. Collectors on the stack are paused when not # the top, and resumed when they become the top again. _collectors = [] def __init__(self, should_trace, timid, branch, warn): """Create a collector. `should_trace` is a function, taking a filename, and returning a canonicalized filename, or None depending on whether the file should be traced or not. If `timid` is true, then a slower simpler trace function will be used. This is important for some environments where manipulation of tracing functions make the faster more sophisticated trace function not operate properly. If `branch` is true, then branches will be measured. This involves collecting data on which statements followed each other (arcs). Use `get_arc_data` to get the arc data. `warn` is a warning function, taking a single string message argument, to be used if a warning needs to be issued. """ self.should_trace = should_trace self.warn = warn self.branch = branch self.reset() if timid: # Being timid: use the simple Python trace function. self._trace_class = PyTracer else: # Being fast: use the C Tracer if it is available, else the Python # trace function. self._trace_class = CTracer or PyTracer def __repr__(self): return "" % id(self) def tracer_name(self): """Return the class name of the tracer we're using.""" return self._trace_class.__name__ def reset(self): """Clear collected data, and prepare to collect more.""" # A dictionary mapping filenames to dicts with linenumber keys, # or mapping filenames to dicts with linenumber pairs as keys. self.data = {} # A cache of the results from should_trace, the decision about whether # to trace execution in a file. A dict of filename to (filename or # None). self.should_trace_cache = {} # Our active Tracers. self.tracers = [] def _start_tracer(self): """Start a new Tracer object, and store it in self.tracers.""" tracer = self._trace_class() tracer.data = self.data tracer.arcs = self.branch tracer.should_trace = self.should_trace tracer.should_trace_cache = self.should_trace_cache tracer.warn = self.warn fn = tracer.start() self.tracers.append(tracer) return fn # The trace function has to be set individually on each thread before # execution begins. Ironically, the only support the threading module has # for running code before the thread main is the tracing function. So we # install this as a trace function, and the first time it's called, it does # the real trace installation. def _installation_trace(self, frame_unused, event_unused, arg_unused): """Called on new threads, installs the real tracer.""" # Remove ourselves as the trace function sys.settrace(None) # Install the real tracer. fn = self._start_tracer() # Invoke the real trace function with the current event, to be sure # not to lose an event. if fn: fn = fn(frame_unused, event_unused, arg_unused) # Return the new trace function to continue tracing in this scope. return fn def start(self): """Start collecting trace information.""" if self._collectors: self._collectors[-1].pause() self._collectors.append(self) #print("Started: %r" % self._collectors, file=sys.stderr) # Check to see whether we had a fullcoverage tracer installed. traces0 = [] if hasattr(sys, "gettrace"): fn0 = sys.gettrace() if fn0: tracer0 = getattr(fn0, '__self__', None) if tracer0: traces0 = getattr(tracer0, 'traces', []) # Install the tracer on this thread. fn = self._start_tracer() for args in traces0: (frame, event, arg), lineno = args try: fn(frame, event, arg, lineno=lineno) except TypeError: raise Exception( "fullcoverage must be run with the C trace function." ) # Install our installation tracer in threading, to jump start other # threads. threading.settrace(self._installation_trace) def stop(self): """Stop collecting trace information.""" #print >>sys.stderr, "Stopping: %r" % self._collectors assert self._collectors assert self._collectors[-1] is self self.pause() self.tracers = [] # Remove this Collector from the stack, and resume the one underneath # (if any). self._collectors.pop() if self._collectors: self._collectors[-1].resume() def pause(self): """Pause tracing, but be prepared to `resume`.""" for tracer in self.tracers: tracer.stop() stats = tracer.get_stats() if stats: print("\nCoverage.py tracer stats:") for k in sorted(stats.keys()): print("%16s: %s" % (k, stats[k])) threading.settrace(None) def resume(self): """Resume tracing after a `pause`.""" for tracer in self.tracers: tracer.start() threading.settrace(self._installation_trace) def get_line_data(self): """Return the line data collected. Data is { filename: { lineno: None, ...}, ...} """ if self.branch: # If we were measuring branches, then we have to re-build the dict # to show line data. line_data = {} for f, arcs in self.data.items(): line_data[f] = ldf = {} for l1, _ in list(arcs.keys()): if l1: ldf[l1] = None return line_data else: return self.data def get_arc_data(self): """Return the arc data collected. Data is { filename: { (l1, l2): None, ...}, ...} Note that no data is collected or returned if the Collector wasn't created with `branch` true. """ if self.branch: return self.data else: return {} python-coverage-3.7.1+dfsg.1.orig/coverage/report.py0000644000175000017500000000572712202156243021361 0ustar barrybarry"""Reporter foundation for Coverage.""" import fnmatch, os from coverage.codeunit import code_unit_factory from coverage.files import prep_patterns from coverage.misc import CoverageException, NoSource, NotPython class Reporter(object): """A base class for all reporters.""" def __init__(self, coverage, config): """Create a reporter. `coverage` is the coverage instance. `config` is an instance of CoverageConfig, for controlling all sorts of behavior. """ self.coverage = coverage self.config = config # The code units to report on. Set by find_code_units. self.code_units = [] # The directory into which to place the report, used by some derived # classes. self.directory = None def find_code_units(self, morfs): """Find the code units we'll report on. `morfs` is a list of modules or filenames. """ morfs = morfs or self.coverage.data.measured_files() file_locator = self.coverage.file_locator self.code_units = code_unit_factory(morfs, file_locator) if self.config.include: patterns = prep_patterns(self.config.include) filtered = [] for cu in self.code_units: for pattern in patterns: if fnmatch.fnmatch(cu.filename, pattern): filtered.append(cu) break self.code_units = filtered if self.config.omit: patterns = prep_patterns(self.config.omit) filtered = [] for cu in self.code_units: for pattern in patterns: if fnmatch.fnmatch(cu.filename, pattern): break else: filtered.append(cu) self.code_units = filtered self.code_units.sort() def report_files(self, report_fn, morfs, directory=None): """Run a reporting function on a number of morfs. `report_fn` is called for each relative morf in `morfs`. It is called as:: report_fn(code_unit, analysis) where `code_unit` is the `CodeUnit` for the morf, and `analysis` is the `Analysis` for the morf. """ self.find_code_units(morfs) if not self.code_units: raise CoverageException("No data to report.") self.directory = directory if self.directory and not os.path.exists(self.directory): os.makedirs(self.directory) for cu in self.code_units: try: report_fn(cu, self.coverage._analyze(cu)) except NoSource: if not self.config.ignore_errors: raise except NotPython: # Only report errors for .py files, and only if we didn't # explicitly suppress those errors. if cu.should_be_python() and not self.config.ignore_errors: raise python-coverage-3.7.1+dfsg.1.orig/coverage/debug.py0000644000175000017500000000325212233013371021121 0ustar barrybarry"""Control of and utilities for debugging.""" import os # When debugging, it can be helpful to force some options, especially when # debugging the configuration mechanisms you usually use to control debugging! # This is a list of forced debugging options. FORCED_DEBUG = [] class DebugControl(object): """Control and output for debugging.""" def __init__(self, options, output): """Configure the options and output file for debugging.""" self.options = options self.output = output def should(self, option): """Decide whether to output debug information in category `option`.""" return (option in self.options or option in FORCED_DEBUG) def write(self, msg): """Write a line of debug output.""" if self.should('pid'): msg = "pid %5d: %s" % (os.getpid(), msg) self.output.write(msg+"\n") self.output.flush() def write_formatted_info(self, info): """Write a sequence of (label,data) pairs nicely.""" for line in info_formatter(info): self.write(" %s" % line) def info_formatter(info): """Produce a sequence of formatted lines from info. `info` is a sequence of pairs (label, data). The produced lines are nicely formatted, ready to print. """ label_len = max([len(l) for l, _d in info]) for label, data in info: if data == []: data = "-none-" if isinstance(data, (list, tuple)): prefix = "%*s:" % (label_len, label) for e in data: yield "%*s %s" % (label_len+1, prefix, e) prefix = "" else: yield "%*s: %s" % (label_len, label, data) python-coverage-3.7.1+dfsg.1.orig/coverage/data.py0000644000175000017500000002174412233220750020753 0ustar barrybarry"""Coverage data for Coverage.""" import os from coverage.backward import iitems, pickle, sorted # pylint: disable=W0622 from coverage.files import PathAliases from coverage.misc import file_be_gone class CoverageData(object): """Manages collected coverage data, including file storage. The data file format is a pickled dict, with these keys: * collector: a string identifying the collecting software * lines: a dict mapping filenames to sorted lists of line numbers executed: { 'file1': [17,23,45], 'file2': [1,2,3], ... } * arcs: a dict mapping filenames to sorted lists of line number pairs: { 'file1': [(17,23), (17,25), (25,26)], ... } """ def __init__(self, basename=None, collector=None, debug=None): """Create a CoverageData. `basename` is the name of the file to use for storing data. `collector` is a string describing the coverage measurement software. `debug` is a `DebugControl` object for writing debug messages. """ self.collector = collector or 'unknown' self.debug = debug self.use_file = True # Construct the filename that will be used for data file storage, if we # ever do any file storage. self.filename = basename or ".coverage" self.filename = os.path.abspath(self.filename) # A map from canonical Python source file name to a dictionary in # which there's an entry for each line number that has been # executed: # # { # 'filename1.py': { 12: None, 47: None, ... }, # ... # } # self.lines = {} # A map from canonical Python source file name to a dictionary with an # entry for each pair of line numbers forming an arc: # # { # 'filename1.py': { (12,14): None, (47,48): None, ... }, # ... # } # self.arcs = {} def usefile(self, use_file=True): """Set whether or not to use a disk file for data.""" self.use_file = use_file def read(self): """Read coverage data from the coverage data file (if it exists).""" if self.use_file: self.lines, self.arcs = self._read_file(self.filename) else: self.lines, self.arcs = {}, {} def write(self, suffix=None): """Write the collected coverage data to a file. `suffix` is a suffix to append to the base file name. This can be used for multiple or parallel execution, so that many coverage data files can exist simultaneously. A dot will be used to join the base name and the suffix. """ if self.use_file: filename = self.filename if suffix: filename += "." + suffix self.write_file(filename) def erase(self): """Erase the data, both in this object, and from its file storage.""" if self.use_file: if self.filename: file_be_gone(self.filename) self.lines = {} self.arcs = {} def line_data(self): """Return the map from filenames to lists of line numbers executed.""" return dict( [(f, sorted(lmap.keys())) for f, lmap in iitems(self.lines)] ) def arc_data(self): """Return the map from filenames to lists of line number pairs.""" return dict( [(f, sorted(amap.keys())) for f, amap in iitems(self.arcs)] ) def write_file(self, filename): """Write the coverage data to `filename`.""" # Create the file data. data = {} data['lines'] = self.line_data() arcs = self.arc_data() if arcs: data['arcs'] = arcs if self.collector: data['collector'] = self.collector if self.debug and self.debug.should('dataio'): self.debug.write("Writing data to %r" % (filename,)) # Write the pickle to the file. fdata = open(filename, 'wb') try: pickle.dump(data, fdata, 2) finally: fdata.close() def read_file(self, filename): """Read the coverage data from `filename`.""" self.lines, self.arcs = self._read_file(filename) def raw_data(self, filename): """Return the raw pickled data from `filename`.""" if self.debug and self.debug.should('dataio'): self.debug.write("Reading data from %r" % (filename,)) fdata = open(filename, 'rb') try: data = pickle.load(fdata) finally: fdata.close() return data def _read_file(self, filename): """Return the stored coverage data from the given file. Returns two values, suitable for assigning to `self.lines` and `self.arcs`. """ lines = {} arcs = {} try: data = self.raw_data(filename) if isinstance(data, dict): # Unpack the 'lines' item. lines = dict([ (f, dict.fromkeys(linenos, None)) for f, linenos in iitems(data.get('lines', {})) ]) # Unpack the 'arcs' item. arcs = dict([ (f, dict.fromkeys(arcpairs, None)) for f, arcpairs in iitems(data.get('arcs', {})) ]) except Exception: pass return lines, arcs def combine_parallel_data(self, aliases=None): """Combine a number of data files together. Treat `self.filename` as a file prefix, and combine the data from all of the data files starting with that prefix plus a dot. If `aliases` is provided, it's a `PathAliases` object that is used to re-map paths to match the local machine's. """ aliases = aliases or PathAliases() data_dir, local = os.path.split(self.filename) localdot = local + '.' for f in os.listdir(data_dir or '.'): if f.startswith(localdot): full_path = os.path.join(data_dir, f) new_lines, new_arcs = self._read_file(full_path) for filename, file_data in iitems(new_lines): filename = aliases.map(filename) self.lines.setdefault(filename, {}).update(file_data) for filename, file_data in iitems(new_arcs): filename = aliases.map(filename) self.arcs.setdefault(filename, {}).update(file_data) if f != local: os.remove(full_path) def add_line_data(self, line_data): """Add executed line data. `line_data` is { filename: { lineno: None, ... }, ...} """ for filename, linenos in iitems(line_data): self.lines.setdefault(filename, {}).update(linenos) def add_arc_data(self, arc_data): """Add measured arc data. `arc_data` is { filename: { (l1,l2): None, ... }, ...} """ for filename, arcs in iitems(arc_data): self.arcs.setdefault(filename, {}).update(arcs) def touch_file(self, filename): """Ensure that `filename` appears in the data, empty if needed.""" self.lines.setdefault(filename, {}) def measured_files(self): """A list of all files that had been measured.""" return list(self.lines.keys()) def executed_lines(self, filename): """A map containing all the line numbers executed in `filename`. If `filename` hasn't been collected at all (because it wasn't executed) then return an empty map. """ return self.lines.get(filename) or {} def executed_arcs(self, filename): """A map containing all the arcs executed in `filename`.""" return self.arcs.get(filename) or {} def add_to_hash(self, filename, hasher): """Contribute `filename`'s data to the Md5Hash `hasher`.""" hasher.update(self.executed_lines(filename)) hasher.update(self.executed_arcs(filename)) def summary(self, fullpath=False): """Return a dict summarizing the coverage data. Keys are based on the filenames, and values are the number of executed lines. If `fullpath` is true, then the keys are the full pathnames of the files, otherwise they are the basenames of the files. """ summ = {} if fullpath: filename_fn = lambda f: f else: filename_fn = os.path.basename for filename, lines in iitems(self.lines): summ[filename_fn(filename)] = len(lines) return summ def has_arcs(self): """Does this data have arcs?""" return bool(self.arcs) if __name__ == '__main__': # Ad-hoc: show the raw data in a data file. import pprint, sys covdata = CoverageData() if sys.argv[1:]: fname = sys.argv[1] else: fname = covdata.filename pprint.pprint(covdata.raw_data(fname)) python-coverage-3.7.1+dfsg.1.orig/coverage/fullcoverage/0000755000175000017500000000000012252501325022137 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/coverage/fullcoverage/encodings.py0000644000175000017500000000452212202156243024465 0ustar barrybarry"""Imposter encodings module that installs a coverage-style tracer. This is NOT the encodings module; it is an imposter that sets up tracing instrumentation and then replaces itself with the real encodings module. If the directory that holds this file is placed first in the PYTHONPATH when using "coverage" to run Python's tests, then this file will become the very first module imported by the internals of Python 3. It installs a coverage-compatible trace function that can watch Standard Library modules execute from the very earliest stages of Python's own boot process. This fixes a problem with coverage - that it starts too late to trace the coverage of many of the most fundamental modules in the Standard Library. """ import sys class FullCoverageTracer(object): def __init__(self): # `traces` is a list of trace events. Frames are tricky: the same # frame object is used for a whole scope, with new line numbers # written into it. So in one scope, all the frame objects are the # same object, and will eventually all will point to the last line # executed. So we keep the line numbers alongside the frames. # The list looks like: # # traces = [ # ((frame, event, arg), lineno), ... # ] # self.traces = [] def fullcoverage_trace(self, *args): frame, event, arg = args self.traces.append((args, frame.f_lineno)) return self.fullcoverage_trace sys.settrace(FullCoverageTracer().fullcoverage_trace) # In coverage/files.py is actual_filename(), which uses glob.glob. I don't # understand why, but that use of glob borks everything if fullcoverage is in # effect. So here we make an ugly hail-mary pass to switch off glob.glob over # there. This means when using fullcoverage, Windows path names will not be # their actual case. #sys.fullcoverage = True # Finally, remove our own directory from sys.path; remove ourselves from # sys.modules; and re-import "encodings", which will be the real package # this time. Note that the delete from sys.modules dictionary has to # happen last, since all of the symbols in this module will become None # at that exact moment, including "sys". parentdir = max(filter(__file__.startswith, sys.path), key=len) sys.path.remove(parentdir) del sys.modules['encodings'] import encodings python-coverage-3.7.1+dfsg.1.orig/CHANGES.txt0000644000175000017500000012351212252471311017504 0ustar barrybarry------------------------------ Change history for Coverage.py ------------------------------ 3.7.1 -- 13 December 2013 ------------------------- - Improved the speed of HTML report generation by about 20%. - Fixed the mechanism for finding OS-installed static files for the HTML report so that it will actually find OS-installed static files. 3.7 --- 6 October 2013 ---------------------- - Added the ``--debug`` switch to ``coverage run``. It accepts a list of options indicating the type of internal activity to log to stderr. - Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_. - Running code with ``coverage run -m`` now behaves more like Python does, setting sys.path properly, which fixes `issue 207`_ and `issue 242`_. - Coverage can now run .pyc files directly, closing `issue 264`_. - Coverage properly supports .pyw files, fixing `issue 261`_. - Omitting files within a tree specified with the ``source`` option would cause them to be incorrectly marked as unexecuted, as described in `issue 218`_. This is now fixed. - When specifying paths to alias together during data combining, you can now specify relative paths, fixing `issue 267`_. - Most file paths can now be specified with username expansion (``~/src``, or ``~build/src``, for example), and with environment variable expansion (``build/$BUILDNUM/src``). - Trying to create an XML report with no files to report on, would cause a ZeroDivideError, but no longer does, fixing `issue 250`_. - When running a threaded program under the Python tracer, coverage no longer issues a spurious warning about the trace function changing: "Trace function changed, measurement is likely wrong: None." This fixes `issue 164`_. - Static files necessary for HTML reports are found in system-installed places, to ease OS-level packaging of coverage.py. Closes `issue 259`_. - Source files with encoding declarations, but a blank first line, were not decoded properly. Now they are. Thanks, Roger Hu. - The source kit now includes the ``__main__.py`` file in the root coverage directory, fixing `issue 255`_. .. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in .. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using .. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain .. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in .. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work .. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag .. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating .. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in .. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party .. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly .. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files .. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work Version 3.6 --- 5 January 2013 ------------------------------ - Added a page to the docs about troublesome situations, closing `issue 226`_, and added some info to the TODO file, closing `issue 227`_. .. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when .. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo Version 3.6b3 --- 29 December 2012 ---------------------------------- - Beta 2 broke the nose plugin. It's fixed again, closing `issue 224`_. .. _issue 224: https://bitbucket.org/ned/coveragepy/issue/224/36b2-breaks-nosexcover Version 3.6b2 --- 23 December 2012 ---------------------------------- - Coverage.py runs on Python 2.3 and 2.4 again. It was broken in 3.6b1. - The C extension is optionally compiled using a different more widely-used technique, taking another stab at fixing `issue 80`_ once and for all. - Combining data files would create entries for phantom files if used with ``source`` and path aliases. It no longer does. - ``debug sys`` now shows the configuration file path that was read. - If an oddly-behaved package claims that code came from an empty-string filename, coverage.py no longer associates it with the directory name, fixing `issue 221`_. .. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant .. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp Version 3.6b1 --- 28 November 2012 ---------------------------------- - Wildcards in ``include=`` and ``omit=`` arguments were not handled properly in reporting functions, though they were when running. Now they are handled uniformly, closing `issue 143`_ and `issue 163`_. **NOTE**: it is possible that your configurations may now be incorrect. If you use ``include`` or ``omit`` during reporting, whether on the command line, through the API, or in a configuration file, please check carefully that you were not relying on the old broken behavior. - The **report**, **html**, and **xml** commands now accept a ``--fail-under`` switch that indicates in the exit status whether the coverage percentage was less than a particular value. Closes `issue 139`_. - The reporting functions coverage.report(), coverage.html_report(), and coverage.xml_report() now all return a float, the total percentage covered measurement. - The HTML report's title can now be set in the configuration file, with the ``--title`` switch on the command line, or via the API. - Configuration files now support substitution of environment variables, using syntax like ``${WORD}``. Closes `issue 97`_. - Embarrassingly, the `[xml] output=` setting in the .coveragerc file simply didn't work. Now it does. - The XML report now consistently uses filenames for the filename attribute, rather than sometimes using module names. Fixes `issue 67`_. Thanks, Marcus Cobden. - Coverage percentage metrics are now computed slightly differently under branch coverage. This means that completely unexecuted files will now correctly have 0% coverage, fixing `issue 156`_. This also means that your total coverage numbers will generally now be lower if you are measuring branch coverage. - When installing, now in addition to creating a "coverage" command, two new aliases are also installed. A "coverage2" or "coverage3" command will be created, depending on whether you are installing in Python 2.x or 3.x. A "coverage-X.Y" command will also be created corresponding to your specific version of Python. Closes `issue 111`_. - The coverage.py installer no longer tries to bootstrap setuptools or Distribute. You must have one of them installed first, as `issue 202`_ recommended. - The coverage.py kit now includes docs (closing `issue 137`_) and tests. - On Windows, files are now reported in their correct case, fixing `issue 89`_ and `issue 203`_. - If a file is missing during reporting, the path shown in the error message is now correct, rather than an incorrect path in the current directory. Fixes `issue 60`_. - Running an HTML report in Python 3 in the same directory as an old Python 2 HTML report would fail with a UnicodeDecodeError. This issue (`issue 193`_) is now fixed. - Fixed yet another error trying to parse non-Python files as Python, this time an IndentationError, closing `issue 82`_ for the fourth time... - If `coverage xml` fails because there is no data to report, it used to create a zero-length XML file. Now it doesn't, fixing `issue 210`_. - Jython files now work with the ``--source`` option, fixing `issue 100`_. - Running coverage under a debugger is unlikely to work, but it shouldn't fail with "TypeError: 'NoneType' object is not iterable". Fixes `issue 201`_. - On some Linux distributions, when installed with the OS package manager, coverage.py would report its own code as part of the results. Now it won't, fixing `issue 214`_, though this will take some time to be repackaged by the operating systems. - Docstrings for the legacy singleton methods are more helpful. Thanks Marius Gedminas. Closes `issue 205`_. - The pydoc tool can now show docmentation for the class `coverage.coverage`. Closes `issue 206`_. - Added a page to the docs about contributing to coverage.py, closing `issue 171`_. - When coverage.py ended unsuccessfully, it may have reported odd errors like ``'NoneType' object has no attribute 'isabs'``. It no longer does, so kiss `issue 153`_ goodbye. .. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files .. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in .. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be .. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages .. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not .. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution .. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests .. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage .. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers .. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14 .. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename .. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests .. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy .. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on .. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and .. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename .. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly .. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error .. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml .. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise Version 3.5.3 --- 29 September 2012 ----------------------------------- - Line numbers in the HTML report line up better with the source lines, fixing `issue 197`_, thanks Marius Gedminas. - When specifying a directory as the source= option, the directory itself no longer needs to have a ``__init__.py`` file, though its subdirectories do, to be considered as source files. - Files encoded as UTF-8 with a BOM are now properly handled, fixing `issue 179`_. Thanks, Pablo Carballo. - Fixed more cases of non-Python files being reported as Python source, and then not being able to parse them as Python. Closes `issue 82`_ (again). Thanks, Julian Berman. - Fixed memory leaks under Python 3, thanks, Brett Cannon. Closes `issue 147`_. - Optimized .pyo files may not have been handled correctly, `issue 195`_. Thanks, Marius Gedminas. - Certain unusually named file paths could have been mangled during reporting, `issue 194`_. Thanks, Marius Gedminas. - Try to do a better job of the impossible task of detecting when we can't build the C extension, fixing `issue 183`_. - Testing is now done with `tox`_, thanks, Marc Abramowitz. .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer .. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is .. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23 .. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle .. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit .. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align .. _tox: http://tox.readthedocs.org/ Version 3.5.2 --- 4 May 2012 ---------------------------- No changes since 3.5.2.b1 Version 3.5.2b1 --- 29 April 2012 --------------------------------- - The HTML report has slightly tweaked controls: the buttons at the top of the page are color-coded to the source lines they affect. - Custom CSS can be applied to the HTML report by specifying a CSS file as the extra_css configuration value in the [html] section. - Source files with custom encodings declared in a comment at the top are now properly handled during reporting on Python 2. Python 3 always handled them properly. This fixes `issue 157`_. - Backup files left behind by editors are no longer collected by the source= option, fixing `issue 168`_. - If a file doesn't parse properly as Python, we don't report it as an error if the filename seems like maybe it wasn't meant to be Python. This is a pragmatic fix for `issue 82`_. - The ``-m`` switch on ``coverage report``, which includes missing line numbers in the summary report, can now be specifed as ``show_missing`` in the config file. Closes `issue 173`_. - When running a module with ``coverage run -m ``, certain details of the execution environment weren't the same as for ``python -m ``. This had the unfortunate side-effect of making ``coverage run -m unittest discover`` not work if you had tests in a directory named "test". This fixes `issue 155`_ and `issue 142`_. - Now the exit status of your product code is properly used as the process status when running ``python -m coverage run ...``. Thanks, JT Olds. - When installing into pypy, we no longer attempt (and fail) to compile the C tracer function, closing `issue 166`_. .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 142: https://bitbucket.org/ned/coveragepy/issue/142/executing-python-file-syspath-is-replaced .. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover .. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8 .. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy .. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings .. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in Version 3.5.1 --- 23 September 2011 ----------------------------------- - The ``[paths]`` feature unfortunately didn't work in real world situations where you wanted to, you know, report on the combined data. Now all paths stored in the combined file are canonicalized properly. Version 3.5.1b1 --- 28 August 2011 ---------------------------------- - When combining data files from parallel runs, you can now instruct coverage about which directories are equivalent on different machines. A ``[paths]`` section in the configuration file lists paths that are to be considered equivalent. Finishes `issue 17`_. - for-else constructs are understood better, and don't cause erroneous partial branch warnings. Fixes `issue 122`_. - Branch coverage for ``with`` statements is improved, fixing `issue 128`_. - The number of partial branches reported on the HTML summary page was different than the number reported on the individual file pages. This is now fixed. - An explicit include directive to measure files in the Python installation wouldn't work because of the standard library exclusion. Now the include directive takes precendence, and the files will be measured. Fixes `issue 138`_. - The HTML report now handles Unicode characters in Python source files properly. This fixes `issue 124`_ and `issue 144`_. Thanks, Devin Jeanpierre. - In order to help the core developers measure the test coverage of the standard library, Brandon Rhodes devised an aggressive hack to trick Python into running some coverage code before anything else in the process. See the coverage/fullcoverage directory if you are interested. .. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from .. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch .. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in .. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27 .. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is .. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for Version 3.5 --- 29 June 2011 ---------------------------- - The HTML report hotkeys now behave slightly differently when the current chunk isn't visible at all: a chunk on the screen will be selected, instead of the old behavior of jumping to the literal next chunk. The hotkeys now work in Google Chrome. Thanks, Guido van Rossum. Version 3.5b1 --- 5 June 2011 ----------------------------- - The HTML report now has hotkeys. Try ``n``, ``s``, ``m``, ``x``, ``b``, ``p``, and ``c`` on the overview page to change the column sorting. On a file page, ``r``, ``m``, ``x``, and ``p`` toggle the run, missing, excluded, and partial line markings. You can navigate the highlighted sections of code by using the ``j`` and ``k`` keys for next and previous. The ``1`` (one) key jumps to the first highlighted section in the file, and ``0`` (zero) scrolls to the top of the file. - The ``--omit`` and ``--include`` switches now interpret their values more usefully. If the value starts with a wildcard character, it is used as-is. If it does not, it is interpreted relative to the current directory. Closes `issue 121`_. - Partial branch warnings can now be pragma'd away. The configuration option ``partial_branches`` is a list of regular expressions. Lines matching any of those expressions will never be marked as a partial branch. In addition, there's a built-in list of regular expressions marking statements which should never be marked as partial. This list includes ``while True:``, ``while 1:``, ``if 1:``, and ``if 0:``. - The ``coverage()`` constructor accepts single strings for the ``omit=`` and ``include=`` arguments, adapting to a common error in programmatic use. - Modules can now be run directly using ``coverage run -m modulename``, to mirror Python's ``-m`` flag. Closes `issue 95`_, thanks, Brandon Rhodes. - ``coverage run`` didn't emulate Python accurately in one small detail: the current directory inserted into ``sys.path`` was relative rather than absolute. This is now fixed. - HTML reporting is now incremental: a record is kept of the data that produced the HTML reports, and only files whose data has changed will be generated. This should make most HTML reporting faster. - Pathological code execution could disable the trace function behind our backs, leading to incorrect code measurement. Now if this happens, coverage.py will issue a warning, at least alerting you to the problem. Closes `issue 93`_. Thanks to Marius Gedminas for the idea. - The C-based trace function now behaves properly when saved and restored with ``sys.gettrace()`` and ``sys.settrace()``. This fixes `issue 125`_ and `issue 123`_. Thanks, Devin Jeanpierre. - Source files are now opened with Python 3.2's ``tokenize.open()`` where possible, to get the best handling of Python source files with encodings. Closes `issue 107`_, thanks, Brett Cannon. - Syntax errors in supposed Python files can now be ignored during reporting with the ``-i`` switch just like other source errors. Closes `issue 115`_. - Installation from source now succeeds on machines without a C compiler, closing `issue 80`_. - Coverage.py can now be run directly from a working tree by specifying the directory name to python: ``python coverage_py_working_dir run ...``. Thanks, Brett Cannon. - A little bit of Jython support: `coverage run` can now measure Jython execution by adapting when $py.class files are traced. Thanks, Adi Roiban. Jython still doesn't provide the Python libraries needed to make coverage reporting work, unfortunately. - Internally, files are now closed explicitly, fixing `issue 104`_. Thanks, Brett Cannon. .. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant .. _issue 93: http://bitbucket.org/ned/coveragepy/issue/93/copying-a-mock-object-breaks-coverage .. _issue 95: https://bitbucket.org/ned/coveragepy/issue/95/run-subcommand-should-take-a-module-name .. _issue 104: https://bitbucket.org/ned/coveragepy/issue/104/explicitly-close-files .. _issue 107: https://bitbucket.org/ned/coveragepy/issue/107/codeparser-not-opening-source-files-with .. _issue 115: https://bitbucket.org/ned/coveragepy/issue/115/fail-gracefully-when-reporting-on-file .. _issue 121: https://bitbucket.org/ned/coveragepy/issue/121/filename-patterns-are-applied-stupidly .. _issue 123: https://bitbucket.org/ned/coveragepy/issue/123/pyeval_settrace-used-in-way-that-breaks .. _issue 125: https://bitbucket.org/ned/coveragepy/issue/125/coverage-removes-decoratortoolss-tracing Version 3.4 --- 19 September 2010 --------------------------------- - The XML report is now sorted by package name, fixing `issue 88`_. - Programs that exited with ``sys.exit()`` with no argument weren't handled properly, producing a coverage.py stack trace. That is now fixed. .. _issue 88: http://bitbucket.org/ned/coveragepy/issue/88/xml-report-lists-packages-in-random-order Version 3.4b2 --- 6 September 2010 ---------------------------------- - Completely unexecuted files can now be included in coverage results, reported as 0% covered. This only happens if the --source option is specified, since coverage.py needs guidance about where to look for source files. - The XML report output now properly includes a percentage for branch coverage, fixing `issue 65`_ and `issue 81`_. - Coverage percentages are now displayed uniformly across reporting methods. Previously, different reports could round percentages differently. Also, percentages are only reported as 0% or 100% if they are truly 0 or 100, and are rounded otherwise. Fixes `issue 41`_ and `issue 70`_. - The precision of reported coverage percentages can be set with the ``[report] precision`` config file setting. Completes `issue 16`_. - Threads derived from ``threading.Thread`` with an overridden `run` method would report no coverage for the `run` method. This is now fixed, closing `issue 85`_. .. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals .. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there .. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura .. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage .. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a .. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured Version 3.4b1 --- 21 August 2010 -------------------------------- - BACKWARD INCOMPATIBILITY: the ``--omit`` and ``--include`` switches now take file patterns rather than file prefixes, closing `issue 34`_ and `issue 36`_. - BACKWARD INCOMPATIBILITY: the `omit_prefixes` argument is gone throughout coverage.py, replaced with `omit`, a list of filename patterns suitable for `fnmatch`. A parallel argument `include` controls what files are included. - The run command now has a ``--source`` switch, a list of directories or module names. If provided, coverage.py will only measure execution in those source files. - Various warnings are printed to stderr for problems encountered during data measurement: if a ``--source`` module has no Python source to measure, or is never encountered at all, or if no data is collected. - The reporting commands (report, annotate, html, and xml) now have an ``--include`` switch to restrict reporting to modules matching those file patterns, similar to the existing ``--omit`` switch. Thanks, Zooko. - The run command now supports ``--include`` and ``--omit`` to control what modules it measures. This can speed execution and reduce the amount of data during reporting. Thanks Zooko. - Since coverage.py 3.1, using the Python trace function has been slower than it needs to be. A cache of tracing decisions was broken, but has now been fixed. - Python 2.7 and 3.2 have introduced new opcodes that are now supported. - Python files with no statements, for example, empty ``__init__.py`` files, are now reported as having zero statements instead of one. Fixes `issue 1`_. - Reports now have a column of missed line counts rather than executed line counts, since developers should focus on reducing the missed lines to zero, rather than increasing the executed lines to varying targets. Once suggested, this seemed blindingly obvious. - Line numbers in HTML source pages are clickable, linking directly to that line, which is highlighted on arrival. Added a link back to the index page at the bottom of each HTML page. - Programs that call ``os.fork`` will properly collect data from both the child and parent processes. Use ``coverage run -p`` to get two data files that can be combined with ``coverage combine``. Fixes `issue 56`_. - Coverage is now runnable as a module: ``python -m coverage``. Thanks, Brett Cannon. - When measuring code running in a virtualenv, most of the system library was being measured when it shouldn't have been. This is now fixed. - Doctest text files are no longer recorded in the coverage data, since they can't be reported anyway. Fixes `issue 52`_ and `issue 61`_. - Jinja HTML templates compile into Python code using the HTML filename, which confused coverage.py. Now these files are no longer traced, fixing `issue 82`_. - Source files can have more than one dot in them (foo.test.py), and will be treated properly while reporting. Fixes `issue 46`_. - Source files with DOS line endings are now properly tokenized for syntax coloring on non-DOS machines. Fixes `issue 53`_. - Unusual code structure that confused exits from methods with exits from classes is now properly analyzed. See `issue 62`_. - Asking for an HTML report with no files now shows a nice error message rather than a cryptic failure ('int' object is unsubscriptable). Fixes `issue 59`_. .. _issue 1: http://bitbucket.org/ned/coveragepy/issue/1/empty-__init__py-files-are-reported-as-1-executable .. _issue 34: http://bitbucket.org/ned/coveragepy/issue/34/enhanced-omit-globbing-handling .. _issue 36: http://bitbucket.org/ned/coveragepy/issue/36/provide-regex-style-omit .. _issue 46: http://bitbucket.org/ned/coveragepy/issue/46 .. _issue 53: http://bitbucket.org/ned/coveragepy/issue/53 .. _issue 52: http://bitbucket.org/ned/coveragepy/issue/52/doctesttestfile-confuses-source-detection .. _issue 56: http://bitbucket.org/ned/coveragepy/issue/56 .. _issue 61: http://bitbucket.org/ned/coveragepy/issue/61/annotate-i-doesnt-work .. _issue 62: http://bitbucket.org/ned/coveragepy/issue/62 .. _issue 59: http://bitbucket.org/ned/coveragepy/issue/59/html-report-fails-with-int-object-is .. _issue 82: http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report Version 3.3.1 --- 6 March 2010 ------------------------------ - Using `parallel=True` in .coveragerc file prevented reporting, but now does not, fixing `issue 49`_. - When running your code with "coverage run", if you call `sys.exit()`, coverage.py will exit with that status code, fixing `issue 50`_. .. _issue 49: http://bitbucket.org/ned/coveragepy/issue/49 .. _issue 50: http://bitbucket.org/ned/coveragepy/issue/50 Version 3.3 --- 24 February 2010 -------------------------------- - Settings are now read from a .coveragerc file. A specific file can be specified on the command line with --rcfile=FILE. The name of the file can be programmatically set with the `config_file` argument to the coverage() constructor, or reading a config file can be disabled with `config_file=False`. - Fixed a problem with nested loops having their branch possibilities mischaracterized: `issue 39`_. - Added coverage.process_start to enable coverage measurement when Python starts. - Parallel data file names now have a random number appended to them in addition to the machine name and process id. - Parallel data files combined with "coverage combine" are deleted after they're combined, to clean up unneeded files. Fixes `issue 40`_. - Exceptions thrown from product code run with "coverage run" are now displayed without internal coverage.py frames, so the output is the same as when the code is run without coverage.py. - The `data_suffix` argument to the coverage constructor is now appended with an added dot rather than simply appended, so that .coveragerc files will not be confused for data files. - Python source files that don't end with a newline can now be executed, fixing `issue 47`_. - Added an AUTHORS.txt file. .. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39 .. _issue 40: http://bitbucket.org/ned/coveragepy/issue/40 .. _issue 47: http://bitbucket.org/ned/coveragepy/issue/47 Version 3.2 --- 5 December 2009 ------------------------------- - Added a ``--version`` option on the command line. Version 3.2b4 --- 1 December 2009 --------------------------------- - Branch coverage improvements: - The XML report now includes branch information. - Click-to-sort HTML report columns are now persisted in a cookie. Viewing a report will sort it first the way you last had a coverage report sorted. Thanks, `Chris Adams`_. - On Python 3.x, setuptools has been replaced by `Distribute`_. .. _Distribute: http://packages.python.org/distribute/ Version 3.2b3 --- 23 November 2009 ---------------------------------- - Fixed a memory leak in the C tracer that was introduced in 3.2b1. - Branch coverage improvements: - Branches to excluded code are ignored. - The table of contents in the HTML report is now sortable: click the headers on any column. Thanks, `Chris Adams`_. .. _Chris Adams: http://improbable.org/chris/ Version 3.2b2 --- 19 November 2009 ---------------------------------- - Branch coverage improvements: - Classes are no longer incorrectly marked as branches: `issue 32`_. - "except" clauses with types are no longer incorrectly marked as branches: `issue 35`_. - Fixed some problems syntax coloring sources with line continuations and source with tabs: `issue 30`_ and `issue 31`_. - The --omit option now works much better than before, fixing `issue 14`_ and `issue 33`_. Thanks, Danek Duvall. .. _issue 14: http://bitbucket.org/ned/coveragepy/issue/14 .. _issue 30: http://bitbucket.org/ned/coveragepy/issue/30 .. _issue 31: http://bitbucket.org/ned/coveragepy/issue/31 .. _issue 32: http://bitbucket.org/ned/coveragepy/issue/32 .. _issue 33: http://bitbucket.org/ned/coveragepy/issue/33 .. _issue 35: http://bitbucket.org/ned/coveragepy/issue/35 Version 3.2b1 --- 10 November 2009 ---------------------------------- - Branch coverage! - XML reporting has file paths that let Cobertura find the source code. - The tracer code has changed, it's a few percent faster. - Some exceptions reported by the command line interface have been cleaned up so that tracebacks inside coverage.py aren't shown. Fixes `issue 23`_. .. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23 Version 3.1 --- 4 October 2009 ------------------------------ - Source code can now be read from eggs. Thanks, Ross Lawley. Fixes `issue 25`_. .. _issue 25: http://bitbucket.org/ned/coveragepy/issue/25 Version 3.1b1 --- 27 September 2009 ----------------------------------- - Python 3.1 is now supported. - Coverage.py has a new command line syntax with sub-commands. This expands the possibilities for adding features and options in the future. The old syntax is still supported. Try "coverage help" to see the new commands. Thanks to Ben Finney for early help. - Added an experimental "coverage xml" command for producing coverage reports in a Cobertura-compatible XML format. Thanks, Bill Hart. - Added the --timid option to enable a simpler slower trace function that works for DecoratorTools projects, including TurboGears. Fixed `issue 12`_ and `issue 13`_. - HTML reports show modules from other directories. Fixed `issue 11`_. - HTML reports now display syntax-colored Python source. - Programs that change directory will still write .coverage files in the directory where execution started. Fixed `issue 24`_. - Added a "coverage debug" command for getting diagnostic information about the coverage.py installation. .. _issue 11: http://bitbucket.org/ned/coveragepy/issue/11 .. _issue 12: http://bitbucket.org/ned/coveragepy/issue/12 .. _issue 13: http://bitbucket.org/ned/coveragepy/issue/13 .. _issue 24: http://bitbucket.org/ned/coveragepy/issue/24 Version 3.0.1 --- 7 July 2009 ----------------------------- - Removed the recursion limit in the tracer function. Previously, code that ran more than 500 frames deep would crash. Fixed `issue 9`_. - Fixed a bizarre problem involving pyexpat, whereby lines following XML parser invocations could be overlooked. Fixed `issue 10`_. - On Python 2.3, coverage.py could mis-measure code with exceptions being raised. This is now fixed. - The coverage.py code itself will now not be measured by coverage.py, and no coverage modules will be mentioned in the nose --with-cover plug-in. Fixed `issue 8`_. - When running source files, coverage.py now opens them in universal newline mode just like Python does. This lets it run Windows files on Mac, for example. .. _issue 9: http://bitbucket.org/ned/coveragepy/issue/9 .. _issue 10: http://bitbucket.org/ned/coveragepy/issue/10 .. _issue 8: http://bitbucket.org/ned/coveragepy/issue/8 Version 3.0 --- 13 June 2009 ---------------------------- - Fixed the way the Python library was ignored. Too much code was being excluded the old way. - Tabs are now properly converted in HTML reports. Previously indentation was lost. Fixed `issue 6`_. - Nested modules now get a proper flat_rootname. Thanks, Christian Heimes. .. _issue 6: http://bitbucket.org/ned/coveragepy/issue/6 Version 3.0b3 --- 16 May 2009 ----------------------------- - Added parameters to coverage.__init__ for options that had been set on the coverage object itself. - Added clear_exclude() and get_exclude_list() methods for programmatic manipulation of the exclude regexes. - Added coverage.load() to read previously-saved data from the data file. - Improved the finding of code files. For example, .pyc files that have been installed after compiling are now located correctly. Thanks, Detlev Offenbach. - When using the object API (that is, constructing a coverage() object), data is no longer saved automatically on process exit. You can re-enable it with the auto_data=True parameter on the coverage() constructor. The module-level interface still uses automatic saving. Version 3.0b --- 30 April 2009 ------------------------------ HTML reporting, and continued refactoring. - HTML reports and annotation of source files: use the new -b (browser) switch. Thanks to George Song for code, inspiration and guidance. - Code in the Python standard library is not measured by default. If you need to measure standard library code, use the -L command-line switch during execution, or the cover_pylib=True argument to the coverage() constructor. - Source annotation into a directory (-a -d) behaves differently. The annotated files are named with their hierarchy flattened so that same-named files from different directories no longer collide. Also, only files in the current tree are included. - coverage.annotate_file is no longer available. - Programs executed with -x now behave more as they should, for example, __file__ has the correct value. - .coverage data files have a new pickle-based format designed for better extensibility. - Removed the undocumented cache_file argument to coverage.usecache(). Version 3.0b1 --- 7 March 2009 ------------------------------ Major overhaul. - Coverage is now a package rather than a module. Functionality has been split into classes. - The trace function is implemented in C for speed. Coverage runs are now much faster. Thanks to David Christian for productive micro-sprints and other encouragement. - Executable lines are identified by reading the line number tables in the compiled code, removing a great deal of complicated analysis code. - Precisely which lines are considered executable has changed in some cases. Therefore, your coverage stats may also change slightly. - The singleton coverage object is only created if the module-level functions are used. This maintains the old interface while allowing better programmatic use of Coverage. - The minimum supported Python version is 2.3. Version 2.85 --- 14 September 2008 ---------------------------------- - Add support for finding source files in eggs. Don't check for morf's being instances of ModuleType, instead use duck typing so that pseudo-modules can participate. Thanks, Imri Goldberg. - Use os.realpath as part of the fixing of file names so that symlinks won't confuse things. Thanks, Patrick Mezard. Version 2.80 --- 25 May 2008 ---------------------------- - Open files in rU mode to avoid line ending craziness. Thanks, Edward Loper. Version 2.78 --- 30 September 2007 ---------------------------------- - Don't try to predict whether a file is Python source based on the extension. Extension-less files are often Pythons scripts. Instead, simply parse the file and catch the syntax errors. Hat tip to Ben Finney. Version 2.77 --- 29 July 2007 ----------------------------- - Better packaging. Version 2.76 --- 23 July 2007 ----------------------------- - Now Python 2.5 is *really* fully supported: the body of the new with statement is counted as executable. Version 2.75 --- 22 July 2007 ----------------------------- - Python 2.5 now fully supported. The method of dealing with multi-line statements is now less sensitive to the exact line that Python reports during execution. Pass statements are handled specially so that their disappearance during execution won't throw off the measurement. Version 2.7 --- 21 July 2007 ---------------------------- - "#pragma: nocover" is excluded by default. - Properly ignore docstrings and other constant expressions that appear in the middle of a function, a problem reported by Tim Leslie. - coverage.erase() shouldn't clobber the exclude regex. Change how parallel mode is invoked, and fix erase() so that it erases the cache when called programmatically. - In reports, ignore code executed from strings, since we can't do anything useful with it anyway. - Better file handling on Linux, thanks Guillaume Chazarain. - Better shell support on Windows, thanks Noel O'Boyle. - Python 2.2 support maintained, thanks Catherine Proulx. - Minor changes to avoid lint warnings. Version 2.6 --- 23 August 2006 ------------------------------ - Applied Joseph Tate's patch for function decorators. - Applied Sigve Tjora and Mark van der Wal's fixes for argument handling. - Applied Geoff Bache's parallel mode patch. - Refactorings to improve testability. Fixes to command-line logic for parallel mode and collect. Version 2.5 --- 4 December 2005 ------------------------------- - Call threading.settrace so that all threads are measured. Thanks Martin Fuzzey. - Add a file argument to report so that reports can be captured to a different destination. - coverage.py can now measure itself. - Adapted Greg Rogers' patch for using relative file names, and sorting and omitting files to report on. Version 2.2 --- 31 December 2004 -------------------------------- - Allow for keyword arguments in the module global functions. Thanks, Allen. Version 2.1 --- 14 December 2004 -------------------------------- - Return 'analysis' to its original behavior and add 'analysis2'. Add a global for 'annotate', and factor it, adding 'annotate_file'. Version 2.0 --- 12 December 2004 -------------------------------- Significant code changes. - Finding executable statements has been rewritten so that docstrings and other quirks of Python execution aren't mistakenly identified as missing lines. - Lines can be excluded from consideration, even entire suites of lines. - The file system cache of covered lines can be disabled programmatically. - Modernized the code. Earlier History --------------- 2001-12-04 GDR Created. 2001-12-06 GDR Added command-line interface and source code annotation. 2001-12-09 GDR Moved design and interface to separate documents. 2001-12-10 GDR Open cache file as binary on Windows. Allow simultaneous -e and -x, or -a and -r. 2001-12-12 GDR Added command-line help. Cache analysis so that it only needs to be done once when you specify -a and -r. 2001-12-13 GDR Improved speed while recording. Portable between Python 1.5.2 and 2.1.1. 2002-01-03 GDR Module-level functions work correctly. 2002-01-07 GDR Update sys.path when running a file with the -x option, so that it matches the value the program would get if it were run on its own. python-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/0000755000175000017500000000000012252501325021153 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/entry_points.txt0000644000175000017500000000014312252501324024446 0ustar barrybarry[console_scripts] coverage2 = coverage:main coverage-2.7 = coverage:main coverage = coverage:main python-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/PKG-INFO0000644000175000017500000000335712252501324022257 0ustar barrybarryMetadata-Version: 1.0 Name: coverage Version: 3.7.1 Summary: Code coverage measurement for Python Home-page: http://nedbatchelder.com/code/coverage Author: Ned Batchelder and others Author-email: ned@nedbatchelder.com License: BSD Description: Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. Coverage.py runs on Pythons 2.3 through 3.3, and PyPy 1.9. Documentation is at `nedbatchelder.com `_. Code repository and issue tracker are on `Bitbucket `_, with a mirrored repo on `Github `_. New in 3.7: ``--debug``, and 12 bugs closed. New in 3.6: ``--fail-under``, and >20 bugs closed. New in 3.5: Branch coverage exclusions, keyboard shortcuts in HTML report. New in 3.4: Better control over source to measure, and unexecuted files can be reported. New in 3.3: .coveragerc files. New in 3.2: Branch coverage! Keywords: code coverage testing Platform: UNKNOWN Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Testing Classifier: Development Status :: 5 - Production/Stable python-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/SOURCES.txt0000644000175000017500000001657412252501324023053 0ustar barrybarryAUTHORS.txt CHANGES.txt MANIFEST.in README.txt __main__.py igor.py requirements.txt setup.py tox.ini coverage/__init__.py coverage/__main__.py coverage/annotate.py coverage/backward.py coverage/bytecode.py coverage/cmdline.py coverage/codeunit.py coverage/collector.py coverage/config.py coverage/control.py coverage/data.py coverage/debug.py coverage/execfile.py coverage/files.py coverage/html.py coverage/misc.py coverage/parser.py coverage/phystokens.py coverage/report.py coverage/results.py coverage/summary.py coverage/templite.py coverage/tracer.c coverage/version.py coverage/xmlreport.py coverage.egg-info/PKG-INFO coverage.egg-info/SOURCES.txt coverage.egg-info/dependency_links.txt coverage.egg-info/entry_points.txt coverage.egg-info/not-zip-safe coverage.egg-info/top_level.txt coverage/fullcoverage/encodings.py coverage/htmlfiles/coverage_html.js coverage/htmlfiles/index.html coverage/htmlfiles/jquery.hotkeys.js coverage/htmlfiles/jquery.isonscreen.js coverage/htmlfiles/jquery.min.js coverage/htmlfiles/jquery.tablesorter.min.js coverage/htmlfiles/keybd_closed.png coverage/htmlfiles/keybd_open.png coverage/htmlfiles/pyfile.html coverage/htmlfiles/style.css doc/api.rst doc/branch.rst doc/changes.rst doc/cmd.rst doc/config.rst doc/contributing.rst doc/excluding.rst doc/faq.rst doc/index.rst doc/install.rst doc/source.rst doc/subprocess.rst doc/trouble.rst tests/__init__.py tests/backtest.py tests/backunittest.py tests/coveragetest.py tests/covmodzip1.py tests/osinfo.py tests/stress_phystoken.tok tests/stress_phystoken_dos.tok tests/test_api.py tests/test_arcs.py tests/test_backward.py tests/test_cmdline.py tests/test_codeunit.py tests/test_collector.py tests/test_config.py tests/test_coverage.py tests/test_data.py tests/test_debug.py tests/test_execfile.py tests/test_farm.py tests/test_files.py tests/test_html.py tests/test_misc.py tests/test_oddball.py tests/test_parser.py tests/test_phystokens.py tests/test_process.py tests/test_results.py tests/test_summary.py tests/test_templite.py tests/test_testing.py tests/test_xml.py tests/try_execfile.py tests/eggsrc/setup.py tests/eggsrc/egg1/__init__.py tests/eggsrc/egg1/egg1.py tests/farm/annotate/annotate_dir.py tests/farm/annotate/run.py tests/farm/annotate/run_multi.py tests/farm/annotate/gold/white.py,cover tests/farm/annotate/gold_anno_dir/a___init__.py,cover tests/farm/annotate/gold_anno_dir/a_a.py,cover tests/farm/annotate/gold_anno_dir/b___init__.py,cover tests/farm/annotate/gold_anno_dir/b_b.py,cover tests/farm/annotate/gold_anno_dir/multi.py,cover tests/farm/annotate/gold_multi/multi.py,cover tests/farm/annotate/gold_multi/a/__init__.py,cover tests/farm/annotate/gold_multi/a/a.py,cover tests/farm/annotate/gold_multi/b/__init__.py,cover tests/farm/annotate/gold_multi/b/b.py,cover tests/farm/annotate/gold_v24/white.py,cover tests/farm/annotate/src/multi.py tests/farm/annotate/src/white.py tests/farm/annotate/src/a/__init__.py tests/farm/annotate/src/a/a.py tests/farm/annotate/src/b/__init__.py tests/farm/annotate/src/b/b.py tests/farm/html/run_a.py tests/farm/html/run_a_xml_1.py tests/farm/html/run_a_xml_2.py tests/farm/html/run_b_branch.py tests/farm/html/run_bom.py tests/farm/html/run_isolatin1.py tests/farm/html/run_omit_1.py tests/farm/html/run_omit_2.py tests/farm/html/run_omit_3.py tests/farm/html/run_omit_4.py tests/farm/html/run_omit_5.py tests/farm/html/run_other.py tests/farm/html/run_partial.py tests/farm/html/run_styled.py tests/farm/html/run_tabbed.py tests/farm/html/run_unicode.py tests/farm/html/run_y_xml_branch.py tests/farm/html/gold_a/a.html tests/farm/html/gold_a/index.html tests/farm/html/gold_b_branch/b.html tests/farm/html/gold_b_branch/index.html tests/farm/html/gold_bom/bom.html tests/farm/html/gold_bom/index.html tests/farm/html/gold_isolatin1/index.html tests/farm/html/gold_isolatin1/isolatin1.html tests/farm/html/gold_omit_1/index.html tests/farm/html/gold_omit_1/m1.html tests/farm/html/gold_omit_1/m2.html tests/farm/html/gold_omit_1/m3.html tests/farm/html/gold_omit_1/main.html tests/farm/html/gold_omit_2/index.html tests/farm/html/gold_omit_2/m2.html tests/farm/html/gold_omit_2/m3.html tests/farm/html/gold_omit_2/main.html tests/farm/html/gold_omit_3/index.html tests/farm/html/gold_omit_3/m3.html tests/farm/html/gold_omit_3/main.html tests/farm/html/gold_omit_4/index.html tests/farm/html/gold_omit_4/m1.html tests/farm/html/gold_omit_4/m3.html tests/farm/html/gold_omit_4/main.html tests/farm/html/gold_omit_5/index.html tests/farm/html/gold_omit_5/m1.html tests/farm/html/gold_omit_5/main.html tests/farm/html/gold_other/blah_blah_other.html tests/farm/html/gold_other/here.html tests/farm/html/gold_other/index.html tests/farm/html/gold_partial/index.html tests/farm/html/gold_partial/partial.html tests/farm/html/gold_styled/a.html tests/farm/html/gold_styled/extra.css tests/farm/html/gold_styled/index.html tests/farm/html/gold_styled/style.css tests/farm/html/gold_unicode/index.html tests/farm/html/gold_unicode/unicode.html tests/farm/html/gold_x_xml/coverage.xml tests/farm/html/gold_y_xml_branch/coverage.xml tests/farm/html/othersrc/other.py tests/farm/html/src/a.py tests/farm/html/src/b.py tests/farm/html/src/bom.py tests/farm/html/src/coverage.xml tests/farm/html/src/extra.css tests/farm/html/src/here.py tests/farm/html/src/isolatin1.py tests/farm/html/src/m1.py tests/farm/html/src/m2.py tests/farm/html/src/m3.py tests/farm/html/src/main.py tests/farm/html/src/omit4.ini tests/farm/html/src/omit5.ini tests/farm/html/src/partial.py tests/farm/html/src/run_a_xml_2.ini tests/farm/html/src/tabbed.py tests/farm/html/src/unicode.py tests/farm/html/src/y.py tests/farm/html/src/htmlcov/coverage_html.js tests/farm/html/src/htmlcov/index.html tests/farm/html/src/htmlcov/jquery-1.4.3.min.js tests/farm/html/src/htmlcov/jquery.hotkeys.js tests/farm/html/src/htmlcov/jquery.isonscreen.js tests/farm/html/src/htmlcov/jquery.tablesorter.min.js tests/farm/html/src/htmlcov/keybd_closed.png tests/farm/html/src/htmlcov/keybd_open.png tests/farm/html/src/htmlcov/m1.html tests/farm/html/src/htmlcov/m2.html tests/farm/html/src/htmlcov/m3.html tests/farm/html/src/htmlcov/main.html tests/farm/html/src/htmlcov/status.dat tests/farm/html/src/htmlcov/style.css tests/farm/run/run_chdir.py tests/farm/run/run_timid.py tests/farm/run/run_xxx.py tests/farm/run/src/chdir.py tests/farm/run/src/showtrace.py tests/farm/run/src/xxx tests/farm/run/src/subdir/placeholder tests/js/index.html tests/js/tests.js tests/modules/covmod1.py tests/modules/runmod1.py tests/modules/usepkgs.py tests/modules/aa/__init__.py tests/modules/aa/afile.odd.py tests/modules/aa/afile.py tests/modules/aa/zfile.py tests/modules/aa/bb/__init__.py tests/modules/aa/bb/bfile.odd.py tests/modules/aa/bb/bfile.py tests/modules/aa/bb.odd/bfile.py tests/modules/aa/bb/cc/__init__.py tests/modules/aa/bb/cc/cfile.py tests/modules/pkg1/__init__.py tests/modules/pkg1/__main__.py tests/modules/pkg1/p1a.py tests/modules/pkg1/p1b.py tests/modules/pkg1/p1c.py tests/modules/pkg1/runmod2.py tests/modules/pkg1/sub/__init__.py tests/modules/pkg1/sub/__main__.py tests/modules/pkg1/sub/ps1a.py tests/modules/pkg1/sub/runmod3.py tests/modules/pkg2/__init__.py tests/modules/pkg2/p2a.py tests/modules/pkg2/p2b.py tests/moremodules/othermods/__init__.py tests/moremodules/othermods/othera.py tests/moremodules/othermods/otherb.py tests/moremodules/othermods/sub/__init__.py tests/moremodules/othermods/sub/osa.py tests/moremodules/othermods/sub/osb.py tests/qunit/jquery.tmpl.min.js tests/qunit/qunit.css tests/qunit/qunit.jspython-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/dependency_links.txt0000644000175000017500000000000112252501324025220 0ustar barrybarry python-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/not-zip-safe0000644000175000017500000000000112252474455023416 0ustar barrybarry python-coverage-3.7.1+dfsg.1.orig/coverage.egg-info/top_level.txt0000644000175000017500000000001112252501324023674 0ustar barrybarrycoverage python-coverage-3.7.1+dfsg.1.orig/doc/0000755000175000017500000000000012252501325016433 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/doc/contributing.rst0000644000175000017500000001256012216144761021707 0ustar barrybarry.. _contributing: =========================== Contributing to coverage.py =========================== :history: 20121112T154100, brand new docs. .. highlight:: console I welcome contributions to coverage.py. Over the years, dozens of people have provided patches of various sizes to add features or fix bugs. This page should have all the information you need to make a contribution. One source of history or ideas are the `bug reports`_ against coverage.py. There you can find ideas for requested features, or the remains of rejected ideas. .. _bug reports: https://bitbucket.org/ned/coveragepy/issues?status=new&status=open Before you begin ---------------- If you have an idea for coverage.py, run it by me before you begin writing code. This way, I can get you going in the right direction, or point you to previous work in the area. Things are not always as straightforward as they seem, and having the benefit of lessons learned by those before you can save you frustration. Getting the code ---------------- The coverage.py code is hosted on a `Mercurial`_ repository at https://bitbucket.org/ned/coveragepy. To get a working environment, follow these steps: #. (Optional, but recommended) Create a virtualenv to work in, and activate it. #. Clone the repo:: $ hg clone https://bitbucket.org/ned/coveragepy #. Install the requirements:: $ pip install -r requirements.txt #. Install a number of versions of Python. Coverage.py supports a wide range of Python versions. The more you can test with, the more easily your code can be used as-is. If you only have one version, that's OK too, but may mean more work integrating your contribution. Running the tests ----------------- The tests are written as standard unittest-style tests, and are run with `tox`_:: $ tox GLOB sdist-make: /home/ned/coverage/setup.py py25 sdist-reinst: /home/ned/coverage/tox/dist/coverage-3.6b1.zip py25 runtests: commands[0] py25 runtests: commands[1] py25 runtests: commands[2] py25 runtests: commands[3] py25 runtests: commands[4] === Python 2.5.5 with Python tracer (/home/ned/coverage/tox/py25/bin/python) === ...........................................................................................(etc) ---------------------------------------------------------------------- Ran 360 tests in 10.836s OK py25 runtests: commands[5] py25 runtests: commands[6] === Python 2.5.5 with C tracer (/home/ned/coverage/tox/py25/bin/python) === ...........................................................................................(etc) ---------------------------------------------------------------------- Ran 360 tests in 10.044s OK py26 sdist-reinst: /home/ned/coverage/trunk/.tox/dist/coverage-3.6b1.zip py26 runtests: commands[0] py26 runtests: commands[1] py26 runtests: commands[2] py26 runtests: commands[3] py26 runtests: commands[4] === CPython 2.6.6 with Python tracer (/home/ned/coverage/tox/py26/bin/python) === ...........................................................................................(etc) ---------------------------------------------------------------------- Ran 364 tests in 12.572s OK py26 runtests: commands[5] py26 runtests: commands[6] === CPython 2.6.6 with C tracer (/home/ned/coverage/tox/py26/bin/python) === ...........................................................................................(etc) ---------------------------------------------------------------------- Ran 364 tests in 11.458s OK (and so on...) Tox runs the complete test suite twice for each version of Python you have installed. The first run uses the Python implementation of the trace function, the second uses the C implementation. To limit tox to just a few versions of Python, use the ``-e`` switch:: $ tox -e py27,py33 To run just a few tests, you can use nose test selector syntax:: $ tox tests.test_misc:SetupPyTest.test_metadata This looks in `tests/test_misc.py` to find the `SetupPyTest` class, and runs the `test_metadata` test method. Of course, run all the tests on every version of Python you have, before submitting a change. Lint, etc --------- I try to keep the coverage.py as clean as possible. I use pylint to alert me to possible problems:: $ make lint pylint --rcfile=.pylintrc coverage setup.py tests python -m tabnanny coverage setup.py tests python igor.py check_eol The source is pylint-clean, even if it's because there are pragmas quieting some warnings. Please try to keep it that way, but don't let pylint warnings keep you from sending patches. I can clean them up. Coverage testing coverage.py ---------------------------- Coverage.py can measure itself, but it's complicated. The process has been packaged up to make it easier:: $ COVERAGE_COVERAGE=yes tox $ python igor.py combine_html Then look at htmlcov/index.html. Note that due to the recursive nature of coverage.py measuring itself, there are some parts of the code that will never appear as covered, even though they are executed. Contributing ------------ When you are ready to contribute a change, any way you can get it to me is probably fine. A pull request on Bitbucket is great, but a simple diff or patch is great too. .. _Mercurial: http://mercurial.selenic.com/ .. _tox: http://tox.testrun.org/ python-coverage-3.7.1+dfsg.1.orig/doc/source.rst0000644000175000017500000000574512216167773020517 0ustar barrybarry.. _source: ======================= Specifying source files ======================= :history: 20100725T172000, new in 3.4 When coverage.py is running your program and measuring its execution, it needs to know what code to measure and what code not to. Measurement imposes a speed penalty, and the collected data must be stored in memory and then on disk. More importantly, when reviewing your coverage reports, you don't want to be distracted with modules that aren't your concern. Coverage.py has a number of ways you can focus it in on the code you care about. .. _source_execution: Execution --------- When running your code, the ``coverage run`` command will by default measure all code, unless it is part of the Python standard library. You can specify source to measure with the ``--source`` command-line switch, or the ``[run] source`` configuration value. The value is a list of directories or package names. If specified, only source inside these directories or packages will be measured. Specifying the source option also enables coverage.py to report on unexecuted files, since it can search the source tree for files that haven't been measured at all. You can further fine-tune coverage.py's attention with the ``--include`` and ``--omit`` switches (or ``[run] include`` and ``[run] omit`` configuration values). ``--include`` is a list of filename patterns. If specified, only files matching those patterns will be measured. ``--omit`` is also a list of filename patterns, specifying files not to measure. If both ``include`` and ``omit`` are specified, first the set of files is reduced to only those that match the include patterns, then any files that match the omit pattern are removed from the set. The ``include`` and ``omit`` filename patterns follow typical shell syntax: ``*`` matches any number of characters and ``?`` matches a single character. Patterns that start with a wildcard character are used as-is, other patterns are interpreted relative to the current directory. The ``source``, ``include``, and ``omit`` values all work together to determine the source that will be measured. .. _source_reporting: Reporting --------- Once your program is measured, you can specify the source files you want reported. Usually you want to see all the code that was measured, but if you are measuring a large project, you may want to get reports for just certain parts. The report commands (``report``, ``html``, ``annotate``, and ``xml``) all take optional ``modules`` arguments, and ``--include`` and ``--omit`` switches. The ``modules`` arguments specify particular modules to report on. The ``include`` and ``omit`` values are lists of filename patterns, just as with the ``run`` command. Remember that the reporting commands can only report on the data that has been collected, so the data you're looking for may not be in the data available for reporting. Note that these are ways of specifying files to measure. You can also exclude individual source lines. See :ref:`excluding` for details. python-coverage-3.7.1+dfsg.1.orig/doc/excluding.rst0000644000175000017500000000653412216145016021160 0ustar barrybarry.. _excluding: ============================ Excluding code from coverage ============================ :history: 20090613T090500, brand new docs. :history: 20100224T200900, updated for 3.3. :history: 20100725T211700, updated for 3.4. :history: 20110604T184400, updated for 3.5. You may have code in your project that you know won't be executed, and you want to tell coverage to ignore it. For example, you may have debugging-only code that won't be executed during your unit tests. You can tell coverage to exclude this code during reporting so that it doesn't clutter your reports with noise about code that you don't need to hear about. Coverage will look for comments marking clauses for exclusion. In this code, the "if debug" clause is excluded from reporting:: a = my_function1() if debug: # pragma: no cover msg = "blah blah" log_message(msg, a) b = my_function2() Any line with a comment of "pragma: no cover" is excluded. If that line introduces a clause, for example, an if clause, or a function or class definition, then the entire clause is also excluded. Here the __repr__ function is not reported as missing:: class MyObject(object): def __init__(self): blah1() blah2() def __repr__(self): # pragma: no cover return "" Excluded code is executed as usual, and its execution is recorded in the coverage data as usual. When producing reports though, coverage excludes it from the list of missing code. Branch coverage --------------- When measuring :ref:`branch coverage `, a condtional will not be counted as a branch if one of its choices is excluded:: def only_one_choice(x): if x: blah1() blah2() else: # pragma: no cover # x is always true. blah3() Because the ``else`` clause is excluded, the ``if`` only has one possible next line, so it isn't considered a branch at all. Advanced exclusion ------------------ Coverage identifies exclusions by matching lines against a list of regular expressions. Using :ref:`configuration files ` or the coverage :ref:`API `, you can add to that list. This is useful if you have often-used constructs to exclude that can be matched with a regex. You can exclude them all at once without littering your code with exclusion pragmas. For example, you might decide that __repr__ functions are usually only used in debugging code, and are uninteresting to test themselves. You could exclude all of them by adding a regex to the exclusion list:: [report] exclude_lines = def __repr__ For example, here's a list of exclusions I've used:: [report] exclude_lines = pragma: no cover def __repr__ if self.debug: if settings.DEBUG raise AssertionError raise NotImplementedError if 0: if __name__ == .__main__.: Note that when using the ``exclude_lines`` option in a configuration file, you are taking control of the entire list of regexes, so you need to re-specify the default "pragma: no cover" match if you still want it to apply. A similar pragma, "no branch", can be used to tailor branch coverage measurement. See :ref:`branch` for details. Excluding source files ---------------------- See :ref:`source` for ways to limit what files coverage.py measures or reports on. python-coverage-3.7.1+dfsg.1.orig/doc/config.rst0000644000175000017500000001561012224256104020436 0ustar barrybarry.. _config: =================== Configuration files =================== :history: 20100223T201600, new for 3.3 :history: 20100725T211700, updated for 3.4. :history: 20100824T092900, added ``precision``. :history: 20110604T184400, updated for 3.5. :history: 20110827T212700, updated for 3.5.1 :history: 20130926T222300, updated for 3.6.1 Coverage.py options can be specified in a configuration file. This makes it easier to re-run coverage with consistent settings, and also allows for specification of options that are otherwise only available in the :ref:`API `. Configuration files also make it easier to get coverage testing of spawned sub-processes. See :ref:`subprocess` for more details. The default name for configuration files is ``.coveragerc``, in the same directory coverage.py is being run in. Most of the settings in the configuration file are tied to your source code and how it should be measured, so it should be stored with your source, and checked into source control, rather than put in your home directory. Syntax ------ A coverage.py configuration file is in classic .ini file format: sections are introduced by a ``[section]`` header, and contain ``name = value`` entries. Lines beginning with ``#`` or ``;`` are ignored as comments. Strings don't need quotes. Multi-valued strings can be created by indenting values on multiple lines. Boolean values can be specified as ``on``, ``off``, ``true``, ``false``, ``1``, or ``0`` and are case-insensitive. Environment variables can be substituted in by using dollar signs: ``$WORD`` ``${WORD}`` will be replaced with the value of ``WORD`` in the environment. A dollar sign can be inserted with ``$$``. Missing environment variables will result in empty strings with no error. Many sections and values correspond roughly to commands and options in the :ref:`command-line interface `. Here's a sample configuration file:: # .coveragerc to control coverage.py [run] branch = True [report] # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain about missing debug-only code: def __repr__ if self\.debug # Don't complain if tests don't hit defensive assertion code: raise AssertionError raise NotImplementedError # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: ignore_errors = True [html] directory = coverage_html_report [run] ----- These values are generally used when running product code, though some apply to more than one command. ``branch`` (boolean, default False): whether to measure :ref:`branch coverage ` in addition to statement coverage. ``cover_pylib`` (boolean, default False): whether to measure the Python standard library. ``data_file`` (string, default ".coverage"): the name of the data file to use for storing or reporting coverage. ``debug`` (multi-string): a list of debug options. See :ref:`the run --debug option ` for details. ``include`` (multi-string): a list of filename patterns, the files to include in measurement or reporting. See :ref:`source` for details. ``omit`` (multi-string): a list of filename patterns, the files to leave out of measurement or reporting. See :ref:`source` for details. ``parallel`` (boolean, default False): append the machine name, process id and random number to the data file name to simplify collecting data from many processes. See :ref:`cmd_combining` for more information. ``source`` (multi-string): a list of packages or directories, the source to measure during execution. See :ref:`source` for details. ``timid`` (boolean, default False): use a simpler but slower trace method. Try this if you get seemingly impossible results. .. _config_paths: [paths] ------- The entries in this section are lists of file paths that should be considered equivalent when combining data from different machines:: [paths] source = src/ /jenkins/build/*/src c:\myproj\src The names of the entries are ignored, you may choose any name that you like. The value is a lists of strings. When combining data with the ``combine`` command, two file paths will be combined if they start with paths from the same list. The first value must be an actual file path on the machine where the reporting will happen, so that source code can be found. The other values can be file patterns to match against the paths of collected data, or they can be absolute or relative file paths on the current machine. See :ref:`cmd_combining` for more information. [report] -------- Values common to many kinds of reporting. ``exclude_lines`` (multi-string): a list of regular expressions. Any line of your source code that matches one of these regexes is excluded from being reported as missing. More details are in :ref:`excluding`. If you use this option, you are replacing all the exclude regexes, so you'll need to also supply the "pragma: no cover" regex if you still want to use it. ``ignore_errors`` (boolean, default False): ignore source code that can't be found. ``include`` (multi-string): a list of filename patterns, the files to include in reporting. See :ref:`source` for details. ``omit`` (multi-string): a list of filename patterns, the files to leave out of reporting. See :ref:`source` for details. ``partial_branches`` (multi-string): a list of regular expressions. Any line of code that matches one of these regexes is excused from being reported as a partial branch. More details are in :ref:`branch`. If you use this option, you are replacing all the partial branch regexes so you'll need to also supply the "pragma: no branch" regex if you still want to use it. ``precision`` (integer): the number of digits after the decimal point to display for reported coverage percentages. The default is 0, displaying for example "87%". A value of 2 will display percentages like "87.32%". ``show_missing`` (boolean, default False): when running a summary report, show missing lines. See :ref:`cmd_summary` for more information. .. _config_html: [html] ------ Values particular to HTML reporting. The values in the ``[report]`` section also apply to HTML output, where appropriate. ``directory`` (string, default "htmlcov"): where to write the HTML report files. ``extra_css`` (string): the path to a file of CSS to apply to the HTML report. The file will be copied into the HTML output directory. Don't name it "style.css". This CSS is in addition to the CSS normally used, though you can overwrite as many of the rules as you like. ``title`` (string, default "Coverage report"): the title to use for the report. Note this is text, not HTML. [xml] ----- Values particular to XML reporting. The values in the ``[report]`` section also apply to XML output, where appropriate. ``output`` (string, default "coverage.xml"): where to write the XML report. python-coverage-3.7.1+dfsg.1.orig/doc/api.rst0000644000175000017500000000210412216144663017743 0ustar barrybarry.. _api: ============ Coverage API ============ :history: 20090524T134300, brand new docs. :history: 20090613T164000, final touches for 3.0 :history: 20100221T151500, docs for 3.3 (on the plane back from PyCon) :history: 20100725T211700, updated for 3.4. :history: 20121111T235800, added a bit of clarification. The API to coverage.py is very simple, contained in a single module called `coverage`. Most of the interface is in a single class, also called `coverage`. Methods on the coverage object correspond roughly to operations available in the command line interface. For example, a simple use would be:: import coverage cov = coverage.coverage() cov.start() # .. call your code .. cov.stop() cov.save() cov.html_report() The coverage module ------------------- .. module:: coverage .. autoclass:: coverage :members: Starting coverage automatically ------------------------------- This function is used to start coverage measurement automatically when Python starts. See :ref:`subprocess` for details. .. autofunction:: process_startup python-coverage-3.7.1+dfsg.1.orig/doc/faq.rst0000644000175000017500000000727612216167700017755 0ustar barrybarry.. _faq: ================== FAQ and other help ================== :history: 20090613T141800, brand new docs. :history: 20091005T073900, updated for 3.1. :history: 20091127T201500, updated for 3.2. :history: 20110605T175500, add the announcement mailing list. :history: 20121231T104700, Tweak the py3 text. Frequently asked questions -------------------------- **Q: I use nose to run my tests, and its cover plugin doesn't let me create HTML or XML reports. What should I do?** First run your tests and collect coverage data with `nose`_ and its plugin. This will write coverage data into a .coverage file. Then run coverage.py from the :ref:`command line ` to create the reports you need from that data. .. _nose: http://somethingaboutorange.com/mrl/projects/nose **Q: Why do unexecutable lines show up as executed?** Usually this is because you've updated your code and run coverage on it again without erasing the old data. Coverage records line numbers executed, so the old data may have recorded a line number which has since moved, causing coverage to claim a line has been executed which cannot be. If you are using the ``-x`` command line action, it doesn't erase first by default. Switch to the ``coverage run`` command, or use the ``-e`` switch to erase all data before starting the next run. **Q: Why do the bodies of functions (or classes) show as executed, but the def lines do not?** This happens because coverage is started after the functions are defined. The definition lines are executed without coverage measurement, then coverage is started, then the function is called. This means the body is measured, but the definition of the function itself is not. To fix this, start coverage earlier. If you use the :ref:`command line ` to run your program with coverage, then your entire program will be monitored. If you are using the :ref:`API `, you need to call coverage.start() before importing the modules that define your functions. **Q: Does coverage.py work on Python 3.x?** Yes, Python 3 is fully supported. **Q: Isn't coverage testing the best thing ever?** It's good, but `it isn't perfect`__. __ http://nedbatchelder.com/blog/200710/flaws_in_coverage_measurement.html .. Other resources --------------- There are a number of projects that help integrate coverage.py into other systems: - `trialcoverage`_ is a plug-in for Twisted trial. .. _trialcoverage: http://pypi.python.org/pypi/trialcoverage - `pytest-coverage`_ .. _pytest-coverage: http://pypi.python.org/pypi/pytest-coverage - `django-coverage`_ for use with Django. .. _django-coverage: http://pypi.python.org/pypi/django-coverage **Q: Where can I get more help with coverage.py?** You can discuss coverage.py or get help using it on the `Testing In Python`_ mailing list. .. _Testing In Python: http://lists.idyll.org/listinfo/testing-in-python Bug reports are gladly accepted at the `Bitbucket issue tracker`_. .. _Bitbucket issue tracker: http://bitbucket.org/ned/coveragepy/issues Announcements of new coverage.py releases are sent to the `coveragepy-announce`_ mailing list. .. _coveragepy-announce: http://groups.google.com/group/coveragepy-announce `I can be reached`__ in a number of ways, I'm happy to answer questions about using coverage.py. __ http://nedbatchelder.com/site/aboutned.html History ------- Coverage.py was originally written by `Gareth Rees`_. Since 2004, `Ned Batchelder`_ has extended and maintained it with the help of `many others`_. The :ref:`change history ` has all the details. .. _Gareth Rees: http://garethrees.org/ .. _Ned Batchelder: http://nedbatchelder.com .. _many others: http://bitbucket.org/ned/coveragepy/src/tip/AUTHORS.txt python-coverage-3.7.1+dfsg.1.orig/doc/changes.rst0000644000175000017500000010035012252470762020606 0ustar barrybarry.. _changes: ==================================== Major change history for coverage.py ==================================== :history: 20090524T134300, brand new docs. :history: 20090613T164000, final touches for 3.0 :history: 20090706T205000, changes for 3.0.1 :history: 20091004T170700, changes for 3.1 :history: 20091128T072200, changes for 3.2 :history: 20091205T161525, 3.2 final :history: 20100221T151900, changes for 3.3 :history: 20100306T181400, changes for 3.3.1 :history: 20100725T211700, updated for 3.4. :history: 20100820T151500, updated for 3.4b1 :history: 20100906T133800, updated for 3.4b2 :history: 20100919T163400, updated for 3.4 release. :history: 20110604T214100, updated for 3.5b1 :history: 20110629T082200, updated for 3.5 :history: 20110923T081600, updated for 3.5.1 :history: 20120429T162100, updated for 3.5.2b1 :history: 20120503T233700, updated for 3.5.2 :history: 20120929T093100, updated for 3.5.3 :history: 20121129T060100, updated for 3.6b1. :history: 20121223T180600, updated for 3.6b2. :history: 20130105T173500, updated for 3.6 :history: 20131005T205700, updated for 3.7 :history: 20131212T213100, updated for 3.7.1 These are the major changes for coverage.py. For a more complete change history, see the `CHANGES.txt`_ file in the source tree. .. _CHANGES.txt: http://bitbucket.org/ned/coveragepy/src/tip/CHANGES.txt .. _changes_371: Version 3.7.1 --- 13 December 2013 ---------------------------------- - Improved the speed of HTML report generation by about 20%. - Fixed the mechanism for finding OS-installed static files for the HTML report so that it will actually find OS-installed static files. .. _changes_37: Version 3.7 --- 6 October 2013 ------------------------------ - Added the ``--debug`` switch to ``coverage run``. It accepts a list of options indicating the type of internal activity to log to stderr. For details, see :ref:`the run --debug options `. - Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_. - Running code with ``coverage run -m`` now behaves more like Python does, setting sys.path properly, which fixes `issue 207`_ and `issue 242`_. - Coverage can now run .pyc files directly, closing `issue 264`_. - Coverage properly supports .pyw files, fixing `issue 261`_. - Omitting files within a tree specified with the ``source`` option would cause them to be incorrectly marked as unexecuted, as described in `issue 218`_. This is now fixed. - When specifying paths to alias together during data combining, you can now specify relative paths, fixing `issue 267`_. - Most file paths can now be specified with username expansion (``~/src``, or ``~build/src``, for example), and with environment variable expansion (``build/$BUILDNUM/src``). - Trying to create an XML report with no files to report on, would cause a ZeroDivideError, but no longer does, fixing `issue 250`_. - When running a threaded program under the Python tracer, coverage no longer issues a spurious warning about the trace function changing: "Trace function changed, measurement is likely wrong: None." This fixes `issue 164`_. - Static files necessary for HTML reports are found in system-installed places, to ease OS-level packaging of coverage.py. Closes `issue 259`_. - Source files with encoding declarations, but a blank first line, were not decoded properly. Now they are. Thanks, Roger Hu. - The source kit now includes the ``__main__.py`` file in the root coverage directory, fixing `issue 255`_. .. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in .. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using .. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain .. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in .. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work .. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag .. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating .. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in .. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party .. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly .. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files .. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work Version 3.6 --- 5 January 2013 ------------------------------ Features: - The **report**, **html**, and **xml** commands now accept a ``--fail-under`` switch that indicates in the exit status whether the coverage percentage was less than a particular value. Closes `issue 139`_. - The reporting functions coverage.report(), coverage.html_report(), and coverage.xml_report() now all return a float, the total percentage covered measurement. - The HTML report's title can now be set in the configuration file, with the ``--title`` switch on the command line, or via the API. - Configuration files now support substitution of environment variables, using syntax like ``${WORD}``. Closes `issue 97`_. Packaging: - The C extension is optionally compiled using a different more widely-used technique, taking another stab at fixing `issue 80`_ once and for all. - When installing, now in addition to creating a "coverage" command, two new aliases are also installed. A "coverage2" or "coverage3" command will be created, depending on whether you are installing in Python 2.x or 3.x. A "coverage-X.Y" command will also be created corresponding to your specific version of Python. Closes `issue 111`_. - The coverage.py installer no longer tries to bootstrap setuptools or Distribute. You must have one of them installed first, as `issue 202`_ recommended. - The coverage.py kit now includes docs (closing `issue 137`_) and tests. Docs: - Added a page to the docs about :doc:`contributing ` to coverage.py, closing `issue 171`_. - Added a page to the docs about :doc:`troublesome situations `, closing `issue 226`_. - Docstrings for the legacy singleton methods are more helpful. Thanks Marius Gedminas. Closes `issue 205`_. - The pydoc tool can now show docmentation for the class `coverage.coverage`. Closes `issue 206`_. - Added some info to the TODO file, closing `issue 227`_. Fixes: - Wildcards in ``include=`` and ``omit=`` arguments were not handled properly in reporting functions, though they were when running. Now they are handled uniformly, closing `issue 143`_ and `issue 163`_. **NOTE**: it is possible that your configurations may now be incorrect. If you use ``include`` or ``omit`` during reporting, whether on the command line, through the API, or in a configuration file, please check carefully that you were not relying on the old broken behavior. - Embarrassingly, the `[xml] output=` setting in the .coveragerc file simply didn't work. Now it does. - Combining data files would create entries for phantom files if used with ``source`` and path aliases. It no longer does. - ``debug sys`` now shows the configuration file path that was read. - If an oddly-behaved package claims that code came from an empty-string filename, coverage.py no longer associates it with the directory name, fixing `issue 221`_. - The XML report now consistently uses filenames for the filename attribute, rather than sometimes using module names. Fixes `issue 67`_. Thanks, Marcus Cobden. - Coverage percentage metrics are now computed slightly differently under branch coverage. This means that completely unexecuted files will now correctly have 0% coverage, fixing `issue 156`_. This also means that your total coverage numbers will generally now be lower if you are measuring branch coverage. - On Windows, files are now reported in their correct case, fixing `issue 89`_ and `issue 203`_. - If a file is missing during reporting, the path shown in the error message is now correct, rather than an incorrect path in the current directory. Fixes `issue 60`_. - Running an HTML report in Python 3 in the same directory as an old Python 2 HTML report would fail with a UnicodeDecodeError. This issue (`issue 193`_) is now fixed. - Fixed yet another error trying to parse non-Python files as Python, this time an IndentationError, closing `issue 82`_ for the fourth time... - If `coverage xml` fails because there is no data to report, it used to create a zero-length XML file. Now it doesn't, fixing `issue 210`_. - Jython files now work with the ``--source`` option, fixing `issue 100`_. - Running coverage under a debugger is unlikely to work, but it shouldn't fail with "TypeError: 'NoneType' object is not iterable". Fixes `issue 201`_. - On some Linux distributions, when installed with the OS package manager, coverage.py would report its own code as part of the results. Now it won't, fixing `issue 214`_, though this will take some time to be repackaged by the operating systems. - When coverage.py ended unsuccessfully, it may have reported odd errors like ``'NoneType' object has no attribute 'isabs'``. It no longer does, so kiss `issue 153`_ goodbye. .. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files .. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated .. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in .. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be .. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages .. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not .. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution .. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests .. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage .. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers .. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14 .. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename .. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests .. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy .. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on .. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and .. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename .. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly .. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error .. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml .. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise .. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp .. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when .. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo Version 3.5.3 --- 29 September 2012 ----------------------------------- - Line numbers in the HTML report line up better with the source lines, fixing `issue 197`_, thanks Marius Gedminas. - When specifying a directory as the source= option, the directory itself no longer needs to have a ``__init__.py`` file, though its subdirectories do, to be considered as source files. - Files encoded as UTF-8 with a BOM are now properly handled, fixing `issue 179`_. Thanks, Pablo Carballo. - Fixed more cases of non-Python files being reported as Python source, and then not being able to parse them as Python. Closes `issue 82`_ (again). Thanks, Julian Berman. - Fixed memory leaks under Python 3, thanks, Brett Cannon. Closes `issue 147`_. - Optimized .pyo files may not have been handled correctly, `issue 195`_. Thanks, Marius Gedminas. - Certain unusually named file paths could have been mangled during reporting, `issue 194`_. Thanks, Marius Gedminas. - Try to do a better job of the impossible task of detecting when we can't build the C extension, fixing `issue 183`_. .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer .. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is .. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23 .. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle .. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit .. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align Version 3.5.2 --- 4 May 2012 ---------------------------- - The HTML report has slightly tweaked controls: the buttons at the top of the page are color-coded to the source lines they affect. - Custom CSS can be applied to the HTML report by specifying a CSS file as the extra_css configuration value in the [html] section. - Source files with custom encodings declared in a comment at the top are now properly handled during reporting on Python 2. Python 3 always handled them properly. This fixes `issue 157`_. - Backup files left behind by editors are no longer collected by the source= option, fixing `issue 168`_. - If a file doesn't parse properly as Python, we don't report it as an error if the filename seems like maybe it wasn't meant to be Python. This is a pragmatic fix for `issue 82`_. - The ``-m`` switch on ``coverage report``, which includes missing line numbers in the summary report, can now be specifed as ``show_missing`` in the config file. Closes `issue 173`_. - When running a module with ``coverage run -m ``, certain details of the execution environment weren't the same as for ``python -m ``. This had the unfortunate side-effect of making ``coverage run -m unittest discover`` not work if you had tests in a directory named "test". This fixes `issue 155`_. - Now the exit status of your product code is properly used as the process status when running ``python -m coverage run ...``. Thanks, JT Olds. - When installing into pypy, we no longer attempt (and fail) to compile the C tracer function, closing `issue 166`_. .. _issue 82: https://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report .. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover .. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8 .. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy .. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings .. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in Version 3.5.1 --- 23 September 2011 ----------------------------------- - When combining data files from parallel runs, you can now instruct coverage about which directories are equivalent on different machines. A ``[paths]`` section in the configuration file lists paths that are to be considered equivalent. Finishes `issue 17`_. - for-else constructs are understood better, and don't cause erroneous partial branch warnings. Fixes `issue 122`_. - Branch coverage for ``with`` statements is improved, fixing `issue 128`_. - The number of partial branches reported on the HTML summary page was different than the number reported on the individual file pages. This is now fixed. - An explicit include directive to measure files in the Python installation wouldn't work because of the standard library exclusion. Now the include directive takes precendence, and the files will be measured. Fixes `issue 138`_. - The HTML report now handles Unicode characters in Python source files properly. This fixes `issue 124`_ and `issue 144`_. Thanks, Devin Jeanpierre. - In order to help the core developers measure the test coverage of the standard library, Brandon Rhodes devised an aggressive hack to trick Python into running some coverage code before anything else in the process. See the coverage/fullcoverage directory if you are interested. .. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from .. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch .. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in .. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27 .. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is .. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for Version 3.5 --- 29 June 2011 ---------------------------- HTML reporting: - The HTML report now has hotkeys. Try ``n``, ``s``, ``m``, ``x``, ``b``, ``p``, and ``c`` on the overview page to change the column sorting. On a file page, ``r``, ``m``, ``x``, and ``p`` toggle the run, missing, excluded, and partial line markings. You can navigate the highlighted sections of code by using the ``j`` and ``k`` keys for next and previous. The ``1`` (one) key jumps to the first highlighted section in the file, and ``0`` (zero) scrolls to the top of the file. - HTML reporting is now incremental: a record is kept of the data that produced the HTML reports, and only files whose data has changed will be generated. This should make most HTML reporting faster. Running Python files - Modules can now be run directly using ``coverage run -m modulename``, to mirror Python's ``-m`` flag. Closes `issue 95`_, thanks, Brandon Rhodes. - ``coverage run`` didn't emulate Python accurately in one detail: the current directory inserted into ``sys.path`` was relative rather than absolute. This is now fixed. - Pathological code execution could disable the trace function behind our backs, leading to incorrect code measurement. Now if this happens, coverage.py will issue a warning, at least alerting you to the problem. Closes `issue 93`_. Thanks to Marius Gedminas for the idea. - The C-based trace function now behaves properly when saved and restored with ``sys.gettrace()`` and ``sys.settrace()``. This fixes `issue 125`_ and `issue 123`_. Thanks, Devin Jeanpierre. - Coverage.py can now be run directly from a working tree by specifying the directory name to python: ``python coverage_py_working_dir run ...``. Thanks, Brett Cannon. - A little bit of Jython support: `coverage run` can now measure Jython execution by adapting when $py.class files are traced. Thanks, Adi Roiban. Reporting - Partial branch warnings can now be pragma'd away. The configuration option ``partial_branches`` is a list of regular expressions. Lines matching any of those expressions will never be marked as a partial branch. In addition, there's a built-in list of regular expressions marking statements which should never be marked as partial. This list includes ``while True:``, ``while 1:``, ``if 1:``, and ``if 0:``. - The ``--omit`` and ``--include`` switches now interpret their values more usefully. If the value starts with a wildcard character, it is used as-is. If it does not, it is interpreted relative to the current directory. Closes `issue 121`_. - Syntax errors in supposed Python files can now be ignored during reporting with the ``-i`` switch just like other source errors. Closes `issue 115`_. .. _issue 93: http://bitbucket.org/ned/coveragepy/issue/93/copying-a-mock-object-breaks-coverage .. _issue 95: https://bitbucket.org/ned/coveragepy/issue/95/run-subcommand-should-take-a-module-name .. _issue 115: https://bitbucket.org/ned/coveragepy/issue/115/fail-gracefully-when-reporting-on-file .. _issue 121: https://bitbucket.org/ned/coveragepy/issue/121/filename-patterns-are-applied-stupidly .. _issue 123: https://bitbucket.org/ned/coveragepy/issue/123/pyeval_settrace-used-in-way-that-breaks .. _issue 125: https://bitbucket.org/ned/coveragepy/issue/125/coverage-removes-decoratortoolss-tracing Version 3.4 --- 19 September 2010 --------------------------------- Controlling source: - BACKWARD INCOMPATIBILITY: the ``--omit`` and ``--include`` switches now take file patterns rather than file prefixes, closing `issue 34`_ and `issue 36`_. - BACKWARD INCOMPATIBILITY: the `omit_prefixes` argument is gone throughout coverage.py, replaced with `omit`, a list of filename patterns suitable for `fnmatch`. A parallel argument `include` controls what files are included. - The run command now has a ``--source`` switch, a list of directories or module names. If provided, coverage.py will only measure execution in those source files. The run command also now supports ``--include`` and ``--omit`` to control what modules it measures. This can speed execution and reduce the amount of data during reporting. Thanks Zooko. - The reporting commands (report, annotate, html, and xml) now have an ``--include`` switch to restrict reporting to modules matching those file patterns, similar to the existing ``--omit`` switch. Thanks, Zooko. Reporting: - Completely unexecuted files can now be included in coverage results, reported as 0% covered. This only happens if the --source option is specified, since coverage.py needs guidance about where to look for source files. - Python files with no statements, for example, empty ``__init__.py`` files, are now reported as having zero statements instead of one. Fixes `issue 1`_. - Reports now have a column of missed line counts rather than executed line counts, since developers should focus on reducing the missed lines to zero, rather than increasing the executed lines to varying targets. Once suggested, this seemed blindingly obvious. - Coverage percentages are now displayed uniformly across reporting methods. Previously, different reports could round percentages differently. Also, percentages are only reported as 0% or 100% if they are truly 0 or 100, and are rounded otherwise. Fixes `issue 41`_ and `issue 70`_. - The XML report output now properly includes a percentage for branch coverage, fixing `issue 65`_ and `issue 81`_, and the report is sorted by package name, fixing `issue 88`_. - The XML report is now sorted by package name, fixing `issue 88`_. - The precision of reported coverage percentages can be set with the ``[report] precision`` config file setting. Completes `issue 16`_. - Line numbers in HTML source pages are clickable, linking directly to that line, which is highlighted on arrival. Added a link back to the index page at the bottom of each HTML page. Execution and measurement: - Various warnings are printed to stderr for problems encountered during data measurement: if a ``--source`` module has no Python source to measure, or is never encountered at all, or if no data is collected. - Doctest text files are no longer recorded in the coverage data, since they can't be reported anyway. Fixes `issue 52`_ and `issue 61`_. - Threads derived from ``threading.Thread`` with an overridden `run` method would report no coverage for the `run` method. This is now fixed, closing `issue 85`_. - Programs that exited with ``sys.exit()`` with no argument weren't handled properly, producing a coverage.py stack trace. This is now fixed. - Programs that call ``os.fork`` will properly collect data from both the child and parent processes. Use ``coverage run -p`` to get two data files that can be combined with ``coverage combine``. Fixes `issue 56`_. - When measuring code running in a virtualenv, most of the system library was being measured when it shouldn't have been. This is now fixed. - Coverage can now be run as a module: ``python -m coverage``. Thanks, Brett Cannon. .. _issue 1: http://bitbucket.org/ned/coveragepy/issue/1/empty-__init__py-files-are-reported-as-1-executable .. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals .. _issue 34: http://bitbucket.org/ned/coveragepy/issue/34/enhanced-omit-globbing-handling .. _issue 36: http://bitbucket.org/ned/coveragepy/issue/36/provide-regex-style-omit .. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there .. _issue 52: http://bitbucket.org/ned/coveragepy/issue/52/doctesttestfile-confuses-source-detection .. _issue 56: http://bitbucket.org/ned/coveragepy/issue/56/coveragepy-cant-trace-child-processes-of-a .. _issue 61: http://bitbucket.org/ned/coveragepy/issue/61/annotate-i-doesnt-work .. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura .. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage .. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a .. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured .. _issue 88: http://bitbucket.org/ned/coveragepy/issue/88/xml-report-lists-packages-in-random-order Version 3.3.1 --- 6 March 2010 ------------------------------ - Using ``parallel=True`` in a .coveragerc file prevented reporting, but now does not, fixing `issue 49`_. - When running your code with ``coverage run``, if you call ``sys.exit()``, coverage.py will exit with that status code, fixing `issue 50`_. .. _issue 49: http://bitbucket.org/ned/coveragepy/issue/49 .. _issue 50: http://bitbucket.org/ned/coveragepy/issue/50 Version 3.3 --- 24 February 2010 -------------------------------- - Settings are now read from a .coveragerc file. A specific file can be specified on the command line with ``--rcfile=FILE``. The name of the file can be programmatically set with the ``config_file`` argument to the coverage() constructor, or reading a config file can be disabled with ``config_file=False``. - Added coverage.process_start to enable coverage measurement when Python starts. - Parallel data file names now have a random number appended to them in addition to the machine name and process id. Also, parallel data files combined with ``coverage combine`` are deleted after they're combined, to clean up unneeded files. Fixes `issue 40`_. - Exceptions thrown from product code run with ``coverage run`` are now displayed without internal coverage.py frames, so the output is the same as when the code is run without coverage.py. - Fixed `issue 39`_ and `issue 47`_. .. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39 .. _issue 40: http://bitbucket.org/ned/coveragepy/issue/40 .. _issue 47: http://bitbucket.org/ned/coveragepy/issue/47 Version 3.2 --- 5 December 2009 ------------------------------- - Branch coverage: coverage.py can tell you which branches didn't have both (or all) choices executed, even where the choice doesn't affect which lines were executed. See :ref:`branch` for more details. - The table of contents in the HTML report is now sortable: click the headers on any column. The sorting is persisted so that subsequent reports are sorted as you wish. Thanks, `Chris Adams`_. - XML reporting has file paths that let Cobertura find the source code, fixing `issue 21`_. - The ``--omit`` option now works much better than before, fixing `issue 14`_ and `issue 33`_. Thanks, Danek Duvall. - Added a ``--version`` option on the command line. - Program execution under coverage is a few percent faster. - Some exceptions reported by the command line interface have been cleaned up so that tracebacks inside coverage.py aren't shown. Fixes `issue 23`_. - Fixed some problems syntax coloring sources with line continuations and source with tabs: `issue 30`_ and `issue 31`_. .. _Chris Adams: http://improbable.org/chris/ .. _issue 21: http://bitbucket.org/ned/coveragepy/issue/21 .. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23 .. _issue 14: http://bitbucket.org/ned/coveragepy/issue/14 .. _issue 30: http://bitbucket.org/ned/coveragepy/issue/30 .. _issue 31: http://bitbucket.org/ned/coveragepy/issue/31 .. _issue 33: http://bitbucket.org/ned/coveragepy/issue/33 Version 3.1 --- 4 October 2009 ------------------------------ - Python 3.1 is now supported. - Coverage.py has a new command line syntax with sub-commands. This expands the possibilities for adding features and options in the future. The old syntax is still supported. Try ``coverage help`` to see the new commands. Thanks to Ben Finney for early help. - Added an experimental ``coverage xml`` command for producing coverage reports in a Cobertura-compatible XML format. Thanks, Bill Hart. - Added the ``--timid`` option to enable a simpler slower trace function that works for DecoratorTools projects, including TurboGears. Fixed `issue 12`_ and `issue 13`_. - HTML reports now display syntax-colored Python source. - Added a ``coverage debug`` command for getting diagnostic information about the coverage.py installation. - Source code can now be read from eggs. Thanks, `Ross Lawley`_. Fixes `issue 25`_. .. _Ross Lawley: http://agileweb.org/ .. _issue 25: http://bitbucket.org/ned/coveragepy/issue/25 .. _issue 12: http://bitbucket.org/ned/coveragepy/issue/12 .. _issue 13: http://bitbucket.org/ned/coveragepy/issue/13 Version 3.0.1 --- 7 July 2009 ----------------------------- - Removed the recursion limit in the tracer function. Previously, code that ran more than 500 frames deep would crash. - Fixed a bizarre problem involving pyexpat, whereby lines following XML parser invocations could be overlooked. - On Python 2.3, coverage.py could mis-measure code with exceptions being raised. This is now fixed. - The coverage.py code itself will now not be measured by coverage.py, and no coverage modules will be mentioned in the nose ``--with-cover`` plugin. - When running source files, coverage.py now opens them in universal newline mode just like Python does. This lets it run Windows files on Mac, for example. Version 3.0 --- 13 June 2009 ---------------------------- - Coverage is now a package rather than a module. Functionality has been split into classes. - HTML reports and annotation of source files: use the new ``-b`` (browser) switch. Thanks to George Song for code, inspiration and guidance. - The trace function is implemented in C for speed. Coverage runs are now much faster. Thanks to David Christian for productive micro-sprints and other encouragement. - The minimum supported Python version is 2.3. - When using the object api (that is, constructing a coverage() object), data is no longer saved automatically on process exit. You can re-enable it with the ``auto_data=True`` parameter on the coverage() constructor. The module-level interface still uses automatic saving. - Code in the Python standard library is not measured by default. If you need to measure standard library code, use the ``-L`` command-line switch during execution, or the ``cover_pylib=True`` argument to the coverage() constructor. - API changes: - Added parameters to coverage.__init__ for options that had been set on the coverage object itself. - Added clear_exclude() and get_exclude_list() methods for programmatic manipulation of the exclude regexes. - Added coverage.load() to read previously-saved data from the data file. - coverage.annotate_file is no longer available. - Removed the undocumented cache_file argument to coverage.usecache(). python-coverage-3.7.1+dfsg.1.orig/doc/subprocess.rst0000644000175000017500000000613212216170032021354 0ustar barrybarry.. _subprocess: ====================== Measuring subprocesses ====================== :history: 20100224T201800, new for 3.3. :history: 20100725T211700, updated for 3.4. Complex test suites may spawn subprocesses to run tests, either to run them in parallel, or because subprocess behavior is an important part of the system under test. Measuring coverage in those subprocesses can be tricky because you have to modify the code spawning the process to invoke coverage.py. There's an easier way to do it: coverage.py includes a function, :func:`coverage.process_startup` designed to be invoked when Python starts. It examines the ``COVERAGE_PROCESS_START`` environment variable, and if it is set, begins coverage measurement. The environment variable's value will be used as the name of the :ref:`configuration file ` to use. When using this technique, be sure to set the parallel option to true so that multiple coverage.py runs will each write their data to a distinct file. Configuring Python for subprocess coverage ------------------------------------------ Measuring coverage in subprocesses is a little tricky. When you spawn a subprocess, you are invoking Python to run your program. Usually, to get coverage measurement, you have to use coverage.py to run your program. Your subprocess won't be using coverage.py, so we have to convince Python to use coverage even when not explicitly invokved. To do that, we'll configure Python to run a little coverage.py code when it starts. That code will look for an environment variable that tells it to start coverage measurement at the start of the process. To arrange all this, you have to do two things: set a value for the ``COVERAGE_PROCESS_START`` environment variable, and then configure Python to invoke :func:`coverage.process_startup` when Python processes start. How you set ``COVERAGE_PROCESS_START`` depends on the details of how you create subprocesses. As long as the environment variable is visible in your subprocess, it will work. You can configure your Python installation to invoke the ``process_startup`` function in two ways: #. Create or append to sitecustomize.py to add these lines:: import coverage coverage.process_startup() #. Create a .pth file in your Python installation containing:: import coverage; coverage.process_startup() The sitecustomize.py technique is cleaner, but may involve modifying an existing sitecustomize.py, since there can be only one. If there is no sitecustomize.py already, you can create it in any directory on the Python path. The .pth technique seems like a hack, but works, and is documented behavior. On the plus side, you can create the file with any name you like so you don't have to coordinate with other .pth files. On the minus side, you have to create the file in a system-defined directory, so you may need privileges to write it. Note that if you use one of these techniques, you must undo them if you uninstall coverage.py, since you will be trying to import it during Python startup. Be sure to remove the change when you uninstall coverage.py, or use a more defensive approach to importing it. python-coverage-3.7.1+dfsg.1.orig/doc/cmd.rst0000644000175000017500000003353312225234050017735 0ustar barrybarry.. _cmd: =========================== Coverage command line usage =========================== :history: 20090524T134300, brand new docs. :history: 20090613T164000, final touches for 3.0 :history: 20090913T084400, new command line syntax :history: 20091004T170700, changes for 3.1 :history: 20091127T200700, changes for 3.2 :history: 20100223T200600, changes for 3.3 :history: 20100725T211700, updated for 3.4 :history: 20110827T212500, updated for 3.5.1, combining aliases :history: 20120119T075600, Added some clarification from George Paci :history: 20120504T091800, Added info about execution warnings, and 3.5.2 stuff. :history: 20120807T211600, Clarified the combine rules. :history: 20121003T074600, Fixed an option reference, https://bitbucket.org/ned/coveragepy/issue/200/documentation-mentions-output-xml-instead :history: 20121117T091000, Added command aliases. .. highlight:: console When you install coverage.py, a command-line script simply called ``coverage`` is placed in your Python scripts directory. To help with multi-version installs, it will also create either a ``coverage2`` or ``coverage3`` alias, and a ``coverage-X.Y`` alias, depending on the version of Python you're using. For example, when installing on Python 2.7, you will be able to use ``coverage``, ``coverage2``, or ``coverage-2.7`` on the command line. Coverage has a number of commands which determine the action performed: * **run** -- Run a Python program and collect execution data. * **report** -- Report coverage results. * **html** -- Produce annotated HTML listings with coverage results. * **xml** -- Produce an XML report with coverage results. * **annotate** -- Annotate source files with coverage results. * **erase** -- Erase previously collected coverage data. * **combine** -- Combine together a number of data files. * **debug** -- Get diagnostic information. Help is available with the **help** command, or with the ``--help`` switch on any other command:: $ coverage help $ coverage help run $ coverage run --help Version information for coverage.py can be displayed with ``coverage --version``. Any command can use a configuration file by specifying it with the ``--rcfile=FILE`` command-line switch. Any option you can set on the command line can also be set in the configuration file. This can be a better way to control coverage.py since the configuration file can be checked into source control, and can provide options that other invocation techniques (like test runner plugins) may not offer. See :ref:`config` for more details. .. _cmd_execution: Execution --------- You collect execution data by running your Python program with the **run** command:: $ coverage run my_program.py arg1 arg2 blah blah ..your program's output.. blah blah Your program runs just as if it had been invoked with the Python command line. Arguments after your file name are passed to your program as usual in ``sys.argv``. Rather than providing a filename, you can use the ``-m`` switch and specify an importable module name instead, just as you can with the Python ``-m`` switch:: $ coverage run -m packagename.modulename arg1 arg2 blah blah ..your program's output.. blah blah If you want :ref:`branch coverage ` measurement, use the ``--branch`` flag. Otherwise only statement coverage is measured. You can specify the code to measure with the ``--source``, ``--include``, and ``--omit`` switches. See :ref:`Specifying source files ` for details of their interpretation. Remember to put options for run after "run", but before the program invocation:: $ coverage run --source=dir1,dir2 my_program.py arg1 arg2 $ coverage run --source=dir1,dir2 -m packagename.modulename arg1 arg2 By default, coverage does not measure code installed with the Python interpreter, for example, the standard library. If you want to measure that code as well as your own, add the ``-L`` flag. If your coverage results seem to be overlooking code that you know has been executed, try running coverage again with the ``--timid`` flag. This uses a simpler but slower trace method. Projects that use DecoratorTools, including TurboGears, will need to use ``--timid`` to get correct results. This option can also be enabled by setting the environment variable COVERAGE_OPTIONS to ``--timid``. If you are measuring coverage in a multi-process program, or across a number of machines, you'll want the ``--parallel-mode`` switch to keep the data separate during measurement. See :ref:`cmd_combining` below. During execution, coverage.py may warn you about conditions it detects that could affect the measurement process. The possible warnings include: * "Trace function changed, measurement is likely wrong: XXX" Coverage measurement depends on a Python setting called the trace function. Other Python code in your product might change that function, which will disrupt coverage.py's measurement. This warning indicate that has happened. The XXX in the message is the new trace function value, which might provide a clue to the cause. * "Module XXX has no Python source" You asked coverage.py to measure module XXX, but once it was imported, it turned out not to have a corresponding .py file. Without a .py file, coverage.py can't report on missing lines. * "Module XXX was never imported" You asked coverage.py to measure module XXX, but it was never imported by your program. * "No data was collected" Coverage.py ran your program, but didn't measure any lines as executed. This could be because you asked to measure only modules that never ran, or for other reasons. .. _cmd_run_debug: The ``--debug`` option instructs coverage to log internal details of its operation, to help with diagnosing problems. It takes a comma-separated list of options, each indicating a facet of operation to log to stderr: * ``trace``: print every decision about whether to trace a file or not. For files not being traced, the reason is also given. * ``config``: before starting, dump all the :ref:`configuration ` values. * ``sys``: before starting, dump all the system and environment information, as with :ref:`coverage debug sys `. * ``dataio``: log when reading or writing any data file. * ``pid``: annotate all debug output with the process id. .. _cmd_datafile: Data file --------- Coverage collects execution data in a file called ".coverage". If need be, you can set a new file name with the COVERAGE_FILE environment variable. By default,each run of your program starts with an empty data set. If you need to run your program multiple times to get complete data (for example, because you need to supply disjoint options), you can accumulate data across runs with the ``-a`` flag on the **run** command. To erase the collected data, use the **erase** command:: $ coverage erase .. _cmd_combining: Combining data files -------------------- If you need to collect coverage data from different machines or processes, coverage can combine multiple files into one for reporting. Use the ``-p`` flag during execution to append distinguishing information to the .coverage data file name. Once you have created a number of these files, you can copy them all to a single directory, and use the **combine** command to combine them into one .coverage data file:: $ coverage combine If the different machines run your code from different places in their file systems, coverage won't know how to combine the data. You can tell coverage how the different locations correlate with a ``[paths]`` section in your configuration file. See :ref:`config_paths` for details. If you are collecting and renaming your own data files, you'll need to name them properly for **combine** to find them. It looks for files named after the data file (defaulting to ".coverage", overridable with COVERAGE_FILE), with a dotted suffix. All such files in the current directory will be combined. Here are some examples of combinable data files:: .coverage.machine1 .coverage.20120807T212300 .coverage.last_good_run.ok .. _cmd_reporting: Reporting --------- Coverage provides a few styles of reporting, with the **report**, **html**, **annotate**, and **xml** commands. They share a number of common options. The command-line arguments are module or file names to report on, if you'd like to report on a subset of the data collected. The ``--include`` and ``--omit`` flags specify lists of filename patterns. They control which files to report on, and are described in more detail in :ref:`source`. The ``-i`` or ``--ignore-errors`` switch tells coverage.py to ignore problems encountered trying to find source files to report on. This can be useful if some files are missing, or if your Python execution is tricky enough that file names are synthesized without real source files. If you provide a ``--fail-under`` value, the total percentage covered will be compared to that value. If it is less, the command will exit with a status code of 2, indicating that the total coverage was less than your target. This can be used as part of a pass/fail condition, for example in a continuous integration server. This option isn't available for **annotate**. .. _cmd_summary: Coverage summary ---------------- The simplest reporting is a textual summary produced with **report**:: $ coverage report Name Stmts Miss Cover --------------------------------------------- my_program 20 4 80% my_module 15 2 86% my_other_module 56 6 89% --------------------------------------------- TOTAL 91 12 87% For each module executed, the report shows the count of executable statements, the number of those statements missed, and the resulting coverage, expressed as a percentage. The ``-m`` flag also shows the line numbers of missing statements:: $ coverage report -m Name Stmts Miss Cover Missing ------------------------------------------------------- my_program 20 4 80% 33-35, 39 my_module 15 2 86% 8, 12 my_other_module 56 6 89% 17-23 ------------------------------------------------------- TOTAL 91 12 87% You can restrict the report to only certain files by naming them on the command line:: $ coverage report -m my_program.py my_other_module.py Name Stmts Miss Cover Missing ------------------------------------------------------- my_program 20 4 80% 33-35, 39 my_other_module 56 6 89% 17-23 ------------------------------------------------------- TOTAL 76 10 87% Other common reporting options are described above in :ref:`cmd_reporting`. .. _cmd_html: HTML annotation --------------- Coverage can annotate your source code for which lines were executed and which were not. The **html** command creates an HTML report similar to the **report** summary, but as an HTML file. Each module name links to the source file decorated to show the status of each line. Here's a `sample report`__. __ /code/coverage/sample_html/index.html Lines are highlighted green for executed, red for missing, and gray for excluded. The counts at the top of the file are buttons to turn on and off the highlighting. A number of keyboard shortcuts are available for navigating the report. Click the keyboard icon in the upper right to see the complete list. The title of the report can be set with the ``title`` setting in the ``[html]`` section of the configuration file, or the ``--title`` switch on the command line. If you prefer a different style for your HTML report, you can provide your own CSS file to apply, by specifying a CSS file in the ``[html]`` section of the configuration file. See :ref:`config_html` for details. The ``-d`` argument specifies an output directory, defaulting to "htmlcov":: $ coverage html -d coverage_html Other common reporting options are described above in :ref:`cmd_reporting`. Generating the HTML report can be time-consuming. Stored with the HTML report is a data file that is used to speed up reporting the next time. If you generate a new report into the same directory, coverage.py will skip generating unchanged pages, making the process faster. .. _cmd_annotation: Text annotation --------------- The **annotate** command produces a text annotation of your source code. With a ``-d`` argument specifying an output directory, each Python file becomes a text file in that directory. Without ``-d``, the files are written into the same directories as the original Python files. Coverage status for each line of source is indicated with a character prefix:: > executed ! missing (not executed) - excluded For example:: # A simple function, never called with x==1 > def h(x): """Silly function.""" - if 0: #pragma: no cover - pass > if x == 1: ! a = 1 > else: > a = 2 Other common reporting options are described above in :ref:`cmd_reporting`. .. _cmd_xml: XML reporting ------------- The **xml** command writes coverage data to a "coverage.xml" file in a format compatible with `Cobertura`_. .. _Cobertura: http://cobertura.sourceforge.net You can specify the name of the output file with the ``-o`` switch. Other common reporting options are described above in :ref:`cmd_reporting`. .. _cmd_debug: Diagnostics ----------- The **debug** command shows internal information to help diagnose problems. If you are reporting a bug about coverage.py, including the output of this command can often help:: $ coverage debug sys > please_attach_to_bug_report.txt Two types of information are available: ``sys`` to show system configuration, and ``data`` to show a summary of the collected coverage data. python-coverage-3.7.1+dfsg.1.orig/doc/index.rst0000644000175000017500000001276012252471072020307 0ustar barrybarry=========== coverage.py =========== :history: 20090524T134300, brand new docs. :history: 20090613T164000, final touches for 3.0 :history: 20090618T195900, minor tweaks :history: 20090707T205200, changes for 3.0.1 :history: 20090913T084400, new command line syntax :history: 20091004T211900, version 3.1 :history: 20091127T155100, version 3.2 :history: 20091205T161429, version 3.2 for real. :history: 20100224T204700, version 3.3 :history: 20100306T181500, version 3.3.1 :history: 20100725T211700, updated for 3.4. :history: 20100820T151500, updated for 3.4b1. :history: 20100906T134700, updated for 3.4b2. :history: 20100919T163500, updated for 3.4 release. :history: 20110213T081200, claim true 3.2 compatibility. :history: 20110604T114800, update for 3.5b1 :history: 20110629T082300, update for 3.5 :history: 20110827T221800, update for 3.5.1b1 :history: 20110923T081800, update for 3.5.1 :history: 20120429T162100, updated for 3.5.2b1 :history: 20120503T233800, updated for 3.5.2 :history: 20120929T093500, updated for 3.5.3 :history: 20121117T094900, Change from easy_install to pip. :history: 20121128T203700, Updated for 3.6b1. :history: 20121223T180600, Updated for 3.6b2. :history: 20121229T112300, Updated for 3.6b3. :history: 20130105T174000, Updated for 3.6 :history: 20131005T210000, Updated for 3.7 :history: 20131212T213300, Updated for 3.7.1 Coverage.py is a tool for measuring code coverage of Python programs. It monitors your program, noting which parts of the code have been executed, then analyzes the source to identify code that could have been executed but was not. Coverage measurement is typically used to gauge the effectiveness of tests. It can show which parts of your code are being exercised by tests, and which are not. .. ifconfig:: not prerelease The latest version is coverage.py 3.7.1, released 13 December 2013. It is supported on Python versions 2.3 through 3.4, and PyPy 2.1. .. ifconfig:: prerelease The latest version is coverage.py 3.6b3, released 29 December 2012. It is supported on Python versions 2.3 through 3.3, and PyPy 1.9. **This is a pre-release build. The usual warnings about possible bugs apply.** The latest stable version is coverage.py 3.5.3, `described here`_. .. _described here: http://nedbatchelder.com/code/coverage Quick start ----------- Getting started is easy: #. Install coverage.py from the `coverage page on the Python Package Index`_, or by using "pip install coverage". For a few more details, see :ref:`install`. #. Use ``coverage run`` to run your program and gather data: .. code-block:: console $ coverage run my_program.py arg1 arg2 blah blah ..your program's output.. blah blah #. Use ``coverage report`` to report on the results: .. code-block:: console $ coverage report -m Name Stmts Miss Cover Missing ------------------------------------------------------- my_program 20 4 80% 33-35, 39 my_other_module 56 6 89% 17-23 ------------------------------------------------------- TOTAL 76 10 87% #. For a nicer presentation, use ``coverage html`` to get annotated HTML listings detailing missed lines: .. code-block:: console $ coverage html .. ifconfig:: not prerelease Then visit htmlcov/index.html in your browser, to see a `report like this`_. .. ifconfig:: prerelease Then visit htmlcov/index.html in your browser, to see a `report like this one`_. .. _coverage page on the Python Package Index: http://pypi.python.org/pypi/coverage .. _report like this: /code/coverage/sample_html/index.html .. _report like this one: /code/coverage/sample_html_beta/index.html Using coverage.py ----------------- There are a few different ways to use coverage.py. The simplest is the :ref:`command line `, which lets you run your program and see the results. If you need more control over how your project is measured, you can use the :ref:`API `. Some test runners provide coverage integration to make it easy to use coverage while running tests. For example, `nose`_ has a `cover plug-in`_. You can fine-tune coverage's view of your code by directing it to ignore parts that you know aren't interesting. See :ref:`source` and :ref:`excluding` for details. .. _nose: http://somethingaboutorange.com/mrl/projects/nose .. _cover plug-in: https://nose.readthedocs.org/en/latest/plugins/cover.html .. _contact: Getting help ------------ If the :ref:`FAQ ` doesn't answer your question, you can discuss coverage.py or get help using it on the `Testing In Python`_ mailing list. .. _Testing In Python: http://lists.idyll.org/listinfo/testing-in-python Bug reports are gladly accepted at the `Bitbucket issue tracker`_. Bitbucket also hosts the `code repository`_. There is a `mirrored repo`_ on Github. .. _Bitbucket issue tracker: http://bitbucket.org/ned/coveragepy/issues .. _code repository: http://bitbucket.org/ned/coveragepy .. _mirrored repo: https://github.com/nedbat/coveragepy `I can be reached`_ in a number of ways. I'm happy to answer questions about using coverage.py. .. _I can be reached: http://nedbatchelder.com/site/aboutned.html More information ---------------- .. toctree:: :maxdepth: 1 install cmd config source excluding branch subprocess api contributing trouble faq changes .. How it works .. .coverage file format python-coverage-3.7.1+dfsg.1.orig/doc/install.rst0000644000175000017500000000450312252471244020643 0ustar barrybarry.. _install: ============ Installation ============ :history: 20100725T225600, new for 3.4. :history: 20100820T151500, updated for 3.4b1. :history: 20100906T134800, updated for 3.4b2. :history: 20110604T213400, updated for 3.5b1. :history: 20110629T082400, updated for 3.5. :history: 20110923T081900, updated for 3.5.1. :history: 20120429T162500, updated for 3.5.2b1. :history: 20120503T234000, updated for 3.5.2. :history: 20120929T093600, updated for 3.5.3. :history: 20121117T095000, Now setuptools is a pre-req. :history: 20121128T203000, updated for 3.6b1. :history: 20121223T180800, updated for 3.6b2. :history: 20121229T112400, updated for 3.6b3. :history: 20130105T174400, updated for 3.6. :history: 20131005T210600, updated for 3.7. :history: 20131212T213500, updated for 3.7.1. .. highlight:: console .. _coverage_pypi: http://pypi.python.org/pypi/coverage .. _setuptools: http://pypi.python.org/pypi/setuptools .. _Distribute: http://packages.python.org/distribute/ Installing coverage.py is done in the usual ways. You must have `setuptools`_ or `Distribute`_ installed already, and then you: #. Download the appropriate kit from the `coverage page on the Python Package Index`__. #. Run ``python setup.py install``. or, use:: $ pip install coverage or even:: $ easy_install coverage .. __: coverage_pypi_ Installing from source ---------------------- Coverage.py includes a C extension for speed. If you are installing from source, you may need to install the python-dev support files, for example with:: $ sudo apt-get install python-dev Installing on Windows --------------------- For Windows, kits are provided on the `PyPI page`__ for different versions of Python and different CPU architectures. These kits require that `setuptools`_ be installed as a pre-requisite, but otherwise are self-contained. They have the C extension pre-compiled so there's no need to worry about compilers. .. __: coverage_pypi_ Checking the installation ------------------------- If all went well, you should be able to open a command prompt, and see coverage installed properly:: $ coverage --version Coverage.py, version 3.7.1. http://nedbatchelder.com/code/coverage You can also invoke coverage as a module:: $ python -m coverage --version Coverage.py, version 3.7.1. http://nedbatchelder.com/code/coverage python-coverage-3.7.1+dfsg.1.orig/doc/branch.rst0000644000175000017500000001006412216144664020434 0ustar barrybarry.. _branch: =========================== Branch coverage measurement =========================== :history: 20091127T201300, new for version 3.2 :history: 20100725T211700, updated for 3.4. :history: 20110604T181700, updated for 3.5. :history: 20111214T181800, Fix a bug that Guido pointed out. .. highlight:: python :linenothreshold: 5 In addition to the usual statement coverage, Coverage.py also supports branch coverage measurement. Where a line in your program could jump to more than one next line, coverage.py tracks which of those destinations are actually visited, and flags lines that haven't visited all of their possible destinations. For example:: def my_partial_fn(x): # line 1 if x: # 2 y = 10 # 3 return y # 4 my_partial_fn(1) In this code, line 2 is an ``if`` statement which can go next to either line 3 or line 4. Statement coverage would show all lines of the function as executed. But the if was never evaluated as false, so line 2 never jumps to line 4. Branch coverage will flag this code as not fully covered because of the missing jump from line 2 to line 4. This is known as a partial branch. How to measure branch coverage ------------------------------ To measure branch coverage, run coverage.py with the ``--branch`` flag:: coverage run --branch myprog.py When you report on the results with ``coverage report`` or ``coverage html``, the percentage of branch possibilities taken will be included in the percentage covered total for each file. The coverage percentage for a file is the actual executions divided by the execution opportunities. Each line in the file is an execution opportunity, as is each branch destination. The HTML report gives information about which lines had missing branches. Lines that were missing some branches are shown in yellow, with an annotation at the far right showing branch destination line numbers that were not exercised. The XML report produced by ``coverage xml`` also includes branch information, including separate statement and branch coverage percentages. How it works ------------ When measuring branches, coverage.py collects pairs of line numbers, a source and destination for each transition from one line to another. Static analysis of the compiled bytecode provides a list of possible transitions. Comparing the measured to the possible indicates missing branches. The idea of tracking how lines follow each other was from `Titus Brown`__. Thanks, Titus! __ http://ivory.idyll.org/blog Excluding code -------------- If you have :ref:`excluded code `, a condtional will not be counted as a branch if one of its choices is excluded:: def only_one_choice(x): if x: blah1() blah2() else: # pragma: no cover # x is always true. blah3() Because the ``else`` clause is excluded, the ``if`` only has one possible next line, so it isn't considered a branch at all. Structurally partial branches ----------------------------- Sometimes branching constructs are used in unusual ways that don't actually branch. For example:: while True: if cond: break do_something() Here the while loop will never exit normally, so it doesn't take both of its "possible" branches. For some of these constructs, such as "while True:" and "if 0:", coverage.py understands what is going on. In these cases, the line will not be marked as a partial branch. But there are many ways in your own code to write intentionally partial branches, and you don't want coverage.py pestering you about them. You can tell coverage.py that you don't want them flagged by marking them with a pragma:: i = 0 while i < 999999999: # pragma: no branch if eventually(): break Here the while loop will never complete because the break will always be taken at some point. Coverage.py can't work that out on its own, but the "no branch" pragma indicates that the branch is known to be partial, and the line is not flagged. python-coverage-3.7.1+dfsg.1.orig/doc/trouble.rst0000644000175000017500000000742412222101352020641 0ustar barrybarry.. _trouble: ========================= Things that cause trouble ========================= :history: 20121231T085200, brand new docs. Coverage works well, and I want it to properly measure any Python program, but there are some situations it can't cope with. This page details some known problems, with possible courses of action, and links to coverage.py bug reports with more information. I would love to :ref:`hear from you ` if you have information about any of these problems, even just to explain to me why you want them to start working properly. If your problem isn't discussed here, you can of course search the `coverage.py bug tracker`_ directly to see if there is some mention of it. .. _coverage.py bug tracker: https://bitbucket.org/ned/coveragepy/issues?status=new&status=open Things that don't work ---------------------- There are a number of popular modules, packages, and libraries that prevent coverage.py from working properly: * `execv`_, or one of its variants. These end the current program and replace it with a new one. This doesn't save the collected coverage data, so your program that calls execv will not be fully measured. A patch for coverage.py is in `issue 43`_. * `multiprocessing`_ launches processes to provide parallelism. These processes don't get measured by coverage.py. Some possible fixes are discussed or linked to in `issue 117`_. * `gevent`_, which is based on `greenlet`_, and is similar to `eventlet`_. All of these manipulate the C stack, and therefore confuse coverage.py. `Issue 149`_ has some pointers to more information. * `thread`_, in the Python standard library, is the low-level threading interface. Threads created with this module will not be traced. Use the higher-level `threading`_ module instead. * `sys.settrace`_ is the Python feature that coverage.py uses to see what's happening in your program. If another part of your program is using sys.settrace, then it will conflict with coverage.py, and it won't be measured properly. .. _execv: http://docs.python.org/library/os#os.execl .. _multiprocessing: http://docs.python.org/library/multiprocessing.html .. _gevent: http://www.gevent.org/ .. _greenlet: http://greenlet.readthedocs.org/ .. _eventlet: http://eventlet.net/ .. _sys.settrace: http://docs.python.org/library/sys.html#sys.settrace .. _thread: http://docs.python.org/library/thread.html .. _threading: http://docs.python.org/library/threading.html .. _issue 43: https://bitbucket.org/ned/coveragepy/issue/43/coverage-measurement-fails-on-code .. _issue 117: https://bitbucket.org/ned/coveragepy/issue/117/enable-coverage-measurement-of-code-run-by .. _issue 149: https://bitbucket.org/ned/coveragepy/issue/149/coverage-gevent-looks-broken Things that require --timid --------------------------- Some packages interfere with coverage measurement, but you might be able to make it work by using the ``--timid`` command-line switch, or the ``[run] timid=True`` configuration option. * `DecoratorTools`_, or any package which uses it, notably `TurboGears`_. DecoratorTools fiddles with the trace function. You will need to use ``--timid``. .. _DecoratorTools: http://pypi.python.org/pypi/DecoratorTools .. _TurboGears: http://turbogears.org/ Really obscure things --------------------- * Python 2.5 had a bug (`1569356`_) that could make your program behave differently when being measured with coverage. This is diagnosed in `issue 51`_. .. _issue 51: http://bitbucket.org/ned/coveragepy/issue/51/turbogears-15-test-failing-with-coverage .. _1569356: http://bugs.python.org/issue1569356 Still having trouble? --------------------- If your problem isn't mentioned here, and isn't already reported in the `coverage.py bug tracker`_, please :ref:`get in touch with me `, we'll figure out a solution. python-coverage-3.7.1+dfsg.1.orig/PKG-INFO0000644000175000017500000000335712252501325016773 0ustar barrybarryMetadata-Version: 1.0 Name: coverage Version: 3.7.1 Summary: Code coverage measurement for Python Home-page: http://nedbatchelder.com/code/coverage Author: Ned Batchelder and others Author-email: ned@nedbatchelder.com License: BSD Description: Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. Coverage.py runs on Pythons 2.3 through 3.3, and PyPy 1.9. Documentation is at `nedbatchelder.com `_. Code repository and issue tracker are on `Bitbucket `_, with a mirrored repo on `Github `_. New in 3.7: ``--debug``, and 12 bugs closed. New in 3.6: ``--fail-under``, and >20 bugs closed. New in 3.5: Branch coverage exclusions, keyboard shortcuts in HTML report. New in 3.4: Better control over source to measure, and unexecuted files can be reported. New in 3.3: .coveragerc files. New in 3.2: Branch coverage! Keywords: code coverage testing Platform: UNKNOWN Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Testing Classifier: Development Status :: 5 - Production/Stable python-coverage-3.7.1+dfsg.1.orig/tests/0000755000175000017500000000000012252501325017030 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/test_parser.py0000644000175000017500000000724312202156243021743 0ustar barrybarry"""Tests for Coverage.py's code parsing.""" import textwrap from tests.coveragetest import CoverageTest from coverage.parser import CodeParser class ParserTest(CoverageTest): """Tests for Coverage.py's code parsing.""" run_in_temp_dir = False def parse_source(self, text): """Parse `text` as source, and return the `CodeParser` used.""" text = textwrap.dedent(text) cp = CodeParser(text=text, exclude="nocover") cp.parse_source() return cp def test_exit_counts(self): cp = self.parse_source("""\ # check some basic branch counting class Foo: def foo(self, a): if a: return 5 else: return 7 class Bar: pass """) self.assertEqual(cp.exit_counts(), { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 }) def test_try_except(self): cp = self.parse_source("""\ try: a = 2 except ValueError: a = 4 except ZeroDivideError: a = 6 except: a = 8 b = 9 """) self.assertEqual(cp.exit_counts(), { 1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 }) def test_excluded_classes(self): cp = self.parse_source("""\ class Foo: def __init__(self): pass if 0: # nocover class Bar: pass """) self.assertEqual(cp.exit_counts(), { 1:0, 2:1, 3:1 }) def test_missing_branch_to_excluded_code(self): cp = self.parse_source("""\ if fooey: a = 2 else: # nocover a = 4 b = 5 """) self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 5:1 }) cp = self.parse_source("""\ def foo(): if fooey: a = 3 else: a = 5 b = 6 """) self.assertEqual(cp.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 }) cp = self.parse_source("""\ def foo(): if fooey: a = 3 else: # nocover a = 5 b = 6 """) self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 3:1, 6:1 }) class ParserFileTest(CoverageTest): """Tests for Coverage.py's code parsing from files.""" def parse_file(self, filename): """Parse `text` as source, and return the `CodeParser` used.""" cp = CodeParser(filename=filename, exclude="nocover") cp.parse_source() return cp def test_line_endings(self): text = """\ # check some basic branch counting class Foo: def foo(self, a): if a: return 5 else: return 7 class Bar: pass """ counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 } name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r")) for fname, newline in name_endings: fname = fname + ".py" self.make_file(fname, text, newline=newline) cp = self.parse_file(fname) self.assertEqual(cp.exit_counts(), counts) def test_encoding(self): self.make_file("encoded.py", """\ coverage = "\xe7\xf6v\xear\xe3g\xe9" """) cp = self.parse_file("encoded.py") cp.exit_counts() python-coverage-3.7.1+dfsg.1.orig/tests/test_debug.py0000644000175000017500000000733012230737117021540 0ustar barrybarry"""Tests of coverage/debug.py""" import os import re import coverage from coverage.backward import StringIO from coverage.debug import info_formatter from tests.coveragetest import CoverageTest class InfoFormatterTest(CoverageTest): """Tests of misc.info_formatter.""" run_in_temp_dir = False def test_info_formatter(self): lines = list(info_formatter([ ('x', 'hello there'), ('very long label', ['one element']), ('regular', ['abc', 'def', 'ghi', 'jkl']), ('nothing', []), ])) self.assertEqual(lines, [ ' x: hello there', 'very long label: one element', ' regular: abc', ' def', ' ghi', ' jkl', ' nothing: -none-', ]) class DebugTraceTest(CoverageTest): """Tests of debug output.""" def f1_debug_output(self, debug): """Runs some code with `debug` option, returns the debug output.""" # Make code to run. self.make_file("f1.py", """\ def f1(x): return x+1 for i in range(5): f1(i) """) debug_out = StringIO() cov = coverage.coverage(debug=debug, debug_file=debug_out) self.start_import_stop(cov, "f1") out_lines = debug_out.getvalue().splitlines() return out_lines def test_debug_no_trace(self): out_lines = self.f1_debug_output([]) # We should have no output at all. self.assertFalse(out_lines) def test_debug_trace(self): out_lines = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'" self.assertIn("Tracing 'f1.py'", out_lines) # We should lines like "Not tracing 'collector.py'..." coverage_lines = lines_matching( out_lines, r"^Not tracing .*: is part of coverage.py$" ) self.assertTrue(coverage_lines) def test_debug_trace_pid(self): out_lines = self.f1_debug_output(["trace", "pid"]) # Now our lines are always prefixed with the process id. pid_prefix = "^pid %5d: " % os.getpid() pid_lines = lines_matching(out_lines, pid_prefix) self.assertEqual(pid_lines, out_lines) # We still have some tracing, and some not tracing. self.assertTrue(lines_matching(out_lines, pid_prefix + "Tracing ")) self.assertTrue(lines_matching(out_lines, pid_prefix + "Not tracing ")) def test_debug_config(self): out_lines = self.f1_debug_output(["config"]) labels = """ attempted_config_files branch config_files cover_pylib data_file debug exclude_list extra_css html_dir html_title ignore_errors include omit parallel partial_always_list partial_list paths precision show_missing source timid xml_output """.split() for label in labels: label_pat = r"^\s*%s: " % label self.assertEqual(len(lines_matching(out_lines, label_pat)), 1) def test_debug_sys(self): out_lines = self.f1_debug_output(["sys"]) labels = """ version coverage cover_dir pylib_dirs tracer config_files configs_read data_path python platform implementation executable cwd path environment command_line cover_match pylib_match """.split() for label in labels: label_pat = r"^\s*%s: " % label self.assertEqual(len(lines_matching(out_lines, label_pat)), 1) def lines_matching(lines, pat): """Gives the list of lines from `lines` that match `pat`.""" return [l for l in lines if re.search(pat, l)] python-coverage-3.7.1+dfsg.1.orig/tests/test_process.py0000644000175000017500000005425012233013371022123 0ustar barrybarry"""Tests for process behavior of coverage.py.""" import glob, os, sys, textwrap from nose.plugins.skip import SkipTest import coverage from tests.coveragetest import CoverageTest here = os.path.dirname(__file__) class ProcessTest(CoverageTest): """Tests of the per-process behavior of coverage.py.""" def number_of_data_files(self): """Return the number of coverage data files in this directory.""" num = 0 for f in os.listdir('.'): if f.startswith('.coverage.') or f == '.coverage': num += 1 return num def test_save_on_exit(self): self.make_file("mycode.py", """\ h = "Hello" w = "world" """) self.assert_doesnt_exist(".coverage") self.run_command("coverage -x mycode.py") self.assert_exists(".coverage") def test_environment(self): # Checks that we can import modules from the test directory at all! self.make_file("mycode.py", """\ import covmod1 import covmodzip1 a = 1 print ('done') """) self.assert_doesnt_exist(".coverage") out = self.run_command("coverage -x mycode.py") self.assert_exists(".coverage") self.assertEqual(out, 'done\n') def test_combine_parallel_data(self): self.make_file("b_or_c.py", """\ import sys a = 1 if sys.argv[1] == 'b': b = 1 else: c = 1 d = 1 print ('done') """) out = self.run_command("coverage -x -p b_or_c.py b") self.assertEqual(out, 'done\n') self.assert_doesnt_exist(".coverage") out = self.run_command("coverage -x -p b_or_c.py c") self.assertEqual(out, 'done\n') self.assert_doesnt_exist(".coverage") # After two -p runs, there should be two .coverage.machine.123 files. self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage -c") self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) # Read the coverage file and see that b_or_c.py has all 7 lines # executed. data = coverage.CoverageData() data.read_file(".coverage") self.assertEqual(data.summary()['b_or_c.py'], 7) def test_combine_parallel_data_in_two_steps(self): self.make_file("b_or_c.py", """\ import sys a = 1 if sys.argv[1] == 'b': b = 1 else: c = 1 d = 1 print ('done') """) out = self.run_command("coverage -x -p b_or_c.py b") self.assertEqual(out, 'done\n') self.assert_doesnt_exist(".coverage") self.assertEqual(self.number_of_data_files(), 1) # Combine the (one) parallel coverage data file into .coverage . self.run_command("coverage -c") self.assert_exists(".coverage") self.assertEqual(self.number_of_data_files(), 1) out = self.run_command("coverage -x -p b_or_c.py c") self.assertEqual(out, 'done\n') self.assert_exists(".coverage") self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage -c") self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) # Read the coverage file and see that b_or_c.py has all 7 lines # executed. data = coverage.CoverageData() data.read_file(".coverage") self.assertEqual(data.summary()['b_or_c.py'], 7) def test_combine_with_rc(self): self.make_file("b_or_c.py", """\ import sys a = 1 if sys.argv[1] == 'b': b = 1 else: c = 1 d = 1 print ('done') """) self.make_file(".coveragerc", """\ [run] parallel = true """) out = self.run_command("coverage run b_or_c.py b") self.assertEqual(out, 'done\n') self.assert_doesnt_exist(".coverage") out = self.run_command("coverage run b_or_c.py c") self.assertEqual(out, 'done\n') self.assert_doesnt_exist(".coverage") # After two runs, there should be two .coverage.machine.123 files. self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage combine") self.assert_exists(".coverage") self.assert_exists(".coveragerc") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) # Read the coverage file and see that b_or_c.py has all 7 lines # executed. data = coverage.CoverageData() data.read_file(".coverage") self.assertEqual(data.summary()['b_or_c.py'], 7) # Reporting should still work even with the .rc file out = self.run_command("coverage report") self.assertMultiLineEqual(out, textwrap.dedent("""\ Name Stmts Miss Cover ---------------------------- b_or_c 7 0 100% """)) def test_combine_with_aliases(self): self.make_file("d1/x.py", """\ a = 1 b = 2 print("%s %s" % (a, b)) """) self.make_file("d2/x.py", """\ # 1 # 2 # 3 c = 4 d = 5 print("%s %s" % (c, d)) """) self.make_file(".coveragerc", """\ [run] parallel = True [paths] source = src */d1 */d2 """) out = self.run_command("coverage run " + os.path.normpath("d1/x.py")) self.assertEqual(out, '1 2\n') out = self.run_command("coverage run " + os.path.normpath("d2/x.py")) self.assertEqual(out, '4 5\n') self.assertEqual(self.number_of_data_files(), 2) self.run_command("coverage combine") self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) # Read the coverage data file and see that the two different x.py # files have been combined together. data = coverage.CoverageData() data.read_file(".coverage") summary = data.summary(fullpath=True) self.assertEqual(len(summary), 1) actual = os.path.normcase(os.path.abspath(list(summary.keys())[0])) expected = os.path.normcase(os.path.abspath('src/x.py')) self.assertEqual(actual, expected) self.assertEqual(list(summary.values())[0], 6) def test_missing_source_file(self): # Check what happens if the source is missing when reporting happens. self.make_file("fleeting.py", """\ s = 'goodbye, cruel world!' """) self.run_command("coverage run fleeting.py") os.remove("fleeting.py") out = self.run_command("coverage html -d htmlcov") self.assertRegexpMatches(out, "No source for code: '.*fleeting.py'") self.assertNotIn("Traceback", out) # It happens that the code paths are different for *.py and other # files, so try again with no extension. self.make_file("fleeting", """\ s = 'goodbye, cruel world!' """) self.run_command("coverage run fleeting") os.remove("fleeting") status, out = self.run_command_status("coverage html -d htmlcov", 1) self.assertRegexpMatches(out, "No source for code: '.*fleeting'") self.assertNotIn("Traceback", out) self.assertEqual(status, 1) def test_running_missing_file(self): status, out = self.run_command_status("coverage run xyzzy.py", 1) self.assertRegexpMatches(out, "No file to run: .*xyzzy.py") self.assertNotIn("raceback", out) self.assertNotIn("rror", out) self.assertEqual(status, 1) def test_code_throws(self): self.make_file("throw.py", """\ def f1(): raise Exception("hey!") def f2(): f1() f2() """) # The important thing is for "coverage run" and "python" to report the # same traceback. status, out = self.run_command_status("coverage run throw.py", 1) out2 = self.run_command("python throw.py") if '__pypy__' in sys.builtin_module_names: # Pypy has an extra frame in the traceback for some reason lines2 = out2.splitlines() out2 = "".join([l+"\n" for l in lines2 if "toplevel" not in l]) self.assertMultiLineEqual(out, out2) # But also make sure that the output is what we expect. self.assertIn('File "throw.py", line 5, in f2', out) self.assertIn('raise Exception("hey!")', out) self.assertNotIn('coverage', out) self.assertEqual(status, 1) def test_code_exits(self): self.make_file("exit.py", """\ import sys def f1(): print("about to exit..") sys.exit(17) def f2(): f1() f2() """) # The important thing is for "coverage run" and "python" to have the # same output. No traceback. status, out = self.run_command_status("coverage run exit.py", 17) status2, out2 = self.run_command_status("python exit.py", 17) self.assertMultiLineEqual(out, out2) self.assertMultiLineEqual(out, "about to exit..\n") self.assertEqual(status, status2) self.assertEqual(status, 17) def test_code_exits_no_arg(self): self.make_file("exit_none.py", """\ import sys def f1(): print("about to exit quietly..") sys.exit() f1() """) status, out = self.run_command_status("coverage run exit_none.py", 0) status2, out2 = self.run_command_status("python exit_none.py", 0) self.assertMultiLineEqual(out, out2) self.assertMultiLineEqual(out, "about to exit quietly..\n") self.assertEqual(status, status2) self.assertEqual(status, 0) def test_coverage_run_is_like_python(self): tryfile = os.path.join(here, "try_execfile.py") self.make_file("run_me.py", open(tryfile).read()) out_cov = self.run_command("coverage run run_me.py") out_py = self.run_command("python run_me.py") self.assertMultiLineEqual(out_cov, out_py) if sys.version_info >= (2, 6): # Doesn't work in 2.5, and I don't care! For some reason, python -m # in 2.5 has __builtins__ as a dictionary instead of a module? def test_coverage_run_dashm_is_like_python_dashm(self): # These -m commands assume the coverage tree is on the path. out_cov = self.run_command("coverage run -m tests.try_execfile") out_py = self.run_command("python -m tests.try_execfile") self.assertMultiLineEqual(out_cov, out_py) def test_coverage_run_dashm_is_like_python_dashm_off_path(self): # https://bitbucket.org/ned/coveragepy/issue/242 tryfile = os.path.join(here, "try_execfile.py") self.make_file("sub/__init__.py", "") self.make_file("sub/run_me.py", open(tryfile).read()) out_cov = self.run_command("coverage run -m sub.run_me") out_py = self.run_command("python -m sub.run_me") self.assertMultiLineEqual(out_cov, out_py) if sys.version_info >= (2, 7): # Coverage isn't bug-for-bug compatible in the behavior of -m for # Pythons < 2.7 def test_coverage_run_dashm_is_like_python_dashm_with__main__207(self): # https://bitbucket.org/ned/coveragepy/issue/207 self.make_file("package/__init__.py", "print('init')") self.make_file("package/__main__.py", "print('main')") out_cov = self.run_command("coverage run -m package") out_py = self.run_command("python -m package") self.assertMultiLineEqual(out_cov, out_py) if hasattr(os, 'fork'): def test_fork(self): self.make_file("fork.py", """\ import os def child(): print('Child!') def main(): ret = os.fork() if ret == 0: child() else: os.waitpid(ret, 0) main() """) out = self.run_command("coverage run -p fork.py") self.assertEqual(out, 'Child!\n') self.assert_doesnt_exist(".coverage") # After running the forking program, there should be two # .coverage.machine.123 files. self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage -c") self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) # Read the coverage file and see that b_or_c.py has all 7 lines # executed. data = coverage.CoverageData() data.read_file(".coverage") self.assertEqual(data.summary()['fork.py'], 9) def test_warnings(self): self.make_file("hello.py", """\ import sys, os print("Hello") """) out = self.run_command("coverage run --source=sys,xyzzy,quux hello.py") self.assertIn("Hello\n", out) self.assertIn(textwrap.dedent("""\ Coverage.py warning: Module sys has no Python source. Coverage.py warning: Module xyzzy was never imported. Coverage.py warning: Module quux was never imported. Coverage.py warning: No data was collected. """), out) def test_warnings_during_reporting(self): # While fixing issue #224, the warnings were being printed far too # often. Make sure they're not any more. self.make_file("hello.py", """\ import sys, os, the_other print("Hello") """) self.make_file("the_other.py", """\ print("What?") """) self.make_file(".coveragerc", """\ [run] source = . xyzzy """) self.run_command("coverage run hello.py") out = self.run_command("coverage html") self.assertEqual(out.count("Module xyzzy was never imported."), 0) def test_warnings_if_never_run(self): out = self.run_command("coverage run i_dont_exist.py") self.assertIn("No file to run: 'i_dont_exist.py'", out) self.assertNotIn("warning", out) self.assertNotIn("Exception", out) out = self.run_command("coverage run -m no_such_module") self.assertTrue( ("No module named no_such_module" in out) or ("No module named 'no_such_module'" in out) ) self.assertNotIn("warning", out) self.assertNotIn("Exception", out) def test_warnings_trace_function_changed_with_threads(self): # https://bitbucket.org/ned/coveragepy/issue/164 self.make_file("bug164.py", """\ import threading import time class MyThread (threading.Thread): def run(self): print("Hello") thr = MyThread() thr.start() thr.join() """) out = self.run_command("coverage run --timid bug164.py") self.assertIn("Hello\n", out) self.assertNotIn("warning", out) def test_warning_trace_function_changed(self): self.make_file("settrace.py", """\ import sys print("Hello") sys.settrace(None) print("Goodbye") """) out = self.run_command("coverage run --timid settrace.py") self.assertIn("Hello\n", out) self.assertIn("Goodbye\n", out) if hasattr(sys, "gettrace"): self.assertIn("Trace function changed", out) if sys.version_info >= (3, 0): # This only works on 3.x for now. # It only works with the C tracer, c_tracer = os.getenv('COVERAGE_TEST_TRACER', 'c') == 'c' # and if we aren't measuring ourselves. metacov = os.getenv('COVERAGE_COVERAGE', '') != '' if c_tracer and not metacov: # pragma: not covered def test_fullcoverage(self): # fullcoverage is a trick to get stdlib modules measured from # the very beginning of the process. Here we import os and # then check how many lines are measured. self.make_file("getenv.py", """\ import os print("FOOEY == %s" % os.getenv("FOOEY")) """) fullcov = os.path.join( os.path.dirname(coverage.__file__), "fullcoverage" ) self.set_environ("FOOEY", "BOO") self.set_environ("PYTHONPATH", fullcov) out = self.run_command("python -m coverage run -L getenv.py") self.assertEqual(out, "FOOEY == BOO\n") data = coverage.CoverageData() data.read_file(".coverage") # The actual number of executed lines in os.py when it's # imported is 120 or so. Just running os.getenv executes # about 5. self.assertGreater(data.summary()['os.py'], 50) class AliasedCommandTest(CoverageTest): """Tests of the version-specific command aliases.""" run_in_temp_dir = False def test_major_version_works(self): # "coverage2" works on py2 cmd = "coverage%d" % sys.version_info[0] out = self.run_command(cmd) self.assertIn("Code coverage for Python", out) def test_wrong_alias_doesnt_work(self): # "coverage3" doesn't work on py2 badcmd = "coverage%d" % (5 - sys.version_info[0]) out = self.run_command(badcmd) self.assertNotIn("Code coverage for Python", out) def test_specific_alias_works(self): # "coverage-2.7" works on py2.7 cmd = "coverage-%d.%d" % sys.version_info[:2] out = self.run_command(cmd) self.assertIn("Code coverage for Python", out) class FailUnderTest(CoverageTest): """Tests of the --fail-under switch.""" def setUp(self): super(FailUnderTest, self).setUp() self.make_file("fifty.py", """\ # I have 50% coverage! a = 1 if a > 2: b = 3 c = 4 """) st, _ = self.run_command_status("coverage run fifty.py", 0) self.assertEqual(st, 0) def test_report(self): st, _ = self.run_command_status("coverage report --fail-under=50", 0) self.assertEqual(st, 0) st, _ = self.run_command_status("coverage report --fail-under=51", 2) self.assertEqual(st, 2) def test_html_report(self): st, _ = self.run_command_status("coverage html --fail-under=50", 0) self.assertEqual(st, 0) st, _ = self.run_command_status("coverage html --fail-under=51", 2) self.assertEqual(st, 2) def test_xml_report(self): st, _ = self.run_command_status("coverage xml --fail-under=50", 0) self.assertEqual(st, 0) st, _ = self.run_command_status("coverage xml --fail-under=51", 2) self.assertEqual(st, 2) class ProcessStartupTest(CoverageTest): """Test that we can measure coverage in subprocesses.""" def setUp(self): super(ProcessStartupTest, self).setUp() # Find a place to put a .pth file. pth_contents = "import coverage; coverage.process_startup()\n" for d in sys.path: # pragma: part covered g = glob.glob(os.path.join(d, "*.pth")) if g: pth_path = os.path.join(d, "subcover.pth") pth = open(pth_path, "w") try: try: pth.write(pth_contents) self.pth_path = pth_path break except (IOError, OSError): # pragma: not covered pass finally: pth.close() else: # pragma: not covered raise Exception("Couldn't find a place for the .pth file") def tearDown(self): super(ProcessStartupTest, self).tearDown() # Clean up the .pth file we made. os.remove(self.pth_path) def test_subprocess_with_pth_files(self): # pragma: not covered if os.environ.get('COVERAGE_COVERAGE', ''): raise SkipTest( "Can't test subprocess pth file suppport during metacoverage" ) # Main will run sub.py self.make_file("main.py", """\ import os, os.path, sys ex = os.path.basename(sys.executable) os.system(ex + " sub.py") """) # sub.py will write a few lines. self.make_file("sub.py", """\ f = open("out.txt", "w") f.write("Hello, world!\\n") f.close() """) self.make_file("coverage.ini", """\ [run] data_file = .mycovdata """) self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") import main # pylint: disable=F0401,W0612 self.assertEqual(open("out.txt").read(), "Hello, world!\n") # Read the data from .coverage self.assert_exists(".mycovdata") data = coverage.CoverageData() data.read_file(".mycovdata") self.assertEqual(data.summary()['sub.py'], 3) python-coverage-3.7.1+dfsg.1.orig/tests/js/0000755000175000017500000000000012252501325017444 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/js/tests.js0000644000175000017500000001176212202156243021153 0ustar barrybarry// Tests of coverage.py HTML report chunk navigation. /*global coverage, test, module, equals, jQuery, $ */ // Test helpers function selection_is(sel) { raw_selection_is(sel, true); } function raw_selection_is(sel, check_highlight) { var beg = sel[0], end = sel[1]; equals(coverage.sel_begin, beg); equals(coverage.sel_end, end); if (check_highlight) { equals(coverage.code_container().find(".highlight").length, end-beg); } } function build_fixture(spec) { var i, data; $("#fixture-template").tmpl().appendTo("#qunit-fixture"); for (i = 0; i < spec.length; i++) { data = {number: i+1, klass: spec.substr(i, 1)}; $("#lineno-template").tmpl(data).appendTo("#qunit-fixture .linenos"); $("#text-template").tmpl(data).appendTo("#qunit-fixture .text"); } coverage.pyfile_ready(jQuery); } // Tests // Zero-chunk tests module("Zero-chunk navigation", { setup: function () { build_fixture("wwww"); } }); test("set_sel defaults", function () { coverage.set_sel(2); equals(coverage.sel_begin, 2); equals(coverage.sel_end, 3); }); test("No first chunk to select", function () { coverage.to_first_chunk(); }); // One-chunk tests $.each([ ['rrrrr', [1,6]], ['r', [1,2]], ['wwrrrr', [3,7]], ['wwrrrrww', [3,7]], ['rrrrww', [1,5]] ], function (i, params) { // Each of these tests uses a fixture with one highlighted chunks. var id = params[0]; var c1 = params[1]; module("One-chunk navigation - " + id, { setup: function () { build_fixture(id); } }); test("First chunk", function () { coverage.to_first_chunk(); selection_is(c1); }); test("Next chunk is first chunk", function () { coverage.to_next_chunk(); selection_is(c1); }); test("There is no next chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); selection_is(c1); }); test("There is no prev chunk", function () { coverage.to_first_chunk(); coverage.to_prev_chunk(); selection_is(c1); }); }); // Two-chunk tests $.each([ ['rrwwrrrr', [1,3], [5,9]], ['rb', [1,2], [2,3]], ['rbbbbbbbbbb', [1,2], [2,12]], ['rrrrrrrrrrb', [1,11], [11,12]], ['wrrwrrrrw', [2,4], [5,9]], ['rrrbbb', [1,4], [4,7]] ], function (i, params) { // Each of these tests uses a fixture with two highlighted chunks. var id = params[0]; var c1 = params[1]; var c2 = params[2]; module("Two-chunk navigation - " + id, { setup: function () { build_fixture(id); } }); test("First chunk", function () { coverage.to_first_chunk(); selection_is(c1); }); test("Next chunk is first chunk", function () { coverage.to_next_chunk(); selection_is(c1); }); test("Move to next chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); selection_is(c2); }); test("Move to first chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); coverage.to_first_chunk(); selection_is(c1); }); test("Move to previous chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); coverage.to_prev_chunk(); selection_is(c1); }); test("Next doesn't move after last chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); coverage.to_next_chunk(); selection_is(c2); }); test("Prev doesn't move before first chunk", function () { coverage.to_first_chunk(); coverage.to_next_chunk(); coverage.to_prev_chunk(); coverage.to_prev_chunk(); selection_is(c1); }); }); module("Miscellaneous"); test("Jump from a line selected", function () { build_fixture("rrwwrr"); coverage.set_sel(3); coverage.to_next_chunk(); selection_is([5,7]); }); // Tests of select_line_or_chunk. $.each([ // The data for each test: a spec for the fixture to build, and an array // of the selection that will be selected by select_line_or_chunk for // each line in the fixture. ['rrwwrr', [[1,3], [1,3], [3,4], [4,5], [5,7], [5,7]]], ['rb', [[1,2], [2,3]]], ['r', [[1,2]]], ['w', [[1,2]]], ['www', [[1,2], [2,3], [3,4]]], ['wwwrrr', [[1,2], [2,3], [3,4], [4,7], [4,7], [4,7]]], ['rrrwww', [[1,4], [1,4], [1,4], [4,5], [5,6], [6,7]]], ['rrrbbb', [[1,4], [1,4], [1,4], [4,7], [4,7], [4,7]]] ], function (i, params) { // Each of these tests uses a fixture with two highlighted chunks. var id = params[0]; var sels = params[1]; module("Select line or chunk - " + id, { setup: function () { build_fixture(id); } }); $.each(sels, function (i, sel) { i++; test("Select line " + i, function () { coverage.select_line_or_chunk(i); raw_selection_is(sel); }); }); }); python-coverage-3.7.1+dfsg.1.orig/tests/js/index.html0000644000175000017500000000346512224242644021456 0ustar barrybarry Coverage.py Javascript Test Suite

Coverage.py Javascript Test Suite

    python-coverage-3.7.1+dfsg.1.orig/tests/test_data.py0000644000175000017500000001125112233013371021350 0ustar barrybarry"""Tests for coverage.data""" from coverage.backward import pickle from coverage.data import CoverageData from coverage.files import PathAliases from tests.coveragetest import CoverageTest DATA_1 = { 'a.py': {1:None, 2:None}, 'b.py': {3:None} } SUMMARY_1 = { 'a.py':2, 'b.py':1 } MEASURED_FILES_1 = [ 'a.py', 'b.py' ] A_PY_LINES_1 = [1,2] B_PY_LINES_1 = [3] DATA_2 = { 'a.py': {1:None, 5:None}, 'c.py': {17:None} } SUMMARY_1_2 = { 'a.py':3, 'b.py':1, 'c.py':1 } MEASURED_FILES_1_2 = [ 'a.py', 'b.py', 'c.py' ] ARC_DATA_3 = { 'x.py': {(1,2):None, (2,3):None}, 'y.py': {(17,23):None} } X_PY_ARCS_3 = [(1,2), (2,3)] Y_PY_ARCS_3 = [(17,23)] class DataTest(CoverageTest): """Test cases for coverage.data.""" run_in_temp_dir = False def assert_summary(self, covdata, summary, fullpath=False): """Check that the summary of `covdata` is `summary`.""" self.assertEqual(covdata.summary(fullpath), summary) def assert_measured_files(self, covdata, measured): """Check that `covdata`'s measured files are `measured`.""" self.assertSameElements(covdata.measured_files(), measured) def test_reading_empty(self): covdata = CoverageData() covdata.read() self.assert_summary(covdata, {}) def test_adding_data(self): covdata = CoverageData() covdata.add_line_data(DATA_1) self.assert_summary(covdata, SUMMARY_1) self.assert_measured_files(covdata, MEASURED_FILES_1) def test_touch_file(self): covdata = CoverageData() covdata.add_line_data(DATA_1) covdata.touch_file('x.py') self.assert_measured_files(covdata, MEASURED_FILES_1 + ['x.py']) def test_writing_and_reading(self): covdata1 = CoverageData() covdata1.add_line_data(DATA_1) covdata1.write() covdata2 = CoverageData() covdata2.read() self.assert_summary(covdata2, SUMMARY_1) def test_combining(self): covdata1 = CoverageData() covdata1.add_line_data(DATA_1) covdata1.write(suffix='1') covdata2 = CoverageData() covdata2.add_line_data(DATA_2) covdata2.write(suffix='2') covdata3 = CoverageData() covdata3.combine_parallel_data() self.assert_summary(covdata3, SUMMARY_1_2) self.assert_measured_files(covdata3, MEASURED_FILES_1_2) def test_erasing(self): covdata1 = CoverageData() covdata1.add_line_data(DATA_1) covdata1.write() covdata1.erase() self.assert_summary(covdata1, {}) covdata2 = CoverageData() covdata2.read() self.assert_summary(covdata2, {}) def test_file_format(self): # Write with CoverageData, then read the pickle explicitly. covdata = CoverageData() covdata.add_line_data(DATA_1) covdata.write() fdata = open(".coverage", 'rb') try: data = pickle.load(fdata) finally: fdata.close() lines = data['lines'] self.assertSameElements(lines.keys(), MEASURED_FILES_1) self.assertSameElements(lines['a.py'], A_PY_LINES_1) self.assertSameElements(lines['b.py'], B_PY_LINES_1) # If not measuring branches, there's no arcs entry. self.assertEqual(data.get('arcs', 'not there'), 'not there') def test_file_format_with_arcs(self): # Write with CoverageData, then read the pickle explicitly. covdata = CoverageData() covdata.add_arc_data(ARC_DATA_3) covdata.write() fdata = open(".coverage", 'rb') try: data = pickle.load(fdata) finally: fdata.close() self.assertSameElements(data['lines'].keys(), []) arcs = data['arcs'] self.assertSameElements(arcs['x.py'], X_PY_ARCS_3) self.assertSameElements(arcs['y.py'], Y_PY_ARCS_3) def test_combining_with_aliases(self): covdata1 = CoverageData() covdata1.add_line_data({ '/home/ned/proj/src/a.py': {1:None, 2:None}, '/home/ned/proj/src/sub/b.py': {3:None}, }) covdata1.write(suffix='1') covdata2 = CoverageData() covdata2.add_line_data({ r'c:\ned\test\a.py': {4:None, 5:None}, r'c:\ned\test\sub\b.py': {6:None}, }) covdata2.write(suffix='2') covdata3 = CoverageData() aliases = PathAliases() aliases.add("/home/ned/proj/src/", "./") aliases.add(r"c:\ned\test", "./") covdata3.combine_parallel_data(aliases=aliases) self.assert_summary( covdata3, { './a.py':4, './sub/b.py':2 }, fullpath=True ) self.assert_measured_files(covdata3, [ './a.py', './sub/b.py' ]) python-coverage-3.7.1+dfsg.1.orig/tests/test_files.py0000644000175000017500000001724112233013371021546 0ustar barrybarry"""Tests for files.py""" import os, os.path from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher from coverage.files import PathAliases, find_python_files, abs_file from coverage.backward import set # pylint: disable=W0622 from coverage.misc import CoverageException from tests.coveragetest import CoverageTest class FileLocatorTest(CoverageTest): """Tests of `FileLocator`.""" def abs_path(self, p): """Return the absolute path for `p`.""" return os.path.join(os.getcwd(), os.path.normpath(p)) def test_simple(self): self.make_file("hello.py") fl = FileLocator() self.assertEqual(fl.relative_filename("hello.py"), "hello.py") a = self.abs_path("hello.py") self.assertNotEqual(a, "hello.py") self.assertEqual(fl.relative_filename(a), "hello.py") def test_peer_directories(self): self.make_file("sub/proj1/file1.py") self.make_file("sub/proj2/file2.py") a1 = self.abs_path("sub/proj1/file1.py") a2 = self.abs_path("sub/proj2/file2.py") d = os.path.normpath("sub/proj1") os.chdir(d) fl = FileLocator() self.assertEqual(fl.relative_filename(a1), "file1.py") self.assertEqual(fl.relative_filename(a2), a2) def test_filepath_contains_absolute_prefix_twice(self): # https://bitbucket.org/ned/coveragepy/issue/194 # Build a path that has two pieces matching the absolute path prefix. # Technically, this test doesn't do that on Windows, but drive # letters make that impractical to acheive. fl = FileLocator() d = abs_file(os.curdir) trick = os.path.splitdrive(d)[1].lstrip(os.path.sep) rel = os.path.join('sub', trick, 'file1.py') self.assertEqual(fl.relative_filename(abs_file(rel)), rel) class MatcherTest(CoverageTest): """Tests of file matchers.""" def test_tree_matcher(self): file1 = self.make_file("sub/file1.py") file2 = self.make_file("sub/file2.c") file3 = self.make_file("sub2/file3.h") file4 = self.make_file("sub3/file4.py") file5 = self.make_file("sub3/file5.c") fl = FileLocator() trees = [ fl.canonical_filename("sub"), fl.canonical_filename(file4), ] tm = TreeMatcher(trees) self.assertTrue(tm.match(fl.canonical_filename(file1))) self.assertTrue(tm.match(fl.canonical_filename(file2))) self.assertFalse(tm.match(fl.canonical_filename(file3))) self.assertTrue(tm.match(fl.canonical_filename(file4))) self.assertFalse(tm.match(fl.canonical_filename(file5))) self.assertEqual(tm.info(), trees) def test_fnmatch_matcher(self): file1 = self.make_file("sub/file1.py") file2 = self.make_file("sub/file2.c") file3 = self.make_file("sub2/file3.h") file4 = self.make_file("sub3/file4.py") file5 = self.make_file("sub3/file5.c") fl = FileLocator() fnm = FnmatchMatcher(["*.py", "*/sub2/*"]) self.assertTrue(fnm.match(fl.canonical_filename(file1))) self.assertFalse(fnm.match(fl.canonical_filename(file2))) self.assertTrue(fnm.match(fl.canonical_filename(file3))) self.assertTrue(fnm.match(fl.canonical_filename(file4))) self.assertFalse(fnm.match(fl.canonical_filename(file5))) self.assertEqual(fnm.info(), ["*.py", "*/sub2/*"]) class PathAliasesTest(CoverageTest): """Tests for coverage/files.py:PathAliases""" run_in_temp_dir = False def test_noop(self): aliases = PathAliases() self.assertEqual(aliases.map('/ned/home/a.py'), '/ned/home/a.py') def test_nomatch(self): aliases = PathAliases() aliases.add('/home/*/src', './mysrc') self.assertEqual(aliases.map('/home/foo/a.py'), '/home/foo/a.py') def test_wildcard(self): aliases = PathAliases() aliases.add('/ned/home/*/src', './mysrc') self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') aliases = PathAliases() aliases.add('/ned/home/*/src/', './mysrc') self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') def test_no_accidental_match(self): aliases = PathAliases() aliases.add('/home/*/src', './mysrc') self.assertEqual(aliases.map('/home/foo/srcetc'), '/home/foo/srcetc') def test_multiple_patterns(self): aliases = PathAliases() aliases.add('/home/*/src', './mysrc') aliases.add('/lib/*/libsrc', './mylib') self.assertEqual(aliases.map('/home/foo/src/a.py'), './mysrc/a.py') self.assertEqual(aliases.map('/lib/foo/libsrc/a.py'), './mylib/a.py') def test_cant_have_wildcard_at_end(self): aliases = PathAliases() self.assertRaisesRegexp( CoverageException, "Pattern must not end with wildcards.", aliases.add, "/ned/home/*", "fooey" ) self.assertRaisesRegexp( CoverageException, "Pattern must not end with wildcards.", aliases.add, "/ned/home/*/", "fooey" ) self.assertRaisesRegexp( CoverageException, "Pattern must not end with wildcards.", aliases.add, "/ned/home/*/*/", "fooey" ) def test_no_accidental_munging(self): aliases = PathAliases() aliases.add(r'c:\Zoo\boo', 'src/') aliases.add('/home/ned$', 'src/') self.assertEqual(aliases.map(r'c:\Zoo\boo\foo.py'), 'src/foo.py') self.assertEqual(aliases.map(r'/home/ned$/foo.py'), 'src/foo.py') def test_paths_are_os_corrected(self): aliases = PathAliases() aliases.add('/home/ned/*/src', './mysrc') aliases.add(r'c:\ned\src', './mysrc') mapped = aliases.map(r'C:\Ned\src\sub\a.py') self.assertEqual(mapped, './mysrc/sub/a.py') aliases = PathAliases() aliases.add('/home/ned/*/src', r'.\mysrc') aliases.add(r'c:\ned\src', r'.\mysrc') mapped = aliases.map(r'/home/ned/foo/src/sub/a.py') self.assertEqual(mapped, r'.\mysrc\sub\a.py') def test_leading_wildcard(self): aliases = PathAliases() aliases.add('*/d1', './mysrc1') aliases.add('*/d2', './mysrc2') self.assertEqual(aliases.map('/foo/bar/d1/x.py'), './mysrc1/x.py') self.assertEqual(aliases.map('/foo/bar/d2/y.py'), './mysrc2/y.py') class RelativePathAliasesTest(CoverageTest): """Tests for coverage/files.py:PathAliases, with relative files.""" run_in_temp_dir = False def test_dot(self): for d in ('.', '..', '../other', '~'): aliases = PathAliases() aliases.add(d, '/the/source') the_file = os.path.join(d, 'a.py') the_file = os.path.expanduser(the_file) the_file = os.path.abspath(the_file) assert '~' not in the_file # to be sure the test is pure. self.assertEqual(aliases.map(the_file), '/the/source/a.py') class FindPythonFilesTest(CoverageTest): """Tests of `find_python_files`.""" def test_find_python_files(self): self.make_file("sub/a.py") self.make_file("sub/b.py") self.make_file("sub/x.c") # nope: not .py self.make_file("sub/ssub/__init__.py") self.make_file("sub/ssub/s.py") self.make_file("sub/ssub/~s.py") # nope: editor effluvia self.make_file("sub/lab/exp.py") # nope: no __init__.py self.make_file("sub/windows.pyw") py_files = set(find_python_files("sub")) self.assert_same_files(py_files, [ "sub/a.py", "sub/b.py", "sub/ssub/__init__.py", "sub/ssub/s.py", "sub/windows.pyw", ]) python-coverage-3.7.1+dfsg.1.orig/tests/test_farm.py0000644000175000017500000003066112233013371021372 0ustar barrybarry"""Run tests in the farm subdirectory. Designed for nose.""" import difflib, filecmp, fnmatch, glob, os, re, shutil, sys from nose.plugins.skip import SkipTest from tests.backtest import run_command, execfile # pylint: disable=W0622 from coverage.control import _TEST_NAME_FILE def test_farm(clean_only=False): """A test-generating function for nose to find and run.""" for fname in glob.glob("tests/farm/*/*.py"): case = FarmTestCase(fname, clean_only) yield (case,) class FarmTestCase(object): """A test case from the farm tree. Tests are short Python script files, often called run.py: copy("src", "out") run(''' coverage -x white.py coverage -a white.py ''', rundir="out") compare("out", "gold", "*,cover") clean("out") Verbs (copy, run, compare, clean) are methods in this class. FarmTestCase has options to allow various uses of the test cases (normal execution, cleaning-only, or run and leave the results for debugging). """ def __init__(self, runpy, clean_only=False, dont_clean=False): """Create a test case from a run.py file. `clean_only` means that only the clean() action is executed. `dont_clean` means that the clean() action is not executed. """ self.description = runpy self.dir, self.runpy = os.path.split(runpy) self.clean_only = clean_only self.dont_clean = dont_clean def cd(self, newdir): """Change the current directory, and return the old one.""" cwd = os.getcwd() os.chdir(newdir) return cwd def addtopath(self, directory): """Add `directory` to the path, and return the old path.""" oldpath = sys.path[:] if directory is not None: sys.path.insert(0, directory) return oldpath def restorepath(self, path): """Restore the system path to `path`.""" sys.path = path def __call__(self): """Execute the test from the run.py file. """ if _TEST_NAME_FILE: f = open(_TEST_NAME_FILE, "w") f.write(self.description.replace("/", "_")) f.close() cwd = self.cd(self.dir) # Prepare a dictionary of globals for the run.py files to use. fns = """ copy run runfunc compare contains doesnt_contain clean skip """.split() if self.clean_only: glo = dict([(fn, self.noop) for fn in fns]) glo['clean'] = self.clean else: glo = dict([(fn, getattr(self, fn)) for fn in fns]) if self.dont_clean: # pragma: not covered glo['clean'] = self.noop old_mods = dict(sys.modules) try: execfile(self.runpy, glo) finally: self.cd(cwd) # Remove any new modules imported during the test run. This lets us # import the same source files for more than one test. to_del = [m for m in sys.modules if m not in old_mods] for m in to_del: del sys.modules[m] def run_fully(self): # pragma: not covered """Run as a full test case, with setUp and tearDown.""" self.setUp() try: self() finally: self.tearDown() def fnmatch_list(self, files, file_pattern): """Filter the list of `files` to only those that match `file_pattern`. If `file_pattern` is None, then return the entire list of files. Returns a list of the filtered files. """ if file_pattern: files = [f for f in files if fnmatch.fnmatch(f, file_pattern)] return files def setUp(self): """Test set up, run by nose before __call__.""" # Modules should be importable from the current directory. self.old_syspath = sys.path[:] sys.path.insert(0, '') def tearDown(self): """Test tear down, run by nose after __call__.""" # Make sure no matter what, the test is cleaned up. if not self.dont_clean: # pragma: part covered self.clean_only = True self() # Restore the original sys.path sys.path = self.old_syspath # Functions usable inside farm run.py files def noop(self, *args, **kwargs): """A no-op function to stub out run, copy, etc, when only cleaning.""" pass def copy(self, src, dst): """Copy a directory.""" if os.path.exists(dst): shutil.rmtree(dst) shutil.copytree(src, dst) def run(self, cmds, rundir="src", outfile=None): """Run a list of commands. `cmds` is a string, commands separated by newlines. `rundir` is the directory in which to run the commands. `outfile` is a filename to redirect stdout to. """ cwd = self.cd(rundir) if outfile: fout = open(outfile, "a+") try: for cmd in cmds.split("\n"): cmd = cmd.strip() if not cmd: continue retcode, output = run_command(cmd) print(output.rstrip()) if outfile: fout.write(output) if retcode: raise Exception("command exited abnormally") finally: if outfile: fout.close() self.cd(cwd) def runfunc(self, fn, rundir="src", addtopath=None): """Run a function. `fn` is a callable. `rundir` is the directory in which to run the function. """ cwd = self.cd(rundir) oldpath = self.addtopath(addtopath) try: fn() finally: self.cd(cwd) self.restorepath(oldpath) def compare(self, dir1, dir2, file_pattern=None, size_within=0, left_extra=False, right_extra=False, scrubs=None ): """Compare files matching `file_pattern` in `dir1` and `dir2`. `dir2` is interpreted as a prefix, with Python version numbers appended to find the actual directory to compare with. "foo" will compare against "foo_v241", "foo_v24", "foo_v2", or "foo", depending on which directory is found first. `size_within` is a percentage delta for the file sizes. If non-zero, then the file contents are not compared (since they are expected to often be different), but the file sizes must be within this amount. For example, size_within=10 means that the two files' sizes must be within 10 percent of each other to compare equal. `left_extra` true means the left directory can have extra files in it without triggering an assertion. `right_extra` means the right directory can. `scrubs` is a list of pairs, regex find and replace patterns to use to scrub the files of unimportant differences. An assertion will be raised if the directories fail one of their matches. """ # Search for a dir2 with a version suffix. version_suff = ''.join(map(str, sys.version_info[:3])) while version_suff: trydir = dir2 + '_v' + version_suff if os.path.exists(trydir): dir2 = trydir break version_suff = version_suff[:-1] assert os.path.exists(dir1), "Left directory missing: %s" % dir1 assert os.path.exists(dir2), "Right directory missing: %s" % dir2 dc = filecmp.dircmp(dir1, dir2) diff_files = self.fnmatch_list(dc.diff_files, file_pattern) left_only = self.fnmatch_list(dc.left_only, file_pattern) right_only = self.fnmatch_list(dc.right_only, file_pattern) if size_within: # The files were already compared, use the diff_files list as a # guide for size comparison. wrong_size = [] for f in diff_files: left = open(os.path.join(dir1, f), "rb").read() right = open(os.path.join(dir2, f), "rb").read() size_l, size_r = len(left), len(right) big, little = max(size_l, size_r), min(size_l, size_r) if (big - little) / float(little) > size_within/100.0: # print "%d %d" % (big, little) # print "Left: ---\n%s\n-----\n%s" % (left, right) wrong_size.append(f) assert not wrong_size, ( "File sizes differ between %s and %s: %s" % ( dir1, dir2, wrong_size )) else: # filecmp only compares in binary mode, but we want text mode. So # look through the list of different files, and compare them # ourselves. text_diff = [] for f in diff_files: left = open(os.path.join(dir1, f), "rU").readlines() right = open(os.path.join(dir2, f), "rU").readlines() if scrubs: left = self._scrub(left, scrubs) right = self._scrub(right, scrubs) if left != right: text_diff.append(f) print("".join(list(difflib.Differ().compare(left, right)))) assert not text_diff, "Files differ: %s" % text_diff if not left_extra: assert not left_only, "Files in %s only: %s" % (dir1, left_only) if not right_extra: assert not right_only, "Files in %s only: %s" % (dir2, right_only) def _scrub(self, strlist, scrubs): """Scrub uninteresting data from the strings in `strlist`. `scrubs is a list of (find, replace) pairs of regexes that are used on each string in `strlist`. A list of scrubbed strings is returned. """ scrubbed = [] for s in strlist: for rgx_find, rgx_replace in scrubs: s = re.sub(rgx_find, rgx_replace, s) scrubbed.append(s) return scrubbed def contains(self, filename, *strlist): """Check that the file contains all of a list of strings. An assert will be raised if one of the arguments in `strlist` is missing in `filename`. """ text = open(filename, "r").read() for s in strlist: assert s in text, "Missing content in %s: %r" % (filename, s) def doesnt_contain(self, filename, *strlist): """Check that the file contains none of a list of strings. An assert will be raised if any of the strings in strlist appears in `filename`. """ text = open(filename, "r").read() for s in strlist: assert s not in text, "Forbidden content in %s: %r" % (filename, s) def clean(self, cleandir): """Clean `cleandir` by removing it and all its children completely.""" # rmtree gives mysterious failures on Win7, so retry a "few" times. # I've seen it take over 100 tries, so, 1000! This is probably the # most unpleasant hack I've written in a long time... tries = 1000 while tries: # pragma: part covered if os.path.exists(cleandir): try: shutil.rmtree(cleandir) except OSError: # pragma: not covered if tries == 1: raise else: tries -= 1 continue break def skip(self, msg=None): """Skip the current test.""" raise SkipTest(msg) def main(): # pragma: not covered """Command-line access to test_farm. Commands: run testcase - Run a single test case. out testcase - Run a test case, but don't clean up, to see the output. clean - Clean all the output for all tests. """ op = 'help' try: op = sys.argv[1] except IndexError: pass if op == 'run': # Run the test for real. case = FarmTestCase(sys.argv[2]) case.run_fully() elif op == 'out': # Run the test, but don't clean up, so we can examine the output. case = FarmTestCase(sys.argv[2], dont_clean=True) case.run_fully() elif op == 'clean': # Run all the tests, but just clean. for test in test_farm(clean_only=True): test[0].run_fully() else: print(main.__doc__) # So that we can run just one farm run.py at a time. if __name__ == '__main__': main() python-coverage-3.7.1+dfsg.1.orig/tests/covmodzip1.py0000644000175000017500000000007612202156242021477 0ustar barrybarry"""covmodzip.py: for putting into a zip file.""" j = 1 j += 1 python-coverage-3.7.1+dfsg.1.orig/tests/moremodules/0000755000175000017500000000000012252501325021363 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/0000755000175000017500000000000012252501325023367 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/otherb.py0000644000175000017500000000001412202156242025216 0ustar barrybarryq = 3 r = 4 python-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/sub/0000755000175000017500000000000012252501325024160 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/sub/osa.py0000644000175000017500000000001412202156242025306 0ustar barrybarrys = 5 t = 6 python-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/sub/__init__.py0000644000175000017500000000000012202156242026256 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/sub/osb.py0000644000175000017500000000001412202156242025307 0ustar barrybarryu = 7 v = 8 python-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/othera.py0000644000175000017500000000001412202156243025216 0ustar barrybarryo = 1 p = 2 python-coverage-3.7.1+dfsg.1.orig/tests/moremodules/othermods/__init__.py0000644000175000017500000000000012202156243025466 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/test_misc.py0000644000175000017500000000506112221603302021370 0ustar barrybarry"""Tests of miscellaneous stuff.""" import sys from coverage.misc import Hasher, file_be_gone from coverage import __version__, __url__ from tests.coveragetest import CoverageTest class HasherTest(CoverageTest): """Test our wrapper of md5 hashing.""" run_in_temp_dir = False def test_string_hashing(self): h1 = Hasher() h1.update("Hello, world!") h2 = Hasher() h2.update("Goodbye!") h3 = Hasher() h3.update("Hello, world!") self.assertNotEqual(h1.digest(), h2.digest()) self.assertEqual(h1.digest(), h3.digest()) def test_dict_hashing(self): h1 = Hasher() h1.update({'a': 17, 'b': 23}) h2 = Hasher() h2.update({'b': 23, 'a': 17}) self.assertEqual(h1.digest(), h2.digest()) class RemoveFileTest(CoverageTest): """Tests of misc.file_be_gone.""" def test_remove_nonexistent_file(self): # it's ok to try to remove a file that doesn't exist. file_be_gone("not_here.txt") def test_remove_actual_file(self): # it really does remove a file that does exist. self.make_file("here.txt", "We are here, we are here, we are here!") file_be_gone("here.txt") self.assert_doesnt_exist("here.txt") def test_actual_errors(self): # Errors can still happen. # ". is a directory" on Unix, or "Access denied" on Windows self.assertRaises(OSError, file_be_gone, ".") class SetupPyTest(CoverageTest): """Tests of setup.py""" run_in_temp_dir = False def test_metadata(self): status, output = self.run_command_status( "python setup.py --description --version --url --author" ) self.assertEqual(status, 0) out = output.splitlines() self.assertIn("measurement", out[0]) self.assertEqual(out[1], __version__) self.assertEqual(out[2], __url__) self.assertIn("Ned Batchelder", out[3]) def test_more_metadata(self): # Let's be sure we pick up our own setup.py # CoverageTest.tearDown restores the original sys.path. sys.path.insert(0, '') from setup import setup_args classifiers = setup_args['classifiers'] self.assertGreater(len(classifiers), 7) self.assertTrue(classifiers[-1].startswith("Development Status ::")) long_description = setup_args['long_description'].splitlines() self.assertGreater(len(long_description), 7) self.assertNotEqual(long_description[0].strip(), "") self.assertNotEqual(long_description[-1].strip(), "") python-coverage-3.7.1+dfsg.1.orig/tests/test_api.py0000644000175000017500000005035112230737046021225 0ustar barrybarry"""Tests for Coverage's api.""" import fnmatch, os, re, sys, textwrap import coverage from coverage.backward import StringIO from tests.coveragetest import CoverageTest class SingletonApiTest(CoverageTest): """Tests of the old-fashioned singleton API.""" def setUp(self): super(SingletonApiTest, self).setUp() # These tests use the singleton module interface. Prevent it from # writing .coverage files at exit. coverage.use_cache(0) def do_report_work(self, modname): """Create a module named `modname`, then measure it.""" coverage.erase() self.make_file(modname+".py", """\ a = 1 b = 2 if b == 3: c = 4 d = 5 e = 6 f = 7 """) # Import the python file, executing it. self.start_import_stop(coverage, modname) def test_simple(self): coverage.erase() self.make_file("mycode.py", """\ a = 1 b = 2 if b == 3: c = 4 d = 5 """) # Import the python file, executing it. self.start_import_stop(coverage, "mycode") _, statements, missing, missingtext = coverage.analysis("mycode.py") self.assertEqual(statements, [1,2,3,4,5]) self.assertEqual(missing, [4]) self.assertEqual(missingtext, "4") def test_report(self): self.do_report_work("mycode2") coverage.report(["mycode2.py"]) self.assertEqual(self.stdout(), textwrap.dedent("""\ Name Stmts Miss Cover Missing --------------------------------------- mycode2 7 3 57% 4-6 """)) def test_report_file(self): # The file= argument of coverage.report makes the report go there. self.do_report_work("mycode3") fout = StringIO() coverage.report(["mycode3.py"], file=fout) self.assertEqual(self.stdout(), "") self.assertEqual(fout.getvalue(), textwrap.dedent("""\ Name Stmts Miss Cover Missing --------------------------------------- mycode3 7 3 57% 4-6 """)) def test_report_default(self): # Calling report() with no morfs will report on whatever was executed. self.do_report_work("mycode4") coverage.report() rpt = re.sub(r"\s+", " ", self.stdout()) self.assertIn("mycode4 7 3 57% 4-6", rpt) class ApiTest(CoverageTest): """Api-oriented tests for Coverage.""" def clean_files(self, files, pats): """Remove names matching `pats` from `files`, a list of filenames.""" good = [] for f in files: for pat in pats: if fnmatch.fnmatch(f, pat): break else: good.append(f) return good def assertFiles(self, files): """Assert that the files here are `files`, ignoring the usual junk.""" here = os.listdir(".") here = self.clean_files(here, ["*.pyc", "__pycache__"]) self.assertSameElements(here, files) def test_unexecuted_file(self): cov = coverage.coverage() self.make_file("mycode.py", """\ a = 1 b = 2 if b == 3: c = 4 d = 5 """) self.make_file("not_run.py", """\ fooey = 17 """) # Import the python file, executing it. self.start_import_stop(cov, "mycode") _, statements, missing, _ = cov.analysis("not_run.py") self.assertEqual(statements, [1]) self.assertEqual(missing, [1]) def test_filenames(self): self.make_file("mymain.py", """\ import mymod a = 1 """) self.make_file("mymod.py", """\ fooey = 17 """) # Import the python file, executing it. cov = coverage.coverage() self.start_import_stop(cov, "mymain") filename, _, _, _ = cov.analysis("mymain.py") self.assertEqual(os.path.basename(filename), "mymain.py") filename, _, _, _ = cov.analysis("mymod.py") self.assertEqual(os.path.basename(filename), "mymod.py") filename, _, _, _ = cov.analysis(sys.modules["mymain"]) self.assertEqual(os.path.basename(filename), "mymain.py") filename, _, _, _ = cov.analysis(sys.modules["mymod"]) self.assertEqual(os.path.basename(filename), "mymod.py") # Import the python file, executing it again, once it's been compiled # already. cov = coverage.coverage() self.start_import_stop(cov, "mymain") filename, _, _, _ = cov.analysis("mymain.py") self.assertEqual(os.path.basename(filename), "mymain.py") filename, _, _, _ = cov.analysis("mymod.py") self.assertEqual(os.path.basename(filename), "mymod.py") filename, _, _, _ = cov.analysis(sys.modules["mymain"]) self.assertEqual(os.path.basename(filename), "mymain.py") filename, _, _, _ = cov.analysis(sys.modules["mymod"]) self.assertEqual(os.path.basename(filename), "mymod.py") def test_ignore_stdlib(self): self.make_file("mymain.py", """\ import colorsys a = 1 hls = colorsys.rgb_to_hls(1.0, 0.5, 0.0) """) # Measure without the stdlib. cov1 = coverage.coverage() self.assertEqual(cov1.config.cover_pylib, False) self.start_import_stop(cov1, "mymain") # some statements were marked executed in mymain.py _, statements, missing, _ = cov1.analysis("mymain.py") self.assertNotEqual(statements, missing) # but none were in colorsys.py _, statements, missing, _ = cov1.analysis("colorsys.py") self.assertEqual(statements, missing) # Measure with the stdlib. cov2 = coverage.coverage(cover_pylib=True) self.start_import_stop(cov2, "mymain") # some statements were marked executed in mymain.py _, statements, missing, _ = cov2.analysis("mymain.py") self.assertNotEqual(statements, missing) # and some were marked executed in colorsys.py _, statements, missing, _ = cov2.analysis("colorsys.py") self.assertNotEqual(statements, missing) def test_include_can_measure_stdlib(self): self.make_file("mymain.py", """\ import colorsys, random a = 1 r, g, b = [random.random() for _ in range(3)] hls = colorsys.rgb_to_hls(r, g, b) """) # Measure without the stdlib, but include colorsys. cov1 = coverage.coverage(cover_pylib=False, include=["*/colorsys.py"]) self.start_import_stop(cov1, "mymain") # some statements were marked executed in colorsys.py _, statements, missing, _ = cov1.analysis("colorsys.py") self.assertNotEqual(statements, missing) # but none were in random.py _, statements, missing, _ = cov1.analysis("random.py") self.assertEqual(statements, missing) def test_exclude_list(self): cov = coverage.coverage() cov.clear_exclude() self.assertEqual(cov.get_exclude_list(), []) cov.exclude("foo") self.assertEqual(cov.get_exclude_list(), ["foo"]) cov.exclude("bar") self.assertEqual(cov.get_exclude_list(), ["foo", "bar"]) self.assertEqual(cov._exclude_regex('exclude'), "(foo)|(bar)") cov.clear_exclude() self.assertEqual(cov.get_exclude_list(), []) def test_exclude_partial_list(self): cov = coverage.coverage() cov.clear_exclude(which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), []) cov.exclude("foo", which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), ["foo"]) cov.exclude("bar", which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), ["foo", "bar"]) self.assertEqual(cov._exclude_regex(which='partial'), "(foo)|(bar)") cov.clear_exclude(which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), []) def test_exclude_and_partial_are_separate_lists(self): cov = coverage.coverage() cov.clear_exclude(which='partial') cov.clear_exclude(which='exclude') cov.exclude("foo", which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) self.assertEqual(cov.get_exclude_list(which='exclude'), []) cov.exclude("bar", which='exclude') self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar']) cov.exclude("p2", which='partial') cov.exclude("e2", which='exclude') self.assertEqual(cov.get_exclude_list(which='partial'), ['foo', 'p2']) self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) cov.clear_exclude(which='partial') self.assertEqual(cov.get_exclude_list(which='partial'), []) self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) cov.clear_exclude(which='exclude') self.assertEqual(cov.get_exclude_list(which='partial'), []) self.assertEqual(cov.get_exclude_list(which='exclude'), []) def test_datafile_default(self): # Default data file behavior: it's .coverage self.make_file("datatest1.py", """\ fooey = 17 """) self.assertFiles(["datatest1.py"]) cov = coverage.coverage() self.start_import_stop(cov, "datatest1") cov.save() self.assertFiles(["datatest1.py", ".coverage"]) def test_datafile_specified(self): # You can specify the data file name. self.make_file("datatest2.py", """\ fooey = 17 """) self.assertFiles(["datatest2.py"]) cov = coverage.coverage(data_file="cov.data") self.start_import_stop(cov, "datatest2") cov.save() self.assertFiles(["datatest2.py", "cov.data"]) def test_datafile_and_suffix_specified(self): # You can specify the data file name and suffix. self.make_file("datatest3.py", """\ fooey = 17 """) self.assertFiles(["datatest3.py"]) cov = coverage.coverage(data_file="cov.data", data_suffix="14") self.start_import_stop(cov, "datatest3") cov.save() self.assertFiles(["datatest3.py", "cov.data.14"]) def test_datafile_from_rcfile(self): # You can specify the data file name in the .coveragerc file self.make_file("datatest4.py", """\ fooey = 17 """) self.make_file(".coveragerc", """\ [run] data_file = mydata.dat """) self.assertFiles(["datatest4.py", ".coveragerc"]) cov = coverage.coverage() self.start_import_stop(cov, "datatest4") cov.save() self.assertFiles(["datatest4.py", ".coveragerc", "mydata.dat"]) def test_empty_reporting(self): # Used to be you'd get an exception reporting on nothing... cov = coverage.coverage() cov.erase() cov.report() def test_start_stop_start_stop(self): self.make_file("code1.py", """\ code1 = 1 """) self.make_file("code2.py", """\ code2 = 1 code2 = 2 """) cov = coverage.coverage() self.start_import_stop(cov, "code1") cov.save() self.start_import_stop(cov, "code2") _, statements, missing, _ = cov.analysis("code1.py") self.assertEqual(statements, [1]) self.assertEqual(missing, []) _, statements, missing, _ = cov.analysis("code2.py") self.assertEqual(statements, [1, 2]) self.assertEqual(missing, []) if 0: # expected failure # for https://bitbucket.org/ned/coveragepy/issue/79 def test_start_save_stop(self): self.make_file("code1.py", """\ code1 = 1 """) self.make_file("code2.py", """\ code2 = 1 code2 = 2 """) cov = coverage.coverage() cov.start() self.import_local_file("code1") cov.save() self.import_local_file("code2") cov.stop() _, statements, missing, _ = cov.analysis("code1.py") self.assertEqual(statements, [1]) self.assertEqual(missing, []) _, statements, missing, _ = cov.analysis("code2.py") self.assertEqual(statements, [1, 2]) self.assertEqual(missing, []) class UsingModulesMixin(object): """A mixin for importing modules from test/modules and test/moremodules.""" run_in_temp_dir = False def setUp(self): super(UsingModulesMixin, self).setUp() # Parent class saves and restores sys.path, we can just modify it. self.old_dir = os.getcwd() os.chdir(self.nice_file(os.path.dirname(__file__), 'modules')) sys.path.append(".") sys.path.append("../moremodules") def tearDown(self): os.chdir(self.old_dir) super(UsingModulesMixin, self).tearDown() class OmitIncludeTestsMixin(UsingModulesMixin): """Test methods for coverage methods taking include and omit.""" def filenames_in(self, summary, filenames): """Assert the `filenames` are in the keys of `summary`.""" for filename in filenames.split(): self.assertIn(filename, summary) def filenames_not_in(self, summary, filenames): """Assert the `filenames` are not in the keys of `summary`.""" for filename in filenames.split(): self.assertNotIn(filename, summary) def test_nothing_specified(self): result = self.coverage_usepkgs() self.filenames_in(result, "p1a p1b p2a p2b othera otherb osa osb") self.filenames_not_in(result, "p1c") # Because there was no source= specified, we don't search for # unexecuted files. def test_include(self): result = self.coverage_usepkgs(include=["*/p1a.py"]) self.filenames_in(result, "p1a") self.filenames_not_in(result, "p1b p1c p2a p2b othera otherb osa osb") def test_include_2(self): result = self.coverage_usepkgs(include=["*a.py"]) self.filenames_in(result, "p1a p2a othera osa") self.filenames_not_in(result, "p1b p1c p2b otherb osb") def test_include_as_string(self): result = self.coverage_usepkgs(include="*a.py") self.filenames_in(result, "p1a p2a othera osa") self.filenames_not_in(result, "p1b p1c p2b otherb osb") def test_omit(self): result = self.coverage_usepkgs(omit=["*/p1a.py"]) self.filenames_in(result, "p1b p2a p2b") self.filenames_not_in(result, "p1a p1c") def test_omit_2(self): result = self.coverage_usepkgs(omit=["*a.py"]) self.filenames_in(result, "p1b p2b otherb osb") self.filenames_not_in(result, "p1a p1c p2a othera osa") def test_omit_as_string(self): result = self.coverage_usepkgs(omit="*a.py") self.filenames_in(result, "p1b p2b otherb osb") self.filenames_not_in(result, "p1a p1c p2a othera osa") def test_omit_and_include(self): result = self.coverage_usepkgs(include=["*/p1*"], omit=["*/p1a.py"]) self.filenames_in(result, "p1b") self.filenames_not_in(result, "p1a p1c p2a p2b") class SourceOmitIncludeTest(OmitIncludeTestsMixin, CoverageTest): """Test using `source`, `omit` and `include` when measuring code.""" def coverage_usepkgs(self, **kwargs): """Run coverage on usepkgs and return the line summary. Arguments are passed to the `coverage.coverage` constructor. """ cov = coverage.coverage(**kwargs) cov.start() import usepkgs # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested cov._harvest_data() # private! sshhh... summary = cov.data.summary() for k, v in list(summary.items()): assert k.endswith(".py") summary[k[:-3]] = v return summary def test_source_package(self): lines = self.coverage_usepkgs(source=["pkg1"]) self.filenames_in(lines, "p1a p1b") self.filenames_not_in(lines, "p2a p2b othera otherb osa osb") # Because source= was specified, we do search for unexecuted files. self.assertEqual(lines['p1c'], 0) def test_source_package_dotted(self): lines = self.coverage_usepkgs(source=["pkg1.p1b"]) self.filenames_in(lines, "p1b") self.filenames_not_in(lines, "p1a p1c p2a p2b othera otherb osa osb") def test_source_package_part_omitted(self): # https://bitbucket.org/ned/coveragepy/issue/218 # Used to be if you omitted something executed and inside the source, # then after it was executed but not recorded, it would be found in # the search for unexecuted files, and given a score of 0%. lines = self.coverage_usepkgs(source=["pkg1"], omit=["pkg1/p1b.py"]) self.filenames_in(lines, "p1a") self.filenames_not_in(lines, "p1b") self.assertEqual(lines['p1c'], 0) class ReportIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): """Tests of the report include/omit functionality.""" def coverage_usepkgs(self, **kwargs): """Try coverage.report().""" cov = coverage.coverage() cov.start() import usepkgs # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested report = StringIO() cov.report(file=report, **kwargs) return report.getvalue() class XmlIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): """Tests of the xml include/omit functionality. This also takes care of the HTML and annotate include/omit, by virtue of the structure of the code. """ def coverage_usepkgs(self, **kwargs): """Try coverage.xml_report().""" cov = coverage.coverage() cov.start() import usepkgs # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested cov.xml_report(outfile="-", **kwargs) return self.stdout() class AnalysisTest(CoverageTest): """Test the numerical analysis of results.""" def test_many_missing_branches(self): cov = coverage.coverage(branch=True) self.make_file("missing.py", """\ def fun1(x): if x == 1: print("one") else: print("not one") print("done") # pragma: nocover def fun2(x): print("x") fun2(3) """) # Import the python file, executing it. self.start_import_stop(cov, "missing") nums = cov._analyze("missing.py").numbers self.assertEqual(nums.n_files, 1) self.assertEqual(nums.n_statements, 7) self.assertEqual(nums.n_excluded, 1) self.assertEqual(nums.n_missing, 3) self.assertEqual(nums.n_branches, 2) self.assertEqual(nums.n_partial_branches, 0) self.assertEqual(nums.n_missing_branches, 2) class PluginTest(CoverageTest): """Test that the API works properly the way the plugins call it. We don't actually use the plugins, but these tests call the API the same way they do. """ def pretend_to_be_nose_with_cover(self, erase): """This is what the nose --with-cover plugin does.""" cov = coverage.coverage() self.make_file("no_biggie.py", """\ a = 1 b = 2 if b == 1: c = 4 """) if erase: cov.combine() cov.erase() cov.load() self.start_import_stop(cov, "no_biggie") cov.combine() cov.save() cov.report(["no_biggie.py"]) self.assertEqual(self.stdout(), textwrap.dedent("""\ Name Stmts Miss Cover Missing ----------------------------------------- no_biggie 4 1 75% 4 """)) def test_nose_plugin(self): self.pretend_to_be_nose_with_cover(erase=False) def test_nose_plugin_with_erase(self): self.pretend_to_be_nose_with_cover(erase=True) python-coverage-3.7.1+dfsg.1.orig/tests/test_cmdline.py0000644000175000017500000007271512221603116022065 0ustar barrybarry"""Test cmdline.py for coverage.""" import pprint, re, shlex, sys, textwrap import mock import coverage import coverage.cmdline from coverage.misc import ExceptionDuringRun from tests.coveragetest import CoverageTest, OK, ERR class CmdLineTest(CoverageTest): """Tests of execution paths through the command line interpreter.""" run_in_temp_dir = False INIT_LOAD = """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .load()\n""" def model_object(self): """Return a Mock suitable for use in CoverageScript.""" mk = mock.Mock() mk.coverage.return_value = mk return mk def mock_command_line(self, args): """Run `args` through the command line, with a Mock. Returns the Mock it used and the status code returned. """ m = self.model_object() ret = coverage.CoverageScript( _covpkg=m, _run_python_file=m.run_python_file, _run_python_module=m.run_python_module, _help_fn=m.help_fn ).command_line(shlex.split(args)) return m, ret def cmd_executes(self, args, code, ret=OK): """Assert that the `args` end up executing the sequence in `code`.""" m1, r1 = self.mock_command_line(args) self.assertEqual(r1, ret, "Wrong status: got %s, wanted %s" % (r1, ret) ) # Remove all indentation, and change ".foo()" to "m2.foo()". code = re.sub(r"(?m)^\s+", "", code) code = re.sub(r"(?m)^\.", "m2.", code) m2 = self.model_object() code_obj = compile(code, "", "exec") eval(code_obj, globals(), { 'm2': m2 }) self.assert_same_method_calls(m1, m2) def cmd_executes_same(self, args1, args2): """Assert that the `args1` executes the same as `args2`.""" m1, r1 = self.mock_command_line(args1) m2, r2 = self.mock_command_line(args2) self.assertEqual(r1, r2) self.assert_same_method_calls(m1, m2) def assert_same_method_calls(self, m1, m2): """Assert that `m1.method_calls` and `m2.method_calls` are the same.""" # Use a real equality comparison, but if it fails, use a nicer assert # so we can tell what's going on. We have to use the real == first due # to CmdOptionParser.__eq__ if m1.method_calls != m2.method_calls: pp1 = pprint.pformat(m1.method_calls) pp2 = pprint.pformat(m2.method_calls) self.assertMultiLineEqual(pp1+'\n', pp2+'\n') def cmd_help(self, args, help_msg=None, topic=None, ret=ERR): """Run a command line, and check that it prints the right help. Only the last function call in the mock is checked, which should be the help message that we want to see. """ m, r = self.mock_command_line(args) self.assertEqual(r, ret, "Wrong status: got %s, wanted %s" % (r, ret) ) if help_msg: self.assertEqual(m.method_calls[-1], ('help_fn', (help_msg,), {}) ) else: self.assertEqual(m.method_calls[-1], ('help_fn', (), {'topic':topic}) ) class CmdLineTestTest(CmdLineTest): """Tests that our CmdLineTest helpers work.""" def test_assert_same_method_calls(self): # All the other tests here use self.cmd_executes_same in successful # ways, so here we just check that it fails. self.assertRaises(AssertionError, self.cmd_executes_same, "-e", "-c") class ClassicCmdLineTest(CmdLineTest): """Tests of the classic coverage.py command line.""" def test_erase(self): # coverage -e self.cmd_executes("-e", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .erase() """) self.cmd_executes_same("-e", "--erase") def test_execute(self): # coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] # -x calls coverage.load first. self.cmd_executes("-x foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .load() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) # -e -x calls coverage.erase first. self.cmd_executes("-e -x foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) # --timid sets a flag, and program arguments get passed through. self.cmd_executes("-x --timid foo.py abc 123", """\ .coverage(cover_pylib=None, data_suffix=None, timid=True, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .load() .start() .run_python_file('foo.py', ['foo.py', 'abc', '123']) .stop() .save() """) # -L sets a flag, and flags for the program don't confuse us. self.cmd_executes("-x -p -L foo.py -a -b", """\ .coverage(cover_pylib=True, data_suffix=True, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .load() .start() .run_python_file('foo.py', ['foo.py', '-a', '-b']) .stop() .save() """) # Check that long forms of flags do the same thing as short forms. self.cmd_executes_same("-x f.py", "--execute f.py") self.cmd_executes_same("-e -x f.py", "--erase --execute f.py") self.cmd_executes_same("-x -p f.py", "-x --parallel-mode f.py") self.cmd_executes_same("-x -L f.py", "-x --pylib f.py") def test_combine(self): # coverage -c self.cmd_executes("-c", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .load() .combine() .save() """) self.cmd_executes_same("-c", "--combine") def test_report(self): # coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] self.cmd_executes("-r", self.INIT_LOAD + """\ .report(ignore_errors=None, omit=None, include=None, morfs=[], show_missing=None) """) self.cmd_executes("-r -i", self.INIT_LOAD + """\ .report(ignore_errors=True, omit=None, include=None, morfs=[], show_missing=None) """) self.cmd_executes("-r -m", self.INIT_LOAD + """\ .report(ignore_errors=None, omit=None, include=None, morfs=[], show_missing=True) """) self.cmd_executes("-r -o fooey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"], debug=None) .load() .report(ignore_errors=None, omit=["fooey"], include=None, morfs=[], show_missing=None) """) self.cmd_executes("-r -o fooey,booey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"], debug=None) .load() .report(ignore_errors=None, omit=["fooey", "booey"], include=None, morfs=[], show_missing=None) """) self.cmd_executes("-r mod1", self.INIT_LOAD + """\ .report(ignore_errors=None, omit=None, include=None, morfs=["mod1"], show_missing=None) """) self.cmd_executes("-r mod1 mod2 mod3", self.INIT_LOAD + """\ .report(ignore_errors=None, omit=None, include=None, morfs=["mod1", "mod2", "mod3"], show_missing=None) """) self.cmd_executes_same("-r", "--report") self.cmd_executes_same("-r -i", "-r --ignore-errors") self.cmd_executes_same("-r -m", "-r --show-missing") self.cmd_executes_same("-r -o f", "-r --omit=f") self.cmd_executes_same("-r -o f", "-r --omit f") self.cmd_executes_same("-r -o f,b", "-r --omit=f,b") self.cmd_executes_same("-r -o f,b", "-r --omit f,b") self.cmd_executes_same("-r -of", "-r --omit=f") self.cmd_executes_same("-r -of,b", "-r --omit=f,b") def test_annotate(self): # coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] self.cmd_executes("-a", self.INIT_LOAD + """\ .annotate(directory=None, ignore_errors=None, omit=None, include=None, morfs=[]) """) self.cmd_executes("-a -d dir1", self.INIT_LOAD + """\ .annotate(directory="dir1", ignore_errors=None, omit=None, include=None, morfs=[]) """) self.cmd_executes("-a -i", self.INIT_LOAD + """\ .annotate(directory=None, ignore_errors=True, omit=None, include=None, morfs=[]) """) self.cmd_executes("-a -o fooey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"], debug=None) .load() .annotate(directory=None, ignore_errors=None, omit=["fooey"], include=None, morfs=[]) """) self.cmd_executes("-a -o fooey,booey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"], debug=None) .load() .annotate(directory=None, ignore_errors=None, omit=["fooey", "booey"], include=None, morfs=[]) """) self.cmd_executes("-a mod1", self.INIT_LOAD + """\ .annotate(directory=None, ignore_errors=None, omit=None, include=None, morfs=["mod1"]) """) self.cmd_executes("-a mod1 mod2 mod3", self.INIT_LOAD + """\ .annotate(directory=None, ignore_errors=None, omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) """) self.cmd_executes_same("-a", "--annotate") self.cmd_executes_same("-a -d d1", "-a --directory=d1") self.cmd_executes_same("-a -i", "-a --ignore-errors") self.cmd_executes_same("-a -o f", "-a --omit=f") self.cmd_executes_same("-a -o f", "-a --omit f") self.cmd_executes_same("-a -o f,b", "-a --omit=f,b") self.cmd_executes_same("-a -o f,b", "-a --omit f,b") self.cmd_executes_same("-a -of", "-a --omit=f") self.cmd_executes_same("-a -of,b", "-a --omit=f,b") def test_html_report(self): # coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] self.cmd_executes("-b", self.INIT_LOAD + """\ .html_report(directory=None, ignore_errors=None, title=None, omit=None, include=None, morfs=[]) """) self.cmd_executes("-b -d dir1", self.INIT_LOAD + """\ .html_report(directory="dir1", ignore_errors=None, title=None, omit=None, include=None, morfs=[]) """) self.cmd_executes("-b -i", self.INIT_LOAD + """\ .html_report(directory=None, ignore_errors=True, title=None, omit=None, include=None, morfs=[]) """) self.cmd_executes("-b -o fooey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"], debug=None) .load() .html_report(directory=None, ignore_errors=None, title=None, omit=["fooey"], include=None, morfs=[]) """) self.cmd_executes("-b -o fooey,booey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"], debug=None) .load() .html_report(directory=None, ignore_errors=None, title=None, omit=["fooey", "booey"], include=None, morfs=[]) """) self.cmd_executes("-b mod1", self.INIT_LOAD + """\ .html_report(directory=None, ignore_errors=None, title=None, omit=None, include=None, morfs=["mod1"]) """) self.cmd_executes("-b mod1 mod2 mod3", self.INIT_LOAD + """\ .html_report(directory=None, ignore_errors=None, title=None, omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) """) self.cmd_executes_same("-b", "--html") self.cmd_executes_same("-b -d d1", "-b --directory=d1") self.cmd_executes_same("-b -i", "-b --ignore-errors") self.cmd_executes_same("-b -o f", "-b --omit=f") self.cmd_executes_same("-b -o f,b", "-b --omit=f,b") self.cmd_executes_same("-b -of", "-b --omit=f") self.cmd_executes_same("-b -of,b", "-b --omit=f,b") def test_help(self): # coverage -h self.cmd_help("-h", topic="help", ret=OK) self.cmd_help("--help", topic="help", ret=OK) def test_version(self): # coverage --version self.cmd_help("--version", topic="version", ret=OK) ## Error cases def test_argless_actions(self): self.cmd_help("-e foo bar", "Unexpected arguments: foo bar") self.cmd_help("-c baz quux", "Unexpected arguments: baz quux") def test_need_action(self): self.cmd_help("-p", "You must specify at least one of " "-e, -x, -c, -r, -a, or -b.") def test_bad_action_combinations(self): self.cmd_help('-e -a', "You can't specify the 'erase' and 'annotate' " "options at the same time." ) self.cmd_help('-e -r', "You can't specify the 'erase' and 'report' " "options at the same time." ) self.cmd_help('-e -b', "You can't specify the 'erase' and 'html' " "options at the same time." ) self.cmd_help('-e -c', "You can't specify the 'erase' and 'combine' " "options at the same time." ) self.cmd_help('-x -a', "You can't specify the 'execute' and 'annotate' " "options at the same time." ) self.cmd_help('-x -r', "You can't specify the 'execute' and 'report' " "options at the same time." ) self.cmd_help('-x -b', "You can't specify the 'execute' and 'html' " "options at the same time." ) self.cmd_help('-x -c', "You can't specify the 'execute' and 'combine' " "options at the same time." ) def test_nothing_to_do(self): self.cmd_help("-x", "Nothing to do.") def test_unknown_option(self): self.cmd_help("-z", "no such option: -z") class FakeCoverageForDebugData(object): """Just enough of a fake coverage package for the 'debug data' tests.""" def __init__(self, summary): self._summary = summary self.filename = "FILENAME" self.data = self # package members def coverage(self, *unused_args, **unused_kwargs): """The coverage class in the package.""" return self # coverage methods def load(self): """Fake coverage().load()""" pass # data methods def has_arcs(self): """Fake coverage().data.has_arcs()""" return False def summary(self, fullpath): # pylint: disable=W0613 """Fake coverage().data.summary()""" return self._summary class NewCmdLineTest(CmdLineTest): """Tests of the coverage.py command line.""" def test_annotate(self): self.cmd_executes_same("annotate", "-a") self.cmd_executes_same("annotate -i", "-a -i") self.cmd_executes_same("annotate -d d1", "-a -d d1") self.cmd_executes_same("annotate --omit f", "-a --omit f") self.cmd_executes_same("annotate --omit f,b", "-a --omit f,b") self.cmd_executes_same("annotate m1", "-a m1") self.cmd_executes_same("annotate m1 m2 m3", "-a m1 m2 m3") def test_combine(self): self.cmd_executes_same("combine", "-c") def test_debug(self): self.cmd_help("debug", "What information would you like: data, sys?") self.cmd_help("debug foo", "Don't know what you mean by 'foo'") def test_debug_data(self): fake = FakeCoverageForDebugData({ 'file1.py': 17, 'file2.py': 23, }) self.command_line("debug data", _covpkg=fake) self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ -- data --------------------------------------- path: FILENAME has_arcs: False 2 files: file1.py: 17 lines file2.py: 23 lines """)) def test_debug_data_with_no_data(self): fake = FakeCoverageForDebugData({}) self.command_line("debug data", _covpkg=fake) self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ -- data --------------------------------------- path: FILENAME has_arcs: False No data collected """)) def test_debug_sys(self): self.command_line("debug sys") out = self.stdout() assert "version:" in out assert "data_path:" in out def test_erase(self): self.cmd_executes_same("erase", "-e") def test_help(self): self.cmd_executes("help", ".help_fn(topic='help')") def test_cmd_help(self): self.cmd_executes("run --help", ".help_fn(parser='')") self.cmd_executes_same("help run", "run --help") def test_html(self): self.cmd_executes_same("html", "-b") self.cmd_executes_same("html -i", "-b -i") self.cmd_executes_same("html -d d1", "-b -d d1") self.cmd_executes_same("html --omit f", "-b --omit f") self.cmd_executes_same("html --omit f,b", "-b --omit f,b") self.cmd_executes_same("html m1", "-b m1") self.cmd_executes_same("html m1 m2 m3", "-b m1 m2 m3") self.cmd_executes("html", self.INIT_LOAD + """\ .html_report(ignore_errors=None, omit=None, include=None, morfs=[], directory=None, title=None) """) self.cmd_executes("html --title=Hello_there", self.INIT_LOAD + """\ .html_report(ignore_errors=None, omit=None, include=None, morfs=[], directory=None, title='Hello_there') """) def test_report(self): self.cmd_executes_same("report", "-r") self.cmd_executes_same("report -i", "-r -i") self.cmd_executes_same("report -m", "-r -m") self.cmd_executes_same("report --omit f", "-r --omit f") self.cmd_executes_same("report --omit f,b", "-r --omit f,b") self.cmd_executes_same("report m1", "-r m1") self.cmd_executes_same("report m1 m2 m3", "-r m1 m2 m3") def test_run(self): self.cmd_executes_same("run f.py", "-e -x f.py") self.cmd_executes_same("run f.py -a arg -z", "-e -x f.py -a arg -z") self.cmd_executes_same("run -a f.py", "-x f.py") self.cmd_executes_same("run -p f.py", "-e -x -p f.py") self.cmd_executes_same("run -L f.py", "-e -x -L f.py") self.cmd_executes_same("run --timid f.py", "-e -x --timid f.py") self.cmd_executes_same("run", "-x") self.cmd_executes("run --branch foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --rcfile=myrc.rc foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file="myrc.rc", source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --include=pre1,pre2 foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=["pre1", "pre2"], omit=None, debug=None) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --omit=opre1,opre2 foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["opre1", "opre2"], debug=None) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --include=pre1,pre2 --omit=opre1,opre2 foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=["pre1", "pre2"], omit=["opre1", "opre2"], debug=None, ) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --source=quux,hi.there,/home/bar foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=["quux", "hi.there", "/home/bar"], include=None, omit=None, debug=None, ) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) def test_run_debug(self): self.cmd_executes("run --debug=opt1 foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=["opt1"], ) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) self.cmd_executes("run --debug=opt1,opt2 foo.py", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=["opt1","opt2"], ) .erase() .start() .run_python_file('foo.py', ['foo.py']) .stop() .save() """) def test_run_module(self): self.cmd_executes("run -m mymodule", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_module('mymodule', ['mymodule']) .stop() .save() """) self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) .stop() .save() """) self.cmd_executes("run --branch -m mymodule", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None, debug=None) .erase() .start() .run_python_module('mymodule', ['mymodule']) .stop() .save() """) self.cmd_executes_same("run -m mymodule", "run --module mymodule") def test_xml(self): # coverage xml [-i] [--omit DIR,...] [FILE1 FILE2 ...] self.cmd_executes("xml", self.INIT_LOAD + """\ .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], outfile=None) """) self.cmd_executes("xml -i", self.INIT_LOAD + """\ .xml_report(ignore_errors=True, omit=None, include=None, morfs=[], outfile=None) """) self.cmd_executes("xml -o myxml.foo", self.INIT_LOAD + """\ .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], outfile="myxml.foo") """) self.cmd_executes("xml -o -", self.INIT_LOAD + """\ .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], outfile="-") """) self.cmd_executes("xml --omit fooey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"], debug=None) .load() .xml_report(ignore_errors=None, omit=["fooey"], include=None, morfs=[], outfile=None) """) self.cmd_executes("xml --omit fooey,booey", """\ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"], debug=None) .load() .xml_report(ignore_errors=None, omit=["fooey", "booey"], include=None, morfs=[], outfile=None) """) self.cmd_executes("xml mod1", self.INIT_LOAD + """\ .xml_report(ignore_errors=None, omit=None, include=None, morfs=["mod1"], outfile=None) """) self.cmd_executes("xml mod1 mod2 mod3", self.INIT_LOAD + """\ .xml_report(ignore_errors=None, omit=None, include=None, morfs=["mod1", "mod2", "mod3"], outfile=None) """) def test_no_arguments_at_all(self): self.cmd_help("", topic="minimum_help", ret=OK) def test_bad_command(self): self.cmd_help("xyzzy", "Unknown command: 'xyzzy'") class CmdLineStdoutTest(CmdLineTest): """Test the command line with real stdout output.""" def test_minimum_help(self): self.command_line("") out = self.stdout() assert "Code coverage for Python." in out assert out.count("\n") < 4 def test_version(self): self.command_line("--version") out = self.stdout() assert "ersion " in out assert out.count("\n") < 4 def test_help(self): self.command_line("help") out = self.stdout() assert "nedbatchelder.com" in out assert out.count("\n") > 10 def test_cmd_help(self): self.command_line("help run") out = self.stdout() assert "" in out assert "--timid" in out assert out.count("\n") > 10 def test_error(self): self.command_line("fooey kablooey", ret=ERR) out = self.stdout() assert "fooey" in out assert "help" in out class CmdMainTest(CoverageTest): """Tests of coverage.cmdline.main(), using mocking for isolation.""" run_in_temp_dir = False class CoverageScriptStub(object): """A stub for coverage.cmdline.CoverageScript, used by CmdMainTest.""" def command_line(self, argv): """Stub for command_line, the arg determines what it will do.""" if argv[0] == 'hello': print("Hello, world!") elif argv[0] == 'raise': try: raise Exception("oh noes!") except: raise ExceptionDuringRun(*sys.exc_info()) elif argv[0] == 'internalraise': raise ValueError("coverage is broken") elif argv[0] == 'exit': sys.exit(23) else: raise AssertionError("Bad CoverageScriptStub: %r"% (argv,)) return 0 def setUp(self): super(CmdMainTest, self).setUp() self.old_CoverageScript = coverage.cmdline.CoverageScript coverage.cmdline.CoverageScript = self.CoverageScriptStub def tearDown(self): coverage.cmdline.CoverageScript = self.old_CoverageScript super(CmdMainTest, self).tearDown() def test_normal(self): ret = coverage.cmdline.main(['hello']) self.assertEqual(ret, 0) self.assertEqual(self.stdout(), "Hello, world!\n") def test_raise(self): ret = coverage.cmdline.main(['raise']) self.assertEqual(ret, 1) self.assertEqual(self.stdout(), "") err = self.stderr().split('\n') self.assertEqual(err[0], 'Traceback (most recent call last):') self.assertEqual(err[-3], ' raise Exception("oh noes!")') self.assertEqual(err[-2], 'Exception: oh noes!') def test_internalraise(self): self.assertRaisesRegexp(ValueError, "coverage is broken", coverage.cmdline.main, ['internalraise'] ) def test_exit(self): ret = coverage.cmdline.main(['exit']) self.assertEqual(ret, 23) python-coverage-3.7.1+dfsg.1.orig/tests/qunit/0000755000175000017500000000000012306175240020173 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/qunit/qunit.js0000644000175000017500000011255012202156243021672 0ustar barrybarry/** * QUnit - A JavaScript Unit Testing Framework * * http://docs.jquery.com/QUnit * * Copyright (c) 2011 John Resig, Jörn Zaefferer * Dual licensed under the MIT (MIT-LICENSE.txt) * or GPL (GPL-LICENSE.txt) licenses. */ (function(window) { var defined = { setTimeout: typeof window.setTimeout !== "undefined", sessionStorage: (function() { try { return !!sessionStorage.getItem; } catch(e){ return false; } })() }; var testId = 0; var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { this.name = name; this.testName = testName; this.expected = expected; this.testEnvironmentArg = testEnvironmentArg; this.async = async; this.callback = callback; this.assertions = []; }; Test.prototype = { init: function() { var tests = id("qunit-tests"); if (tests) { var b = document.createElement("strong"); b.innerHTML = "Running " + this.name; var li = document.createElement("li"); li.appendChild( b ); li.className = "running"; li.id = this.id = "test-output" + testId++; tests.appendChild( li ); } }, setup: function() { if (this.module != config.previousModule) { if ( config.previousModule ) { QUnit.moduleDone( { name: config.previousModule, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, total: config.moduleStats.all } ); } config.previousModule = this.module; config.moduleStats = { all: 0, bad: 0 }; QUnit.moduleStart( { name: this.module } ); } config.current = this; this.testEnvironment = extend({ setup: function() {}, teardown: function() {} }, this.moduleTestEnvironment); if (this.testEnvironmentArg) { extend(this.testEnvironment, this.testEnvironmentArg); } QUnit.testStart( { name: this.testName } ); // allow utility functions to access the current test environment // TODO why?? QUnit.current_testEnvironment = this.testEnvironment; try { if ( !config.pollution ) { saveGlobal(); } this.testEnvironment.setup.call(this.testEnvironment); } catch(e) { QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message ); } }, run: function() { if ( this.async ) { QUnit.stop(); } if ( config.notrycatch ) { this.callback.call(this.testEnvironment); return; } try { this.callback.call(this.testEnvironment); } catch(e) { fail("Test " + this.testName + " died, exception and test follows", e, this.callback); QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); // else next test will carry the responsibility saveGlobal(); // Restart the tests if they're blocking if ( config.blocking ) { start(); } } }, teardown: function() { try { this.testEnvironment.teardown.call(this.testEnvironment); checkPollution(); } catch(e) { QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); } }, finish: function() { if ( this.expected && this.expected != this.assertions.length ) { QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); } var good = 0, bad = 0, tests = id("qunit-tests"); config.stats.all += this.assertions.length; config.moduleStats.all += this.assertions.length; if ( tests ) { var ol = document.createElement("ol"); for ( var i = 0; i < this.assertions.length; i++ ) { var assertion = this.assertions[i]; var li = document.createElement("li"); li.className = assertion.result ? "pass" : "fail"; li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); ol.appendChild( li ); if ( assertion.result ) { good++; } else { bad++; config.stats.bad++; config.moduleStats.bad++; } } // store result when possible if ( QUnit.config.reorder && defined.sessionStorage ) { if (bad) { sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad); } else { sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName); } } if (bad == 0) { ol.style.display = "none"; } var b = document.createElement("strong"); b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; var a = document.createElement("a"); a.innerHTML = "Rerun"; a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); addEvent(b, "click", function() { var next = b.nextSibling.nextSibling, display = next.style.display; next.style.display = display === "none" ? "block" : "none"; }); addEvent(b, "dblclick", function(e) { var target = e && e.target ? e.target : window.event.srcElement; if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { target = target.parentNode; } if ( window.location && target.nodeName.toLowerCase() === "strong" ) { window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); } }); var li = id(this.id); li.className = bad ? "fail" : "pass"; li.removeChild( li.firstChild ); li.appendChild( b ); li.appendChild( a ); li.appendChild( ol ); } else { for ( var i = 0; i < this.assertions.length; i++ ) { if ( !this.assertions[i].result ) { bad++; config.stats.bad++; config.moduleStats.bad++; } } } try { QUnit.reset(); } catch(e) { fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset); } QUnit.testDone( { name: this.testName, failed: bad, passed: this.assertions.length - bad, total: this.assertions.length } ); }, queue: function() { var test = this; synchronize(function() { test.init(); }); function run() { // each of these can by async synchronize(function() { test.setup(); }); synchronize(function() { test.run(); }); synchronize(function() { test.teardown(); }); synchronize(function() { test.finish(); }); } // defer when previous test run passed, if storage is available var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName); if (bad) { run(); } else { synchronize(run); }; } }; var QUnit = { // call on start of module test to prepend name to all tests module: function(name, testEnvironment) { config.currentModule = name; config.currentModuleTestEnviroment = testEnvironment; }, asyncTest: function(testName, expected, callback) { if ( arguments.length === 2 ) { callback = expected; expected = 0; } QUnit.test(testName, expected, callback, true); }, test: function(testName, expected, callback, async) { var name = '' + testName + '', testEnvironmentArg; if ( arguments.length === 2 ) { callback = expected; expected = null; } // is 2nd argument a testEnvironment? if ( expected && typeof expected === 'object') { testEnvironmentArg = expected; expected = null; } if ( config.currentModule ) { name = '' + config.currentModule + ": " + name; } if ( !validTest(config.currentModule + ": " + testName) ) { return; } var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); test.module = config.currentModule; test.moduleTestEnvironment = config.currentModuleTestEnviroment; test.queue(); }, /** * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. */ expect: function(asserts) { config.current.expected = asserts; }, /** * Asserts true. * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); */ ok: function(a, msg) { a = !!a; var details = { result: a, message: msg }; msg = escapeHtml(msg); QUnit.log(details); config.current.assertions.push({ result: a, message: msg }); }, /** * Checks that the first two arguments are equal, with an optional message. * Prints out both actual and expected values. * * Prefered to ok( actual == expected, message ) * * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); * * @param Object actual * @param Object expected * @param String message (optional) */ equal: function(actual, expected, message) { QUnit.push(expected == actual, actual, expected, message); }, notEqual: function(actual, expected, message) { QUnit.push(expected != actual, actual, expected, message); }, deepEqual: function(actual, expected, message) { QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); }, notDeepEqual: function(actual, expected, message) { QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); }, strictEqual: function(actual, expected, message) { QUnit.push(expected === actual, actual, expected, message); }, notStrictEqual: function(actual, expected, message) { QUnit.push(expected !== actual, actual, expected, message); }, raises: function(block, expected, message) { var actual, ok = false; if (typeof expected === 'string') { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } if (actual) { // we don't want to validate thrown error if (!expected) { ok = true; // expected is a regexp } else if (QUnit.objectType(expected) === "regexp") { ok = expected.test(actual); // expected is a constructor } else if (actual instanceof expected) { ok = true; // expected is a validation function which returns true is validation passed } else if (expected.call({}, actual) === true) { ok = true; } } QUnit.ok(ok, message); }, start: function() { config.semaphore--; if (config.semaphore > 0) { // don't start until equal number of stop-calls return; } if (config.semaphore < 0) { // ignore if start is called more often then stop config.semaphore = 0; } // A slight delay, to avoid any current callbacks if ( defined.setTimeout ) { window.setTimeout(function() { if ( config.timeout ) { clearTimeout(config.timeout); } config.blocking = false; process(); }, 13); } else { config.blocking = false; process(); } }, stop: function(timeout) { config.semaphore++; config.blocking = true; if ( timeout && defined.setTimeout ) { clearTimeout(config.timeout); config.timeout = window.setTimeout(function() { QUnit.ok( false, "Test timed out" ); QUnit.start(); }, timeout); } } }; // Backwards compatibility, deprecated QUnit.equals = QUnit.equal; QUnit.same = QUnit.deepEqual; // Maintain internal state var config = { // The queue of tests to run queue: [], // block until document ready blocking: true, // by default, run previously failed tests first // very useful in combination with "Hide passed tests" checked reorder: true, noglobals: false, notrycatch: false }; // Load paramaters (function() { var location = window.location || { search: "", protocol: "file:" }, params = location.search.slice( 1 ).split( "&" ), length = params.length, urlParams = {}, current; if ( params[ 0 ] ) { for ( var i = 0; i < length; i++ ) { current = params[ i ].split( "=" ); current[ 0 ] = decodeURIComponent( current[ 0 ] ); // allow just a key to turn on a flag, e.g., test.html?noglobals current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; urlParams[ current[ 0 ] ] = current[ 1 ]; if ( current[ 0 ] in config ) { config[ current[ 0 ] ] = current[ 1 ]; } } } QUnit.urlParams = urlParams; config.filter = urlParams.filter; // Figure out if we're running the tests from a server or not QUnit.isLocal = !!(location.protocol === 'file:'); })(); // Expose the API as global variables, unless an 'exports' // object exists, in that case we assume we're in CommonJS if ( typeof exports === "undefined" || typeof require === "undefined" ) { extend(window, QUnit); window.QUnit = QUnit; } else { extend(exports, QUnit); exports.QUnit = QUnit; } // define these after exposing globals to keep them in these QUnit namespace only extend(QUnit, { config: config, // Initialize the configuration options init: function() { extend(config, { stats: { all: 0, bad: 0 }, moduleStats: { all: 0, bad: 0 }, started: +new Date, updateRate: 1000, blocking: false, autostart: true, autorun: false, filter: "", queue: [], semaphore: 0 }); var tests = id( "qunit-tests" ), banner = id( "qunit-banner" ), result = id( "qunit-testresult" ); if ( tests ) { tests.innerHTML = ""; } if ( banner ) { banner.className = ""; } if ( result ) { result.parentNode.removeChild( result ); } if ( tests ) { result = document.createElement( "p" ); result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore( result, tests ); result.innerHTML = 'Running...
     '; } }, /** * Resets the test setup. Useful for tests that modify the DOM. * * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. */ reset: function() { if ( window.jQuery ) { jQuery( "#qunit-fixture" ).html( config.fixture ); } else { var main = id( 'qunit-fixture' ); if ( main ) { main.innerHTML = config.fixture; } } }, /** * Trigger an event on an element. * * @example triggerEvent( document.body, "click" ); * * @param DOMElement elem * @param String type */ triggerEvent: function( elem, type, event ) { if ( document.createEvent ) { event = document.createEvent("MouseEvents"); event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); elem.dispatchEvent( event ); } else if ( elem.fireEvent ) { elem.fireEvent("on"+type); } }, // Safe object type checking is: function( type, obj ) { return QUnit.objectType( obj ) == type; }, objectType: function( obj ) { if (typeof obj === "undefined") { return "undefined"; // consider: typeof null === object } if (obj === null) { return "null"; } var type = Object.prototype.toString.call( obj ) .match(/^\[object\s(.*)\]$/)[1] || ''; switch (type) { case 'Number': if (isNaN(obj)) { return "nan"; } else { return "number"; } case 'String': case 'Boolean': case 'Array': case 'Date': case 'RegExp': case 'Function': return type.toLowerCase(); } if (typeof obj === "object") { return "object"; } return undefined; }, push: function(result, actual, expected, message) { var details = { result: result, message: message, actual: actual, expected: expected }; message = escapeHtml(message) || (result ? "okay" : "failed"); message = '' + message + ""; expected = escapeHtml(QUnit.jsDump.parse(expected)); actual = escapeHtml(QUnit.jsDump.parse(actual)); var output = message + ''; if (actual != expected) { output += ''; output += ''; } if (!result) { var source = sourceFromStacktrace(); if (source) { details.source = source; output += ''; } } output += "
    Expected:
    ' + expected + '
    Result:
    ' + actual + '
    Diff:
    ' + QUnit.diff(expected, actual) +'
    Source:
    ' + escapeHtml(source) + '
    "; QUnit.log(details); config.current.assertions.push({ result: !!result, message: output }); }, url: function( params ) { params = extend( extend( {}, QUnit.urlParams ), params ); var querystring = "?", key; for ( key in params ) { querystring += encodeURIComponent( key ) + "=" + encodeURIComponent( params[ key ] ) + "&"; } return window.location.pathname + querystring.slice( 0, -1 ); }, // Logging callbacks; all receive a single argument with the listed properties // run test/logs.html for any related changes begin: function() {}, // done: { failed, passed, total, runtime } done: function() {}, // log: { result, actual, expected, message } log: function() {}, // testStart: { name } testStart: function() {}, // testDone: { name, failed, passed, total } testDone: function() {}, // moduleStart: { name } moduleStart: function() {}, // moduleDone: { name, failed, passed, total } moduleDone: function() {} }); if ( typeof document === "undefined" || document.readyState === "complete" ) { config.autorun = true; } addEvent(window, "load", function() { QUnit.begin({}); // Initialize the config, saving the execution queue var oldconfig = extend({}, config); QUnit.init(); extend(config, oldconfig); config.blocking = false; var userAgent = id("qunit-userAgent"); if ( userAgent ) { userAgent.innerHTML = navigator.userAgent; } var banner = id("qunit-header"); if ( banner ) { banner.innerHTML = ' ' + banner.innerHTML + ' ' + '' + ''; addEvent( banner, "change", function( event ) { var params = {}; params[ event.target.name ] = event.target.checked ? true : undefined; window.location = QUnit.url( params ); }); } var toolbar = id("qunit-testrunner-toolbar"); if ( toolbar ) { var filter = document.createElement("input"); filter.type = "checkbox"; filter.id = "qunit-filter-pass"; addEvent( filter, "click", function() { var ol = document.getElementById("qunit-tests"); if ( filter.checked ) { ol.className = ol.className + " hidepass"; } else { var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; ol.className = tmp.replace(/ hidepass /, " "); } if ( defined.sessionStorage ) { if (filter.checked) { sessionStorage.setItem("qunit-filter-passed-tests", "true"); } else { sessionStorage.removeItem("qunit-filter-passed-tests"); } } }); if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { filter.checked = true; var ol = document.getElementById("qunit-tests"); ol.className = ol.className + " hidepass"; } toolbar.appendChild( filter ); var label = document.createElement("label"); label.setAttribute("for", "qunit-filter-pass"); label.innerHTML = "Hide passed tests"; toolbar.appendChild( label ); } var main = id('qunit-fixture'); if ( main ) { config.fixture = main.innerHTML; } if (config.autostart) { QUnit.start(); } }); function done() { config.autorun = true; // Log the last module results if ( config.currentModule ) { QUnit.moduleDone( { name: config.currentModule, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, total: config.moduleStats.all } ); } var banner = id("qunit-banner"), tests = id("qunit-tests"), runtime = +new Date - config.started, passed = config.stats.all - config.stats.bad, html = [ 'Tests completed in ', runtime, ' milliseconds.
    ', '', passed, ' tests of ', config.stats.all, ' passed, ', config.stats.bad, ' failed.' ].join(''); if ( banner ) { banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); } if ( tests ) { id( "qunit-testresult" ).innerHTML = html; } if ( typeof document !== "undefined" && document.title ) { // show ✖ for good, ✔ for bad suite result in title // use escape sequences in case file gets loaded with non-utf-8-charset document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title; } QUnit.done( { failed: config.stats.bad, passed: passed, total: config.stats.all, runtime: runtime } ); } function validTest( name ) { var filter = config.filter, run = false; if ( !filter ) { return true; } var not = filter.charAt( 0 ) === "!"; if ( not ) { filter = filter.slice( 1 ); } if ( name.indexOf( filter ) !== -1 ) { return !not; } if ( not ) { run = true; } return run; } // so far supports only Firefox, Chrome and Opera (buggy) // could be extended in the future to use something like https://github.com/csnover/TraceKit function sourceFromStacktrace() { try { throw new Error(); } catch ( e ) { if (e.stacktrace) { // Opera return e.stacktrace.split("\n")[6]; } else if (e.stack) { // Firefox, Chrome return e.stack.split("\n")[4]; } } } function escapeHtml(s) { if (!s) { return ""; } s = s + ""; return s.replace(/[\&"<>\\]/g, function(s) { switch(s) { case "&": return "&"; case "\\": return "\\\\"; case '"': return '\"'; case "<": return "<"; case ">": return ">"; default: return s; } }); } function synchronize( callback ) { config.queue.push( callback ); if ( config.autorun && !config.blocking ) { process(); } } function process() { var start = (new Date()).getTime(); while ( config.queue.length && !config.blocking ) { if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) { config.queue.shift()(); } else { window.setTimeout( process, 13 ); break; } } if (!config.blocking && !config.queue.length) { done(); } } function saveGlobal() { config.pollution = []; if ( config.noglobals ) { for ( var key in window ) { config.pollution.push( key ); } } } function checkPollution( name ) { var old = config.pollution; saveGlobal(); var newGlobals = diff( config.pollution, old ); if ( newGlobals.length > 0 ) { ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); } var deletedGlobals = diff( old, config.pollution ); if ( deletedGlobals.length > 0 ) { ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); } } // returns a new Array with the elements that are in a but not in b function diff( a, b ) { var result = a.slice(); for ( var i = 0; i < result.length; i++ ) { for ( var j = 0; j < b.length; j++ ) { if ( result[i] === b[j] ) { result.splice(i, 1); i--; break; } } } return result; } function fail(message, exception, callback) { if ( typeof console !== "undefined" && console.error && console.warn ) { console.error(message); console.error(exception); console.warn(callback.toString()); } else if ( window.opera && opera.postError ) { opera.postError(message, exception, callback.toString); } } function extend(a, b) { for ( var prop in b ) { if ( b[prop] === undefined ) { delete a[prop]; } else { a[prop] = b[prop]; } } return a; } function addEvent(elem, type, fn) { if ( elem.addEventListener ) { elem.addEventListener( type, fn, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, fn ); } else { fn(); } } function id(name) { return !!(typeof document !== "undefined" && document && document.getElementById) && document.getElementById( name ); } // Test for equality any JavaScript type. // Discussions and reference: http://philrathe.com/articles/equiv // Test suites: http://philrathe.com/tests/equiv // Author: Philippe Rathé QUnit.equiv = function () { var innerEquiv; // the real equiv function var callers = []; // stack to decide between skip/abort functions var parents = []; // stack to avoiding loops from circular referencing // Call the o related callback with the given arguments. function bindCallbacks(o, callbacks, args) { var prop = QUnit.objectType(o); if (prop) { if (QUnit.objectType(callbacks[prop]) === "function") { return callbacks[prop].apply(callbacks, args); } else { return callbacks[prop]; // or undefined } } } var callbacks = function () { // for string, boolean, number and null function useStrictEquality(b, a) { if (b instanceof a.constructor || a instanceof b.constructor) { // to catch short annotaion VS 'new' annotation of a declaration // e.g. var i = 1; // var j = new Number(1); return a == b; } else { return a === b; } } return { "string": useStrictEquality, "boolean": useStrictEquality, "number": useStrictEquality, "null": useStrictEquality, "undefined": useStrictEquality, "nan": function (b) { return isNaN(b); }, "date": function (b, a) { return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); }, "regexp": function (b, a) { return QUnit.objectType(b) === "regexp" && a.source === b.source && // the regex itself a.global === b.global && // and its modifers (gmi) ... a.ignoreCase === b.ignoreCase && a.multiline === b.multiline; }, // - skip when the property is a method of an instance (OOP) // - abort otherwise, // initial === would have catch identical references anyway "function": function () { var caller = callers[callers.length - 1]; return caller !== Object && typeof caller !== "undefined"; }, "array": function (b, a) { var i, j, loop; var len; // b could be an object literal here if ( ! (QUnit.objectType(b) === "array")) { return false; } len = a.length; if (len !== b.length) { // safe and faster return false; } //track reference to avoid circular references parents.push(a); for (i = 0; i < len; i++) { loop = false; for(j=0;j= 0) { type = "array"; } else { type = typeof obj; } return type; }, separator:function() { return this.multiline ? this.HTML ? '
    ' : '\n' : this.HTML ? ' ' : ' '; }, indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing if ( !this.multiline ) return ''; var chr = this.indentChar; if ( this.HTML ) chr = chr.replace(/\t/g,' ').replace(/ /g,' '); return Array( this._depth_ + (extra||0) ).join(chr); }, up:function( a ) { this._depth_ += a || 1; }, down:function( a ) { this._depth_ -= a || 1; }, setParser:function( name, parser ) { this.parsers[name] = parser; }, // The next 3 are exposed so you can use them quote:quote, literal:literal, join:join, // _depth_: 1, // This is the list of parsers, to modify them, use jsDump.setParser parsers:{ window: '[Window]', document: '[Document]', error:'[ERROR]', //when no parser is found, shouldn't happen unknown: '[Unknown]', 'null':'null', 'undefined':'undefined', 'function':function( fn ) { var ret = 'function', name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE if ( name ) ret += ' ' + name; ret += '('; ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); }, array: array, nodelist: array, arguments: array, object:function( map ) { var ret = [ ]; QUnit.jsDump.up(); for ( var key in map ) ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); QUnit.jsDump.down(); return join( '{', ret, '}' ); }, node:function( node ) { var open = QUnit.jsDump.HTML ? '<' : '<', close = QUnit.jsDump.HTML ? '>' : '>'; var tag = node.nodeName.toLowerCase(), ret = open + tag; for ( var a in QUnit.jsDump.DOMAttrs ) { var val = node[QUnit.jsDump.DOMAttrs[a]]; if ( val ) ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); } return ret + close + open + '/' + tag + close; }, functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function var l = fn.length; if ( !l ) return ''; var args = Array(l); while ( l-- ) args[l] = String.fromCharCode(97+l);//97 is 'a' return ' ' + args.join(', ') + ' '; }, key:quote, //object calls it internally, the key part of an item in a map functionCode:'[code]', //function calls it internally, it's the content of the function attribute:quote, //node calls it internally, it's an html attribute value string:quote, date:quote, regexp:literal, //regex number:literal, 'boolean':literal }, DOMAttrs:{//attributes to dump from nodes, name=>realName id:'id', name:'name', 'class':'className' }, HTML:false,//if true, entities are escaped ( <, >, \t, space and \n ) indentChar:' ',//indentation unit multiline:true //if true, items in a collection, are separated by a \n, else just a space. }; return jsDump; })(); // from Sizzle.js function getText( elems ) { var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += getText( elem.childNodes ); } } return ret; }; /* * Javascript Diff Algorithm * By John Resig (http://ejohn.org/) * Modified by Chu Alan "sprite" * * Released under the MIT license. * * More Info: * http://ejohn.org/projects/javascript-diff-algorithm/ * * Usage: QUnit.diff(expected, actual) * * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick brown fox jumped jumps over" */ QUnit.diff = (function() { function diff(o, n){ var ns = new Object(); var os = new Object(); for (var i = 0; i < n.length; i++) { if (ns[n[i]] == null) ns[n[i]] = { rows: new Array(), o: null }; ns[n[i]].rows.push(i); } for (var i = 0; i < o.length; i++) { if (os[o[i]] == null) os[o[i]] = { rows: new Array(), n: null }; os[o[i]].rows.push(i); } for (var i in ns) { if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] }; o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] }; } } for (var i = 0; i < n.length - 1; i++) { if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) { n[i + 1] = { text: n[i + 1], row: n[i].row + 1 }; o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 }; } } for (var i = n.length - 1; i > 0; i--) { if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && n[i - 1] == o[n[i].row - 1]) { n[i - 1] = { text: n[i - 1], row: n[i].row - 1 }; o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 }; } } return { o: o, n: n }; } return function(o, n){ o = o.replace(/\s+$/, ''); n = n.replace(/\s+$/, ''); var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); var str = ""; var oSpace = o.match(/\s+/g); if (oSpace == null) { oSpace = [" "]; } else { oSpace.push(" "); } var nSpace = n.match(/\s+/g); if (nSpace == null) { nSpace = [" "]; } else { nSpace.push(" "); } if (out.n.length == 0) { for (var i = 0; i < out.o.length; i++) { str += '' + out.o[i] + oSpace[i] + ""; } } else { if (out.n[0].text == null) { for (n = 0; n < out.o.length && out.o[n].text == null; n++) { str += '' + out.o[n] + oSpace[n] + ""; } } for (var i = 0; i < out.n.length; i++) { if (out.n[i].text == null) { str += '' + out.n[i] + nSpace[i] + ""; } else { var pre = ""; for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { pre += '' + out.o[n] + oSpace[n] + ""; } str += " " + out.n[i].text + nSpace[i] + pre; } } } return str; }; })(); })(this); python-coverage-3.7.1+dfsg.1.orig/tests/qunit/qunit.css0000644000175000017500000001061312202156243022043 0ustar barrybarry/** * QUnit - A JavaScript Unit Testing Framework * * http://docs.jquery.com/QUnit * * Copyright (c) 2011 John Resig, Jörn Zaefferer * Dual licensed under the MIT (MIT-LICENSE.txt) * or GPL (GPL-LICENSE.txt) licenses. */ /** Font Family and Sizes */ #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; } #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } #qunit-tests { font-size: smaller; } /** Resets */ #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { margin: 0; padding: 0; } /** Header */ #qunit-header { padding: 0.5em 0 0.5em 1em; color: #8699a4; background-color: #0d3349; font-size: 1.5em; line-height: 1em; font-weight: normal; border-radius: 15px 15px 0 0; -moz-border-radius: 15px 15px 0 0; -webkit-border-top-right-radius: 15px; -webkit-border-top-left-radius: 15px; } #qunit-header a { text-decoration: none; color: #c2ccd1; } #qunit-header a:hover, #qunit-header a:focus { color: #fff; } #qunit-banner { height: 5px; } #qunit-testrunner-toolbar { padding: 0.5em 0 0.5em 2em; color: #5E740B; background-color: #eee; } #qunit-userAgent { padding: 0.5em 0 0.5em 2.5em; background-color: #2b81af; color: #fff; text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; } /** Tests: Pass/Fail */ #qunit-tests { list-style-position: inside; } #qunit-tests li { padding: 0.4em 0.5em 0.4em 2.5em; border-bottom: 1px solid #fff; list-style-position: inside; } #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { display: none; } #qunit-tests li strong { cursor: pointer; } #qunit-tests li a { padding: 0.5em; color: #c2ccd1; text-decoration: none; } #qunit-tests li a:hover, #qunit-tests li a:focus { color: #000; } #qunit-tests ol { margin-top: 0.5em; padding: 0.5em; background-color: #fff; border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; box-shadow: inset 0px 2px 13px #999; -moz-box-shadow: inset 0px 2px 13px #999; -webkit-box-shadow: inset 0px 2px 13px #999; } #qunit-tests table { border-collapse: collapse; margin-top: .2em; } #qunit-tests th { text-align: right; vertical-align: top; padding: 0 .5em 0 0; } #qunit-tests td { vertical-align: top; } #qunit-tests pre { margin: 0; white-space: pre-wrap; word-wrap: break-word; } #qunit-tests del { background-color: #e0f2be; color: #374e0c; text-decoration: none; } #qunit-tests ins { background-color: #ffcaca; color: #500; text-decoration: none; } /*** Test Counts */ #qunit-tests b.counts { color: black; } #qunit-tests b.passed { color: #5E740B; } #qunit-tests b.failed { color: #710909; } #qunit-tests li li { margin: 0.5em; padding: 0.4em 0.5em 0.4em 0.5em; background-color: #fff; border-bottom: none; list-style-position: inside; } /*** Passing Styles */ #qunit-tests li li.pass { color: #5E740B; background-color: #fff; border-left: 26px solid #C6E746; } #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } #qunit-tests .pass .test-name { color: #366097; } #qunit-tests .pass .test-actual, #qunit-tests .pass .test-expected { color: #999999; } #qunit-banner.qunit-pass { background-color: #C6E746; } /*** Failing Styles */ #qunit-tests li li.fail { color: #710909; background-color: #fff; border-left: 26px solid #EE5757; } #qunit-tests > li:last-child { border-radius: 0 0 15px 15px; -moz-border-radius: 0 0 15px 15px; -webkit-border-bottom-right-radius: 15px; -webkit-border-bottom-left-radius: 15px; } #qunit-tests .fail { color: #000000; background-color: #EE5757; } #qunit-tests .fail .test-name, #qunit-tests .fail .module-name { color: #000000; } #qunit-tests .fail .test-actual { color: #EE5757; } #qunit-tests .fail .test-expected { color: green; } #qunit-banner.qunit-fail { background-color: #EE5757; } /** Result */ #qunit-testresult { padding: 0.5em 0.5em 0.5em 2.5em; color: #2b81af; background-color: #D2E0E6; border-bottom: 1px solid white; } /** Fixture */ #qunit-fixture { position: absolute; top: -10000px; left: -10000px; } python-coverage-3.7.1+dfsg.1.orig/tests/test_phystokens.py0000644000175000017500000001132312233013371022646 0ustar barrybarry"""Tests for Coverage.py's improved tokenizer.""" import os, re, sys from tests.coveragetest import CoverageTest from coverage.phystokens import source_token_lines, source_encoding SIMPLE = """\ # yay! def foo(): say('two = %d' % 2) """ MIXED_WS = """\ def hello(): a="Hello world!" \tb="indented" """ HERE = os.path.split(__file__)[0] class PhysTokensTest(CoverageTest): """Tests for Coverage.py's improver tokenizer.""" run_in_temp_dir = False def check_tokenization(self, source): """Tokenize `source`, then put it back together, should be the same.""" tokenized = "" for line in source_token_lines(source): text = "".join([t for _,t in line]) tokenized += text + "\n" # source_token_lines doesn't preserve trailing spaces, so trim all that # before comparing. source = source.replace('\r\n', '\n') source = re.sub(r"(?m)[ \t]+$", "", source) tokenized = re.sub(r"(?m)[ \t]+$", "", tokenized) self.assertMultiLineEqual(source, tokenized) def check_file_tokenization(self, fname): """Use the contents of `fname` for `check_tokenization`.""" self.check_tokenization(open(fname).read()) def test_simple(self): self.assertEqual(list(source_token_lines(SIMPLE)), [ [('com', "# yay!")], [('key', 'def'), ('ws', ' '), ('nam', 'foo'), ('op', '('), ('op', ')'), ('op', ':')], [('ws', ' '), ('nam', 'say'), ('op', '('), ('str', "'two = %d'"), ('ws', ' '), ('op', '%'), ('ws', ' '), ('num', '2'), ('op', ')')] ]) self.check_tokenization(SIMPLE) def test_tab_indentation(self): # Mixed tabs and spaces... self.assertEqual(list(source_token_lines(MIXED_WS)), [ [('key', 'def'), ('ws', ' '), ('nam', 'hello'), ('op', '('), ('op', ')'), ('op', ':')], [('ws', ' '), ('nam', 'a'), ('op', '='), ('str', '"Hello world!"')], [('ws', ' '), ('nam', 'b'), ('op', '='), ('str', '"indented"')], ]) def test_tokenize_real_file(self): # Check the tokenization of a real file (large, btw). real_file = os.path.join(HERE, "test_coverage.py") self.check_file_tokenization(real_file) def test_stress(self): # Check the tokenization of a stress-test file. stress = os.path.join(HERE, "stress_phystoken.tok") self.check_file_tokenization(stress) stress = os.path.join(HERE, "stress_phystoken_dos.tok") self.check_file_tokenization(stress) # source_encoding is only used on Py2. if sys.version_info < (3, 0): class SourceEncodingTest(CoverageTest): """Tests of source_encoding() for detecting encodings on Py2.""" run_in_temp_dir = False if sys.version_info >= (2,4): default_encoding = 'ascii' else: default_encoding = 'iso-8859-1' def test_detect_source_encoding(self): # Various forms from http://www.python.org/dev/peps/pep-0263/ source = "# coding=cp850\n\n" self.assertEqual(source_encoding(source), 'cp850') source = "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n" self.assertEqual(source_encoding(source), 'utf-8') source = "#!/usr/bin/python\n# vim: set fileencoding=utf8 :\n" self.assertEqual(source_encoding(source), 'utf8') source = "# This Python file uses this encoding: utf-8\n" self.assertEqual(source_encoding(source), 'utf-8') def test_detect_source_encoding_on_second_line(self): # A coding declaration should be found despite a first blank line. source = "\n# coding=cp850\n\n" self.assertEqual(source_encoding(source), 'cp850') def test_dont_detect_source_encoding_on_third_line(self): # A coding declaration doesn't count on the third line. source = "\n\n# coding=cp850\n\n" self.assertEqual(source_encoding(source), self.default_encoding) def test_detect_source_encoding_of_empty_file(self): # An important edge case. self.assertEqual(source_encoding(""), self.default_encoding) def test_bom(self): # A BOM means utf-8. source = "\xEF\xBB\xBFtext = 'hello'\n" self.assertEqual(source_encoding(source), 'utf-8-sig') # But it has to be the only authority. source = "\xEF\xBB\xBF# coding: cp850\n" self.assertRaises(SyntaxError, source_encoding, source) python-coverage-3.7.1+dfsg.1.orig/tests/test_summary.py0000644000175000017500000002766112233013371022150 0ustar barrybarry"""Test text-based summary reporting for coverage.py""" import os, re, sys import coverage from coverage.backward import StringIO from tests.coveragetest import CoverageTest class SummaryTest(CoverageTest): """Tests of the text summary reporting for coverage.py.""" def setUp(self): super(SummaryTest, self).setUp() self.make_file("mycode.py", """\ import covmod1 import covmodzip1 a = 1 print ('done') """) # Parent class saves and restores sys.path, we can just modify it. sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) def report_from_command(self, cmd): """Return the report from the `cmd`, with some convenience added.""" report = self.run_command(cmd).replace('\\', '/') self.assertNotIn("error", report.lower()) return report def line_count(self, report): """How many lines are in `report`?""" self.assertEqual(report.split('\n')[-1], "") return len(report.split('\n')) - 1 def last_line_squeezed(self, report): """Return the last line of `report` with the spaces squeezed down.""" last_line = report.split('\n')[-2] return re.sub(r"\s+", " ", last_line) def test_report(self): out = self.run_command("coverage -x mycode.py") self.assertEqual(out, 'done\n') report = self.report_from_command("coverage -r") # Name Stmts Miss Cover # --------------------------------------------------------------------- # c:/ned/coverage/trunk/tests/modules/covmod1 2 0 100% # c:/ned/coverage/trunk/tests/zipmods.zip/covmodzip1 2 0 100% # mycode 4 0 100% # --------------------------------------------------------------------- # TOTAL 8 0 100% self.assertNotIn("/coverage/__init__/", report) self.assertIn("/tests/modules/covmod1 ", report) self.assertIn("/tests/zipmods.zip/covmodzip1 ", report) self.assertIn("mycode ", report) self.assertEqual(self.last_line_squeezed(report), "TOTAL 8 0 100%") def test_report_just_one(self): # Try reporting just one module self.run_command("coverage -x mycode.py") report = self.report_from_command("coverage -r mycode.py") # Name Stmts Miss Cover # ---------------------------- # mycode 4 0 100% self.assertEqual(self.line_count(report), 3) self.assertNotIn("/coverage/", report) self.assertNotIn("/tests/modules/covmod1 ", report) self.assertNotIn("/tests/zipmods.zip/covmodzip1 ", report) self.assertIn("mycode ", report) self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") def test_report_omitting(self): # Try reporting while omitting some modules prefix = os.path.split(__file__)[0] self.run_command("coverage -x mycode.py") report = self.report_from_command("coverage -r -o '%s/*'" % prefix) # Name Stmts Miss Cover # ---------------------------- # mycode 4 0 100% self.assertEqual(self.line_count(report), 3) self.assertNotIn("/coverage/", report) self.assertNotIn("/tests/modules/covmod1 ", report) self.assertNotIn("/tests/zipmods.zip/covmodzip1 ", report) self.assertIn("mycode ", report) self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") def test_report_including(self): # Try reporting while including some modules self.run_command("coverage run mycode.py") report = self.report_from_command("coverage report --include=mycode*") # Name Stmts Miss Cover # ---------------------------- # mycode 4 0 100% self.assertEqual(self.line_count(report), 3) self.assertNotIn("/coverage/", report) self.assertNotIn("/tests/modules/covmod1 ", report) self.assertNotIn("/tests/zipmods.zip/covmodzip1 ", report) self.assertIn("mycode ", report) self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") def test_report_branches(self): self.make_file("mybranch.py", """\ def branch(x): if x: print("x") return x branch(1) """) out = self.run_command("coverage run --branch mybranch.py") self.assertEqual(out, 'x\n') report = self.report_from_command("coverage report") # Name Stmts Miss Branch BrMiss Cover # -------------------------------------------- # mybranch 5 0 2 1 85% self.assertEqual(self.line_count(report), 3) self.assertIn("mybranch ", report) self.assertEqual(self.last_line_squeezed(report), "mybranch 5 0 2 1 86%") def test_dotpy_not_python(self): # We run a .py file, and when reporting, we can't parse it as Python. # We should get an error message in the report. self.run_command("coverage run mycode.py") self.make_file("mycode.py", "This isn't python at all!") report = self.report_from_command("coverage -r mycode.py") # pylint: disable=C0301 # Name Stmts Miss Cover # ---------------------------- # mycode NotPython: Couldn't parse '/tmp/test_cover/63354509363/mycode.py' as Python source: 'invalid syntax' at line 1 last = self.last_line_squeezed(report) # The actual file name varies run to run. last = re.sub(r"parse '.*mycode.py", "parse 'mycode.py", last) # The actual error message varies version to version last = re.sub(r": '.*' at", ": 'error' at", last) self.assertEqual(last, "mycode NotPython: " "Couldn't parse 'mycode.py' as Python source: " "'error' at line 1" ) def test_dotpy_not_python_ignored(self): # We run a .py file, and when reporting, we can't parse it as Python, # but we've said to ignore errors, so there's no error reported. self.run_command("coverage run mycode.py") self.make_file("mycode.py", "This isn't python at all!") report = self.report_from_command("coverage -r -i mycode.py") # Name Stmts Miss Cover # ---------------------------- self.assertEqual(self.line_count(report), 2) def test_dothtml_not_python(self): # We run a .html file, and when reporting, we can't parse it as # Python. Since it wasn't .py, no error is reported. # Run an "html" file self.make_file("mycode.html", "a = 1") self.run_command("coverage run mycode.html") # Before reporting, change it to be an HTML file. self.make_file("mycode.html", "

    This isn't python at all!

    ") report = self.report_from_command("coverage -r mycode.html") # Name Stmts Miss Cover # ---------------------------- self.assertEqual(self.line_count(report), 2) def get_report(self, cov): """Get the report from `cov`, and canonicalize it.""" repout = StringIO() cov.report(file=repout, show_missing=False) report = repout.getvalue().replace('\\', '/') report = re.sub(r" +", " ", report) return report def test_bug_156_file_not_run_should_be_zero(self): # https://bitbucket.org/ned/coveragepy/issue/156 self.make_file("mybranch.py", """\ def branch(x): if x: print("x") return x branch(1) """) self.make_file("main.py", """\ print("y") """) cov = coverage.coverage(branch=True, source=["."]) cov.start() import main # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested report = self.get_report(cov).splitlines() self.assertIn("mybranch 5 5 2 2 0%", report) def run_TheCode_and_report_it(self): """A helper for the next few tests.""" cov = coverage.coverage() cov.start() import TheCode # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested return self.get_report(cov) def test_bug_203_mixed_case_listed_twice_with_rc(self): self.make_file("TheCode.py", "a = 1\n") self.make_file(".coveragerc", "[run]\nsource = .\n") report = self.run_TheCode_and_report_it() self.assertIn("TheCode", report) self.assertNotIn("thecode", report) def test_bug_203_mixed_case_listed_twice(self): self.make_file("TheCode.py", "a = 1\n") report = self.run_TheCode_and_report_it() self.assertIn("TheCode", report) self.assertNotIn("thecode", report) if sys.platform == 'win32': def test_pyw_files(self): # https://bitbucket.org/ned/coveragepy/issue/261 self.make_file("start.pyw", """\ import mod print("In start.pyw") """) self.make_file("mod.pyw", """\ print("In mod.pyw") """) cov = coverage.coverage() cov.start() import start # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested report = self.get_report(cov) self.assertNotIn("NoSource", report) report = report.splitlines() self.assertIn("start 2 0 100%", report) self.assertIn("mod 1 0 100%", report) class SummaryTest2(CoverageTest): """Another bunch of summary tests.""" # This class exists because tests naturally clump into classes based on the # needs of their setUp and tearDown, rather than the product features they # are testing. There's probably a better way to organize these. run_in_temp_dir = False def setUp(self): super(SummaryTest2, self).setUp() # Parent class saves and restores sys.path, we can just modify it. this_dir = os.path.dirname(__file__) sys.path.append(self.nice_file(this_dir, 'modules')) sys.path.append(self.nice_file(this_dir, 'moremodules')) def test_empty_files(self): # Shows that empty files like __init__.py are listed as having zero # statements, not one statement. cov = coverage.coverage() cov.start() import usepkgs # pragma: nested # pylint: disable=F0401,W0612 cov.stop() # pragma: nested repout = StringIO() cov.report(file=repout, show_missing=False) report = repout.getvalue().replace('\\', '/') report = re.sub(r"\s+", " ", report) self.assertIn("tests/modules/pkg1/__init__ 1 0 100%", report) self.assertIn("tests/modules/pkg2/__init__ 0 0 100%", report) class ReportingReturnValueTest(CoverageTest): """Tests of reporting functions returning values.""" def run_coverage(self): """Run coverage on doit.py and return the coverage object.""" self.make_file("doit.py", """\ a = 1 b = 2 c = 3 d = 4 if a > 10: f = 6 g = 7 """) cov = coverage.coverage() self.start_import_stop(cov, "doit") return cov def test_report(self): cov = self.run_coverage() val = cov.report(include="*/doit.py") self.assertAlmostEqual(val, 85.7, 1) def test_html(self): cov = self.run_coverage() val = cov.html_report(include="*/doit.py") self.assertAlmostEqual(val, 85.7, 1) def test_xml(self): cov = self.run_coverage() val = cov.xml_report(include="*/doit.py") self.assertAlmostEqual(val, 85.7, 1) python-coverage-3.7.1+dfsg.1.orig/tests/__init__.py0000644000175000017500000000005312202156243021137 0ustar barrybarry"""Automated tests. Run with nosetests.""" python-coverage-3.7.1+dfsg.1.orig/tests/backunittest.py0000644000175000017500000001041312233013371022077 0ustar barrybarry"""Implementations of unittest features from the future.""" import difflib, re, sys, unittest from coverage.backward import set # pylint: disable=W0622 def _need(method): """Do we need to define our own `method` method?""" return not hasattr(unittest.TestCase, method) class TestCase(unittest.TestCase): """Just like unittest.TestCase, but with assert methods added. Designed to be compatible with 3.1 unittest. Methods are only defined if the builtin `unittest` doesn't have them. """ if _need('assertTrue'): def assertTrue(self, exp, msg=None): """Assert that `exp` is true.""" if not exp: self.fail(msg) if _need('assertFalse'): def assertFalse(self, exp, msg=None): """Assert that `exp` is false.""" if exp: self.fail(msg) if _need('assertIn'): def assertIn(self, member, container, msg=None): """Assert that `member` is in `container`.""" if member not in container: msg = msg or ('%r not found in %r' % (member, container)) self.fail(msg) if _need('assertNotIn'): def assertNotIn(self, member, container, msg=None): """Assert that `member` is not in `container`.""" if member in container: msg = msg or ('%r found in %r' % (member, container)) self.fail(msg) if _need('assertGreater'): def assertGreater(self, a, b, msg=None): """Assert that `a` is greater than `b`.""" if not a > b: msg = msg or ('%r not greater than %r' % (a, b)) self.fail(msg) if _need('assertRaisesRegexp'): def assertRaisesRegexp(self, excClass, regexp, callobj, *args, **kw): """ Just like unittest.TestCase.assertRaises, but checks that the message is right too. """ try: callobj(*args, **kw) except excClass: _, exc, _ = sys.exc_info() excMsg = str(exc) if re.search(regexp, excMsg): # Message provided, and we got the right one: it passes. return else: # Message provided, and it didn't match: fail! raise self.failureException( "Right exception, wrong message: " "%r doesn't match %r" % (excMsg, regexp) ) # No need to catch other exceptions: They'll fail the test all by # themselves! else: if hasattr(excClass, '__name__'): excName = excClass.__name__ else: excName = str(excClass) raise self.failureException( "Expected to raise %s, didn't get an exception at all" % excName ) if _need('assertSameElements'): def assertSameElements(self, s1, s2): """Assert that the two arguments are equal as sets.""" self.assertEqual(set(s1), set(s2)) if _need('assertRegexpMatches'): def assertRegexpMatches(self, text, regex, msg=None): """Assert that `text` matches `regex`.""" m = re.search(regex, text) if not m: msg = msg or ("%r doesn't match %r" % (text, regex)) raise self.failureException(msg) if _need('assertMultiLineEqual'): def assertMultiLineEqual(self, first, second, msg=None): """Assert that two multi-line strings are equal. If they aren't, show a nice diff. """ # Adapted from Py3.1 unittest. self.assertTrue(isinstance(first, str), 'First argument is not a string') self.assertTrue(isinstance(second, str), 'Second argument is not a string') if first != second: message = ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) if msg: message += " : " + msg self.fail("Multi-line strings are unequal:\n" + message) python-coverage-3.7.1+dfsg.1.orig/tests/test_oddball.py0000644000175000017500000003306212233013371022044 0ustar barrybarry"""Oddball cases for testing coverage.py""" import os, sys import coverage from tests.coveragetest import CoverageTest from tests import osinfo class ThreadingTest(CoverageTest): """Tests of the threading support.""" def test_threading(self): self.check_coverage("""\ import threading def fromMainThread(): return "called from main thread" def fromOtherThread(): return "called from other thread" def neverCalled(): return "no one calls me" other = threading.Thread(target=fromOtherThread) other.start() fromMainThread() other.join() """, [1,3,4,6,7,9,10,12,13,14,15], "10") def test_thread_run(self): self.check_coverage("""\ import threading class TestThread(threading.Thread): def run(self): self.a = 5 self.do_work() self.a = 7 def do_work(self): self.a = 10 thd = TestThread() thd.start() thd.join() """, [1,3,4,5,6,7,9,10,12,13,14], "") class RecursionTest(CoverageTest): """Check what happens when recursive code gets near limits.""" def test_short_recursion(self): # We can definitely get close to 500 stack frames. self.check_coverage("""\ def recur(n): if n == 0: return 0 else: return recur(n-1)+1 recur(495) # We can get at least this many stack frames. i = 8 # and this line will be traced """, [1,2,3,5,7,8], "") def test_long_recursion(self): # We can't finish a very deep recursion, but we don't crash. self.assertRaises(RuntimeError, self.check_coverage, """\ def recur(n): if n == 0: return 0 else: return recur(n-1)+1 recur(100000) # This is definitely too many frames. """, [1,2,3,5,7], "") def test_long_recursion_recovery(self): # Test the core of bug 93: http://bitbucket.org/ned/coveragepy/issue/93 # When recovering from a stack overflow, the Python trace function is # disabled, but the C trace function is not. So if we're using a # Python trace function, we won't trace anything after the stack # overflow, and there should be a warning about it. If we're using # the C trace function, only line 3 will be missing, and all else # will be traced. self.make_file("recur.py", """\ def recur(n): if n == 0: return 0 # never hit else: return recur(n-1)+1 try: recur(100000) # This is definitely too many frames. except RuntimeError: i = 10 i = 11 """) cov = coverage.coverage() self.start_import_stop(cov, "recur") pytrace = (cov.collector.tracer_name() == "PyTracer") expected_missing = [3] if pytrace: expected_missing += [9,10,11] _, statements, missing, _ = cov.analysis("recur.py") self.assertEqual(statements, [1,2,3,5,7,8,9,10,11]) self.assertEqual(missing, expected_missing) # We can get a warning about the stackoverflow effect on the tracing # function only if we have sys.gettrace if pytrace and hasattr(sys, "gettrace"): self.assertEqual(cov._warnings, ["Trace function changed, measurement is likely wrong: None"] ) else: self.assertEqual(cov._warnings, []) class MemoryLeakTest(CoverageTest): """Attempt the impossible: test that memory doesn't leak. Note: this test is truly unusual, and has had a colorful history. See for example: https://bitbucket.org/ned/coveragepy/issue/186 It may still fail occasionally, especially on PyPy. """ def test_for_leaks(self): # Our original bad memory leak only happened on line numbers > 255, so # make a code object with more lines than that. Ugly string mumbo # jumbo to get 300 blank lines at the beginning.. code = """\ # blank line\n""" * 300 + """\ def once(x): # line 301 if x % 100 == 0: raise Exception("100!") elif x % 2: return 10 else: # line 306 return 11 i = 0 # Portable loop without alloc'ing memory. while i < ITERS: try: once(i) except: pass i += 1 # line 315 """ lines = list(range(301, 315)) lines.remove(306) # Line 306 is the "else". # This is a non-deterministic test, so try it a few times, and fail it # only if it predominantly fails. fails = 0 for _ in range(10): ram_0 = osinfo.process_ram() self.check_coverage(code.replace("ITERS", "10"), lines, "") ram_10 = osinfo.process_ram() self.check_coverage(code.replace("ITERS", "10000"), lines, "") ram_10k = osinfo.process_ram() # Running the code 10k times shouldn't grow the ram much more than # running it 10 times. ram_growth = (ram_10k - ram_10) - (ram_10 - ram_0) if ram_growth > 100000: fails += 1 if fails > 8: self.fail("RAM grew by %d" % (ram_growth)) class PyexpatTest(CoverageTest): """Pyexpat screws up tracing. Make sure we've counter-defended properly.""" def test_pyexpat(self): # pyexpat calls the trace function explicitly (inexplicably), and does # it wrong for exceptions. Parsing a DOCTYPE for some reason throws # an exception internally, and triggers its wrong behavior. This test # checks that our fake PyTrace_RETURN hack in tracer.c works. It will # also detect if the pyexpat bug is fixed unbeknownst to us, meaning # we'd see two RETURNs where there should only be one. self.make_file("trydom.py", """\ import xml.dom.minidom XML = '''\\ ''' def foo(): dom = xml.dom.minidom.parseString(XML) assert len(dom.getElementsByTagName('child')) == 2 a = 11 foo() """) self.make_file("outer.py", "\n"*100 + "import trydom\na = 102\n") cov = coverage.coverage() cov.erase() # Import the python file, executing it. self.start_import_stop(cov, "outer") _, statements, missing, _ = cov.analysis("trydom.py") self.assertEqual(statements, [1,3,8,9,10,11,13]) self.assertEqual(missing, []) _, statements, missing, _ = cov.analysis("outer.py") self.assertEqual(statements, [101,102]) self.assertEqual(missing, []) class ExceptionTest(CoverageTest): """I suspect different versions of Python deal with exceptions differently in the trace function. """ def test_exception(self): # Python 2.3's trace function doesn't get called with "return" if the # scope is exiting due to an exception. This confounds our trace # function which relies on scope announcements to track which files to # trace. # # This test is designed to sniff this out. Each function in the call # stack is in a different file, to try to trip up the tracer. Each # file has active lines in a different range so we'll see if the lines # get attributed to the wrong file. self.make_file("oops.py", """\ def oops(args): a = 2 raise Exception("oops") a = 4 """) self.make_file("fly.py", "\n"*100 + """\ def fly(calls): a = 2 calls[0](calls[1:]) a = 4 """) self.make_file("catch.py", "\n"*200 + """\ def catch(calls): try: a = 3 calls[0](calls[1:]) a = 5 except: a = 7 """) self.make_file("doit.py", "\n"*300 + """\ def doit(calls): try: calls[0](calls[1:]) except: a = 5 """) # Import all the modules before starting coverage, so the def lines # won't be in all the results. for mod in "oops fly catch doit".split(): self.import_local_file(mod) # Each run nests the functions differently to get different # combinations of catching exceptions and letting them fly. runs = [ ("doit fly oops", { 'doit.py': [302,303,304,305], 'fly.py': [102,103], 'oops.py': [2,3], }), ("doit catch oops", { 'doit.py': [302,303], 'catch.py': [202,203,204,206,207], 'oops.py': [2,3], }), ("doit fly catch oops", { 'doit.py': [302,303], 'fly.py': [102,103,104], 'catch.py': [202,203,204,206,207], 'oops.py': [2,3], }), ("doit catch fly oops", { 'doit.py': [302,303], 'catch.py': [202,203,204,206,207], 'fly.py': [102,103], 'oops.py': [2,3], }), ] for callnames, lines_expected in runs: # Make the list of functions we'll call for this test. calls = [getattr(sys.modules[cn], cn) for cn in callnames.split()] cov = coverage.coverage() cov.start() # Call our list of functions: invoke the first, with the rest as # an argument. calls[0](calls[1:]) # pragma: nested cov.stop() # pragma: nested # Clean the line data and compare to expected results. # The filenames are absolute, so keep just the base. cov._harvest_data() # private! sshhh... lines = cov.data.line_data() clean_lines = {} for f, llist in lines.items(): # f is a path to a python module, so we drop the '.py' to get # a callname basename = os.path.basename(f) assert basename.endswith(".py") if basename[:-3] in callnames: clean_lines[basename] = llist self.assertEqual(clean_lines, lines_expected) if sys.version_info >= (2, 5): class DoctestTest(CoverageTest): """Tests invoked with doctest should measure properly.""" def setUp(self): super(DoctestTest, self).setUp() # Oh, the irony! This test case exists because Python 2.4's # doctest module doesn't play well with coverage. But nose fixes # the problem by monkeypatching doctest. I want to undo the # monkeypatch to be sure I'm getting the doctest module that users # of coverage will get. Deleting the imported module here is # enough: when the test imports doctest again, it will get a fresh # copy without the monkeypatch. del sys.modules['doctest'] def test_doctest(self): self.check_coverage('''\ def return_arg_or_void(arg): """If is None, return "Void"; otherwise return >>> return_arg_or_void(None) 'Void' >>> return_arg_or_void("arg") 'arg' >>> return_arg_or_void("None") 'None' """ if arg is None: return "Void" else: return arg import doctest, sys doctest.testmod(sys.modules[__name__]) # we're not __main__ :( ''', [1,11,12,14,16,17], "") if hasattr(sys, 'gettrace'): class GettraceTest(CoverageTest): """Tests that we work properly with `sys.gettrace()`.""" def test_round_trip(self): self.check_coverage('''\ import sys def foo(n): return 3*n def bar(n): return 5*n a = foo(6) sys.settrace(sys.gettrace()) a = bar(8) ''', [1,2,3,4,5,6,7,8], "") def test_multi_layers(self): self.check_coverage('''\ import sys def level1(): a = 3 level2() b = 5 def level2(): c = 7 sys.settrace(sys.gettrace()) d = 9 e = 10 level1() f = 12 ''', [1,2,3,4,5,6,7,8,9,10,11,12], "") python-coverage-3.7.1+dfsg.1.orig/tests/try_execfile.py0000644000175000017500000000135212202156243022065 0ustar barrybarry"""Test file for run_python_file.""" import os, pprint, sys DATA = "xyzzy" import __main__ def my_function(a): """A function to force execution of module-level values.""" return "my_fn(%r)" % a FN_VAL = my_function("fooey") try: pkg = __package__ except NameError: pkg = "*No __package__*" globals_to_check = { '__name__': __name__, '__file__': __file__, '__doc__': __doc__, '__builtins__.has_open': hasattr(__builtins__, 'open'), '__builtins__.dir': dir(__builtins__), '__package__': pkg, 'DATA': DATA, 'FN_VAL': FN_VAL, '__main__.DATA': getattr(__main__, "DATA", "nothing"), 'argv': sys.argv, 'path': [os.path.normcase(p) for p in sys.path], } pprint.pprint(globals_to_check) python-coverage-3.7.1+dfsg.1.orig/tests/test_collector.py0000644000175000017500000000345412233013371022433 0ustar barrybarry"""Tests of coverage/collector.py and other collectors.""" import re import coverage from coverage.backward import StringIO from coverage.backward import set # pylint: disable=W0622 from tests.coveragetest import CoverageTest class CollectorTest(CoverageTest): """Test specific aspects of the collection process.""" def test_should_trace_cache(self): # The tracers should only invoke should_trace once for each file name. # TODO: Might be better to do this with a mocked _should_trace, # rather than by examining debug output. # Make some files that invoke each other. self.make_file("f1.py", """\ def f1(x, f): return f(x) """) self.make_file("f2.py", """\ import f1 def func(x): return f1.f1(x, otherfunc) def otherfunc(x): return x*x for i in range(10): func(i) """) # Trace one file, but not the other, and get the debug output. debug_out = StringIO() cov = coverage.coverage( include=["f1.py"], debug=['trace'], debug_file=debug_out ) # Import the python file, executing it. self.start_import_stop(cov, "f2") # Grab all the filenames mentioned in debug output, there should be no # duplicates. trace_lines = [ l for l in debug_out.getvalue().splitlines() if l.startswith("Tracing ") or l.startswith("Not tracing ") ] filenames = [re.search(r"'[^']+'", l).group() for l in trace_lines] self.assertEqual(len(filenames), len(set(filenames))) # Double-check that the tracing messages are in there somewhere. self.assertGreater(len(filenames), 5) python-coverage-3.7.1+dfsg.1.orig/tests/test_coverage.py0000644000175000017500000013405712233013371022244 0ustar barrybarry"""Tests for Coverage.""" # http://nedbatchelder.com/code/coverage import sys import coverage from coverage.misc import CoverageException from tests.coveragetest import CoverageTest class TestCoverageTest(CoverageTest): """Make sure our complex self.check_coverage method works.""" def test_successful_coverage(self): # The simplest run possible. self.check_coverage("""\ a = 1 b = 2 """, [1,2] ) # You can provide a list of possible statement matches. self.check_coverage("""\ a = 1 b = 2 """, ([100], [1,2], [1723,47]), ) # You can specify missing lines. self.check_coverage("""\ a = 1 if a == 2: a = 3 """, [1,2,3], missing="3", ) # You can specify a list of possible missing lines. self.check_coverage("""\ a = 1 if a == 2: a = 3 """, [1,2,3], missing=("47-49", "3", "100,102") ) def test_failed_coverage(self): # If the lines are wrong, the message shows right and wrong. self.assertRaisesRegexp(AssertionError, r"\[1, 2] != \[1]", self.check_coverage, """\ a = 1 b = 2 """, [1] ) # If the list of lines possibilities is wrong, the msg shows right. self.assertRaisesRegexp(AssertionError, r"None of the lines choices matched \[1, 2]", self.check_coverage, """\ a = 1 b = 2 """, ([1], [2]) ) # If the missing lines are wrong, the message shows right and wrong. self.assertRaisesRegexp(AssertionError, r"'3' != '37'", self.check_coverage, """\ a = 1 if a == 2: a = 3 """, [1,2,3], missing="37", ) # If the missing lines possibilities are wrong, the msg shows right. self.assertRaisesRegexp(AssertionError, r"None of the missing choices matched '3'", self.check_coverage, """\ a = 1 if a == 2: a = 3 """, [1,2,3], missing=("37", "4-10"), ) class BasicCoverageTest(CoverageTest): """The simplest tests, for quick smoke testing of fundamental changes.""" def test_simple(self): self.check_coverage("""\ a = 1 b = 2 c = 4 # Nothing here d = 6 """, [1,2,4,6], report="4 0 100%") def test_indentation_wackiness(self): # Partial final lines are OK. self.check_coverage("""\ import sys if not sys.path: a = 1 """, [1,2,3], "3") def test_multiline_initializer(self): self.check_coverage("""\ d = { 'foo': 1+2, 'bar': (lambda x: x+1)(1), 'baz': str(1), } e = { 'foo': 1, 'bar': 2 } """, [1,7], "") def test_list_comprehension(self): self.check_coverage("""\ l = [ 2*i for i in range(10) if i > 5 ] assert l == [12, 14, 16, 18] """, [1,5], "") class SimpleStatementTest(CoverageTest): """Testing simple single-line statements.""" def test_expression(self): # Bare expressions as statements are tricky: some implementations # optimize some of them away. All implementations seem to count # the implicit return at the end as executable. self.check_coverage("""\ 12 23 """, ([1,2],[2]), "") self.check_coverage("""\ 12 23 a = 3 """, ([1,2,3],[3]), "") self.check_coverage("""\ 1 + 2 1 + \\ 2 """, ([1,2], [2]), "") self.check_coverage("""\ 1 + 2 1 + \\ 2 a = 4 """, ([1,2,4], [4]), "") def test_assert(self): self.check_coverage("""\ assert (1 + 2) assert (1 + 2) assert (1 + 2), 'the universe is broken' assert (1 + 2), \\ 'something is amiss' """, [1,2,4,5], "") def test_assignment(self): # Simple variable assignment self.check_coverage("""\ a = (1 + 2) b = (1 + 2) c = \\ 1 """, [1,2,4], "") def test_assign_tuple(self): self.check_coverage("""\ a = 1 a,b,c = 7,8,9 assert a == 7 and b == 8 and c == 9 """, [1,2,3], "") def test_attribute_assignment(self): # Attribute assignment self.check_coverage("""\ class obj: pass o = obj() o.foo = (1 + 2) o.foo = (1 + 2) o.foo = \\ 1 """, [1,2,3,4,6], "") def test_list_of_attribute_assignment(self): self.check_coverage("""\ class obj: pass o = obj() o.a, o.b = (1 + 2), 3 o.a, o.b = (1 + 2), (3 + 4) o.a, o.b = \\ 1, \\ 2 """, [1,2,3,4,7], "") def test_augmented_assignment(self): self.check_coverage("""\ a = 1 a += 1 a += (1 + 2) a += \\ 1 """, [1,2,3,5], "") def test_triple_string_stuff(self): self.check_coverage("""\ a = ''' a multiline string. ''' b = ''' long expression ''' + ''' on many lines. ''' c = len(''' long expression ''' + ''' on many lines. ''') """, [1,5,11], "") def test_pass(self): # pass is tricky: if it's the only statement in a block, then it is # "executed". But if it is not the only statement, then it is not. self.check_coverage("""\ if 1==1: pass """, [1,2], "") self.check_coverage("""\ def foo(): pass foo() """, [1,2,3], "") self.check_coverage("""\ def foo(): "doc" pass foo() """, ([1,3,4], [1,4]), "") self.check_coverage("""\ class Foo: def foo(self): pass Foo().foo() """, [1,2,3,4], "") self.check_coverage("""\ class Foo: def foo(self): "Huh?" pass Foo().foo() """, ([1,2,4,5], [1,2,5]), "") def test_del(self): self.check_coverage("""\ d = { 'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1 } del d['a'] del d[ 'b' ] del d['c'], \\ d['d'], \\ d['e'] assert(len(d.keys()) == 0) """, [1,2,3,6,9], "") if sys.version_info < (3, 0): # Print statement is gone in Py3k. def test_print(self): self.check_coverage("""\ print "hello, world!" print ("hey: %d" % 17) print "goodbye" print "hello, world!", print ("hey: %d" % 17), print "goodbye", """, [1,2,4,5,6,8], "") def test_raise(self): self.check_coverage("""\ try: raise Exception( "hello %d" % 17) except: pass """, [1,2,5,6], "") def test_return(self): self.check_coverage("""\ def fn(): a = 1 return a x = fn() assert(x == 1) """, [1,2,3,5,6], "") self.check_coverage("""\ def fn(): a = 1 return ( a + 1) x = fn() assert(x == 2) """, [1,2,3,7,8], "") self.check_coverage("""\ def fn(): a = 1 return (a, a + 1, a + 2) x,y,z = fn() assert x == 1 and y == 2 and z == 3 """, [1,2,3,7,8], "") def test_yield(self): self.check_coverage("""\ from __future__ import generators def gen(): yield 1 yield (2+ 3+ 4) yield 1, \\ 2 a,b,c = gen() assert a == 1 and b == 9 and c == (1,2) """, [1,2,3,4,7,9,10], "") def test_break(self): self.check_coverage("""\ for x in range(10): a = 2 + x break a = 4 assert a == 2 """, [1,2,3,4,5], "4") def test_continue(self): self.check_coverage("""\ for x in range(10): a = 2 + x continue a = 4 assert a == 11 """, [1,2,3,4,5], "4") if 0: # expected failure # Peephole optimization of jumps to jumps can mean that some statements # never hit the line tracer. The behavior is different in different # versions of Python, so don't run this test: def test_strange_unexecuted_continue(self): self.check_coverage("""\ a = b = c = 0 for n in range(100): if n % 2: if n % 4: a += 1 continue # <-- This line may not be hit. else: b += 1 c += 1 assert a == 50 and b == 50 and c == 50 a = b = c = 0 for n in range(100): if n % 2: if n % 3: a += 1 continue # <-- This line is always hit. else: b += 1 c += 1 assert a == 33 and b == 50 and c == 50 """, [1,2,3,4,5,6,8,9,10, 12,13,14,15,16,17,19,20,21], "") def test_import(self): self.check_coverage("""\ import string from sys import path a = 1 """, [1,2,3], "") self.check_coverage("""\ import string if 1 == 2: from sys import path a = 1 """, [1,2,3,4], "3") self.check_coverage("""\ import string, \\ os, \\ re from sys import path, \\ stdout a = 1 """, [1,4,6], "") self.check_coverage("""\ import sys, sys as s assert s.path == sys.path """, [1,2], "") self.check_coverage("""\ import sys, \\ sys as s assert s.path == sys.path """, [1,3], "") self.check_coverage("""\ from sys import path, \\ path as p assert p == path """, [1,3], "") self.check_coverage("""\ from sys import \\ * assert len(path) > 0 """, [1,3], "") def test_global(self): self.check_coverage("""\ g = h = i = 1 def fn(): global g global h, \\ i g = h = i = 2 fn() assert g == 2 and h == 2 and i == 2 """, [1,2,6,7,8], "") self.check_coverage("""\ g = h = i = 1 def fn(): global g; g = 2 fn() assert g == 2 and h == 1 and i == 1 """, [1,2,3,4,5], "") if sys.version_info < (3, 0): # In Python 2.x, exec is a statement. def test_exec(self): self.check_coverage("""\ a = b = c = 1 exec "a = 2" exec ("b = " + "c = " + "2") assert a == 2 and b == 2 and c == 2 """, [1,2,3,6], "") self.check_coverage("""\ vars = {'a': 1, 'b': 1, 'c': 1} exec "a = 2" in vars exec ("b = " + "c = " + "2") in vars assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 """, [1,2,3,6], "") self.check_coverage("""\ globs = {} locs = {'a': 1, 'b': 1, 'c': 1} exec "a = 2" in globs, locs exec ("b = " + "c = " + "2") in globs, locs assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 """, [1,2,3,4,7], "") else: # In Python 3.x, exec is a function. def test_exec(self): self.check_coverage("""\ a = b = c = 1 exec("a = 2") exec("b = " + "c = " + "2") assert a == 2 and b == 2 and c == 2 """, [1,2,3,6], "") self.check_coverage("""\ vars = {'a': 1, 'b': 1, 'c': 1} exec("a = 2", vars) exec("b = " + "c = " + "2", vars) assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 """, [1,2,3,6], "") self.check_coverage("""\ globs = {} locs = {'a': 1, 'b': 1, 'c': 1} exec("a = 2", globs, locs) exec("b = " + "c = " + "2", globs, locs) assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 """, [1,2,3,4,7], "") def test_extra_doc_string(self): self.check_coverage("""\ a = 1 "An extra docstring, should be a comment." b = 3 assert (a,b) == (1,3) """, [1,3,4], "") self.check_coverage("""\ a = 1 "An extra docstring, should be a comment." b = 3 123 # A number for some reason: ignored 1+1 # An expression: executed. c = 6 assert (a,b,c) == (1,3,6) """, ([1,3,6,7], [1,3,5,6,7], [1,3,4,5,6,7]), "") class CompoundStatementTest(CoverageTest): """Testing coverage of multi-line compound statements.""" def test_statement_list(self): self.check_coverage("""\ a = 1; b = 2; c = 3 d = 4; e = 5; assert (a,b,c,d,e) == (1,2,3,4,5) """, [1,2,3,5], "") def test_if(self): self.check_coverage("""\ a = 1 if a == 1: x = 3 assert x == 3 if (a == 1): x = 7 assert x == 7 """, [1,2,3,4,5,7,8], "") self.check_coverage("""\ a = 1 if a == 1: x = 3 else: y = 5 assert x == 3 """, [1,2,3,5,6], "5") self.check_coverage("""\ a = 1 if a != 1: x = 3 else: y = 5 assert y == 5 """, [1,2,3,5,6], "3") self.check_coverage("""\ a = 1; b = 2 if a == 1: if b == 2: x = 4 else: y = 6 else: z = 8 assert x == 4 """, [1,2,3,4,6,8,9], "6-8") def test_elif(self): self.check_coverage("""\ a = 1; b = 2; c = 3; if a == 1: x = 3 elif b == 2: y = 5 else: z = 7 assert x == 3 """, [1,2,3,4,5,7,8], "4-7", report="7 3 57% 4-7") self.check_coverage("""\ a = 1; b = 2; c = 3; if a != 1: x = 3 elif b == 2: y = 5 else: z = 7 assert y == 5 """, [1,2,3,4,5,7,8], "3, 7", report="7 2 71% 3, 7") self.check_coverage("""\ a = 1; b = 2; c = 3; if a != 1: x = 3 elif b != 2: y = 5 else: z = 7 assert z == 7 """, [1,2,3,4,5,7,8], "3, 5", report="7 2 71% 3, 5") def test_elif_no_else(self): self.check_coverage("""\ a = 1; b = 2; c = 3; if a == 1: x = 3 elif b == 2: y = 5 assert x == 3 """, [1,2,3,4,5,6], "4-5", report="6 2 67% 4-5") self.check_coverage("""\ a = 1; b = 2; c = 3; if a != 1: x = 3 elif b == 2: y = 5 assert y == 5 """, [1,2,3,4,5,6], "3", report="6 1 83% 3") def test_elif_bizarre(self): self.check_coverage("""\ def f(self): if self==1: x = 3 elif self.m('fred'): x = 5 elif (g==1) and (b==2): x = 7 elif self.m('fred')==True: x = 9 elif ((g==1) and (b==2))==True: x = 11 else: x = 13 """, [1,2,3,4,5,6,7,8,9,10,11,13], "2-13") def test_split_if(self): self.check_coverage("""\ a = 1; b = 2; c = 3; if \\ a == 1: x = 3 elif \\ b == 2: y = 5 else: z = 7 assert x == 3 """, [1,2,4,5,7,9,10], "5-9") self.check_coverage("""\ a = 1; b = 2; c = 3; if \\ a != 1: x = 3 elif \\ b == 2: y = 5 else: z = 7 assert y == 5 """, [1,2,4,5,7,9,10], "4, 9") self.check_coverage("""\ a = 1; b = 2; c = 3; if \\ a != 1: x = 3 elif \\ b != 2: y = 5 else: z = 7 assert z == 7 """, [1,2,4,5,7,9,10], "4, 7") def test_pathological_split_if(self): self.check_coverage("""\ a = 1; b = 2; c = 3; if ( a == 1 ): x = 3 elif ( b == 2 ): y = 5 else: z = 7 assert x == 3 """, [1,2,5,6,9,11,12], "6-11") self.check_coverage("""\ a = 1; b = 2; c = 3; if ( a != 1 ): x = 3 elif ( b == 2 ): y = 5 else: z = 7 assert y == 5 """, [1,2,5,6,9,11,12], "5, 11") self.check_coverage("""\ a = 1; b = 2; c = 3; if ( a != 1 ): x = 3 elif ( b != 2 ): y = 5 else: z = 7 assert z == 7 """, [1,2,5,6,9,11,12], "5, 9") def test_absurd_split_if(self): self.check_coverage("""\ a = 1; b = 2; c = 3; if a == 1 \\ : x = 3 elif b == 2 \\ : y = 5 else: z = 7 assert x == 3 """, [1,2,4,5,7,9,10], "5-9") self.check_coverage("""\ a = 1; b = 2; c = 3; if a != 1 \\ : x = 3 elif b == 2 \\ : y = 5 else: z = 7 assert y == 5 """, [1,2,4,5,7,9,10], "4, 9") self.check_coverage("""\ a = 1; b = 2; c = 3; if a != 1 \\ : x = 3 elif b != 2 \\ : y = 5 else: z = 7 assert z == 7 """, [1,2,4,5,7,9,10], "4, 7") if sys.version_info >= (2, 4): # In 2.4 and up, constant if's were compiled away. def test_constant_if(self): self.check_coverage("""\ if 1: a = 2 assert a == 2 """, [2,3], "") def test_while(self): self.check_coverage("""\ a = 3; b = 0 while a: b += 1 a -= 1 assert a == 0 and b == 3 """, [1,2,3,4,5], "") self.check_coverage("""\ a = 3; b = 0 while a: b += 1 break b = 99 assert a == 3 and b == 1 """, [1,2,3,4,5,6], "5") def test_while_else(self): # Take the else branch. self.check_coverage("""\ a = 3; b = 0 while a: b += 1 a -= 1 else: b = 99 assert a == 0 and b == 99 """, [1,2,3,4,6,7], "") # Don't take the else branch. self.check_coverage("""\ a = 3; b = 0 while a: b += 1 a -= 1 break b = 123 else: b = 99 assert a == 2 and b == 1 """, [1,2,3,4,5,6,8,9], "6-8") def test_split_while(self): self.check_coverage("""\ a = 3; b = 0 while \\ a: b += 1 a -= 1 assert a == 0 and b == 3 """, [1,2,4,5,6], "") self.check_coverage("""\ a = 3; b = 0 while ( a ): b += 1 a -= 1 assert a == 0 and b == 3 """, [1,2,5,6,7], "") def test_for(self): self.check_coverage("""\ a = 0 for i in [1,2,3,4,5]: a += i assert a == 15 """, [1,2,3,4], "") self.check_coverage("""\ a = 0 for i in [1, 2,3,4, 5]: a += i assert a == 15 """, [1,2,5,6], "") self.check_coverage("""\ a = 0 for i in [1,2,3,4,5]: a += i break a = 99 assert a == 1 """, [1,2,3,4,5,6], "5") def test_for_else(self): self.check_coverage("""\ a = 0 for i in range(5): a += i+1 else: a = 99 assert a == 99 """, [1,2,3,5,6], "") self.check_coverage("""\ a = 0 for i in range(5): a += i+1 break a = 99 else: a = 123 assert a == 1 """, [1,2,3,4,5,7,8], "5-7") def test_split_for(self): self.check_coverage("""\ a = 0 for \\ i in [1,2,3,4,5]: a += i assert a == 15 """, [1,2,4,5], "") self.check_coverage("""\ a = 0 for \\ i in [1, 2,3,4, 5]: a += i assert a == 15 """, [1,2,6,7], "") def test_try_except(self): self.check_coverage("""\ a = 0 try: a = 1 except: a = 99 assert a == 1 """, [1,2,3,4,5,6], "4-5") self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except: a = 99 assert a == 99 """, [1,2,3,4,5,6,7], "") self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except ImportError: a = 99 except: a = 123 assert a == 123 """, [1,2,3,4,5,6,7,8,9], "6") self.check_coverage("""\ a = 0 try: a = 1 raise IOError("foo") except ImportError: a = 99 except IOError: a = 17 except: a = 123 assert a == 17 """, [1,2,3,4,5,6,7,8,9,10,11], "6, 9-10") self.check_coverage("""\ a = 0 try: a = 1 except: a = 99 else: a = 123 assert a == 123 """, [1,2,3,4,5,7,8], "4-5") self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except: a = 99 else: a = 123 assert a == 99 """, [1,2,3,4,5,6,8,9], "8") def test_try_finally(self): self.check_coverage("""\ a = 0 try: a = 1 finally: a = 99 assert a == 99 """, [1,2,3,5,6], "") self.check_coverage("""\ a = 0; b = 0 try: a = 1 try: raise Exception("foo") finally: b = 123 except: a = 99 assert a == 99 and b == 123 """, [1,2,3,4,5,7,8,9,10], "") def test_function_def(self): self.check_coverage("""\ a = 99 def foo(): ''' docstring ''' return 1 a = foo() assert a == 1 """, [1,2,5,7,8], "") self.check_coverage("""\ def foo( a, b ): ''' docstring ''' return a+b x = foo(17, 23) assert x == 40 """, [1,7,9,10], "") self.check_coverage("""\ def foo( a = (lambda x: x*2)(10), b = ( lambda x: x+1 )(1) ): ''' docstring ''' return a+b x = foo() assert x == 22 """, [1,10,12,13], "") def test_class_def(self): self.check_coverage("""\ # A comment. class theClass: ''' the docstring. Don't be fooled. ''' def __init__(self): ''' Another docstring. ''' self.a = 1 def foo(self): return self.a x = theClass().foo() assert x == 1 """, [2,6,8,10,11,13,14], "") class ExcludeTest(CoverageTest): """Tests of the exclusion feature to mark lines as not covered.""" def test_default(self): # A number of forms of pragma comment are accepted. self.check_coverage("""\ a = 1 b = 2 # pragma: no cover c = 3 d = 4 #pragma NOCOVER e = 5 """, [1,3,5] ) def test_simple(self): self.check_coverage("""\ a = 1; b = 2 if 0: a = 4 # -cc """, [1,3], "", excludes=['-cc']) def test_two_excludes(self): self.check_coverage("""\ a = 1; b = 2 if a == 99: a = 4 # -cc b = 5 c = 6 # -xx assert a == 1 and b == 2 """, [1,3,5,7], "5", excludes=['-cc', '-xx']) def test_excluding_if_suite(self): self.check_coverage("""\ a = 1; b = 2 if 0: a = 4 b = 5 c = 6 assert a == 1 and b == 2 """, [1,7], "", excludes=['if 0:']) def test_excluding_if_but_not_else_suite(self): self.check_coverage("""\ a = 1; b = 2 if 0: a = 4 b = 5 c = 6 else: a = 8 b = 9 assert a == 8 and b == 9 """, [1,8,9,10], "", excludes=['if 0:']) def test_excluding_else_suite(self): self.check_coverage("""\ a = 1; b = 2 if 1==1: a = 4 b = 5 c = 6 else: #pragma: NO COVER a = 8 b = 9 assert a == 4 and b == 5 and c == 6 """, [1,3,4,5,6,10], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 1; b = 2 if 1==1: a = 4 b = 5 c = 6 # Lots of comments to confuse the else handler. # more. else: #pragma: NO COVER # Comments here too. a = 8 b = 9 assert a == 4 and b == 5 and c == 6 """, [1,3,4,5,6,17], "", excludes=['#pragma: NO COVER']) def test_excluding_elif_suites(self): self.check_coverage("""\ a = 1; b = 2 if 1==1: a = 4 b = 5 c = 6 elif 1==0: #pragma: NO COVER a = 8 b = 9 else: a = 11 b = 12 assert a == 4 and b == 5 and c == 6 """, [1,3,4,5,6,11,12,13], "11-12", excludes=['#pragma: NO COVER']) def test_excluding_oneline_if(self): self.check_coverage("""\ def foo(): a = 2 if 0: x = 3 # no cover b = 4 foo() """, [1,2,4,6], "", excludes=["no cover"]) def test_excluding_a_colon_not_a_suite(self): self.check_coverage("""\ def foo(): l = list(range(10)) a = l[:3] # no cover b = 4 foo() """, [1,2,4,6], "", excludes=["no cover"]) def test_excluding_for_suite(self): self.check_coverage("""\ a = 0 for i in [1,2,3,4,5]: #pragma: NO COVER a += i assert a == 15 """, [1,4], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 for i in [1, 2,3,4, 5]: #pragma: NO COVER a += i assert a == 15 """, [1,6], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 for i in [1,2,3,4,5 ]: #pragma: NO COVER a += i break a = 99 assert a == 1 """, [1,7], "", excludes=['#pragma: NO COVER']) def test_excluding_for_else(self): self.check_coverage("""\ a = 0 for i in range(5): a += i+1 break a = 99 else: #pragma: NO COVER a = 123 assert a == 1 """, [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) def test_excluding_while(self): self.check_coverage("""\ a = 3; b = 0 while a*b: #pragma: NO COVER b += 1 break b = 99 assert a == 3 and b == 0 """, [1,6], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 3; b = 0 while ( a*b ): #pragma: NO COVER b += 1 break b = 99 assert a == 3 and b == 0 """, [1,8], "", excludes=['#pragma: NO COVER']) def test_excluding_while_else(self): self.check_coverage("""\ a = 3; b = 0 while a: b += 1 break b = 99 else: #pragma: NO COVER b = 123 assert a == 3 and b == 1 """, [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) def test_excluding_try_except(self): self.check_coverage("""\ a = 0 try: a = 1 except: #pragma: NO COVER a = 99 assert a == 1 """, [1,2,3,6], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except: a = 99 assert a == 99 """, [1,2,3,4,5,6,7], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except ImportError: #pragma: NO COVER a = 99 except: a = 123 assert a == 123 """, [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 except: #pragma: NO COVER a = 99 else: a = 123 assert a == 123 """, [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except: a = 99 else: #pragma: NO COVER a = 123 assert a == 99 """, [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) def test_excluding_try_except_pass(self): self.check_coverage("""\ a = 0 try: a = 1 except: #pragma: NO COVER x = 2 assert a == 1 """, [1,2,3,6], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except ImportError: #pragma: NO COVER x = 2 except: a = 123 assert a == 123 """, [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 except: #pragma: NO COVER x = 2 else: a = 123 assert a == 123 """, [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) self.check_coverage("""\ a = 0 try: a = 1 raise Exception("foo") except: a = 99 else: #pragma: NO COVER x = 2 assert a == 99 """, [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) def test_excluding_if_pass(self): # From a comment on the coverage page by Michael McNeil Forbes: self.check_coverage("""\ def f(): if False: # pragma: no cover pass # This line still reported as missing if False: # pragma: no cover x = 1 # Now it is skipped. f() """, [1,7], "", excludes=["no cover"]) def test_excluding_function(self): self.check_coverage("""\ def fn(foo): #pragma: NO COVER a = 1 b = 2 c = 3 x = 1 assert x == 1 """, [6,7], "", excludes=['#pragma: NO COVER']) def test_excluding_method(self): self.check_coverage("""\ class Fooey: def __init__(self): self.a = 1 def foo(self): #pragma: NO COVER return self.a x = Fooey() assert x.a == 1 """, [1,2,3,8,9], "", excludes=['#pragma: NO COVER']) def test_excluding_class(self): self.check_coverage("""\ class Fooey: #pragma: NO COVER def __init__(self): self.a = 1 def foo(self): return self.a x = 1 assert x == 1 """, [8,9], "", excludes=['#pragma: NO COVER']) if sys.version_info >= (2, 4): class Py24Test(CoverageTest): """Tests of new syntax in Python 2.4.""" def test_function_decorators(self): self.check_coverage("""\ def require_int(func): def wrapper(arg): assert isinstance(arg, int) return func(arg) return wrapper @require_int def p1(arg): return arg*2 assert p1(10) == 20 """, [1,2,3,4,6,8,10,12], "") def test_function_decorators_with_args(self): self.check_coverage("""\ def boost_by(extra): def decorator(func): def wrapper(arg): return extra*func(arg) return wrapper return decorator @boost_by(10) def boosted(arg): return arg*2 assert boosted(10) == 200 """, [1,2,3,4,5,6,8,10,12], "") def test_double_function_decorators(self): self.check_coverage("""\ def require_int(func): def wrapper(arg): assert isinstance(arg, int) return func(arg) return wrapper def boost_by(extra): def decorator(func): def wrapper(arg): return extra*func(arg) return wrapper return decorator @require_int @boost_by(10) def boosted1(arg): return arg*2 assert boosted1(10) == 200 @boost_by(10) @require_int def boosted2(arg): return arg*2 assert boosted2(10) == 200 """, ([1,2,3,4,5,7,8,9,10,11,12,14,15,17,19,21,22,24,26], [1,2,3,4,5,7,8,9,10,11,12,14, 17,19,21, 24,26]), "") if sys.version_info >= (2, 5): class Py25Test(CoverageTest): """Tests of new syntax in Python 2.5.""" def test_with_statement(self): self.check_coverage("""\ from __future__ import with_statement class Managed: def __enter__(self): desc = "enter" def __exit__(self, type, value, tb): desc = "exit" m = Managed() with m: desc = "block1a" desc = "block1b" try: with m: desc = "block2" raise Exception("Boo!") except: desc = "caught" """, [1,3,4,5,7,8,10,11,12,13,15,16,17,18,19,20], "") def test_try_except_finally(self): self.check_coverage("""\ a = 0; b = 0 try: a = 1 except: a = 99 finally: b = 2 assert a == 1 and b == 2 """, [1,2,3,4,5,7,8], "4-5") self.check_coverage("""\ a = 0; b = 0 try: a = 1 raise Exception("foo") except: a = 99 finally: b = 2 assert a == 99 and b == 2 """, [1,2,3,4,5,6,8,9], "") self.check_coverage("""\ a = 0; b = 0 try: a = 1 raise Exception("foo") except ImportError: a = 99 except: a = 123 finally: b = 2 assert a == 123 and b == 2 """, [1,2,3,4,5,6,7,8,10,11], "6") self.check_coverage("""\ a = 0; b = 0 try: a = 1 raise IOError("foo") except ImportError: a = 99 except IOError: a = 17 except: a = 123 finally: b = 2 assert a == 17 and b == 2 """, [1,2,3,4,5,6,7,8,9,10,12,13], "6, 9-10") self.check_coverage("""\ a = 0; b = 0 try: a = 1 except: a = 99 else: a = 123 finally: b = 2 assert a == 123 and b == 2 """, [1,2,3,4,5,7,9,10], "4-5") self.check_coverage("""\ a = 0; b = 0 try: a = 1 raise Exception("foo") except: a = 99 else: a = 123 finally: b = 2 assert a == 99 and b == 2 """, [1,2,3,4,5,6,8,10,11], "8") class ModuleTest(CoverageTest): """Tests for the module-level behavior of the `coverage` module.""" run_in_temp_dir = False def test_not_singleton(self): # You *can* create another coverage object. coverage.coverage() coverage.coverage() class ReportingTest(CoverageTest): """Tests of some reporting behavior.""" # We don't make any temp files, but we need an empty directory to run the # tests in. run_in_temp_dir = True def test_no_data_to_report_on_annotate(self): # Reporting with no data produces a nice message and no output dir. self.assertRaisesRegexp( CoverageException, "No data to report.", self.command_line, "annotate -d ann" ) self.assert_doesnt_exist("ann") # CoverageTest will yell at us for using a temp directory with no files # made. Instead of adding a way to shut it up, just make a file. self.make_file("touch.txt", "") def test_no_data_to_report_on_html(self): # Reporting with no data produces a nice message and no output dir. self.assertRaisesRegexp( CoverageException, "No data to report.", self.command_line, "html -d htmlcov" ) self.assert_doesnt_exist("htmlcov") def test_no_data_to_report_on_xml(self): # Reporting with no data produces a nice message. self.assertRaisesRegexp( CoverageException, "No data to report.", self.command_line, "xml" ) self.assert_doesnt_exist("coverage.xml") python-coverage-3.7.1+dfsg.1.orig/tests/farm/0000755000175000017500000000000012252501325017755 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/0000755000175000017500000000000012252501325020721 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_unicode.py0000644000175000017500000000174112202156243023610 0ustar barrybarryimport sys def html_it(): """Run coverage and make an HTML report for unicode.py.""" import coverage cov = coverage.coverage() cov.start() import unicode # pragma: nested cov.stop() # pragma: nested cov.html_report(unicode, directory="../html_unicode") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_unicode", "html_unicode", size_within=10, file_pattern="*.html") contains("html_unicode/unicode.html", ""ʎd˙ǝbɐɹǝʌoɔ"", ) if sys.maxunicode == 65535: contains("html_unicode/unicode.html", ""db40,dd00: x��"", ) else: contains("html_unicode/unicode.html", ""db40,dd00: x󠄀"", ) clean("html_unicode") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_styled/0000755000175000017500000000000012252501325023232 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_styled/a.html0000644000175000017500000000753212224243313024346 0ustar barrybarry Coverage for a: 67%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    # A test file for HTML reporting by coverage. 

     

    if 1 < 2: 

        # Needed a < to look at HTML entities. 

        a = 3 

    else: 

        a = 4 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_styled/extra.css0000644000175000017500000000007012202156243025064 0ustar barrybarry/* Doesn't matter what goes in here, it gets copied. */ python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_styled/style.css0000644000175000017500000001140512202156243025105 0ustar barrybarry/* CSS styles for Coverage. */ /* Page-wide styles */ html, body, h1, h2, h3, p, td, th { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } /* Set baseline grid to 16 pt. */ body { font-family: georgia, serif; font-size: 1em; } html>body { font-size: 16px; } /* Set base font size to 12/16 */ p { font-size: .75em; /* 12/16 */ line-height: 1.3333em; /* 16/12 */ } table { border-collapse: collapse; } a.nav { text-decoration: none; color: inherit; } a.nav:hover { text-decoration: underline; color: inherit; } /* Page structure */ #header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; } #source { padding: 1em; font-family: "courier new", monospace; } #indexfile #footer { margin: 1em 3em; } #pyfile #footer { margin: 1em 1em; } #footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; } #index { margin: 1em 0 0 3em; } /* Header styles */ #header .content { padding: 1em 3em; } h1 { font-size: 1.25em; } h2.stats { margin-top: .5em; font-size: 1em; } .stats span { border: 1px solid; padding: .1em .25em; margin: 0 .1em; cursor: pointer; border-color: #999 #ccc #ccc #999; } .stats span.hide_run, .stats span.hide_exc, .stats span.hide_mis, .stats span.hide_par, .stats span.par.hide_run.hide_par { border-color: #ccc #999 #999 #ccc; } .stats span.par.hide_run { border-color: #999 #ccc #ccc #999; } /* Help panel */ #keyboard_icon { float: right; cursor: pointer; } .help_panel { position: absolute; background: #ffc; padding: .5em; border: 1px solid #883; display: none; } #indexfile .help_panel { width: 20em; height: 4em; } #pyfile .help_panel { width: 16em; height: 8em; } .help_panel .legend { font-style: italic; margin-bottom: 1em; } #panel_icon { float: right; cursor: pointer; } .keyhelp { margin: .75em; } .keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; } /* Source file styles */ .linenos p { text-align: right; margin: 0; padding: 0 .5em; color: #999999; font-family: verdana, sans-serif; font-size: .625em; /* 10/16 */ line-height: 1.6em; /* 16/10 */ } .linenos p.highlight { background: #ffdd00; } .linenos p a { text-decoration: none; color: #999999; } .linenos p a:hover { text-decoration: underline; color: #999999; } td.text { width: 100%; } .text p { margin: 0; padding: 0 0 0 .5em; border-left: 2px solid #ffffff; white-space: nowrap; } .text p.mis { background: #ffdddd; border-left: 2px solid #ff0000; } .text p.run, .text p.run.hide_par { background: #ddffdd; border-left: 2px solid #00ff00; } .text p.exc { background: #eeeeee; border-left: 2px solid #808080; } .text p.par, .text p.par.hide_run { background: #ffffaa; border-left: 2px solid #eeee99; } .text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, .text p.hide_run.hide_par { background: inherit; } .text span.annotate { font-family: georgia; font-style: italic; color: #666; float: right; padding-right: .5em; } .text p.hide_par span.annotate { display: none; } /* Syntax coloring */ .text .com { color: green; font-style: italic; line-height: 1px; } .text .key { font-weight: bold; line-height: 1px; } .text .str { color: #000080; } /* index styles */ #index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; } #index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; } #index th:hover { background: #eee; border-bottom: 1px solid #999; } #index td.left, #index th.left { padding-left: 0; } #index td.right, #index th.right { padding-right: 0; } #index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; } #index td.name, #index th.name { text-align: left; width: auto; } #index td.name a { text-decoration: none; color: #000; } #index td.name a:hover { text-decoration: underline; color: #000; } #index tr.total { } #index tr.total td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } #index tr.file:hover { background: #eeeeee; } python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_styled/index.html0000644000175000017500000000505212224243313025230 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 3 1 0 67%
    a 3 1 0 67%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_tabbed.py0000644000175000017500000000154512202156243023405 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for tabbed.""" import coverage cov = coverage.coverage() cov.start() import tabbed # pragma: nested cov.stop() # pragma: nested cov.html_report(tabbed, directory="../html_tabbed") runfunc(html_it, rundir="src") # Editors like to change things, make sure our source file still has tabs. contains("src/tabbed.py", "\tif x:\t\t\t\t\t# look nice") contains("html_tabbed/tabbed.html", ">        if " "x:" "                    " "               " "# look nice" ) doesnt_contain("html_tabbed/tabbed.html", "\t") clean("html_tabbed") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_a_xml_2.py0000644000175000017500000000111612202156243023477 0ustar barrybarrydef html_it(): """Run coverage and make an XML report for a.""" import coverage cov = coverage.coverage(config_file="run_a_xml_2.ini") cov.start() import a # pragma: nested cov.stop() # pragma: nested cov.xml_report(a) import os if not os.path.exists("xml_2"): os.makedirs("xml_2") runfunc(html_it, rundir="src") compare("gold_x_xml", "xml_2", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), (r' version="[-.\w]+"', ' version="VERSION"'), (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), ]) clean("xml_2") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/0000755000175000017500000000000012252501325023116 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/m2.html0000644000175000017500000000571712224243313024333 0ustar barrybarry Coverage for m2: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m2a = 1 

    m2b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/main.html0000644000175000017500000001116212224243313024730 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/m3.html0000644000175000017500000000571712224243313024334 0ustar barrybarry Coverage for m3: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m3a = 1 

    m3b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/m1.html0000644000175000017500000000571712224243313024332 0ustar barrybarry Coverage for m1: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m1a = 1 

    m1b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_1/index.html0000644000175000017500000000654112224243313025120 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 14 0 0 100%
    m1 2 0 0 100%
    m2 2 0 0 100%
    m3 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_omit_3.py0000644000175000017500000000064712202156242023357 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for main.""" import coverage cov = coverage.coverage() cov.start() import main # pragma: nested cov.stop() # pragma: nested cov.html_report(directory="../html_omit_3", omit=["m1.py", "m2.py"]) runfunc(html_it, rundir="src") compare("gold_omit_3", "html_omit_3", size_within=10, file_pattern="*.html") clean("html_omit_3") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_partial/0000755000175000017500000000000012252501325023362 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_partial/partial.html0000644000175000017500000001351412224243313025707 0ustar barrybarry Coverage for partial: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    # partial branches 

     

    a = 3 

     

    while True: 

        break 

     

    while 1: 

        break 

     

    while a:        # pragma: no branch 

        break 

     

    if 0: 

        never_happen() 

     

    if 1: 

        a = 13 

     

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_partial/index.html0000644000175000017500000000562012224243313025361 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x b p c   change column sorting

    Module statements missing excluded branches partial coverage
    Total 8 0 0 6 0 100%
    partial 8 0 0 6 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_other.py0000644000175000017500000000152512202156243023303 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for everything.""" import coverage cov = coverage.coverage() cov.start() import here # pragma: nested cov.stop() # pragma: nested cov.html_report(directory="../html_other") runfunc(html_it, rundir="src", addtopath="../othersrc") # Different platforms will name the "other" file differently. Rename it import os, glob for p in glob.glob("html_other/*_other.html"): os.rename(p, "html_other/blah_blah_other.html") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_other", "html_other", size_within=10, file_pattern="*.html") contains("html_other/index.html", "here", "other.html'>", "other", ) clean("html_other") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_b_branch.py0000644000175000017500000000230012202156243023710 0ustar barrybarrydef html_it(): """Run coverage with branches and make an HTML report for b.""" import coverage cov = coverage.coverage(branch=True) cov.start() import b # pragma: nested cov.stop() # pragma: nested cov.html_report(b, directory="../html_b_branch") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_b_branch", "html_b_branch", size_within=10, file_pattern="*.html") contains("html_b_branch/b.html", "if x < 2", "    a = 3", "70%", "8", "exit", "23   25", ) contains("html_b_branch/index.html", "b", "70%" ) clean("html_b_branch") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_y_xml_branch.py0000644000175000017500000000117312202156243024626 0ustar barrybarrydef xml_it(): """Run coverage and make an XML report for y.""" import coverage cov = coverage.coverage(branch=True) cov.start() import y # pragma: nested cov.stop() # pragma: nested cov.xml_report(y, outfile="../xml_branch/coverage.xml") import os if not os.path.exists("xml_branch"): os.makedirs("xml_branch") runfunc(xml_it, rundir="src") compare("gold_y_xml_branch", "xml_branch", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), (r' version="[-.\w]+"', ' version="VERSION"'), (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), ]) clean("xml_branch") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_3/0000755000175000017500000000000012252501325023120 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_3/main.html0000644000175000017500000001116212224243313024732 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_3/m3.html0000644000175000017500000000571712224243313024336 0ustar barrybarry Coverage for m3: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m3a = 1 

    m3b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_3/index.html0000644000175000017500000000550312224243313025117 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 10 0 0 100%
    m3 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_bom/0000755000175000017500000000000012252501325022503 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_bom/bom.html0000644000175000017500000001273012224243313024150 0ustar barrybarry Coverage for bom: 71%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    # A python source file in utf-8, with BOM 

    math = "3×4 = 12, ÷2 = 6±0" 

     

    import sys 

     

    if sys.version_info >= (3, 0): 

        assert len(math) == 18 

        assert len(math.encode('utf-8')) == 21 

    else: 

        assert len(math) == 21 

        assert len(math.decode('utf-8')) == 18 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_bom/index.html0000644000175000017500000000505512224243313024504 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 7 2 0 71%
    bom 7 2 0 71%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_a_xml_1.py0000644000175000017500000000112212202156243023473 0ustar barrybarrydef html_it(): """Run coverage and make an XML report for a.""" import coverage cov = coverage.coverage() cov.start() import a # pragma: nested cov.stop() # pragma: nested cov.xml_report(a, outfile="../xml_1/coverage.xml") import os if not os.path.exists("xml_1"): os.makedirs("xml_1") runfunc(html_it, rundir="src") compare("gold_x_xml", "xml_1", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), (r' version="[-.\w]+"', ' version="VERSION"'), (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), ]) clean("xml_1") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_isolatin1/0000755000175000017500000000000012252501325023631 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_isolatin1/isolatin1.html0000644000175000017500000000707312224243313026430 0ustar barrybarry Coverage for isolatin1: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    # A python source file in another encoding. 

    # -*- coding: iso8859-1 -*- 

     

    math = "3×4 = 12, ÷2 = 6±0" 

    assert len(math) == 18 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_isolatin1/index.html0000644000175000017500000000510112224243313025622 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 2 0 0 100%
    isolatin1 2 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_omit_1.py0000644000175000017500000000061612202156242023351 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for main.""" import coverage cov = coverage.coverage() cov.start() import main # pragma: nested cov.stop() # pragma: nested cov.html_report(directory="../html_omit_1") runfunc(html_it, rundir="src") compare("gold_omit_1", "html_omit_1", size_within=10, file_pattern="*.html") clean("html_omit_1") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_a/0000755000175000017500000000000012252501325022146 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_a/a.html0000644000175000017500000000753212224243313023262 0ustar barrybarry Coverage for a: 67%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    # A test file for HTML reporting by coverage. 

     

    if 1 < 2: 

        # Needed a < to look at HTML entities. 

        a = 3 

    else: 

        a = 4 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_a/index.html0000644000175000017500000000505212224243313024144 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 3 1 0 67%
    a 3 1 0 67%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_x_xml/0000755000175000017500000000000012252501325023055 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_x_xml/coverage.xml0000644000175000017500000000125612202156243025376 0ustar barrybarry python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_omit_5.py0000644000175000017500000000061312202156243023353 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for main.""" import coverage cov = coverage.coverage(config_file="omit5.ini") cov.start() import main # pragma: nested cov.stop() # pragma: nested cov.html_report() runfunc(html_it, rundir="src") compare("gold_omit_5", "html_omit_5", size_within=10, file_pattern="*.html") clean("html_omit_5") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/0000755000175000017500000000000012252501325021510 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/0000755000175000017500000000000012306175240023167 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/keybd_open.png0000644000175000017500000000041312215441077026015 0ustar barrybarry‰PNG  IHDR# è#ºsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 3‘pb‹IDAT8˽“Aà ÇW¾‰ßßäî©Q5©­ÌÉHV»¶ð?F2%Òl–§GDxEQUTu©žsžÞâbîPkõ݉¥”SɈéCï};¯Ôû>€ÒZ»üpŒñHŒà r„¤Ç´ÍÌ/AŽ˜™¹öñ¢ûZíãÇOEã²2C;gÒ,´ÚÙF¼£Ÿ™óÅIEND®B`‚python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/m2.html0000644000175000017500000000562412215441062024377 0ustar barrybarry Coverage for m2: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m2a = 1 

    m2b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/jquery.hotkeys.js0000644000175000017500000000577112215441077026546 0ustar barrybarry/* * jQuery Hotkeys Plugin * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * * Based upon the plugin by Tzury Bar Yochay: * http://github.com/tzuryby/hotkeys * * Original idea by: * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ (function(jQuery){ jQuery.hotkeys = { version: "0.8", specialKeys: { 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" }, shiftNums: { "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", ".": ">", "/": "?", "\\": "|" } }; function keyHandler( handleObj ) { // Only care when a possible input has been specified if ( typeof handleObj.data !== "string" ) { return; } var origHandler = handleObj.handler, keys = handleObj.data.toLowerCase().split(" "); handleObj.handler = function( event ) { // Don't fire in text-accepting inputs that we didn't directly bind to if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) || event.target.type === "text") ) { return; } // Keypress represents characters, not special keys var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ], character = String.fromCharCode( event.which ).toLowerCase(), key, modif = "", possible = {}; // check combinations (alt|ctrl|shift+anything) if ( event.altKey && special !== "alt" ) { modif += "alt+"; } if ( event.ctrlKey && special !== "ctrl" ) { modif += "ctrl+"; } // TODO: Need to make sure this works consistently across platforms if ( event.metaKey && !event.ctrlKey && special !== "meta" ) { modif += "meta+"; } if ( event.shiftKey && special !== "shift" ) { modif += "shift+"; } if ( special ) { possible[ modif + special ] = true; } else { possible[ modif + character ] = true; possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true; // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" if ( modif === "shift+" ) { possible[ jQuery.hotkeys.shiftNums[ character ] ] = true; } } for ( var i = 0, l = keys.length; i < l; i++ ) { if ( possible[ keys[i] ] ) { return origHandler.apply( this, arguments ); } } }; } jQuery.each([ "keydown", "keyup", "keypress" ], function() { jQuery.event.special[ this ] = { add: keyHandler }; }); })( jQuery ); python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/style.css0000644000175000017500000001221012215441077025040 0ustar barrybarry/* CSS styles for Coverage. */ /* Page-wide styles */ html, body, h1, h2, h3, p, td, th { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } /* Set baseline grid to 16 pt. */ body { font-family: georgia, serif; font-size: 1em; } html>body { font-size: 16px; } /* Set base font size to 12/16 */ p { font-size: .75em; /* 12/16 */ line-height: 1.33333333em; /* 16/12 */ } table { border-collapse: collapse; } a.nav { text-decoration: none; color: inherit; } a.nav:hover { text-decoration: underline; color: inherit; } /* Page structure */ #header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; } #source { padding: 1em; font-family: "courier new", monospace; } #indexfile #footer { margin: 1em 3em; } #pyfile #footer { margin: 1em 1em; } #footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; } #index { margin: 1em 0 0 3em; } /* Header styles */ #header .content { padding: 1em 3em; } h1 { font-size: 1.25em; } h2.stats { margin-top: .5em; font-size: 1em; } .stats span { border: 1px solid; padding: .1em .25em; margin: 0 .1em; cursor: pointer; border-color: #999 #ccc #ccc #999; } .stats span.hide_run, .stats span.hide_exc, .stats span.hide_mis, .stats span.hide_par, .stats span.par.hide_run.hide_par { border-color: #ccc #999 #999 #ccc; } .stats span.par.hide_run { border-color: #999 #ccc #ccc #999; } .stats span.run { background: #ddffdd; } .stats span.exc { background: #eeeeee; } .stats span.mis { background: #ffdddd; } .stats span.hide_run { background: #eeffee; } .stats span.hide_exc { background: #f5f5f5; } .stats span.hide_mis { background: #ffeeee; } .stats span.par { background: #ffffaa; } .stats span.hide_par { background: #ffffcc; } /* Help panel */ #keyboard_icon { float: right; cursor: pointer; } .help_panel { position: absolute; background: #ffc; padding: .5em; border: 1px solid #883; display: none; } #indexfile .help_panel { width: 20em; height: 4em; } #pyfile .help_panel { width: 16em; height: 8em; } .help_panel .legend { font-style: italic; margin-bottom: 1em; } #panel_icon { float: right; cursor: pointer; } .keyhelp { margin: .75em; } .keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; } /* Source file styles */ .linenos p { text-align: right; margin: 0; padding: 0 .5em; color: #999999; font-family: verdana, sans-serif; font-size: .625em; /* 10/16 */ line-height: 1.6em; /* 16/10 */ } .linenos p.highlight { background: #ffdd00; } .linenos p a { text-decoration: none; color: #999999; } .linenos p a:hover { text-decoration: underline; color: #999999; } td.text { width: 100%; } .text p { margin: 0; padding: 0 0 0 .5em; border-left: 2px solid #ffffff; white-space: nowrap; } .text p.mis { background: #ffdddd; border-left: 2px solid #ff0000; } .text p.run, .text p.run.hide_par { background: #ddffdd; border-left: 2px solid #00ff00; } .text p.exc { background: #eeeeee; border-left: 2px solid #808080; } .text p.par, .text p.par.hide_run { background: #ffffaa; border-left: 2px solid #eeee99; } .text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, .text p.hide_run.hide_par { background: inherit; } .text span.annotate { font-family: georgia; font-style: italic; color: #666; float: right; padding-right: .5em; } .text p.hide_par span.annotate { display: none; } /* Syntax coloring */ .text .com { color: green; font-style: italic; line-height: 1px; } .text .key { font-weight: bold; line-height: 1px; } .text .str { color: #000080; } /* index styles */ #index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; } #index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; } #index th:hover { background: #eee; border-bottom: 1px solid #999; } #index td.left, #index th.left { padding-left: 0; } #index td.right, #index th.right { padding-right: 0; } #index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; } #index td.name, #index th.name { text-align: left; width: auto; } #index td.name a { text-decoration: none; color: #000; } #index td.name a:hover { text-decoration: underline; color: #000; } #index tr.total { } #index tr.total td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } #index tr.file:hover { background: #eeeeee; } python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/jquery.isonscreen.js0000644000175000017500000000273612215441077027226 0ustar barrybarry/* Copyright (c) 2010 * @author Laurence Wheway * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * @version 1.2.0 */ (function($) { jQuery.extend({ isOnScreen: function(box, container) { //ensure numbers come in as intgers (not strings) and remove 'px' is it's there for(var i in box){box[i] = parseFloat(box[i])}; for(var i in container){container[i] = parseFloat(container[i])}; if(!container){ container = { left: $(window).scrollLeft(), top: $(window).scrollTop(), width: $(window).width(), height: $(window).height() } } if( box.left+box.width-container.left > 0 && box.left < container.width+container.left && box.top+box.height-container.top > 0 && box.top < container.height+container.top ) return true; return false; } }) jQuery.fn.isOnScreen = function (container) { for(var i in container){container[i] = parseFloat(container[i])}; if(!container){ container = { left: $(window).scrollLeft(), top: $(window).scrollTop(), width: $(window).width(), height: $(window).height() } } if( $(this).offset().left+$(this).width()-container.left > 0 && $(this).offset().left < container.width+container.left && $(this).offset().top+$(this).height()-container.top > 0 && $(this).offset().top < container.height+container.top ) return true; return false; } })(jQuery); python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/main.html0000644000175000017500000001106712215441062025003 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/coverage_html.js0000644000175000017500000002573512215441077026363 0ustar barrybarry// Coverage.py HTML report browser code. /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ /*global coverage: true, document, window, $ */ coverage = {}; // Find all the elements with shortkey_* class, and use them to assign a shotrtcut key. coverage.assign_shortkeys = function () { $("*[class*='shortkey_']").each(function (i, e) { $.each($(e).attr("class").split(" "), function (i, c) { if (/^shortkey_/.test(c)) { $(document).bind('keydown', c.substr(9), function () { $(e).click(); }); } }); }); }; // Create the events for the help panel. coverage.wire_up_help_panel = function () { $("#keyboard_icon").click(function () { // Show the help panel, and position it so the keyboard icon in the // panel is in the same place as the keyboard icon in the header. $(".help_panel").show(); var koff = $("#keyboard_icon").offset(); var poff = $("#panel_icon").position(); $(".help_panel").offset({ top: koff.top-poff.top, left: koff.left-poff.left }); }); $("#panel_icon").click(function () { $(".help_panel").hide(); }); }; // Loaded on index.html coverage.index_ready = function ($) { // Look for a cookie containing previous sort settings: var sort_list = []; var cookie_name = "COVERAGE_INDEX_SORT"; var i; // This almost makes it worth installing the jQuery cookie plugin: if (document.cookie.indexOf(cookie_name) > -1) { var cookies = document.cookie.split(";"); for (i = 0; i < cookies.length; i++) { var parts = cookies[i].split("="); if ($.trim(parts[0]) === cookie_name && parts[1]) { sort_list = eval("[[" + parts[1] + "]]"); break; } } } // Create a new widget which exists only to save and restore // the sort order: $.tablesorter.addWidget({ id: "persistentSort", // Format is called by the widget before displaying: format: function (table) { if (table.config.sortList.length === 0 && sort_list.length > 0) { // This table hasn't been sorted before - we'll use // our stored settings: $(table).trigger('sorton', [sort_list]); } else { // This is not the first load - something has // already defined sorting so we'll just update // our stored value to match: sort_list = table.config.sortList; } } }); // Configure our tablesorter to handle the variable number of // columns produced depending on report options: var headers = []; var col_count = $("table.index > thead > tr > th").length; headers[0] = { sorter: 'text' }; for (i = 1; i < col_count-1; i++) { headers[i] = { sorter: 'digit' }; } headers[col_count-1] = { sorter: 'percent' }; // Enable the table sorter: $("table.index").tablesorter({ widgets: ['persistentSort'], headers: headers }); coverage.assign_shortkeys(); coverage.wire_up_help_panel(); // Watch for page unload events so we can save the final sort settings: $(window).unload(function () { document.cookie = cookie_name + "=" + sort_list.toString() + "; path=/"; }); }; // -- pyfile stuff -- coverage.pyfile_ready = function ($) { // If we're directed to a particular line number, highlight the line. var frag = location.hash; if (frag.length > 2 && frag[1] === 'n') { $(frag).addClass('highlight'); coverage.set_sel(parseInt(frag.substr(2), 10)); } else { coverage.set_sel(0); } $(document) .bind('keydown', 'j', coverage.to_next_chunk_nicely) .bind('keydown', 'k', coverage.to_prev_chunk_nicely) .bind('keydown', '0', coverage.to_top) .bind('keydown', '1', coverage.to_first_chunk) ; $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.target, "run");}); $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.target, "exc");}); $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.target, "mis");}); $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.target, "par");}); coverage.assign_shortkeys(); coverage.wire_up_help_panel(); }; coverage.toggle_lines = function (btn, cls) { btn = $(btn); var hide = "hide_"+cls; if (btn.hasClass(hide)) { $("#source ."+cls).removeClass(hide); btn.removeClass(hide); } else { $("#source ."+cls).addClass(hide); btn.addClass(hide); } }; // Return the nth line div. coverage.line_elt = function (n) { return $("#t" + n); }; // Return the nth line number div. coverage.num_elt = function (n) { return $("#n" + n); }; // Return the container of all the code. coverage.code_container = function () { return $(".linenos"); }; // Set the selection. b and e are line numbers. coverage.set_sel = function (b, e) { // The first line selected. coverage.sel_begin = b; // The next line not selected. coverage.sel_end = (e === undefined) ? b+1 : e; }; coverage.to_top = function () { coverage.set_sel(0, 1); coverage.scroll_window(0); }; coverage.to_first_chunk = function () { coverage.set_sel(0, 1); coverage.to_next_chunk(); }; coverage.is_transparent = function (color) { // Different browsers return different colors for "none". return color === "transparent" || color === "rgba(0, 0, 0, 0)"; }; coverage.to_next_chunk = function () { var c = coverage; // Find the start of the next colored chunk. var probe = c.sel_end; while (true) { var probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } var color = probe_line.css("background-color"); if (!c.is_transparent(color)) { break; } probe++; } // There's a next chunk, `probe` points to it. var begin = probe; // Find the end of this chunk. var next_color = color; while (next_color === color) { probe++; probe_line = c.line_elt(probe); next_color = probe_line.css("background-color"); } c.set_sel(begin, probe); c.show_selection(); }; coverage.to_prev_chunk = function () { var c = coverage; // Find the end of the prev colored chunk. var probe = c.sel_begin-1; var probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } var color = probe_line.css("background-color"); while (probe > 0 && c.is_transparent(color)) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } color = probe_line.css("background-color"); } // There's a prev chunk, `probe` points to its last line. var end = probe+1; // Find the beginning of this chunk. var prev_color = color; while (prev_color === color) { probe--; probe_line = c.line_elt(probe); prev_color = probe_line.css("background-color"); } c.set_sel(probe+1, end); c.show_selection(); }; // Return the line number of the line nearest pixel position pos coverage.line_at_pos = function (pos) { var l1 = coverage.line_elt(1), l2 = coverage.line_elt(2), result; if (l1.length && l2.length) { var l1_top = l1.offset().top, line_height = l2.offset().top - l1_top, nlines = (pos - l1_top) / line_height; if (nlines < 1) { result = 1; } else { result = Math.ceil(nlines); } } else { result = 1; } return result; }; // Returns 0, 1, or 2: how many of the two ends of the selection are on // the screen right now? coverage.selection_ends_on_screen = function () { if (coverage.sel_begin === 0) { return 0; } var top = coverage.line_elt(coverage.sel_begin); var next = coverage.line_elt(coverage.sel_end-1); return ( (top.isOnScreen() ? 1 : 0) + (next.isOnScreen() ? 1 : 0) ); }; coverage.to_next_chunk_nicely = function () { coverage.finish_scrolling(); if (coverage.selection_ends_on_screen() === 0) { // The selection is entirely off the screen: select the top line on // the screen. var win = $(window); coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); } coverage.to_next_chunk(); }; coverage.to_prev_chunk_nicely = function () { coverage.finish_scrolling(); if (coverage.selection_ends_on_screen() === 0) { var win = $(window); coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height())); } coverage.to_prev_chunk(); }; // Select line number lineno, or if it is in a colored chunk, select the // entire chunk coverage.select_line_or_chunk = function (lineno) { var c = coverage; var probe_line = c.line_elt(lineno); if (probe_line.length === 0) { return; } var the_color = probe_line.css("background-color"); if (!c.is_transparent(the_color)) { // The line is in a highlighted chunk. // Search backward for the first line. var probe = lineno; var color = the_color; while (probe > 0 && color === the_color) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { break; } color = probe_line.css("background-color"); } var begin = probe + 1; // Search forward for the last line. probe = lineno; color = the_color; while (color === the_color) { probe++; probe_line = c.line_elt(probe); color = probe_line.css("background-color"); } coverage.set_sel(begin, probe); } else { coverage.set_sel(lineno); } }; coverage.show_selection = function () { var c = coverage; // Highlight the lines in the chunk c.code_container().find(".highlight").removeClass("highlight"); for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { c.num_elt(probe).addClass("highlight"); } c.scroll_to_selection(); }; coverage.scroll_to_selection = function () { // Scroll the page if the chunk isn't fully visible. if (coverage.selection_ends_on_screen() < 2) { // Need to move the page. The html,body trick makes it scroll in all // browsers, got it from http://stackoverflow.com/questions/3042651 var top = coverage.line_elt(coverage.sel_begin); var top_pos = parseInt(top.offset().top, 10); coverage.scroll_window(top_pos - 30); } }; coverage.scroll_window = function (to_pos) { $("html,body").animate({scrollTop: to_pos}, 200); }; coverage.finish_scrolling = function () { $("html,body").stop(true, true); }; python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/m3.html0000644000175000017500000000562412215441062024400 0ustar barrybarry Coverage for m3: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m3a = 1 

    m3b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/keybd_closed.png0000644000175000017500000000041012215441077026322 0ustar barrybarry‰PNG  IHDR# è#ºsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ ÚòÕWˆIDAT8ËÍ•K€ D§Æ-×lÏ×äug¥|Dâ¬JCÉd^ãRLÖþfXuž"–7™¹ëˆ4Õ1Æâw3#†Z圳ӱŒ„*”æb2w†™k†.1{ïÏsKÎ1­@Ö©‚j-¦¢ÓSü¹,t&¦#Ÿ«cGt¦(ýé;8Õ¶˜§f·AIEND®B`‚python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/m1.html0000644000175000017500000000562412215441062024376 0ustar barrybarry Coverage for m1: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m1a = 1 

    m1b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/status.dat0000644000175000017500000000223612215441077025212 0ustar barrybarry(dp1 S'files' p2 (dp3 S'main' p4 (dp5 S'index' p6 (dp7 S'html_filename' p8 S'main.html' p9 sS'name' p10 g4 sS'nums' p11 ccopy_reg _reconstructor p12 (ccoverage.results Numbers p13 c__builtin__ object p14 NtRp15 (dp16 S'n_files' p17 I1 sS'n_branches' p18 I0 sS'n_statements' p19 I8 sS'n_excluded' p20 I0 sS'n_partial_branches' p21 I0 sS'n_missing' p22 I0 sS'n_missing_branches' p23 I0 sbssS'hash' p24 S'\xcbCI\xb8\r\x11fY5\x9f`d\x15\xdc\x95\x96' p25 ssS'm1' p26 (dp27 g6 (dp28 g8 S'm1.html' p29 sg10 g26 sg11 g12 (g13 g14 NtRp30 (dp31 g17 I1 sg18 I0 sg19 I2 sg20 I0 sg21 I0 sg22 I0 sg23 I0 sbssg24 S'\xbb\xfe\x89 +\xe0\x7fmyvs,\xb5y\xe8@' p32 ssS'm3' p33 (dp34 g6 (dp35 g8 S'm3.html' p36 sg10 g33 sg11 g12 (g13 g14 NtRp37 (dp38 g17 I1 sg18 I0 sg19 I2 sg20 I0 sg21 I0 sg22 I0 sg23 I0 sbssg24 S'\x87F\xfe\x94\xf4\x82/\xe2\xe2\xab\xd9\x8e\xab\xd5A\xcc' p39 ssS'm2' p40 (dp41 g6 (dp42 g8 S'm2.html' p43 sg10 g40 sg11 g12 (g13 g14 NtRp44 (dp45 g17 I1 sg18 I0 sg19 I2 sg20 I0 sg21 I0 sg22 I0 sg23 I0 sbssg24 S'\xda,\xfd4\xe9o\xfa\xccp\xde\xaag\xd8\xe6"\xd3' p46 sssS'version' p47 S'3.6.1a1' p48 sS'settings' p49 S'M\x7f#\xfa\xd2=\xc0\xc5s\x14\xe2\xb5\xfa\x14H\xd3' p50 sS'format' p51 I1 s.python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/htmlcov/index.html0000644000175000017500000000656012215441077025176 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 14 0 0 100%
    m1 2 0 0 100%
    m2 2 0 0 100%
    m3 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/run_a_xml_2.ini0000644000175000017500000000010712202156243024414 0ustar barrybarry# Put all the XML output in xml_2 [xml] output = ../xml_2/coverage.xml python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/unicode.py0000644000175000017500000000021212202156243023503 0ustar barrybarry# A python source file with exotic characters # -*- coding: utf-8 -*- upside_down = "ÊŽdË™ÇbÉɹÇÊŒoÉ”" surrogate = "db40,dd00: xó „€" python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/y.py0000644000175000017500000000021612202156243022331 0ustar barrybarry# A test file for XML reporting by coverage. def choice(x): if x < 2: return 3 else: return 4 assert choice(1) == 3 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/partial.py0000644000175000017500000000024012202156243023512 0ustar barrybarry# partial branches a = 3 while True: break while 1: break while a: # pragma: no branch break if 0: never_happen() if 1: a = 13 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/isolatin1.py0000644000175000017500000000017412202156243023767 0ustar barrybarry# A python source file in another encoding. # -*- coding: iso8859-1 -*- math = "3×4 = 12, ÷2 = 6±0" assert len(math) == 18 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/main.py0000644000175000017500000000014512202156243023006 0ustar barrybarryimport m1 import m2 import m3 a = 5 b = 6 assert m1.m1a == 1 assert m2.m2a == 1 assert m3.m3a == 1 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/omit5.ini0000644000175000017500000000015012202156243023242 0ustar barrybarry[report] omit = fooey gooey, m[23]*, kablooey helloworld [html] directory = ../html_omit_5 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/a.py0000644000175000017500000000017612202156243022306 0ustar barrybarry# A test file for HTML reporting by coverage. if 1 < 2: # Needed a < to look at HTML entities. a = 3 else: a = 4 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/extra.css0000644000175000017500000000007012202156243023342 0ustar barrybarry/* Doesn't matter what goes in here, it gets copied. */ python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/tabbed.py0000644000175000017500000000023712202156243023305 0ustar barrybarry# This file should have tabs. x = 1 if x: a = "Tabbed" # Aligned comments if x: # look nice b = "No spaces" # when they c = "Done" # line up. python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/m2.py0000644000175000017500000000002012202156243022370 0ustar barrybarrym2a = 1 m2b = 2 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/m1.py0000644000175000017500000000002012202156243022367 0ustar barrybarrym1a = 1 m1b = 2 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/here.py0000644000175000017500000000014112202156243023001 0ustar barrybarry# A test file for HTML reporting by coverage. import other if 1 < 2: h = 3 else: h = 4 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/b.py0000644000175000017500000000073012202156243022303 0ustar barrybarry# A test file for HTML reporting by coverage. def one(x): # This will be a branch that misses the else. if x < 2: a = 3 else: a = 4 one(1) def two(x): # A missed else that branches to "exit" if x: a = 5 two(1) def three(): try: # This if has two branches, *neither* one taken. if name_error_this_variable_doesnt_exist: a = 1 else: a = 2 except: pass three() python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/omit4.ini0000644000175000017500000000002612202156243023243 0ustar barrybarry[report] omit = m2.py python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/m3.py0000644000175000017500000000002012202156243022371 0ustar barrybarrym3a = 1 m3b = 2 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/coverage.xml0000644000175000017500000000131412215600116024021 0ustar barrybarry python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/src/bom.py0000644000175000017500000000042412202156243022637 0ustar barrybarry# A python source file in utf-8, with BOM math = "3×4 = 12, ÷2 = 6±0" import sys if sys.version_info >= (3, 0): assert len(math) == 18 assert len(math.encode('utf-8')) == 21 else: assert len(math) == 21 assert len(math.decode('utf-8')) == 18 python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_4/0000755000175000017500000000000012252501325023121 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_4/main.html0000644000175000017500000001116212224243313024733 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_4/m3.html0000644000175000017500000000571712224243313024337 0ustar barrybarry Coverage for m3: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m3a = 1 

    m3b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_4/m1.html0000644000175000017500000000571712224243313024335 0ustar barrybarry Coverage for m1: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m1a = 1 

    m1b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_4/index.html0000644000175000017500000000612212224243313025116 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 12 0 0 100%
    m1 2 0 0 100%
    m3 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_a.py0000644000175000017500000000160512202156243022401 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for a.""" import coverage cov = coverage.coverage() cov.start() import a # pragma: nested cov.stop() # pragma: nested cov.html_report(a, directory="../html_a") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_a", "html_a", size_within=10, file_pattern="*.html") contains("html_a/a.html", "if 1 < 2", "    a = 3", "67%" ) contains("html_a/index.html", "a", "67%" ) clean("html_a") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_omit_2.py0000644000175000017500000000063612202156242023354 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for main.""" import coverage cov = coverage.coverage() cov.start() import main # pragma: nested cov.stop() # pragma: nested cov.html_report(directory="../html_omit_2", omit=["m1.py"]) runfunc(html_it, rundir="src") compare("gold_omit_2", "html_omit_2", size_within=10, file_pattern="*.html") clean("html_omit_2") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_unicode/0000755000175000017500000000000012252501325023354 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_unicode/unicode.html0000644000175000017500000000701012224243313025665 0ustar barrybarry Coverage for unicode: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    # A python source file with exotic characters 

    # -*- coding: utf-8 -*- 

     

    upside_down = "ʎd˙ǝbɐɹǝʌoɔ" 

    surrogate = "db40,dd00: x�� 󠄀" 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_unicode/index.html0000644000175000017500000000507512224243313025357 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 1 0 0 100%
    unicode 1 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_5/0000755000175000017500000000000012252501325023122 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_5/main.html0000644000175000017500000001116212224243313024734 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_5/m1.html0000644000175000017500000000571712224243313024336 0ustar barrybarry Coverage for m1: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m1a = 1 

    m1b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_5/index.html0000644000175000017500000000550312224243313025121 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 10 0 0 100%
    m1 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_partial.py0000644000175000017500000000203312233013371023607 0ustar barrybarryimport sys def html_it(): """Run coverage and make an HTML report for partial.""" import coverage cov = coverage.coverage(branch=True) cov.start() import partial # pragma: nested cov.stop() # pragma: nested cov.html_report(partial, directory="../html_partial") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_partial", "html_partial", size_within=10, file_pattern="*.html") contains("html_partial/partial.html", "

    ", "

    ", "

    ", # The "if 0" and "if 1" statements are optimized away. "

    ", ) contains("html_partial/index.html", "partial", ) if sys.version_info >= (2, 4): contains("html_partial/index.html", "100%" ) clean("html_partial") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_isolatin1.py0000644000175000017500000000131112202156242024055 0ustar barrybarryimport sys def html_it(): """Run coverage and make an HTML report for isolatin1.py.""" import coverage cov = coverage.coverage() cov.start() import isolatin1 # pragma: nested cov.stop() # pragma: nested cov.html_report(isolatin1, directory="../html_isolatin1") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_isolatin1", "html_isolatin1", size_within=10, file_pattern="*.html") contains("html_isolatin1/isolatin1.html", ""3×4 = 12, ÷2 = 6±0"", ) clean("html_isolatin1") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_b_branch/0000755000175000017500000000000012252501325023464 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_b_branch/b.html0000644000175000017500000002120512224243313024572 0ustar barrybarry Coverage for b: 76%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    # A test file for HTML reporting by coverage. 

     

    def one(x): 

        # This will be a branch that misses the else. 

    8    if x < 2: 

            a = 3 

        else: 

            a = 4 

     

    one(1) 

     

    def two(x): 

        # A missed else that branches to "exit" 

    exit    if x: 

            a = 5 

     

    two(1) 

     

    def three_way(): 

        # for-else can be a three-way branch. 

    25   26    for i in range(10): 

            if i == 3: 

                break 

        else: 

            return 23 

        return 17 

     

    three_way() 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_b_branch/index.html0000644000175000017500000000560312224243313025464 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x b p c   change column sorting

    Module statements missing excluded branches partial coverage
    Total 16 2 0 9 4 76%
    b 16 2 0 9 4 76%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_omit_4.py0000644000175000017500000000064512202156243023357 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for main.""" import coverage cov = coverage.coverage(config_file="omit4.ini") cov.start() import main # pragma: nested cov.stop() # pragma: nested cov.html_report(directory="../html_omit_4") runfunc(html_it, rundir="src") compare("gold_omit_4", "html_omit_4", size_within=10, file_pattern="*.html") clean("html_omit_4") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_styled.py0000644000175000017500000000220612202156243023463 0ustar barrybarrydef html_it(): """Run coverage and make an HTML report for a.""" import coverage cov = coverage.coverage() cov.start() import a # pragma: nested cov.stop() # pragma: nested cov.html_report(a, directory="../html_styled", extra_css="extra.css") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_styled", "html_styled", size_within=10, file_pattern="*.html") compare("gold_styled", "html_styled", size_within=10, file_pattern="*.css") contains("html_styled/a.html", "", "if 1 < 2", "    a = 3", "67%" ) contains("html_styled/index.html", "", "a", "67%" ) clean("html_styled") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/othersrc/0000755000175000017500000000000012252501325022552 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/othersrc/other.py0000644000175000017500000000016612202156243024250 0ustar barrybarry# A file in another directory. We're checking that it ends up in the # HTML report. print("This is the other src!") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_2/0000755000175000017500000000000012252501325023117 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_2/m2.html0000644000175000017500000000571712224243313024334 0ustar barrybarry Coverage for m2: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m2a = 1 

    m2b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_2/main.html0000644000175000017500000001116212224243313024731 0ustar barrybarry Coverage for main: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    import m1 

    import m2 

    import m3 

     

    a = 5 

    b = 6 

     

    assert m1.m1a == 1 

    assert m2.m2a == 1 

    assert m3.m3a == 1 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_2/m3.html0000644000175000017500000000571712224243313024335 0ustar barrybarry Coverage for m3: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    m3a = 1 

    m3b = 2 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_omit_2/index.html0000644000175000017500000000612212224243313025114 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 12 0 0 100%
    m2 2 0 0 100%
    m3 2 0 0 100%
    main 8 0 0 100%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_y_xml_branch/0000755000175000017500000000000012252501325024373 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_y_xml_branch/coverage.xml0000644000175000017500000000143612202156243026714 0ustar barrybarry python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/run_bom.py0000644000175000017500000000121112202156242022726 0ustar barrybarryimport sys def html_it(): """Run coverage and make an HTML report for bom.py.""" import coverage cov = coverage.coverage() cov.start() import bom # pragma: nested cov.stop() # pragma: nested cov.html_report(bom, directory="../html_bom") runfunc(html_it, rundir="src") # HTML files will change often. Check that the sizes are reasonable, # and check that certain key strings are in the output. compare("gold_bom", "html_bom", size_within=10, file_pattern="*.html") contains("html_bom/bom.html", ""3×4 = 12, ÷2 = 6±0"", ) clean("html_bom") python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_other/0000755000175000017500000000000012252501325023047 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_other/here.html0000644000175000017500000000772412224243313024671 0ustar barrybarry Coverage for here: 75%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    5

    6

    7

    8

    # A test file for HTML reporting by coverage. 

     

    import other 

     

    if 1 < 2: 

        h = 3 

    else: 

        h = 4 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_other/blah_blah_other.html0000644000175000017500000000655612224243313027045 0ustar barrybarry Coverage for /home/ned/coverage/trunk/tests/farm/html/othersrc/other: 100%

    Hot-keys on this page

    r m x p   toggle line displays

    j k   next/prev highlighted chunk

    0   (zero) top of page

    1   (one) first highlighted chunk

    1

    2

    3

    4

    # A file in another directory.  We're checking that it ends up in the 

    # HTML report. 

     

    print("This is the other src!") 

    python-coverage-3.7.1+dfsg.1.orig/tests/farm/html/gold_other/index.html0000644000175000017500000000565112224243313025052 0ustar barrybarry Coverage report

    Hot-keys on this page

    n s m x c   change column sorting

    Module statements missing excluded coverage
    Total 5 1 0 80%
    /home/ned/coverage/trunk/tests/farm/html/othersrc/other 1 0 0 100%
    here 4 1 0 75%
    python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/0000755000175000017500000000000012252501325021566 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/run.py0000644000175000017500000000022612202156243022744 0ustar barrybarrycopy("src", "out") run(""" coverage -e -x white.py coverage -a white.py """, rundir="out") compare("out", "gold", "*,cover") clean("out") python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold/0000755000175000017500000000000012252501325022513 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold/white.py,cover0000644000175000017500000000101712202156243025317 0ustar barrybarry # A test case sent to me by Steve White > def f(self): ! if self==1: ! pass ! elif self.m('fred'): ! pass ! elif (g==1) and (b==2): ! pass ! elif self.m('fred')==True: ! pass ! elif ((g==1) and (b==2))==True: ! pass ! else: ! pass > def g(x): > if x == 1: > a = 1 ! else: ! a = 2 > g(1) > def h(x): - if 0: #pragma: no cover - pass > if x == 1: ! a = 1 > else: > a = 2 > h(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/0000755000175000017500000000000012252501325023725 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/b/0000755000175000017500000000000012252501325024146 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/b/__init__.py,cover0000644000175000017500000000000012202156243027360 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/b/b.py,cover0000644000175000017500000000004612202156243026054 0ustar barrybarry> def b(x): > print "x is %s" % x python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/a/0000755000175000017500000000000012252501325024145 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/a/a.py,cover0000644000175000017500000000013712202156243026053 0ustar barrybarry> def a(x): > if x == 1: > print "x is 1" ! else: ! print "x is not 1" python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/a/__init__.py,cover0000644000175000017500000000000012202156243027357 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_multi/multi.py,cover0000644000175000017500000000006312202156243026543 0ustar barrybarry> import a.a > import b.b > a.a.a(1) > b.b.b(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/run_multi.py0000644000175000017500000000025312202156243024156 0ustar barrybarrycopy("src", "out_multi") run(""" coverage -e -x multi.py coverage -a """, rundir="out_multi") compare("out_multi", "gold_multi", "*,cover") clean("out_multi") python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_v24/0000755000175000017500000000000012252501325023206 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_v24/white.py,cover0000644000175000017500000000101712202156243026012 0ustar barrybarry # A test case sent to me by Steve White > def f(self): ! if self==1: ! pass ! elif self.m('fred'): ! pass ! elif (g==1) and (b==2): ! pass ! elif self.m('fred')==True: ! pass ! elif ((g==1) and (b==2))==True: ! pass > else: ! pass > def g(x): > if x == 1: > a = 1 ! else: ! a = 2 > g(1) > def h(x): - if 0: #pragma: no cover - pass > if x == 1: ! a = 1 > else: > a = 2 > h(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/0000755000175000017500000000000012252501325022355 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/multi.py0000644000175000017500000000005112202156243024055 0ustar barrybarryimport a.a import b.b a.a.a(1) b.b.b(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/b/0000755000175000017500000000000012252501325022576 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/b/__init__.py0000644000175000017500000000000012202156243024675 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/b/b.py0000644000175000017500000000006112202156243023366 0ustar barrybarrydef b(x): msg = "x is %s" % x print(msg) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/a/0000755000175000017500000000000012252501325022575 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/a/a.py0000644000175000017500000000012712202156243023367 0ustar barrybarrydef a(x): if x == 1: print("x is 1") else: print("x is not 1") python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/a/__init__.py0000644000175000017500000000000012202156243024674 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/src/white.py0000644000175000017500000000071512202156243024052 0ustar barrybarry# A test case sent to me by Steve White def f(self): if self==1: pass elif self.m('fred'): pass elif (g==1) and (b==2): pass elif self.m('fred')==True: pass elif ((g==1) and (b==2))==True: pass else: pass def g(x): if x == 1: a = 1 else: a = 2 g(1) def h(x): if 0: #pragma: no cover pass if x == 1: a = 1 else: a = 2 h(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/annotate_dir.py0000644000175000017500000000030412202156242024603 0ustar barrybarrycopy("src", "run") run(""" coverage -e -x multi.py coverage -a -d out_anno_dir """, rundir="run") compare("run/out_anno_dir", "gold_anno_dir", "*,cover", left_extra=True) clean("run") python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/0000755000175000017500000000000012252501325024364 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/a_a.py,cover0000644000175000017500000000014112202156243026565 0ustar barrybarry> def a(x): > if x == 1: > print("x is 1") ! else: ! print("x is not 1") python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/a___init__.py,cover0000644000175000017500000000000012202156243030076 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/b_b.py,cover0000644000175000017500000000006712202156243026576 0ustar barrybarry> def b(x): > msg = "x is %s" % x > print(msg) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/multi.py,cover0000644000175000017500000000006312202156243027202 0ustar barrybarry> import a.a > import b.b > a.a.a(1) > b.b.b(2) python-coverage-3.7.1+dfsg.1.orig/tests/farm/annotate/gold_anno_dir/b___init__.py,cover0000644000175000017500000000000012202156243030077 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/run/0000755000175000017500000000000012252501325020561 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/run/run_chdir.py0000644000175000017500000000043212202156243023107 0ustar barrybarrycopy("src", "out") run(""" coverage run chdir.py coverage -r """, rundir="out", outfile="stdout.txt") contains("out/stdout.txt", "Line One", "Line Two", "chdir" ) doesnt_contain("out/stdout.txt", "No such file or directory") clean("out") python-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/0000755000175000017500000000000012252501325021350 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/chdir.py0000644000175000017500000000010112202156242023002 0ustar barrybarryimport os print("Line One") os.chdir("subdir") print("Line Two") python-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/showtrace.py0000644000175000017500000000145512202156242023725 0ustar barrybarry# Show the current frame's trace function, so that we can test what the # command-line options do to the trace function used. import sys # Show what the trace function is. If a C-based function is used, then f_trace # may be None. trace_fn = sys._getframe(0).f_trace if trace_fn is None: trace_name = "None" else: # Get the name of the tracer class. Py3k has a different way to get it. try: trace_name = trace_fn.im_class.__name__ except AttributeError: try: trace_name = trace_fn.__self__.__class__.__name__ except AttributeError: # A C-based function could also manifest as an f_trace value # which doesn't have im_class or __self__. trace_name = trace_fn.__class__.__name__ print("%s %s" % (sys.argv[1], trace_name)) python-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/subdir/0000755000175000017500000000000012252501325022640 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/subdir/placeholder0000644000175000017500000000000012202156242025032 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/farm/run/src/xxx0000644000175000017500000000025512202156242022123 0ustar barrybarry# This is a python file though it doesn't look like it, like a main script. a = b = c = d = 0 a = 3 b = 4 if not b: c = 6 d = 7 print("xxx: %r %r %r %r" % (a, b, c, d)) python-coverage-3.7.1+dfsg.1.orig/tests/farm/run/run_xxx.py0000644000175000017500000000055112202156243022647 0ustar barrybarrycopy("src", "out") run(""" coverage -e -x xxx coverage -r """, rundir="out", outfile="stdout.txt") contains("out/stdout.txt", "xxx: 3 4 0 7", "\nxxx ", # The reporting line for xxx " 7 1 86%" # The reporting data for xxx ) doesnt_contain("out/stdout.txt", "No such file or directory") clean("out") python-coverage-3.7.1+dfsg.1.orig/tests/farm/run/run_timid.py0000644000175000017500000000364012202156243023130 0ustar barrybarry# Test that the --timid command line argument properly swaps the tracer # function for a simpler one. # # This is complicated by the fact that the tests are run twice for each # version: once with a compiled C-based trace function, and once without # it, to also test the Python trace function. So this test has to examine # an environment variable set in igor.py to know whether to expect to see # the C trace function or not. import os # When meta-coverage testing, this test doesn't work, because it finds # coverage.py's own trace function. if os.environ.get('COVERAGE_COVERAGE', ''): skip("Can't test timid during coverage measurement.") copy("src", "out") run(""" python showtrace.py none coverage -e -x showtrace.py regular coverage -e -x --timid showtrace.py timid """, rundir="out", outfile="showtraceout.txt") # When running without coverage, no trace function # When running timidly, the trace function is always Python. contains("out/showtraceout.txt", "none None", "timid PyTracer", ) if os.environ.get('COVERAGE_TEST_TRACER', 'c') == 'c': # If the C trace function is being tested, then regular running should have # the C function, which registers itself as f_trace. contains("out/showtraceout.txt", "regular CTracer") else: # If the Python trace function is being tested, then regular running will # also show the Python function. contains("out/showtraceout.txt", "regular PyTracer") # Try the environment variable. old_opts = os.environ.get('COVERAGE_OPTIONS') os.environ['COVERAGE_OPTIONS'] = '--timid' run(""" coverage -e -x showtrace.py regular coverage -e -x --timid showtrace.py timid """, rundir="out", outfile="showtraceout.txt") contains("out/showtraceout.txt", "none None", "timid PyTracer", "regular PyTracer", ) if old_opts: os.environ['COVERAGE_OPTIONS'] = old_opts else: del os.environ['COVERAGE_OPTIONS'] clean("out") python-coverage-3.7.1+dfsg.1.orig/tests/test_results.py0000644000175000017500000000470312202156243022146 0ustar barrybarry"""Tests for Coverage.py's results analysis.""" from coverage.results import Numbers from tests.coveragetest import CoverageTest class NumbersTest(CoverageTest): """Tests for Coverage.py's numeric measurement summaries.""" run_in_temp_dir = False def test_basic(self): n1 = Numbers(n_files=1, n_statements=200, n_missing=20) self.assertEqual(n1.n_statements, 200) self.assertEqual(n1.n_executed, 180) self.assertEqual(n1.n_missing, 20) self.assertEqual(n1.pc_covered, 90) def test_addition(self): n1 = Numbers(n_files=1, n_statements=200, n_missing=20) n2 = Numbers(n_files=1, n_statements=10, n_missing=8) n3 = n1 + n2 self.assertEqual(n3.n_files, 2) self.assertEqual(n3.n_statements, 210) self.assertEqual(n3.n_executed, 182) self.assertEqual(n3.n_missing, 28) self.assertAlmostEqual(n3.pc_covered, 86.666666666) def test_sum(self): n1 = Numbers(n_files=1, n_statements=200, n_missing=20) n2 = Numbers(n_files=1, n_statements=10, n_missing=8) n3 = sum([n1, n2]) self.assertEqual(n3.n_files, 2) self.assertEqual(n3.n_statements, 210) self.assertEqual(n3.n_executed, 182) self.assertEqual(n3.n_missing, 28) self.assertAlmostEqual(n3.pc_covered, 86.666666666) def test_pc_covered_str(self): n0 = Numbers(n_files=1, n_statements=1000, n_missing=0) n1 = Numbers(n_files=1, n_statements=1000, n_missing=1) n999 = Numbers(n_files=1, n_statements=1000, n_missing=999) n1000 = Numbers(n_files=1, n_statements=1000, n_missing=1000) self.assertEqual(n0.pc_covered_str, "100") self.assertEqual(n1.pc_covered_str, "99") self.assertEqual(n999.pc_covered_str, "1") self.assertEqual(n1000.pc_covered_str, "0") def test_pc_covered_str_precision(self): assert Numbers._precision == 0 Numbers.set_precision(1) n0 = Numbers(n_files=1, n_statements=10000, n_missing=0) n1 = Numbers(n_files=1, n_statements=10000, n_missing=1) n9999 = Numbers(n_files=1, n_statements=10000, n_missing=9999) n10000 = Numbers(n_files=1, n_statements=10000, n_missing=10000) self.assertEqual(n0.pc_covered_str, "100.0") self.assertEqual(n1.pc_covered_str, "99.9") self.assertEqual(n9999.pc_covered_str, "0.1") self.assertEqual(n10000.pc_covered_str, "0.0") Numbers.set_precision(0) python-coverage-3.7.1+dfsg.1.orig/tests/stress_phystoken_dos.tok0000644000175000017500000000174512202156243024052 0ustar barrybarry# Here's some random Python so that test_tokenize_myself will have some # stressful stuff to try. This file is .tok instead of .py so pylint won't # complain about it, check_eol won't look at it, etc. first_back = """\ hey there! """ other_back = """ hey \ there """ lots_of_back = """\ hey \ there """ # This next line is supposed to have trailing whitespace: fake_back = """\ ouch """ # Lots of difficulty happens with code like: # # fake_back = """\ # ouch # """ # # Ugh, the edge cases... # What about a comment like this\ "what's this string doing here?" class C(object): def there(): this = 5 + \ 7 that = \ "a continued line" cont1 = "one line of text" + \ "another line of text" a_long_string = \ "part 1" \ "2" \ "3 is longer" def hello(): print("Hello world!") hello() python-coverage-3.7.1+dfsg.1.orig/tests/test_html.py0000644000175000017500000003263312233013371021412 0ustar barrybarry# -*- coding: utf-8 -*- """Tests that HTML generation is awesome.""" import os.path, re, sys import coverage import coverage.html from coverage.misc import CoverageException, NotPython, NoSource from tests.coveragetest import CoverageTest class HtmlTestHelpers(CoverageTest): """Methods that help with HTML tests.""" def create_initial_files(self): """Create the source files we need to run these tests.""" self.make_file("main_file.py", """\ import helper1, helper2 helper1.func1(12) helper2.func2(12) """) self.make_file("helper1.py", """\ def func1(x): if x % 2: print("odd") """) self.make_file("helper2.py", """\ def func2(x): print("x is %d" % x) """) def run_coverage(self, covargs=None, htmlargs=None): """Run coverage on main_file.py, and create an HTML report.""" self.clean_local_file_imports() cov = coverage.coverage(**(covargs or {})) self.start_import_stop(cov, "main_file") cov.html_report(**(htmlargs or {})) def remove_html_files(self): """Remove the HTML files created as part of the HTML report.""" os.remove("htmlcov/index.html") os.remove("htmlcov/main_file.html") os.remove("htmlcov/helper1.html") os.remove("htmlcov/helper2.html") class HtmlDeltaTest(HtmlTestHelpers, CoverageTest): """Tests of the HTML delta speed-ups.""" def setUp(self): super(HtmlDeltaTest, self).setUp() # At least one of our tests monkey-patches the version of coverage, # so grab it here to restore it later. self.real_coverage_version = coverage.__version__ def tearDown(self): coverage.__version__ = self.real_coverage_version super(HtmlDeltaTest, self).tearDown() def test_html_created(self): # Test basic HTML generation: files should be created. self.create_initial_files() self.run_coverage() self.assert_exists("htmlcov/index.html") self.assert_exists("htmlcov/main_file.html") self.assert_exists("htmlcov/helper1.html") self.assert_exists("htmlcov/helper2.html") self.assert_exists("htmlcov/style.css") self.assert_exists("htmlcov/coverage_html.js") def test_html_delta_from_source_change(self): # HTML generation can create only the files that have changed. # In this case, helper1 changes because its source is different. self.create_initial_files() self.run_coverage() index1 = open("htmlcov/index.html").read() self.remove_html_files() # Now change a file and do it again self.make_file("helper1.py", """\ def func1(x): # A nice function if x % 2: print("odd") """) self.run_coverage() # Only the changed files should have been created. self.assert_exists("htmlcov/index.html") self.assert_exists("htmlcov/helper1.html") self.assert_doesnt_exist("htmlcov/main_file.html") self.assert_doesnt_exist("htmlcov/helper2.html") index2 = open("htmlcov/index.html").read() self.assertMultiLineEqual(index1, index2) def test_html_delta_from_coverage_change(self): # HTML generation can create only the files that have changed. # In this case, helper1 changes because its coverage is different. self.create_initial_files() self.run_coverage() self.remove_html_files() # Now change a file and do it again self.make_file("main_file.py", """\ import helper1, helper2 helper1.func1(23) helper2.func2(23) """) self.run_coverage() # Only the changed files should have been created. self.assert_exists("htmlcov/index.html") self.assert_exists("htmlcov/helper1.html") self.assert_exists("htmlcov/main_file.html") self.assert_doesnt_exist("htmlcov/helper2.html") def test_html_delta_from_settings_change(self): # HTML generation can create only the files that have changed. # In this case, everything changes because the coverage settings have # changed. self.create_initial_files() self.run_coverage(covargs=dict(omit=[])) index1 = open("htmlcov/index.html").read() self.remove_html_files() self.run_coverage(covargs=dict(omit=['xyzzy*'])) # All the files have been reported again. self.assert_exists("htmlcov/index.html") self.assert_exists("htmlcov/helper1.html") self.assert_exists("htmlcov/main_file.html") self.assert_exists("htmlcov/helper2.html") index2 = open("htmlcov/index.html").read() self.assertMultiLineEqual(index1, index2) def test_html_delta_from_coverage_version_change(self): # HTML generation can create only the files that have changed. # In this case, everything changes because the coverage version has # changed. self.create_initial_files() self.run_coverage() index1 = open("htmlcov/index.html").read() self.remove_html_files() # "Upgrade" coverage.py! coverage.__version__ = "XYZZY" self.run_coverage() # All the files have been reported again. self.assert_exists("htmlcov/index.html") self.assert_exists("htmlcov/helper1.html") self.assert_exists("htmlcov/main_file.html") self.assert_exists("htmlcov/helper2.html") index2 = open("htmlcov/index.html").read() fixed_index2 = index2.replace("XYZZY", self.real_coverage_version) self.assertMultiLineEqual(index1, fixed_index2) class HtmlTitleTest(HtmlTestHelpers, CoverageTest): """Tests of the HTML title support.""" def test_default_title(self): self.create_initial_files() self.run_coverage() index = open("htmlcov/index.html").read() self.assertIn("Coverage report", index) self.assertIn("

    Coverage report:", index) def test_title_set_in_config_file(self): self.create_initial_files() self.make_file(".coveragerc", "[html]\ntitle = Metrics & stuff!\n") self.run_coverage() index = open("htmlcov/index.html").read() self.assertIn("Metrics & stuff!", index) self.assertIn("

    Metrics & stuff!:", index) if sys.version_info[:2] != (3,1): def test_non_ascii_title_set_in_config_file(self): self.create_initial_files() self.make_file(".coveragerc", "[html]\ntitle = «ταБЬℓσ» numbers" ) self.run_coverage() index = open("htmlcov/index.html").read() self.assertIn( "«ταБЬℓσ»" " numbers", index ) self.assertIn( "<h1>«ταБЬℓσ»" " numbers", index ) def test_title_set_in_args(self): self.create_initial_files() self.make_file(".coveragerc", "[html]\ntitle = Good title\n") self.run_coverage(htmlargs=dict(title="«ταБЬℓσ» & stüff!")) index = open("htmlcov/index.html").read() self.assertIn( "<title>«ταБЬℓσ»" " & stüff!", index ) self.assertIn( "

    «ταБЬℓσ»" " & stüff!:", index ) class HtmlWithUnparsableFilesTest(CoverageTest): """Test the behavior when measuring unparsable files.""" def test_dotpy_not_python(self): self.make_file("innocuous.py", "a = 1") cov = coverage.coverage() self.start_import_stop(cov, "innocuous") self.make_file("innocuous.py", "

    This isn't python!

    ") self.assertRaisesRegexp( NotPython, "Couldn't parse '.*innocuous.py' as Python source: '.*' at line 1", cov.html_report ) def test_dotpy_not_python_ignored(self): self.make_file("innocuous.py", "a = 2") cov = coverage.coverage() self.start_import_stop(cov, "innocuous") self.make_file("innocuous.py", "

    This isn't python!

    ") cov.html_report(ignore_errors=True) self.assert_exists("htmlcov/index.html") # this would be better as a glob, if the html layout changes: self.assert_doesnt_exist("htmlcov/innocuous.html") def test_dothtml_not_python(self): # We run a .html file, and when reporting, we can't parse it as # Python. Since it wasn't .py, no error is reported. # Run an "html" file self.make_file("innocuous.html", "a = 3") self.run_command("coverage run innocuous.html") # Before reporting, change it to be an HTML file. self.make_file("innocuous.html", "

    This isn't python at all!

    ") output = self.run_command("coverage html") self.assertEqual(output.strip(), "No data to report.") def test_execed_liar_ignored(self): # Jinja2 sets __file__ to be a non-Python file, and then execs code. # If that file contains non-Python code, a TokenError shouldn't # have been raised when writing the HTML report. if sys.version_info < (3, 0): source = "exec compile('','','exec') in {'__file__': 'liar.html'}" else: source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" self.make_file("liar.py", source) self.make_file("liar.html", "{# Whoops, not python code #}") cov = coverage.coverage() self.start_import_stop(cov, "liar") cov.html_report() self.assert_exists("htmlcov/index.html") def test_execed_liar_ignored_indentation_error(self): # Jinja2 sets __file__ to be a non-Python file, and then execs code. # If that file contains untokenizable code, we shouldn't get an # exception. if sys.version_info < (3, 0): source = "exec compile('','','exec') in {'__file__': 'liar.html'}" else: source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" self.make_file("liar.py", source) # Tokenize will raise an IndentationError if it can't dedent. self.make_file("liar.html", "0\n 2\n 1\n") cov = coverage.coverage() self.start_import_stop(cov, "liar") cov.html_report() self.assert_exists("htmlcov/index.html") class HtmlTest(CoverageTest): """Moar HTML tests.""" def test_missing_source_file_incorrect_message(self): # https://bitbucket.org/ned/coveragepy/issue/60 self.make_file("thefile.py", "import sub.another\n") self.make_file("sub/__init__.py", "") self.make_file("sub/another.py", "print('another')\n") cov = coverage.coverage() self.start_import_stop(cov, 'thefile') os.remove("sub/another.py") missing_file = os.path.join(self.temp_dir, "sub", "another.py") missing_file = os.path.realpath(missing_file) self.assertRaisesRegexp( NoSource, "(?i)No source for code: '%s'" % re.escape(missing_file), cov.html_report ) class HtmlStaticFileTest(CoverageTest): """Tests of the static file copying for the HTML report.""" def setUp(self): super(HtmlStaticFileTest, self).setUp() self.original_path = list(coverage.html.STATIC_PATH) def tearDown(self): coverage.html.STATIC_PATH = self.original_path super(HtmlStaticFileTest, self).tearDown() def test_copying_static_files_from_system(self): # Make a new place for static files. self.make_file("static_here/jquery.min.js", "Not Really JQuery!") coverage.html.STATIC_PATH.insert(0, "static_here") self.make_file("main.py", "print(17)") cov = coverage.coverage() self.start_import_stop(cov, "main") cov.html_report() jquery = open("htmlcov/jquery.min.js").read() self.assertEqual(jquery, "Not Really JQuery!") def test_copying_static_files_from_system_in_dir(self): # Make a new place for static files. INSTALLED = [ "jquery/jquery.min.js", "jquery-hotkeys/jquery.hotkeys.js", "jquery-isonscreen/jquery.isonscreen.js", "jquery-tablesorter/jquery.tablesorter.min.js", ] for fpath in INSTALLED: self.make_file(os.path.join("static_here", fpath), "Not real.") coverage.html.STATIC_PATH.insert(0, "static_here") self.make_file("main.py", "print(17)") cov = coverage.coverage() self.start_import_stop(cov, "main") cov.html_report() for fpath in INSTALLED: the_file = os.path.basename(fpath) contents = open(os.path.join("htmlcov", the_file)).read() self.assertEqual(contents, "Not real.") def test_cant_find_static_files(self): # Make the path point to useless places. coverage.html.STATIC_PATH = ["/xyzzy"] self.make_file("main.py", "print(17)") cov = coverage.coverage() self.start_import_stop(cov, "main") self.assertRaisesRegexp( CoverageException, "Couldn't find static file '.*'", cov.html_report ) python-coverage-3.7.1+dfsg.1.orig/tests/eggsrc/0000755000175000017500000000000012252501325020302 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/eggsrc/egg1/0000755000175000017500000000000012252501325021125 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/eggsrc/egg1/egg1.py0000644000175000017500000000007212202156242022320 0ustar barrybarry# My egg file! walrus = "Eggman" says = "coo-coo cachoo" python-coverage-3.7.1+dfsg.1.orig/tests/eggsrc/egg1/__init__.py0000644000175000017500000000000012202156242023223 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/eggsrc/setup.py0000644000175000017500000000020612202156242022011 0ustar barrybarryfrom setuptools import setup setup( name="covtestegg1", packages=['egg1'], zip_safe=True, install_requires=[], ) python-coverage-3.7.1+dfsg.1.orig/tests/test_codeunit.py0000644000175000017500000001146312202156243022260 0ustar barrybarry"""Tests for coverage.codeunit""" import os, sys from coverage.codeunit import code_unit_factory from coverage.files import FileLocator from tests.coveragetest import CoverageTest # pylint: disable=F0401 # Unable to import 'aa' (No module named aa) class CodeUnitTest(CoverageTest): """Tests for coverage.codeunit""" run_in_temp_dir = False def setUp(self): super(CodeUnitTest, self).setUp() # Parent class saves and restores sys.path, we can just modify it. testmods = self.nice_file(os.path.dirname(__file__), 'modules') sys.path.append(testmods) def test_filenames(self): acu = code_unit_factory("aa/afile.py", FileLocator()) bcu = code_unit_factory("aa/bb/bfile.py", FileLocator()) ccu = code_unit_factory("aa/bb/cc/cfile.py", FileLocator()) self.assertEqual(acu[0].name, "aa/afile") self.assertEqual(bcu[0].name, "aa/bb/bfile") self.assertEqual(ccu[0].name, "aa/bb/cc/cfile") self.assertEqual(acu[0].flat_rootname(), "aa_afile") self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile") self.assertEqual(ccu[0].flat_rootname(), "aa_bb_cc_cfile") self.assertEqual(acu[0].source_file().read(), "# afile.py\n") self.assertEqual(bcu[0].source_file().read(), "# bfile.py\n") self.assertEqual(ccu[0].source_file().read(), "# cfile.py\n") def test_odd_filenames(self): acu = code_unit_factory("aa/afile.odd.py", FileLocator()) bcu = code_unit_factory("aa/bb/bfile.odd.py", FileLocator()) b2cu = code_unit_factory("aa/bb.odd/bfile.py", FileLocator()) self.assertEqual(acu[0].name, "aa/afile.odd") self.assertEqual(bcu[0].name, "aa/bb/bfile.odd") self.assertEqual(b2cu[0].name, "aa/bb.odd/bfile") self.assertEqual(acu[0].flat_rootname(), "aa_afile_odd") self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile_odd") self.assertEqual(b2cu[0].flat_rootname(), "aa_bb_odd_bfile") self.assertEqual(acu[0].source_file().read(), "# afile.odd.py\n") self.assertEqual(bcu[0].source_file().read(), "# bfile.odd.py\n") self.assertEqual(b2cu[0].source_file().read(), "# bfile.py\n") def test_modules(self): import aa, aa.bb, aa.bb.cc cu = code_unit_factory([aa, aa.bb, aa.bb.cc], FileLocator()) self.assertEqual(cu[0].name, "aa") self.assertEqual(cu[1].name, "aa.bb") self.assertEqual(cu[2].name, "aa.bb.cc") self.assertEqual(cu[0].flat_rootname(), "aa") self.assertEqual(cu[1].flat_rootname(), "aa_bb") self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc") self.assertEqual(cu[0].source_file().read(), "# aa\n") self.assertEqual(cu[1].source_file().read(), "# bb\n") self.assertEqual(cu[2].source_file().read(), "") # yes, empty def test_module_files(self): import aa.afile, aa.bb.bfile, aa.bb.cc.cfile cu = code_unit_factory([aa.afile, aa.bb.bfile, aa.bb.cc.cfile], FileLocator()) self.assertEqual(cu[0].name, "aa.afile") self.assertEqual(cu[1].name, "aa.bb.bfile") self.assertEqual(cu[2].name, "aa.bb.cc.cfile") self.assertEqual(cu[0].flat_rootname(), "aa_afile") self.assertEqual(cu[1].flat_rootname(), "aa_bb_bfile") self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc_cfile") self.assertEqual(cu[0].source_file().read(), "# afile.py\n") self.assertEqual(cu[1].source_file().read(), "# bfile.py\n") self.assertEqual(cu[2].source_file().read(), "# cfile.py\n") def test_comparison(self): acu = code_unit_factory("aa/afile.py", FileLocator())[0] acu2 = code_unit_factory("aa/afile.py", FileLocator())[0] zcu = code_unit_factory("aa/zfile.py", FileLocator())[0] bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())[0] assert acu == acu2 and acu <= acu2 and acu >= acu2 assert acu < zcu and acu <= zcu and acu != zcu assert zcu > acu and zcu >= acu and zcu != acu assert acu < bcu and acu <= bcu and acu != bcu assert bcu > acu and bcu >= acu and bcu != acu def test_egg(self): # Test that we can get files out of eggs, and read their source files. # The egg1 module is installed by an action in igor.py. import egg1, egg1.egg1 # Verify that we really imported from an egg. If we did, then the # __file__ won't be an actual file, because one of the "directories" # in the path is actually the .egg zip file. self.assert_doesnt_exist(egg1.__file__) cu = code_unit_factory([egg1, egg1.egg1], FileLocator()) self.assertEqual(cu[0].source_file().read(), "") self.assertEqual(cu[1].source_file().read().split("\n")[0], "# My egg file!" ) python-coverage-3.7.1+dfsg.1.orig/tests/coveragetest.py0000644000175000017500000004712512233013371022104 0ustar barrybarry"""Base test case class for coverage testing.""" import glob, imp, os, random, shlex, shutil, sys, tempfile, textwrap import atexit import coverage from coverage.backward import sorted, StringIO # pylint: disable=W0622 from coverage.backward import to_bytes from coverage.control import _TEST_NAME_FILE from tests.backtest import run_command from tests.backunittest import TestCase class Tee(object): """A file-like that writes to all the file-likes it has.""" def __init__(self, *files): """Make a Tee that writes to all the files in `files.`""" self._files = files if hasattr(files[0], "encoding"): self.encoding = files[0].encoding def write(self, data): """Write `data` to all the files.""" for f in self._files: f.write(data) if 0: # Use this if you need to use a debugger, though it makes some tests # fail, I'm not sure why... def __getattr__(self, name): return getattr(self._files[0], name) # Status returns for the command line. OK, ERR = 0, 1 class CoverageTest(TestCase): """A base class for Coverage test cases.""" # Our own setting: most CoverageTests run in their own temp directory. run_in_temp_dir = True # Standard unittest setting: show me diffs even if they are very long. maxDiff = None def setUp(self): super(CoverageTest, self).setUp() if _TEST_NAME_FILE: f = open(_TEST_NAME_FILE, "w") f.write("%s_%s" % (self.__class__.__name__, self._testMethodName)) f.close() # Tell newer unittest implementations to print long helpful messages. self.longMessage = True # tearDown will restore the original sys.path self.old_syspath = sys.path[:] if self.run_in_temp_dir: # Create a temporary directory. self.noise = str(random.random())[2:] self.temp_root = os.path.join(tempfile.gettempdir(), 'test_cover') self.temp_dir = os.path.join(self.temp_root, self.noise) os.makedirs(self.temp_dir) self.old_dir = os.getcwd() os.chdir(self.temp_dir) # Modules should be importable from this temp directory. We don't # use '' because we make lots of different temp directories and # nose's caching importer can get confused. The full path prevents # problems. sys.path.insert(0, os.getcwd()) # Keep a counter to make every call to check_coverage unique. self.n = 0 # Record environment variables that we changed with set_environ. self.environ_undos = {} # Capture stdout and stderr so we can examine them in tests. # nose keeps stdout from littering the screen, so we can safely Tee it, # but it doesn't capture stderr, so we don't want to Tee stderr to the # real stderr, since it will interfere with our nice field of dots. self.old_stdout = sys.stdout self.captured_stdout = StringIO() sys.stdout = Tee(sys.stdout, self.captured_stdout) self.old_stderr = sys.stderr self.captured_stderr = StringIO() sys.stderr = self.captured_stderr # Record sys.modules here so we can restore it in tearDown. self.old_modules = dict(sys.modules) class_behavior = self.class_behavior() class_behavior.tests += 1 class_behavior.test_method_made_any_files = False class_behavior.temp_dir = self.run_in_temp_dir def tearDown(self): super(CoverageTest, self).tearDown() # Restore the original sys.path. sys.path = self.old_syspath if self.run_in_temp_dir: # Get rid of the temporary directory. os.chdir(self.old_dir) shutil.rmtree(self.temp_root) # Restore the environment. self.undo_environ() # Restore stdout and stderr sys.stdout = self.old_stdout sys.stderr = self.old_stderr self.clean_modules() class_behavior = self.class_behavior() if class_behavior.test_method_made_any_files: class_behavior.tests_making_files += 1 def clean_modules(self): """Remove any new modules imported during the test run. This lets us import the same source files for more than one test. """ for m in [m for m in sys.modules if m not in self.old_modules]: del sys.modules[m] def set_environ(self, name, value): """Set an environment variable `name` to be `value`. The environment variable is set, and record is kept that it was set, so that `tearDown` can restore its original value. """ if name not in self.environ_undos: self.environ_undos[name] = os.environ.get(name) os.environ[name] = value def original_environ(self, name, if_missing=None): """The environment variable `name` from when the test started.""" if name in self.environ_undos: ret = self.environ_undos[name] else: ret = os.environ.get(name) if ret is None: ret = if_missing return ret def undo_environ(self): """Undo all the changes made by `set_environ`.""" for name, value in self.environ_undos.items(): if value is None: del os.environ[name] else: os.environ[name] = value def stdout(self): """Return the data written to stdout during the test.""" return self.captured_stdout.getvalue() def stderr(self): """Return the data written to stderr during the test.""" return self.captured_stderr.getvalue() def make_file(self, filename, text="", newline=None): """Create a temp file. `filename` is the path to the file, including directories if desired, and `text` is the content. If `newline` is provided, it is a string that will be used as the line endings in the created file. Returns the path to the file. """ # Tests that call `make_file` should be run in a temp environment. assert self.run_in_temp_dir self.class_behavior().test_method_made_any_files = True text = textwrap.dedent(text) if newline: text = text.replace("\n", newline) # Make sure the directories are available. dirs, _ = os.path.split(filename) if dirs and not os.path.exists(dirs): os.makedirs(dirs) # Create the file. f = open(filename, 'wb') try: f.write(to_bytes(text)) finally: f.close() return filename def clean_local_file_imports(self): """Clean up the results of calls to `import_local_file`. Use this if you need to `import_local_file` the same file twice in one test. """ # So that we can re-import files, clean them out first. self.clean_modules() # Also have to clean out the .pyc file, since the timestamp # resolution is only one second, a changed file might not be # picked up. for pyc in glob.glob('*.pyc'): os.remove(pyc) if os.path.exists("__pycache__"): shutil.rmtree("__pycache__") def import_local_file(self, modname): """Import a local file as a module. Opens a file in the current directory named `modname`.py, imports it as `modname`, and returns the module object. """ modfile = modname + '.py' f = open(modfile, 'r') for suff in imp.get_suffixes(): if suff[0] == '.py': break try: # pylint: disable=W0631 # (Using possibly undefined loop variable 'suff') mod = imp.load_module(modname, f, modfile, suff) finally: f.close() return mod def start_import_stop(self, cov, modname): """Start coverage, import a file, then stop coverage. `cov` is started and stopped, with an `import_local_file` of `modname` in the middle. The imported module is returned. """ cov.start() try: # pragma: nested # Import the python file, executing it. mod = self.import_local_file(modname) finally: # pragma: nested # Stop Coverage. cov.stop() return mod def get_module_name(self): """Return the module name to use for this test run.""" # We append self.n because otherwise two calls in one test will use the # same filename and whether the test works or not depends on the # timestamps in the .pyc file, so it becomes random whether the second # call will use the compiled version of the first call's code or not! modname = 'coverage_test_' + self.noise + str(self.n) self.n += 1 return modname # Map chars to numbers for arcz_to_arcs _arcz_map = {'.': -1} _arcz_map.update(dict([(c, ord(c)-ord('0')) for c in '123456789'])) _arcz_map.update(dict( [(c, 10+ord(c)-ord('A')) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] )) def arcz_to_arcs(self, arcz): """Convert a compact textual representation of arcs to a list of pairs. The text has space-separated pairs of letters. Period is -1, 1-9 are 1-9, A-Z are 10 through 36. The resulting list is sorted regardless of the order of the input pairs. ".1 12 2." --> [(-1,1), (1,2), (2,-1)] Minus signs can be included in the pairs: "-11, 12, 2-5" --> [(-1,1), (1,2), (2,-5)] """ arcs = [] for pair in arcz.split(): asgn = bsgn = 1 if len(pair) == 2: a,b = pair else: assert len(pair) == 3 if pair[0] == '-': _,a,b = pair asgn = -1 else: assert pair[1] == '-' a,_,b = pair bsgn = -1 arcs.append((asgn*self._arcz_map[a], bsgn*self._arcz_map[b])) return sorted(arcs) def assertEqualArcs(self, a1, a2, msg=None): """Assert that the arc lists `a1` and `a2` are equal.""" # Make them into multi-line strings so we can see what's going wrong. s1 = "\n".join([repr(a) for a in a1]) + "\n" s2 = "\n".join([repr(a) for a in a2]) + "\n" self.assertMultiLineEqual(s1, s2, msg) def check_coverage(self, text, lines=None, missing="", report="", excludes=None, partials="", arcz=None, arcz_missing="", arcz_unpredicted=""): """Check the coverage measurement of `text`. The source `text` is run and measured. `lines` are the line numbers that are executable, or a list of possible line numbers, any of which could match. `missing` are the lines not executed, `excludes` are regexes to match against for excluding lines, and `report` is the text of the measurement report. For arc measurement, `arcz` is a string that can be decoded into arcs in the code (see `arcz_to_arcs` for the encoding scheme), `arcz_missing` are the arcs that are not executed, and `arcs_unpredicted` are the arcs executed in the code, but not deducible from the code. """ # We write the code into a file so that we can import it. # Coverage wants to deal with things as modules with file names. modname = self.get_module_name() self.make_file(modname+".py", text) arcs = arcs_missing = arcs_unpredicted = None if arcz is not None: arcs = self.arcz_to_arcs(arcz) arcs_missing = self.arcz_to_arcs(arcz_missing or "") arcs_unpredicted = self.arcz_to_arcs(arcz_unpredicted or "") # Start up Coverage. cov = coverage.coverage(branch=(arcs_missing is not None)) cov.erase() for exc in excludes or []: cov.exclude(exc) for par in partials or []: cov.exclude(par, which='partial') mod = self.start_import_stop(cov, modname) # Clean up our side effects del sys.modules[modname] # Get the analysis results, and check that they are right. analysis = cov._analyze(mod) statements = sorted(analysis.statements) if lines is not None: if type(lines[0]) == type(1): # lines is just a list of numbers, it must match the statements # found in the code. self.assertEqual(statements, lines) else: # lines is a list of possible line number lists, one of them # must match. for line_list in lines: if statements == line_list: break else: self.fail("None of the lines choices matched %r" % statements ) if type(missing) == type(""): self.assertEqual(analysis.missing_formatted(), missing) else: for missing_list in missing: if analysis.missing_formatted() == missing_list: break else: self.fail("None of the missing choices matched %r" % analysis.missing_formatted() ) if arcs is not None: self.assertEqualArcs( analysis.arc_possibilities(), arcs, "Possible arcs differ" ) if arcs_missing is not None: self.assertEqualArcs( analysis.arcs_missing(), arcs_missing, "Missing arcs differ" ) if arcs_unpredicted is not None: self.assertEqualArcs( analysis.arcs_unpredicted(), arcs_unpredicted, "Unpredicted arcs differ" ) if report: frep = StringIO() cov.report(mod, file=frep) rep = " ".join(frep.getvalue().split("\n")[2].split()[1:]) self.assertEqual(report, rep) def nice_file(self, *fparts): """Canonicalize the filename composed of the parts in `fparts`.""" fname = os.path.join(*fparts) return os.path.normcase(os.path.abspath(os.path.realpath(fname))) def assert_same_files(self, flist1, flist2): """Assert that `flist1` and `flist2` are the same set of file names.""" flist1_nice = [self.nice_file(f) for f in flist1] flist2_nice = [self.nice_file(f) for f in flist2] self.assertSameElements(flist1_nice, flist2_nice) def assert_exists(self, fname): """Assert that `fname` is a file that exists.""" msg = "File %r should exist" % fname self.assert_(os.path.exists(fname), msg) def assert_doesnt_exist(self, fname): """Assert that `fname` is a file that doesn't exist.""" msg = "File %r shouldn't exist" % fname self.assert_(not os.path.exists(fname), msg) def command_line(self, args, ret=OK, _covpkg=None): """Run `args` through the command line. Use this when you want to run the full coverage machinery, but in the current process. Exceptions may be thrown from deep in the code. Asserts that `ret` is returned by `CoverageScript.command_line`. Compare with `run_command`. Returns None. """ script = coverage.CoverageScript(_covpkg=_covpkg) ret_actual = script.command_line(shlex.split(args)) self.assertEqual(ret_actual, ret) def run_command(self, cmd): """Run the command-line `cmd` in a subprocess, and print its output. Use this when you need to test the process behavior of coverage. Compare with `command_line`. Returns the process' stdout text. """ # Running Python subprocesses can be tricky. Use the real name of our # own executable. So "python foo.py" might get executed as # "python3.3 foo.py". This is important because Python 3.x doesn't # install as "python", so you might get a Python 2 executable instead # if you don't use the executable's basename. if cmd.startswith("python "): cmd = os.path.basename(sys.executable) + cmd[6:] _, output = self.run_command_status(cmd) return output def run_command_status(self, cmd, status=0): """Run the command-line `cmd` in a subprocess, and print its output. Use this when you need to test the process behavior of coverage. Compare with `command_line`. Returns a pair: the process' exit status and stdout text. The `status` argument is returned as the status on older Pythons where we can't get the actual exit status of the process. """ # Add our test modules directory to PYTHONPATH. I'm sure there's too # much path munging here, but... here = os.path.dirname(self.nice_file(coverage.__file__, "..")) testmods = self.nice_file(here, 'tests/modules') zipfile = self.nice_file(here, 'tests/zipmods.zip') pypath = os.getenv('PYTHONPATH', '') if pypath: pypath += os.pathsep pypath += testmods + os.pathsep + zipfile self.set_environ('PYTHONPATH', pypath) status, output = run_command(cmd, status=status) print(output) return status, output # We run some tests in temporary directories, because they may need to make # files for the tests. But this is expensive, so we can change per-class # whether a temp dir is used or not. It's easy to forget to set that # option properly, so we track information about what the tests did, and # then report at the end of the process on test classes that were set # wrong. class ClassBehavior(object): """A value object to store per-class in CoverageTest.""" def __init__(self): self.tests = 0 self.temp_dir = True self.tests_making_files = 0 self.test_method_made_any_files = False # Map from class to info about how it ran. class_behaviors = {} def report_on_class_behavior(cls): """Called at process exit to report on class behavior.""" for test_class, behavior in cls.class_behaviors.items(): if behavior.temp_dir and behavior.tests_making_files == 0: bad = "Inefficient" elif not behavior.temp_dir and behavior.tests_making_files > 0: bad = "Unsafe" else: bad = "" if bad: if behavior.temp_dir: where = "in a temp directory" else: where = "without a temp directory" print( "%s: %s ran %d tests, %d made files %s" % ( bad, test_class.__name__, behavior.tests, behavior.tests_making_files, where, ) ) report_on_class_behavior = classmethod(report_on_class_behavior) def class_behavior(self): """Get the ClassBehavior instance for this test.""" cls = self.__class__ if cls not in self.class_behaviors: self.class_behaviors[cls] = self.ClassBehavior() return self.class_behaviors[cls] # When the process ends, find out about bad classes. atexit.register(CoverageTest.report_on_class_behavior) python-coverage-3.7.1+dfsg.1.orig/tests/test_xml.py0000644000175000017500000000672712222261225021254 0ustar barrybarry"""Tests for XML reports from coverage.py.""" import os import re import coverage from tests.coveragetest import CoverageTest class XmlReportTest(CoverageTest): """Tests of the XML reports from coverage.py.""" def run_mycode(self): """Run mycode.py, so we can report on it.""" self.make_file("mycode.py", "print('hello')\n") self.run_command("coverage run mycode.py") def test_default_file_placement(self): self.run_mycode() self.run_command("coverage xml") self.assert_exists("coverage.xml") def test_argument_affects_xml_placement(self): self.run_mycode() self.run_command("coverage xml -o put_it_there.xml") self.assert_doesnt_exist("coverage.xml") self.assert_exists("put_it_there.xml") def test_config_affects_xml_placement(self): self.run_mycode() self.make_file(".coveragerc", "[xml]\noutput = xml.out\n") self.run_command("coverage xml") self.assert_doesnt_exist("coverage.xml") self.assert_exists("xml.out") def test_no_data(self): # https://bitbucket.org/ned/coveragepy/issue/210 self.run_command("coverage xml") self.assert_doesnt_exist("coverage.xml") def test_no_source(self): # Written while investigating a bug, might as well keep it. # https://bitbucket.org/ned/coveragepy/issue/208 self.make_file("innocuous.py", "a = 4") cov = coverage.coverage() self.start_import_stop(cov, "innocuous") os.remove("innocuous.py") cov.xml_report(ignore_errors=True) self.assert_exists("coverage.xml") def run_doit(self): """Construct a simple sub-package.""" self.make_file("sub/__init__.py") self.make_file("sub/doit.py", "print('doit!')") self.make_file("main.py", "import sub.doit") cov = coverage.coverage() self.start_import_stop(cov, "main") return cov def test_filename_format_showing_everything(self): cov = self.run_doit() cov.xml_report(outfile="-") xml = self.stdout() doit_line = re_line(xml, "class.*doit") self.assertIn('filename="sub/doit.py"', doit_line) def test_filename_format_including_filename(self): cov = self.run_doit() cov.xml_report(["sub/doit.py"], outfile="-") xml = self.stdout() doit_line = re_line(xml, "class.*doit") self.assertIn('filename="sub/doit.py"', doit_line) def test_filename_format_including_module(self): cov = self.run_doit() import sub.doit # pylint: disable=F0401 cov.xml_report([sub.doit], outfile="-") xml = self.stdout() doit_line = re_line(xml, "class.*doit") self.assertIn('filename="sub/doit.py"', doit_line) def test_reporting_on_nothing(self): # Used to raise a zero division error: # https://bitbucket.org/ned/coveragepy/issue/250 self.make_file("empty.py", "") cov = coverage.coverage() empty = self.start_import_stop(cov, "empty") cov.xml_report([empty], outfile="-") xml = self.stdout() empty_line = re_line(xml, "class.*empty") self.assertIn('filename="empty.py"', empty_line) self.assertIn('line-rate="0"', empty_line) def re_line(text, pat): """Return the one line in `text` that matches regex `pat`.""" lines = [l for l in text.splitlines() if re.search(pat, l)] assert len(lines) == 1 return lines[0] python-coverage-3.7.1+dfsg.1.orig/tests/test_templite.py0000644000175000017500000001742012233267136022300 0ustar barrybarry"""Tests for coverage.templite.""" from coverage.templite import Templite from tests.coveragetest import CoverageTest # pylint: disable=W0612,E1101 # Disable W0612 (Unused variable) and # E1101 (Instance of 'foo' has no 'bar' member) class AnyOldObject(object): """Simple testing object. Use keyword arguments in the constructor to set attributes on the object. """ def __init__(self, **attrs): for n, v in attrs.items(): setattr(self, n, v) class TempliteTest(CoverageTest): """Tests for Templite.""" run_in_temp_dir = False def try_render(self, text, ctx, result): """Render `text` through `ctx`, and it had better be `result`.""" self.assertEqual(Templite(text).render(ctx), result) def test_passthrough(self): # Strings without variables are passed through unchanged. self.assertEqual(Templite("Hello").render(), "Hello") self.assertEqual( Templite("Hello, 20% fun time!").render(), "Hello, 20% fun time!" ) def test_variables(self): # Variables use {{var}} syntax. self.try_render("Hello, {{name}}!", {'name':'Ned'}, "Hello, Ned!") def test_undefined_variables(self): # Using undefined names is an error. self.assertRaises( Exception, self.try_render, "Hi, {{name}}!", {}, "xyz" ) def test_pipes(self): # Variables can be filtered with pipes. data = { 'name': 'Ned', 'upper': lambda x: x.upper(), 'second': lambda x: x[1], } self.try_render("Hello, {{name|upper}}!", data, "Hello, NED!") # Pipes can be concatenated. self.try_render("Hello, {{name|upper|second}}!", data, "Hello, E!") def test_reusability(self): # A single Templite can be used more than once with different data. globs = { 'upper': lambda x: x.upper(), 'punct': '!', } template = Templite("This is {{name|upper}}{{punct}}", globs) self.assertEqual(template.render({'name':'Ned'}), "This is NED!") self.assertEqual(template.render({'name':'Ben'}), "This is BEN!") def test_attribute(self): # Variables' attributes can be accessed with dots. obj = AnyOldObject(a="Ay") self.try_render("{{obj.a}}", locals(), "Ay") obj2 = AnyOldObject(obj=obj, b="Bee") self.try_render("{{obj2.obj.a}} {{obj2.b}}", locals(), "Ay Bee") def test_member_function(self): # Variables' member functions can be used, as long as they are nullary. class WithMemberFns(AnyOldObject): """A class to try out member function access.""" def ditto(self): """Return twice the .txt attribute.""" return self.txt + self.txt obj = WithMemberFns(txt="Once") self.try_render("{{obj.ditto}}", locals(), "OnceOnce") def test_item_access(self): # Variables' items can be used. d = {'a':17, 'b':23} self.try_render("{{d.a}} < {{d.b}}", locals(), "17 < 23") def test_loops(self): # Loops work like in Django. nums = [1,2,3,4] self.try_render( "Look: {% for n in nums %}{{n}}, {% endfor %}done.", locals(), "Look: 1, 2, 3, 4, done." ) # Loop iterables can be filtered. def rev(l): """Return the reverse of `l`.""" l = l[:] l.reverse() return l self.try_render( "Look: {% for n in nums|rev %}{{n}}, {% endfor %}done.", locals(), "Look: 4, 3, 2, 1, done." ) def test_empty_loops(self): self.try_render( "Empty: {% for n in nums %}{{n}}, {% endfor %}done.", {'nums':[]}, "Empty: done." ) def test_multiline_loops(self): self.try_render( "Look: \n{% for n in nums %}\n{{n}}, \n{% endfor %}done.", {'nums':[1,2,3]}, "Look: \n\n1, \n\n2, \n\n3, \ndone." ) def test_multiple_loops(self): self.try_render( "{% for n in nums %}{{n}}{% endfor %} and " "{% for n in nums %}{{n}}{% endfor %}", {'nums': [1,2,3]}, "123 and 123" ) def test_comments(self): # Single-line comments work: self.try_render( "Hello, {# Name goes here: #}{{name}}!", {'name':'Ned'}, "Hello, Ned!" ) # and so do multi-line comments: self.try_render( "Hello, {# Name\ngoes\nhere: #}{{name}}!", {'name':'Ned'}, "Hello, Ned!" ) def test_if(self): self.try_render( "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", {'ned': 1, 'ben': 0}, "Hi, NED!" ) self.try_render( "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", {'ned': 0, 'ben': 1}, "Hi, BEN!" ) self.try_render( "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", {'ned': 0, 'ben': 0}, "Hi, !" ) self.try_render( "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", {'ned': 1, 'ben': 0}, "Hi, NED!" ) self.try_render( "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", {'ned': 1, 'ben': 1}, "Hi, NEDBEN!" ) def test_complex_if(self): class Complex(AnyOldObject): """A class to try out complex data access.""" def getit(self): """Return it.""" return self.it obj = Complex(it={'x':"Hello", 'y': 0}) self.try_render( "@" "{% if obj.getit.x %}X{% endif %}" "{% if obj.getit.y %}Y{% endif %}" "{% if obj.getit.y|str %}S{% endif %}" "!", { 'obj': obj, 'str': str }, "@XS!" ) def test_loop_if(self): self.try_render( "@{% for n in nums %}{% if n %}Z{% endif %}{{n}}{% endfor %}!", {'nums': [0,1,2]}, "@0Z1Z2!" ) self.try_render( "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", {'nums': [0,1,2]}, "X@012!" ) self.try_render( "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", {'nums': []}, "X!" ) def test_nested_loops(self): self.try_render( "@" "{% for n in nums %}" "{% for a in abc %}{{a}}{{n}}{% endfor %}" "{% endfor %}" "!", {'nums': [0,1,2], 'abc': ['a', 'b', 'c']}, "@a0b0c0a1b1c1a2b2c2!" ) def test_exception_during_evaluation(self): # TypeError: Couldn't evaluate {{ foo.bar.baz }}: # 'NoneType' object is unsubscriptable self.assertRaises(TypeError, self.try_render, "Hey {{foo.bar.baz}} there", {'foo': None}, "Hey ??? there" ) def test_bogus_tag_syntax(self): self.assertRaisesRegexp( SyntaxError, "Don't understand tag: 'bogus'", self.try_render, "Huh: {% bogus %}!!{% endbogus %}??", {}, "" ) def test_bad_nesting(self): self.assertRaisesRegexp( SyntaxError, "Unmatched action tag: 'if'", self.try_render, "{% if x %}X", {}, "" ) self.assertRaisesRegexp( SyntaxError, "Mismatched end tag: 'for'", self.try_render, "{% if x %}X{% endfor %}", {}, "" ) python-coverage-3.7.1+dfsg.1.orig/tests/osinfo.py0000644000175000017500000000504012233013371020674 0ustar barrybarry"""OS information for testing.""" import sys if sys.version_info >= (2, 5) and sys.platform == 'win32': # Windows implementation def process_ram(): """How much RAM is this process using? (Windows)""" import ctypes # lifted from: # lists.ubuntu.com/archives/bazaar-commits/2009-February/011990.html class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): """Used by GetProcessMemoryInfo""" _fields_ = [('cb', ctypes.c_ulong), ('PageFaultCount', ctypes.c_ulong), ('PeakWorkingSetSize', ctypes.c_size_t), ('WorkingSetSize', ctypes.c_size_t), ('QuotaPeakPagedPoolUsage', ctypes.c_size_t), ('QuotaPagedPoolUsage', ctypes.c_size_t), ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t), ('QuotaNonPagedPoolUsage', ctypes.c_size_t), ('PagefileUsage', ctypes.c_size_t), ('PeakPagefileUsage', ctypes.c_size_t), ('PrivateUsage', ctypes.c_size_t), ] mem_struct = PROCESS_MEMORY_COUNTERS_EX() ret = ctypes.windll.psapi.GetProcessMemoryInfo( ctypes.windll.kernel32.GetCurrentProcess(), ctypes.byref(mem_struct), ctypes.sizeof(mem_struct) ) if not ret: return 0 return mem_struct.PrivateUsage elif sys.platform == 'linux2': # Linux implementation import os _scale = {'kb': 1024, 'mb': 1024*1024} def _VmB(key): """Read the /proc/PID/status file to find memory use.""" try: # get pseudo file /proc//status t = open('/proc/%d/status' % os.getpid()) try: v = t.read() finally: t.close() except IOError: return 0 # non-Linux? # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' i = v.index(key) v = v[i:].split(None, 3) if len(v) < 3: return 0 # invalid format? # convert Vm value to bytes return int(float(v[1]) * _scale[v[2].lower()]) def process_ram(): """How much RAM is this process using? (Linux implementation)""" return _VmB('VmRSS') else: # Don't have an implementation, at least satisfy the interface. def process_ram(): """How much RAM is this process using? (placebo implementation)""" return 0 python-coverage-3.7.1+dfsg.1.orig/tests/test_execfile.py0000644000175000017500000001363312233013371022231 0ustar barrybarry"""Tests for coverage.execfile""" import compileall, os, re, sys from coverage.backward import binary_bytes from coverage.execfile import run_python_file, run_python_module from coverage.misc import NoCode, NoSource from tests.coveragetest import CoverageTest here = os.path.dirname(__file__) class RunFileTest(CoverageTest): """Test cases for `run_python_file`.""" def test_run_python_file(self): tryfile = os.path.join(here, "try_execfile.py") run_python_file(tryfile, [tryfile, "arg1", "arg2"]) mod_globs = eval(self.stdout()) # The file should think it is __main__ self.assertEqual(mod_globs['__name__'], "__main__") # It should seem to come from a file named try_execfile.py dunder_file = os.path.basename(mod_globs['__file__']) self.assertEqual(dunder_file, "try_execfile.py") # It should have its correct module data. self.assertEqual(mod_globs['__doc__'], "Test file for run_python_file.") self.assertEqual(mod_globs['DATA'], "xyzzy") self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')") # It must be self-importable as __main__. self.assertEqual(mod_globs['__main__.DATA'], "xyzzy") # Argv should have the proper values. self.assertEqual(mod_globs['argv'], [tryfile, "arg1", "arg2"]) # __builtins__ should have the right values, like open(). self.assertEqual(mod_globs['__builtins__.has_open'], True) def test_no_extra_file(self): # Make sure that running a file doesn't create an extra compiled file. self.make_file("xxx", """\ desc = "a non-.py file!" """) self.assertEqual(os.listdir("."), ["xxx"]) run_python_file("xxx", ["xxx"]) self.assertEqual(os.listdir("."), ["xxx"]) def test_universal_newlines(self): # Make sure we can read any sort of line ending. pylines = """# try newlines|print('Hello, world!')|""".split('|') for nl in ('\n', '\r\n', '\r'): fpy = open('nl.py', 'wb') try: fpy.write(nl.join(pylines).encode('utf-8')) finally: fpy.close() run_python_file('nl.py', ['nl.py']) self.assertEqual(self.stdout(), "Hello, world!\n"*3) def test_missing_final_newline(self): # Make sure we can deal with a Python file with no final newline. self.make_file("abrupt.py", """\ if 1: a = 1 print("a is %r" % a) #""") abrupt = open("abrupt.py").read() self.assertEqual(abrupt[-1], '#') run_python_file("abrupt.py", ["abrupt.py"]) self.assertEqual(self.stdout(), "a is 1\n") def test_no_such_file(self): self.assertRaises(NoSource, run_python_file, "xyzzy.py", []) class RunPycFileTest(CoverageTest): """Test cases for `run_python_file`.""" def make_pyc(self): """Create a .pyc file, and return the relative path to it.""" self.make_file("compiled.py", """\ def doit(): print("I am here!") doit() """) compileall.compile_dir(".", quiet=True) os.remove("compiled.py") # Find the .pyc file! for there, _, files in os.walk("."): for f in files: if f.endswith(".pyc"): return os.path.join(there, f) def test_running_pyc(self): pycfile = self.make_pyc() run_python_file(pycfile, [pycfile]) self.assertEqual(self.stdout(), "I am here!\n") def test_running_pyo(self): pycfile = self.make_pyc() pyofile = re.sub(r"[.]pyc$", ".pyo", pycfile) self.assertNotEqual(pycfile, pyofile) os.rename(pycfile, pyofile) run_python_file(pyofile, [pyofile]) self.assertEqual(self.stdout(), "I am here!\n") def test_running_pyc_from_wrong_python(self): pycfile = self.make_pyc() # Jam Python 2.1 magic number into the .pyc file. fpyc = open(pycfile, "r+b") fpyc.seek(0) fpyc.write(binary_bytes([0x2a, 0xeb, 0x0d, 0x0a])) fpyc.close() self.assertRaisesRegexp( NoCode, "Bad magic number in .pyc file", run_python_file, pycfile, [pycfile] ) def test_no_such_pyc_file(self): self.assertRaisesRegexp( NoCode, "No file to run: 'xyzzy.pyc'", run_python_file, "xyzzy.pyc", [] ) class RunModuleTest(CoverageTest): """Test run_python_module.""" run_in_temp_dir = False def setUp(self): super(RunModuleTest, self).setUp() # Parent class saves and restores sys.path, we can just modify it. sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) def test_runmod1(self): run_python_module("runmod1", ["runmod1", "hello"]) self.assertEqual(self.stdout(), "runmod1: passed hello\n") def test_runmod2(self): run_python_module("pkg1.runmod2", ["runmod2", "hello"]) self.assertEqual(self.stdout(), "runmod2: passed hello\n") def test_runmod3(self): run_python_module("pkg1.sub.runmod3", ["runmod3", "hello"]) self.assertEqual(self.stdout(), "runmod3: passed hello\n") def test_pkg1_main(self): run_python_module("pkg1", ["pkg1", "hello"]) self.assertEqual(self.stdout(), "pkg1.__main__: passed hello\n") def test_pkg1_sub_main(self): run_python_module("pkg1.sub", ["pkg1.sub", "hello"]) self.assertEqual(self.stdout(), "pkg1.sub.__main__: passed hello\n") def test_no_such_module(self): self.assertRaises(NoSource, run_python_module, "i_dont_exist", []) self.assertRaises(NoSource, run_python_module, "i.dont_exist", []) self.assertRaises(NoSource, run_python_module, "i.dont.exist", []) def test_no_main(self): self.assertRaises(NoSource, run_python_module, "pkg2", ["pkg2", "hi"]) python-coverage-3.7.1+dfsg.1.orig/tests/test_testing.py0000644000175000017500000002064012233013371022116 0ustar barrybarry# -*- coding: utf-8 -*- """Tests that our test infrastructure is really working!""" import os, sys from coverage.backward import to_bytes, rpartition from tests.backunittest import TestCase from tests.coveragetest import CoverageTest from coverage.backward import set # pylint: disable=W0622 class TestingTest(TestCase): """Tests of helper methods on `backunittest.TestCase`.""" run_in_temp_dir = False def please_raise(self, exc, msg): """Raise an exception for testing assertRaisesRegexp.""" raise exc(msg) def please_succeed(self): """A simple successful method for testing assertRaisesRegexp.""" return "All is well" def test_assert_same_elements(self): self.assertSameElements(set(), set()) self.assertSameElements(set([1,2,3]), set([3,1,2])) self.assertRaises(AssertionError, self.assertSameElements, set([1,2,3]), set() ) self.assertRaises(AssertionError, self.assertSameElements, set([1,2,3]), set([4,5,6]) ) def test_assert_regexp_matches(self): self.assertRegexpMatches("hello", "hel*o") self.assertRegexpMatches("Oh, hello there!", "hel*o") self.assertRaises(AssertionError, self.assertRegexpMatches, "hello there", "^hello$" ) def test_assert_multiline_equal(self): self.assertMultiLineEqual("hello", "hello") self.assertRaises(AssertionError, self.assertMultiLineEqual, "hello there", "Hello there" ) self.assertRaises(AssertionError, self.assertMultiLineEqual, "hello\nthere", "hello\nThere" ) # With messages also. self.assertMultiLineEqual("hi", "hi", "it's ok") self.assertRaisesRegexp( AssertionError, "my message", self.assertMultiLineEqual, "xyz", "abc", "my message" ) def test_assert_raises_regexp(self): # Raising the right error with the right message passes. self.assertRaisesRegexp( ZeroDivisionError, "Wow! Zero!", self.please_raise, ZeroDivisionError, "Wow! Zero!" ) # Raising the right error with a match passes. self.assertRaisesRegexp( ZeroDivisionError, "Zero", self.please_raise, ZeroDivisionError, "Wow! Zero!" ) # Raising the right error with a mismatch fails. self.assertRaises(AssertionError, self.assertRaisesRegexp, ZeroDivisionError, "XYZ", self.please_raise, ZeroDivisionError, "Wow! Zero!" ) # Raising the right error with a mismatch fails. self.assertRaises(AssertionError, self.assertRaisesRegexp, ZeroDivisionError, "XYZ", self.please_raise, ZeroDivisionError, "Wow! Zero!" ) # Raising the wrong error raises the error itself. self.assertRaises(ZeroDivisionError, self.assertRaisesRegexp, IOError, "Wow! Zero!", self.please_raise, ZeroDivisionError, "Wow! Zero!" ) # Raising no error fails. self.assertRaises(AssertionError, self.assertRaisesRegexp, ZeroDivisionError, "XYZ", self.please_succeed ) def test_assert_true(self): self.assertTrue(True) self.assertRaises(AssertionError, self.assertTrue, False) def test_assert_false(self): self.assertFalse(False) self.assertRaises(AssertionError, self.assertFalse, True) def test_assert_in(self): self.assertIn("abc", "hello abc") self.assertIn("abc", ["xyz", "abc", "foo"]) self.assertIn("abc", {'abc': 1, 'xyz': 2}) self.assertRaises(AssertionError, self.assertIn, "abc", "xyz") self.assertRaises(AssertionError, self.assertIn, "abc", ["x", "xabc"]) self.assertRaises(AssertionError, self.assertIn, "abc", {'x':'abc'}) def test_assert_not_in(self): self.assertRaises(AssertionError, self.assertNotIn, "abc", "hello abc") self.assertRaises(AssertionError, self.assertNotIn, "abc", ["xyz", "abc", "foo"] ) self.assertRaises(AssertionError, self.assertNotIn, "abc", {'abc': 1, 'xyz': 2} ) self.assertNotIn("abc", "xyz") self.assertNotIn("abc", ["x", "xabc"]) self.assertNotIn("abc", {'x':'abc'}) def test_assert_greater(self): self.assertGreater(10, 9) self.assertGreater("xyz", "abc") self.assertRaises(AssertionError, self.assertGreater, 9, 10) self.assertRaises(AssertionError, self.assertGreater, 10, 10) self.assertRaises(AssertionError, self.assertGreater, "abc", "xyz") self.assertRaises(AssertionError, self.assertGreater, "xyz", "xyz") class CoverageTestTest(CoverageTest): """Test the methods in `CoverageTest`.""" def file_text(self, fname): """Return the text read from a file.""" return open(fname, "rb").read().decode('ascii') def test_make_file(self): # A simple file. self.make_file("fooey.boo", "Hello there") self.assertEqual(open("fooey.boo").read(), "Hello there") # A file in a sub-directory self.make_file("sub/another.txt", "Another") self.assertEqual(open("sub/another.txt").read(), "Another") # A second file in that sub-directory self.make_file("sub/second.txt", "Second") self.assertEqual(open("sub/second.txt").read(), "Second") # A deeper directory self.make_file("sub/deeper/evenmore/third.txt") self.assertEqual(open("sub/deeper/evenmore/third.txt").read(), "") def test_make_file_newline(self): self.make_file("unix.txt", "Hello\n") self.assertEqual(self.file_text("unix.txt"), "Hello\n") self.make_file("dos.txt", "Hello\n", newline="\r\n") self.assertEqual(self.file_text("dos.txt"), "Hello\r\n") self.make_file("mac.txt", "Hello\n", newline="\r") self.assertEqual(self.file_text("mac.txt"), "Hello\r") def test_make_file_non_ascii(self): self.make_file("unicode.txt", "tabblo: «ταБЬℓσ»") self.assertEqual( open("unicode.txt", "rb").read(), to_bytes("tabblo: «ταБЬℓσ»") ) def test_file_exists(self): self.make_file("whoville.txt", "We are here!") self.assert_exists("whoville.txt") self.assert_doesnt_exist("shadow.txt") self.assertRaises( AssertionError, self.assert_doesnt_exist, "whoville.txt" ) self.assertRaises(AssertionError, self.assert_exists, "shadow.txt") def test_sub_python_is_this_python(self): # Try it with a python command. os.environ['COV_FOOBAR'] = 'XYZZY' self.make_file("showme.py", """\ import os, sys print(sys.executable) print(os.__file__) print(os.environ['COV_FOOBAR']) """) out = self.run_command("python showme.py").splitlines() self.assertEqual(out[0], sys.executable) self.assertEqual(out[1], os.__file__) self.assertEqual(out[2], 'XYZZY') # Try it with a "coverage debug sys" command. out = self.run_command("coverage debug sys").splitlines() # "environment: COV_FOOBAR = XYZZY" or "COV_FOOBAR = XYZZY" executable = [l for l in out if "executable:" in l][0] executable = executable.split(":", 1)[1].strip() self.assertTrue(same_python_executable(executable, sys.executable)) environ = [l for l in out if "COV_FOOBAR" in l][0] _, _, environ = rpartition(environ, ":") self.assertEqual(environ.strip(), "COV_FOOBAR = XYZZY") def same_python_executable(e1, e2): """Determine if `e1` and `e2` refer to the same Python executable. Either path could include symbolic links. The two paths might not refer to the exact same file, but if they are in the same directory and their numeric suffixes aren't different, they are the same executable. """ e1 = os.path.abspath(os.path.realpath(e1)) e2 = os.path.abspath(os.path.realpath(e2)) if os.path.dirname(e1) != os.path.dirname(e2): return False e1 = os.path.basename(e1) e2 = os.path.basename(e2) if e1 == "python" or e2 == "python" or e1 == e2: # python and python2.3: ok # python2.3 and python: ok # python and python: ok # python2.3 and python2.3: ok return True return False python-coverage-3.7.1+dfsg.1.orig/tests/test_backward.py0000644000175000017500000000136712221561212022223 0ustar barrybarry"""Tests that our version shims in backward.py are working.""" from coverage.backward import iitems, binary_bytes, byte_to_int, bytes_to_ints from tests.backunittest import TestCase class BackwardTest(TestCase): """Tests of things from backward.py.""" run_in_temp_dir = False def test_iitems(self): d = {'a': 1, 'b': 2, 'c': 3} items = [('a', 1), ('b', 2), ('c', 3)] self.assertSameElements(list(iitems(d)), items) def test_binary_bytes(self): byte_values = [0, 255, 17, 23, 42, 57] bb = binary_bytes(byte_values) self.assertEqual(len(bb), len(byte_values)) self.assertEqual(byte_values, list(bytes_to_ints(bb))) self.assertEqual(byte_values, [byte_to_int(b) for b in bb]) python-coverage-3.7.1+dfsg.1.orig/tests/stress_phystoken.tok0000644000175000017500000000166112202156243023202 0ustar barrybarry# Here's some random Python so that test_tokenize_myself will have some # stressful stuff to try. This file is .tok instead of .py so pylint won't # complain about it, check_eol won't look at it, etc. first_back = """\ hey there! """ other_back = """ hey \ there """ lots_of_back = """\ hey \ there """ # This next line is supposed to have trailing whitespace: fake_back = """\ ouch """ # Lots of difficulty happens with code like: # # fake_back = """\ # ouch # """ # # Ugh, the edge cases... # What about a comment like this\ "what's this string doing here?" class C(object): def there(): this = 5 + \ 7 that = \ "a continued line" cont1 = "one line of text" + \ "another line of text" a_long_string = \ "part 1" \ "2" \ "3 is longer" def hello(): print("Hello world!") hello() python-coverage-3.7.1+dfsg.1.orig/tests/backtest.py0000644000175000017500000000271412221560605021210 0ustar barrybarry"""Add things to old Pythons so I can pretend they are newer, for tests.""" # pylint: disable=W0622 # (Redefining built-in blah) # The whole point of this file is to redefine built-ins, so shut up about it. import os # Py2 and Py3 don't agree on how to run commands in a subprocess. try: import subprocess except ImportError: def run_command(cmd, status=0): """Run a command in a subprocess. Returns the exit status code and the combined stdout and stderr. """ _, stdouterr = os.popen4(cmd) return status, stdouterr.read() else: def run_command(cmd, status=0): """Run a command in a subprocess. Returns the exit status code and the combined stdout and stderr. """ proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) output, _ = proc.communicate() status = proc.returncode # pylint: disable=E1101 # Get the output, and canonicalize it to strings with newlines. if not isinstance(output, str): output = output.decode('utf-8') output = output.replace('\r', '') return status, output # No more execfile in Py3 try: execfile = execfile except NameError: def execfile(filename, globs): """A Python 3 implementation of execfile.""" exec(compile(open(filename).read(), filename, 'exec'), globs) python-coverage-3.7.1+dfsg.1.orig/tests/modules/0000755000175000017500000000000012252501325020500 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/0000755000175000017500000000000012252501325021342 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/p1c.py0000644000175000017500000000002212202156243022371 0ustar barrybarrya = 1 b = 2 c = 3 python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/runmod2.py0000644000175000017500000000013712202156243023303 0ustar barrybarry# Used in the tests for run_python_module import sys print("runmod2: passed %s" % sys.argv[1]) python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/p1a.py0000644000175000017500000000020412202156243022371 0ustar barrybarryimport os, sys # Invoke functions in os and sys so we can see if we measure code there. x = sys.getcheckinterval() y = os.getcwd() python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/sub/0000755000175000017500000000000012252501325022133 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/sub/runmod3.py0000644000175000017500000000013712202156243024075 0ustar barrybarry# Used in the tests for run_python_module import sys print("runmod3: passed %s" % sys.argv[1]) python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/sub/ps1a.py0000644000175000017500000000002212202156243023343 0ustar barrybarryd = 1 e = 2 f = 3 python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/sub/__init__.py0000644000175000017500000000000012202156243024232 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/sub/__main__.py0000644000175000017500000000015112202156243024222 0ustar barrybarry# Used in the tests for run_python_module import sys print("pkg1.sub.__main__: passed %s" % sys.argv[1]) python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/p1b.py0000644000175000017500000000002212202156243022370 0ustar barrybarryx = 1 y = 2 z = 3 python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/__init__.py0000644000175000017500000000017512202156243023456 0ustar barrybarry# This __init__.py has a module-level docstring, which is counted as a # statement. """A simple package for testing with.""" python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg1/__main__.py0000644000175000017500000000014512202156243023434 0ustar barrybarry# Used in the tests for run_python_module import sys print("pkg1.__main__: passed %s" % sys.argv[1]) python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/0000755000175000017500000000000012252501325021061 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/afile.py0000644000175000017500000000001312202156243022505 0ustar barrybarry# afile.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/zfile.py0000644000175000017500000000001312202156243022536 0ustar barrybarry# zfile.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/__init__.py0000644000175000017500000000000512202156243023165 0ustar barrybarry# aa python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb.odd/0000755000175000017500000000000012252501325022211 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb.odd/bfile.py0000644000175000017500000000001312202156243023636 0ustar barrybarry# bfile.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/afile.odd.py0000644000175000017500000000001712202156243023256 0ustar barrybarry# afile.odd.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/0000755000175000017500000000000012252501325021444 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/bfile.odd.py0000644000175000017500000000001712202156243023642 0ustar barrybarry# bfile.odd.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/bfile.py0000644000175000017500000000001312202156243023071 0ustar barrybarry# bfile.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/cc/0000755000175000017500000000000012252501325022031 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/cc/__init__.py0000644000175000017500000000000012202156243024130 0ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/cc/cfile.py0000644000175000017500000000001312202156243023457 0ustar barrybarry# cfile.py python-coverage-3.7.1+dfsg.1.orig/tests/modules/aa/bb/__init__.py0000644000175000017500000000000512202156243023550 0ustar barrybarry# bb python-coverage-3.7.1+dfsg.1.orig/tests/modules/covmod1.py0000644000175000017500000000007012202156243022417 0ustar barrybarry# covmod1.py: Simplest module for testing. i = 1 i += 1 python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg2/0000755000175000017500000000000012252501325021343 5ustar barrybarrypython-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg2/__init__.py0000644000175000017500000000016112202156243023452 0ustar barrybarry# This is an __init__.py file, with no executable statements in it. # This comment shouldn't confuse the parser. python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg2/p2a.py0000644000175000017500000000002212202156243022371 0ustar barrybarryq = 1 r = 1 s = 1 python-coverage-3.7.1+dfsg.1.orig/tests/modules/pkg2/p2b.py0000644000175000017500000000002212202156243022372 0ustar barrybarryt = 1 u = 1 v = 1 python-coverage-3.7.1+dfsg.1.orig/tests/modules/runmod1.py0000644000175000017500000000013712202156243022440 0ustar barrybarry# Used in the tests for run_python_module import sys print("runmod1: passed %s" % sys.argv[1]) python-coverage-3.7.1+dfsg.1.orig/tests/modules/usepkgs.py0000644000175000017500000000021212202156243022526 0ustar barrybarryimport pkg1.p1a, pkg1.p1b import pkg2.p2a, pkg2.p2b import othermods.othera, othermods.otherb import othermods.sub.osa, othermods.sub.osb python-coverage-3.7.1+dfsg.1.orig/tests/test_config.py0000644000175000017500000001705712233013371021716 0ustar barrybarry# -*- coding: utf-8 -*- """Test the config file handling for coverage.py""" import sys import coverage from coverage.misc import CoverageException from tests.coveragetest import CoverageTest class ConfigTest(CoverageTest): """Tests of the different sources of configuration settings.""" def test_default_config(self): # Just constructing a coverage() object gets the right defaults. cov = coverage.coverage() self.assertFalse(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, ".coverage") def test_arguments(self): # Arguments to the constructor are applied to the configuation. cov = coverage.coverage(timid=True, data_file="fooey.dat") self.assertTrue(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, "fooey.dat") def test_config_file(self): # A .coveragerc file will be read into the configuration. self.make_file(".coveragerc", """\ # This is just a bogus .rc file for testing. [run] timid = True data_file = .hello_kitty.data """) cov = coverage.coverage() self.assertTrue(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, ".hello_kitty.data") def test_named_config_file(self): # You can name the config file what you like. self.make_file("my_cov.ini", """\ [run] timid = True ; I wouldn't really use this as a data file... data_file = delete.me """) cov = coverage.coverage(config_file="my_cov.ini") self.assertTrue(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, "delete.me") def test_ignored_config_file(self): # You can disable reading the .coveragerc file. self.make_file(".coveragerc", """\ [run] timid = True data_file = delete.me """) cov = coverage.coverage(config_file=False) self.assertFalse(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, ".coverage") def test_config_file_then_args(self): # The arguments override the .coveragerc file. self.make_file(".coveragerc", """\ [run] timid = True data_file = weirdo.file """) cov = coverage.coverage(timid=False, data_file=".mycov") self.assertFalse(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, ".mycov") def test_data_file_from_environment(self): # There's an environment variable for the data_file. self.make_file(".coveragerc", """\ [run] timid = True data_file = weirdo.file """) self.set_environ("COVERAGE_FILE", "fromenv.dat") cov = coverage.coverage() self.assertEqual(cov.config.data_file, "fromenv.dat") # But the constructor args override the env var. cov = coverage.coverage(data_file="fromarg.dat") self.assertEqual(cov.config.data_file, "fromarg.dat") def test_parse_errors(self): # Im-parseable values raise CoverageException self.make_file(".coveragerc", """\ [run] timid = maybe? """) self.assertRaises(CoverageException, coverage.coverage) def test_environment_vars_in_config(self): # Config files can have $envvars in them. self.make_file(".coveragerc", """\ [run] data_file = $DATA_FILE.fooey branch = $OKAY [report] exclude_lines = the_$$one another${THING} x${THING}y x${NOTHING}y huh$${X}what """) self.set_environ("DATA_FILE", "hello-world") self.set_environ("THING", "ZZZ") self.set_environ("OKAY", "yes") cov = coverage.coverage() self.assertEqual(cov.config.data_file, "hello-world.fooey") self.assertEqual(cov.config.branch, True) self.assertEqual(cov.config.exclude_list, ["the_$one", "anotherZZZ", "xZZZy", "xy", "huh${X}what"] ) class ConfigFileTest(CoverageTest): """Tests of the config file settings in particular.""" def test_config_file_settings(self): # This sample file tries to use lots of variation of syntax... self.make_file(".coveragerc", """\ # This is a settings file for coverage.py [run] timid = yes data_file = something_or_other.dat branch = 1 cover_pylib = TRUE parallel = on include = a/ , b/ [report] ; these settings affect reporting. exclude_lines = if 0: pragma:?\\s+no cover another_tab ignore_errors = TRUE omit = one, another, some_more, yet_more precision = 3 partial_branches = pragma:?\\s+no branch partial_branches_always = if 0: while True: show_missing= TruE [html] directory = c:\\tricky\\dir.somewhere extra_css=something/extra.css title = Title & nums # nums! [xml] output=mycov.xml [paths] source = . /home/ned/src/ other = other, /home/ned/other, c:\\Ned\\etc """) cov = coverage.coverage() self.assertTrue(cov.config.timid) self.assertEqual(cov.config.data_file, "something_or_other.dat") self.assertTrue(cov.config.branch) self.assertTrue(cov.config.cover_pylib) self.assertTrue(cov.config.parallel) self.assertEqual(cov.get_exclude_list(), ["if 0:", r"pragma:?\s+no cover", "another_tab"] ) self.assertTrue(cov.config.ignore_errors) self.assertEqual(cov.config.include, ["a/", "b/"]) self.assertEqual(cov.config.omit, ["one", "another", "some_more", "yet_more"] ) self.assertEqual(cov.config.precision, 3) self.assertEqual(cov.config.partial_list, [r"pragma:?\s+no branch"] ) self.assertEqual(cov.config.partial_always_list, ["if 0:", "while True:"] ) self.assertTrue(cov.config.show_missing) self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere") self.assertEqual(cov.config.extra_css, "something/extra.css") self.assertEqual(cov.config.html_title, "Title & nums # nums!") self.assertEqual(cov.config.xml_output, "mycov.xml") self.assertEqual(cov.config.paths, { 'source': ['.', '/home/ned/src/'], 'other': ['other', '/home/ned/other', 'c:\\Ned\\etc'] }) if sys.version_info[:2] != (3,1): def test_one(self): # This sample file tries to use lots of variation of syntax... self.make_file(".coveragerc", """\ [html] title = tabblo & «ταБЬℓσ» # numbers """) cov = coverage.coverage() self.assertEqual(cov.config.html_title, "tabblo & «ταБЬℓσ» # numbers" ) python-coverage-3.7.1+dfsg.1.orig/tests/test_arcs.py0000644000175000017500000004263512233013371021401 0ustar barrybarry"""Tests for Coverage.py's arc measurement.""" import sys from tests.coveragetest import CoverageTest class SimpleArcTest(CoverageTest): """Tests for Coverage.py's arc measurement.""" def test_simple_sequence(self): self.check_coverage("""\ a = 1 b = 2 """, arcz=".1 12 2.") self.check_coverage("""\ a = 1 b = 3 """, arcz=".1 13 3.") self.check_coverage("""\ a = 2 b = 3 c = 5 """, arcz=".2 23 35 5-2") def test_function_def(self): self.check_coverage("""\ def foo(): a = 2 foo() """, arcz=".1 .2 14 2. 4.") def test_if(self): self.check_coverage("""\ a = 1 if len([]) == 0: a = 3 assert a == 3 """, arcz=".1 12 23 24 34 4.", arcz_missing="24") self.check_coverage("""\ a = 1 if len([]) == 1: a = 3 assert a == 1 """, arcz=".1 12 23 24 34 4.", arcz_missing="23 34") def test_if_else(self): self.check_coverage("""\ if len([]) == 0: a = 2 else: a = 4 assert a == 2 """, arcz=".1 12 25 14 45 5.", arcz_missing="14 45") self.check_coverage("""\ if len([]) == 1: a = 2 else: a = 4 assert a == 4 """, arcz=".1 12 25 14 45 5.", arcz_missing="12 25") def test_compact_if(self): self.check_coverage("""\ a = 1 if len([]) == 0: a = 2 assert a == 2 """, arcz=".1 12 23 3.", arcz_missing="") self.check_coverage("""\ def fn(x): if x % 2: return True return False a = fn(1) assert a == True """, arcz=".1 14 45 5. .2 2. 23 3.", arcz_missing="23 3.") def test_multiline(self): # The firstlineno of the a assignment below differs among Python # versions. if sys.version_info >= (2, 5): arcz = ".1 15 5-2" else: arcz = ".1 15 5-1" self.check_coverage("""\ a = ( 2 + 3 ) b = \\ 6 """, arcz=arcz, arcz_missing="") def test_if_return(self): self.check_coverage("""\ def if_ret(a): if a: return 3 b = 4 return 5 x = if_ret(0) + if_ret(1) assert x == 8 """, arcz=".1 16 67 7. .2 23 24 3. 45 5.", arcz_missing="" ) def test_dont_confuse_exit_and_else(self): self.check_coverage("""\ def foo(): if foo: a = 3 else: a = 5 return a assert foo() == 3 # 7 """, arcz=".1 17 7. .2 23 36 25 56 6.", arcz_missing="25 56" ) self.check_coverage("""\ def foo(): if foo: a = 3 else: a = 5 foo() # 6 """, arcz=".1 16 6. .2 23 3. 25 5.", arcz_missing="25 5." ) if 0: # expected failure def test_unused_lambdas_are_confusing_bug_90(self): self.check_coverage("""\ a = 1 fn = lambda x: x b = 3 """, arcz=".1 12 .2 2-2 23 3." ) if sys.version_info >= (2, 6): class WithTest(CoverageTest): """Arc-measuring tests involving context managers.""" def test_with(self): self.check_coverage("""\ def example(): with open("test", "w") as f: # exit f.write("") return 1 example() """, arcz=".1 .2 23 34 4. 16 6." ) def test_bug_146(self): # https://bitbucket.org/ned/coveragepy/issue/146 self.check_coverage("""\ for i in range(2): with open("test", "w") as f: print(3) print(4) print(5) """, arcz=".1 12 23 34 41 15 5." ) class LoopArcTest(CoverageTest): """Arc-measuring tests involving loops.""" def test_loop(self): self.check_coverage("""\ for i in range(10): a = i assert a == 9 """, arcz=".1 12 21 13 3.", arcz_missing="") self.check_coverage("""\ a = -1 for i in range(0): a = i assert a == -1 """, arcz=".1 12 23 32 24 4.", arcz_missing="23 32") def test_nested_loop(self): self.check_coverage("""\ for i in range(3): for j in range(3): a = i + j assert a == 4 """, arcz=".1 12 23 32 21 14 4.", arcz_missing="") def test_break(self): self.check_coverage("""\ for i in range(10): a = i break # 3 a = 99 assert a == 0 # 5 """, arcz=".1 12 23 35 15 41 5.", arcz_missing="15 41") def test_continue(self): self.check_coverage("""\ for i in range(10): a = i continue # 3 a = 99 assert a == 9 # 5 """, arcz=".1 12 23 31 15 41 5.", arcz_missing="41") def test_nested_breaks(self): self.check_coverage("""\ for i in range(3): for j in range(3): a = i + j break # 4 if i == 2: break assert a == 2 and i == 2 # 7 """, arcz=".1 12 23 34 45 25 56 51 67 17 7.", arcz_missing="17 25") def test_while_true(self): # With "while 1", the loop knows it's constant. self.check_coverage("""\ a, i = 1, 0 while 1: if i >= 3: a = 4 break i += 1 assert a == 4 and i == 3 """, arcz=".1 12 23 34 45 36 63 57 7.", ) # With "while True", 2.x thinks it's computation, 3.x thinks it's # constant. if sys.version_info >= (3, 0): arcz = ".1 12 23 34 45 36 63 57 7." else: arcz = ".1 12 23 27 34 45 36 62 57 7." self.check_coverage("""\ a, i = 1, 0 while True: if i >= 3: a = 4 break i += 1 assert a == 4 and i == 3 """, arcz=arcz, ) def test_for_if_else_for(self): self.check_coverage("""\ def branches_2(l): if l: for e in l: a = 4 else: a = 6 def branches_3(l): for x in l: if x: for e in l: a = 12 else: a = 14 branches_2([0,1]) branches_3([0,1]) """, arcz= ".1 18 8G GH H. " ".2 23 34 43 26 3. 6. " ".9 9A 9-8 AB BC CB B9 AE E9", arcz_missing="26 6." ) def test_for_else(self): self.check_coverage("""\ def forelse(seq): for n in seq: if n > 5: break else: print('None of the values were greater than 5') print('Done') forelse([1,2]) forelse([1,6]) """, arcz=".1 .2 23 32 34 47 26 67 7. 18 89 9." ) def test_confusing_for_loop_bug_175(self): if sys.version_info >= (3, 0): # Py3 counts the list comp as a separate code object. arcz = ".1 .2 2-2 12 23 34 45 53 3." else: arcz = ".1 12 23 34 45 53 3." self.check_coverage("""\ o = [(1,2), (3,4)] o = [a for a in o] for tup in o: x = tup[0] y = tup[1] """, arcz=arcz, arcz_missing="", arcz_unpredicted="") if sys.version_info >= (3, 0): arcz = ".1 12 .2 2-2 23 34 42 2." else: arcz = ".1 12 23 34 42 2." self.check_coverage("""\ o = [(1,2), (3,4)] for tup in [a for a in o]: x = tup[0] y = tup[1] """, arcz=arcz, arcz_missing="", arcz_unpredicted="") class ExceptionArcTest(CoverageTest): """Arc-measuring tests involving exception handling.""" def test_try_except(self): self.check_coverage("""\ a, b = 1, 1 try: a = 3 except: b = 5 assert a == 3 and b == 1 """, arcz=".1 12 23 36 45 56 6.", arcz_missing="45 56") self.check_coverage("""\ a, b = 1, 1 try: a = 3 raise Exception("Yikes!") a = 5 except: b = 7 assert a == 3 and b == 7 """, arcz=".1 12 23 34 58 67 78 8.", arcz_missing="58", arcz_unpredicted="46") def test_hidden_raise(self): self.check_coverage("""\ a, b = 1, 1 def oops(x): if x % 2: raise Exception("odd") try: a = 5 oops(1) a = 7 except: b = 9 assert a == 5 and b == 9 """, arcz=".1 12 .3 3-2 24 45 56 67 7A 89 9A A.", arcz_missing="67 7A", arcz_unpredicted="68") def test_except_with_type(self): self.check_coverage("""\ a, b = 1, 1 def oops(x): if x % 2: raise ValueError("odd") def try_it(x): try: a = 6 oops(x) a = 8 except ValueError: b = 10 return a assert try_it(0) == 8 # C assert try_it(1) == 6 # D """, arcz=".1 12 .3 3-2 24 4C CD D. .5 56 67 78 8B 9A AB B-4", arcz_missing="", arcz_unpredicted="79") def test_try_finally(self): self.check_coverage("""\ a, c = 1, 1 try: a = 3 finally: c = 5 assert a == 3 and c == 5 """, arcz=".1 12 23 35 56 6.", arcz_missing="") self.check_coverage("""\ a, c, d = 1, 1, 1 try: try: a = 4 finally: c = 6 except: d = 8 assert a == 4 and c == 6 and d == 1 # 9 """, arcz=".1 12 23 34 46 67 78 89 69 9.", arcz_missing="67 78 89", arcz_unpredicted="") self.check_coverage("""\ a, c, d = 1, 1, 1 try: try: a = 4 raise Exception("Yikes!") a = 6 finally: c = 8 except: d = 10 # A assert a == 4 and c == 8 and d == 10 # B """, arcz=".1 12 23 34 45 68 89 8B 9A AB B.", arcz_missing="68 8B", arcz_unpredicted="58") def test_finally_in_loop(self): self.check_coverage("""\ a, c, d, i = 1, 1, 1, 99 try: for i in range(5): try: a = 5 if i > 0: raise Exception("Yikes!") a = 8 finally: c = 10 except: d = 12 # C assert a == 5 and c == 10 and d == 12 # D """, arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB BC CD D.", arcz_missing="3D", arcz_unpredicted="7A") self.check_coverage("""\ a, c, d, i = 1, 1, 1, 99 try: for i in range(5): try: a = 5 if i > 10: raise Exception("Yikes!") a = 8 finally: c = 10 except: d = 12 # C assert a == 8 and c == 10 and d == 1 # D """, arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB BC CD D.", arcz_missing="67 AB BC CD", arcz_unpredicted="") def test_break_in_finally(self): self.check_coverage("""\ a, c, d, i = 1, 1, 1, 99 try: for i in range(5): try: a = 5 if i > 0: break a = 8 finally: c = 10 except: d = 12 # C assert a == 5 and c == 10 and d == 1 # D """, arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB BC CD D.", arcz_missing="3D AB BC CD", arcz_unpredicted="AD") def test_finally_in_loop_bug_92(self): self.check_coverage("""\ for i in range(5): try: j = 3 finally: f = 5 g = 6 h = 7 """, arcz=".1 12 23 35 56 61 17 7.", arcz_missing="", arcz_unpredicted="") # Run this test only on 2.6 and 2.7 for now. I hope to fix it on Py3 # eventually... if (2, 6) <= sys.version_info < (3,): # "except Exception as e" is crucial here. def test_bug_212(self): self.check_coverage("""\ def b(exc): try: while 1: raise Exception(exc) # 4 except Exception as e: if exc != 'expected': raise q = 8 b('expected') try: b('unexpected') # C except: pass """, arcz=".1 .2 1A 23 34 56 67 68 8. AB BC C. DE E.", arcz_missing="C.", arcz_unpredicted="45 7. CD") if sys.version_info >= (2, 5): # Try-except-finally was new in 2.5 def test_except_finally(self): self.check_coverage("""\ a, b, c = 1, 1, 1 try: a = 3 except: b = 5 finally: c = 7 assert a == 3 and b == 1 and c == 7 """, arcz=".1 12 23 45 37 57 78 8.", arcz_missing="45 57") self.check_coverage("""\ a, b, c = 1, 1, 1 def oops(x): if x % 2: raise Exception("odd") try: a = 5 oops(1) a = 7 except: b = 9 finally: c = 11 assert a == 5 and b == 9 and c == 11 """, arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.", arcz_missing="67 7B", arcz_unpredicted="68") class MiscArcTest(CoverageTest): """Miscellaneous arc-measuring tests.""" def test_dict_literal(self): self.check_coverage("""\ d = { 'a': 2, 'b': 3, 'c': { 'd': 5, 'e': 6, } } assert d """, arcz=".1 19 9.") class ExcludeTest(CoverageTest): """Tests of exclusions to indicate known partial branches.""" def test_default(self): # A number of forms of pragma comment are accepted. self.check_coverage("""\ a = 1 if a: #pragma: no branch b = 3 c = 4 if c: # pragma NOBRANCH d = 6 e = 7 """, [1,2,3,4,5,6,7], arcz=".1 12 23 24 34 45 56 57 67 7.", arcz_missing="") def test_custom_pragmas(self): self.check_coverage("""\ a = 1 while a: # [only some] c = 3 break assert c == 5-2 """, [1,2,3,4,5], partials=["only some"], arcz=".1 12 23 34 45 25 5.", arcz_missing="") python-coverage-3.7.1+dfsg.1.orig/README.txt0000644000175000017500000000064112202156243017365 0ustar barrybarryCoverage.py: code coverage testing for Python Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. For more information, see http://nedbatchelder.com/code/coverage Code repo and issue tracking are at http://bitbucket.org/ned/coveragepy python-coverage-3.7.1+dfsg.1.orig/__main__.py0000644000175000017500000000110012202156243017750 0ustar barrybarry"""Be able to execute coverage.py by pointing Python at a working tree.""" import runpy, os PKG = 'coverage' try: run_globals = runpy.run_module(PKG, run_name='__main__', alter_sys=True) executed = os.path.splitext(os.path.basename(run_globals['__file__']))[0] if executed != '__main__': # For Python 2.5 compatibility raise ImportError( 'Incorrectly executed %s instead of __main__' % executed ) except ImportError: # For Python 2.6 compatibility runpy.run_module('%s.__main__' % PKG, run_name='__main__', alter_sys=True) python-coverage-3.7.1+dfsg.1.orig/setup.py0000644000175000017500000001400712233013371017400 0ustar barrybarry# setup.py for coverage.py """Code coverage measurement for Python Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. Coverage.py runs on Pythons 2.3 through 3.3, and PyPy 1.9. Documentation is at `nedbatchelder.com <%s>`_. Code repository and issue tracker are on `Bitbucket `_, with a mirrored repo on `Github `_. New in 3.7: ``--debug``, and 12 bugs closed. New in 3.6: ``--fail-under``, and >20 bugs closed. New in 3.5: Branch coverage exclusions, keyboard shortcuts in HTML report. New in 3.4: Better control over source to measure, and unexecuted files can be reported. New in 3.3: .coveragerc files. New in 3.2: Branch coverage! """ # This file is used unchanged under all versions of Python, 2.x and 3.x. classifiers = """\ Environment :: Console Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent Programming Language :: Python :: 2 Programming Language :: Python :: 3 Topic :: Software Development :: Quality Assurance Topic :: Software Development :: Testing """ # Pull in the tools we need. import os, sys from setuptools import setup from distutils.core import Extension # pylint: disable=E0611,F0401 from distutils.command.build_ext import build_ext # pylint: disable=E0611,F0401,C0301 from distutils import errors # pylint: disable=E0611,F0401 # Get or massage our metadata. We exec coverage/version.py so we can avoid # importing the product code into setup.py. doc = __doc__ # __doc__ will be overwritten by version.py. __version__ = __url__ = "" # Keep pylint happy. cov_ver_py = os.path.join(os.path.split(__file__)[0], "coverage/version.py") version_file = open(cov_ver_py) try: exec(compile(version_file.read(), cov_ver_py, 'exec')) finally: version_file.close() doclines = (doc % __url__).splitlines() classifier_list = classifiers.splitlines() if 'a' in __version__: devstat = "3 - Alpha" elif 'b' in __version__: devstat = "4 - Beta" else: devstat = "5 - Production/Stable" classifier_list.append("Development Status :: " + devstat) # Install a script as "coverage", and as "coverage[23]", and as # "coverage-2.7" (or whatever). scripts = [ 'coverage = coverage:main', 'coverage%d = coverage:main' % sys.version_info[:1], 'coverage-%d.%d = coverage:main' % sys.version_info[:2], ] # Create the keyword arguments for setup() setup_args = dict( name = 'coverage', version = __version__, packages = [ 'coverage', ], package_data = { 'coverage': [ 'htmlfiles/*.*', ] }, entry_points = {'console_scripts': scripts}, # We need to get HTML assets from our htmlfiles dir. zip_safe = False, author = 'Ned Batchelder and others', author_email = 'ned@nedbatchelder.com', description = doclines[0], long_description = '\n'.join(doclines[2:]), keywords = 'code coverage testing', license = 'BSD', classifiers = classifier_list, url = __url__, ) # A replacement for the build_ext command which raises a single exception # if the build fails, so we can fallback nicely. ext_errors = ( errors.CCompilerError, errors.DistutilsExecError, errors.DistutilsPlatformError, ) if sys.platform == 'win32' and sys.version_info > (2, 6): # 2.6's distutils.msvc9compiler can raise an IOError when failing to # find the compiler ext_errors += (IOError,) class BuildFailed(Exception): """Raise this to indicate the C extension wouldn't build.""" def __init__(self): Exception.__init__(self) self.cause = sys.exc_info()[1] # work around py 2/3 different syntax class ve_build_ext(build_ext): """Build C extensions, but fail with a straightforward exception.""" def run(self): """Wrap `run` with `BuildFailed`.""" try: build_ext.run(self) except errors.DistutilsPlatformError: raise BuildFailed() def build_extension(self, ext): """Wrap `build_extension` with `BuildFailed`.""" try: # Uncomment to test compile failures: # raise errors.CCompilerError("OOPS") build_ext.build_extension(self, ext) except ext_errors: raise BuildFailed() except ValueError: # this can happen on Windows 64 bit, see Python issue 7511 if "'path'" in str(sys.exc_info()[1]): # works with both py 2/3 raise BuildFailed() raise # There are a few reasons we might not be able to compile the C extension. # Figure out if we should attempt the C extension or not. compile_extension = True if sys.platform.startswith('java'): # Jython can't compile C extensions compile_extension = False if '__pypy__' in sys.builtin_module_names: # Pypy can't compile C extensions compile_extension = False if compile_extension: setup_args.update(dict( ext_modules = [ Extension("coverage.tracer", sources=["coverage/tracer.c"]) ], cmdclass = { 'build_ext': ve_build_ext, }, )) # Py3.x-specific details. if sys.version_info >= (3, 0): setup_args.update(dict( use_2to3 = False, )) def main(): """Actually invoke setup() with the arguments we built above.""" # For a variety of reasons, it might not be possible to install the C # extension. Try it with, and if it fails, try it without. try: setup(**setup_args) except BuildFailed: msg = "Couldn't install with extension module, trying without it..." exc = sys.exc_info()[1] exc_msg = "%s: %s" % (exc.__class__.__name__, exc.cause) print("**\n** %s\n** %s\n**" % (msg, exc_msg)) del setup_args['ext_modules'] setup(**setup_args) if __name__ == '__main__': main() python-coverage-3.7.1+dfsg.1.orig/tox.ini0000644000175000017500000000160712233013371017203 0ustar barrybarry# Tox (http://tox.testrun.org/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] envlist = py25, py26, py27, py31, py32, py33, pypy [testenv] commands = {envpython} setup.py --quiet clean develop # Create tests/zipmods.zip # Install the egg1 egg # Remove the C extension so that we can test the PyTracer {envpython} igor.py zip_mods install_egg remove_extension # Test with the PyTracer {envpython} igor.py test_with_tracer py {posargs} # Build the C extension and test with the CTracer {envpython} setup.py --quiet build_ext --inplace {envpython} igor.py test_with_tracer c {posargs} deps = nose mock [testenv:pypy] # PyPy has no C extensions setenv = COVERAGE_NO_EXTENSION=1 python-coverage-3.7.1+dfsg.1.orig/requirements.txt0000644000175000017500000000003412202156243021147 0ustar barrybarrynose mock tox pylint sphinx python-coverage-3.7.1+dfsg.1.orig/AUTHORS.txt0000644000175000017500000000127012215612274017561 0ustar barrybarryCoverage.py was originally written by Gareth Rees, and since 2004 has been extended and maintained by Ned Batchelder. Other contributions have been made by: Marc Abramowitz Chris Adams Geoff Bache Julian Berman Titus Brown Brett Cannon Pablo Carballo Guillaume Chazarain David Christian Marcus Cobden Matthew Desmarais Danek Duvall Ben Finney Martin Fuzzey Imri Goldberg Bill Hart Christian Heimes Roger Hu Devin Jeanpierre Ross Lawley Edward Loper Sandra Martocchia Patrick Mezard Noel O'Boyle Detlev Offenbach JT Olds George Paci Catherine Proulx Brandon Rhodes Adi Roiban Greg Rogers George Song David Stanek Joseph Tate Sigve Tjora Mark van der Wal Zooko Wilcox-O'Hearn Christoph Zwerschke python-coverage-3.7.1+dfsg.1.orig/igor.py0000644000175000017500000002043712233013371017204 0ustar barrybarry"""Helper for building, testing, and linting coverage.py. To get portability, all these operations are written in Python here instead of in shell scripts, batch files, or Makefiles. """ import fnmatch import glob import inspect import os import platform import socket import sys import zipfile # Functions named do_* are executable from the command line: do_blah is run # by "python igor.py blah". def do_remove_extension(): """Remove the compiled C extension, no matter what its name.""" so_patterns = """ tracer.so tracer.*.so tracer.pyd """.split() for pattern in so_patterns: pattern = os.path.join("coverage", pattern) for filename in glob.glob(pattern): try: os.remove(filename) except OSError: pass def run_tests(tracer, *nose_args): """The actual running of tests.""" import nose.core if tracer == "py": label = "with Python tracer" else: label = "with C tracer" if os.environ.get("COVERAGE_NO_EXTENSION"): print("Skipping tests, no C extension in this environment") return print_banner(label) os.environ["COVERAGE_TEST_TRACER"] = tracer nose_args = ["nosetests"] + list(nose_args) nose.core.main(argv=nose_args) def run_tests_with_coverage(tracer, *nose_args): """Run tests, but with coverage.""" import coverage os.environ['COVERAGE_PROCESS_START'] = os.path.abspath('metacov.ini') os.environ['COVERAGE_HOME'] = os.getcwd() # Create the .pth file that will let us measure coverage in sub-processes. import nose pth_dir = os.path.dirname(os.path.dirname(nose.__file__)) pth_path = os.path.join(pth_dir, "covcov.pth") pth_file = open(pth_path, "w") try: pth_file.write("import coverage; coverage.process_startup()\n") finally: pth_file.close() version = "%s%s" % sys.version_info[:2] suffix = "%s_%s_%s" % (version, tracer, socket.gethostname()) cov = coverage.coverage(config_file="metacov.ini", data_suffix=suffix) # Cheap trick: the coverage code itself is excluded from measurement, but # if we clobber the cover_prefix in the coverage object, we can defeat the # self-detection. cov.cover_prefix = "Please measure coverage.py!" cov.erase() cov.start() try: # Re-import coverage to get it coverage tested! I don't understand all # the mechanics here, but if I don't carry over the imported modules # (in covmods), then things go haywire (os == None, eventually). covmods = {} covdir = os.path.split(coverage.__file__)[0] # We have to make a list since we'll be deleting in the loop. modules = list(sys.modules.items()) for name, mod in modules: if name.startswith('coverage'): if getattr(mod, '__file__', "??").startswith(covdir): covmods[name] = mod del sys.modules[name] import coverage # don't warn about re-import: pylint: disable=W0404 sys.modules.update(covmods) # Run nosetests, with the arguments from our command line. try: run_tests(tracer, *nose_args) except SystemExit: # nose3 seems to raise SystemExit, not sure why? pass finally: cov.stop() os.remove(pth_path) cov.save() def do_combine_html(): """Combine data from a meta-coverage run, and make the HTML report.""" import coverage os.environ['COVERAGE_HOME'] = os.getcwd() cov = coverage.coverage(config_file="metacov.ini") cov.load() cov.combine() cov.save() cov.html_report() def do_test_with_tracer(tracer, *noseargs): """Run nosetests with a particular tracer.""" if os.environ.get("COVERAGE_COVERAGE", ""): return run_tests_with_coverage(tracer, *noseargs) else: return run_tests(tracer, *noseargs) def do_zip_mods(): """Build the zipmods.zip file.""" zf = zipfile.ZipFile("tests/zipmods.zip", "w") zf.write("tests/covmodzip1.py", "covmodzip1.py") zf.close() def do_install_egg(): """Install the egg1 egg for tests.""" # I am pretty certain there are easier ways to install eggs... # pylint: disable=F0401,E0611,E1101 import distutils.core cur_dir = os.getcwd() os.chdir("tests/eggsrc") distutils.core.run_setup("setup.py", ["--quiet", "bdist_egg"]) egg = glob.glob("dist/*.egg")[0] distutils.core.run_setup( "setup.py", ["--quiet", "easy_install", "--no-deps", "--zip-ok", egg] ) os.chdir(cur_dir) def do_check_eol(): """Check files for incorrect newlines and trailing whitespace.""" ignore_dirs = [ '.svn', '.hg', '.tox', '.tox_kits', 'coverage.egg-info', '_build', 'covtestegg1.egg-info', ] checked = set([]) def check_file(fname, crlf=True, trail_white=True): """Check a single file for whitespace abuse.""" fname = os.path.relpath(fname) if fname in checked: return checked.add(fname) line = None for n, line in enumerate(open(fname, "rb")): if crlf: if "\r" in line: print("%s@%d: CR found" % (fname, n+1)) return if trail_white: line = line[:-1] if not crlf: line = line.rstrip('\r') if line.rstrip() != line: print("%s@%d: trailing whitespace found" % (fname, n+1)) return if line is not None and not line.strip(): print("%s: final blank line" % (fname,)) def check_files(root, patterns, **kwargs): """Check a number of files for whitespace abuse.""" for root, dirs, files in os.walk(root): for f in files: fname = os.path.join(root, f) for p in patterns: if fnmatch.fnmatch(fname, p): check_file(fname, **kwargs) break for dir_name in ignore_dirs: if dir_name in dirs: dirs.remove(dir_name) check_files("coverage", ["*.py", "*.c"]) check_files("coverage/htmlfiles", ["*.html", "*.css", "*.js"]) check_file("tests/farm/html/src/bom.py", crlf=False) check_files("tests", ["*.py"]) check_files("tests", ["*,cover"], trail_white=False) check_files("tests/js", ["*.js", "*.html"]) check_file("setup.py") check_file("igor.py") check_file("Makefile") check_file(".hgignore") check_file(".travis.yml") check_files("doc", ["*.rst"]) check_files(".", ["*.txt"]) def print_banner(label): """Print the version of Python.""" try: impl = platform.python_implementation() except AttributeError: impl = "Python" version = platform.python_version() if '__pypy__' in sys.builtin_module_names: pypy_version = sys.pypy_version_info # pylint: disable=E1101 version += " (pypy %s)" % ".".join([str(v) for v in pypy_version]) print('=== %s %s %s (%s) ===' % (impl, version, label, sys.executable)) def do_help(): """List the available commands""" items = list(globals().items()) items.sort() for name, value in items: if name.startswith('do_'): print("%-20s%s" % (name[3:], value.__doc__)) def main(args): """Main command-line execution for igor. Verbs are taken from the command line, and extra words taken as directed by the arguments needed by the handler. """ while args: verb = args.pop(0) handler = globals().get('do_'+verb) if handler is None: print("*** No handler for %r" % verb) return 1 argspec = inspect.getargspec(handler) if argspec[1]: # Handler has *args, give it all the rest of the command line. handler_args = args args = [] else: # Handler has specific arguments, give it only what it needs. num_args = len(argspec[0]) handler_args = args[:num_args] args = args[num_args:] ret = handler(*handler_args) # If a handler returns a failure-like value, stop. if ret: return ret if __name__ == '__main__': sys.exit(main(sys.argv[1:])) python-coverage-3.7.1+dfsg.1.orig/setup.cfg0000644000175000017500000000007312252501325017507 0ustar barrybarry[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0