summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2013-12-13 22:45:10 -0500
committerNed Batchelder <ned@nedbatchelder.com>2013-12-13 22:45:10 -0500
commit2df9b1c35cbb5c92204fc5923368a3d619a34f6d (patch)
treed1ede8ffef812ba4e345b08f698f001ebe69cb56
parent84221611890880b749dbb650e8d07ac8918dba46 (diff)
parent7c66441eab3af17539c478a2cb4e19cd93ba0cf4 (diff)
downloadpython-coveragepy-git-2df9b1c35cbb5c92204fc5923368a3d619a34f6d.tar.gz
Merged 4.0 to default
-rw-r--r--CHANGES.txt6
-rw-r--r--TODO.txt15
-rw-r--r--coverage/annotate.py1
-rw-r--r--coverage/backward.py43
-rw-r--r--coverage/cmdline.py31
-rw-r--r--coverage/codeunit.py2
-rw-r--r--coverage/config.py2
-rw-r--r--coverage/control.py16
-rw-r--r--coverage/data.py16
-rw-r--r--coverage/debug.py2
-rw-r--r--coverage/execfile.py64
-rw-r--r--coverage/files.py2
-rw-r--r--coverage/html.py29
-rw-r--r--coverage/misc.py10
-rw-r--r--coverage/parser.py50
-rw-r--r--coverage/phystokens.py10
-rw-r--r--coverage/results.py43
-rw-r--r--coverage/templite.py2
-rw-r--r--coverage/version.py2
-rw-r--r--coverage/xmlreport.py7
-rw-r--r--doc/_ext/px_cleaner.py11
-rw-r--r--igor.py13
-rw-r--r--lab/parser.py15
-rw-r--r--setup.py18
-rw-r--r--tests/backunittest.py19
-rw-r--r--tests/coveragetest.py36
-rw-r--r--tests/farm/html/run_partial.py7
-rw-r--r--tests/osinfo.py7
-rw-r--r--tests/test_arcs.py117
-rw-r--r--tests/test_collector.py3
-rw-r--r--tests/test_config.py24
-rw-r--r--tests/test_coverage.py332
-rw-r--r--tests/test_data.py10
-rw-r--r--tests/test_execfile.py5
-rw-r--r--tests/test_farm.py4
-rw-r--r--tests/test_files.py1
-rw-r--r--tests/test_html.py31
-rw-r--r--tests/test_oddball.py73
-rw-r--r--tests/test_phystokens.py11
-rw-r--r--tests/test_process.py44
-rw-r--r--tests/test_summary.py2
-rw-r--r--tests/test_testing.py9
-rw-r--r--tox.ini2
43 files changed, 486 insertions, 661 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 1e4b888b..8819a98f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -2,6 +2,12 @@
Change history for Coverage.py
------------------------------
+4.0
+---
+
+- Python versions supported are now 2.6, 2.7, 3.2, 3.3.
+
+
3.7.1 -- 13 December 2013
-------------------------
diff --git a/TODO.txt b/TODO.txt
index 3a07a079..d6e0ec0b 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -13,15 +13,18 @@ Key:
- --branch = True ?
- Remove 2.3, 2.4, 2.5 limitations
- - set, sorted, reversed, rpartition
- - generator expressions
- - decorators
- - collections.defaultdict
- - .startswith((,))
+ + set, sorted, reversed, rpartition
+ + generator expressions
+ + decorators
+ + collections.defaultdict
+ + .startswith((,))
+ + "with" statements
+ - .format() ?
+ + try/except/finally
- with assertRaises
- exec statement can look like a function in py2 (since when?)
-- Remove code only run on <2.6
++ Remove code only run on <2.6
- Change data file to json
- Create data api
- New ast-based branch coverage?
diff --git a/coverage/annotate.py b/coverage/annotate.py
index 5c396784..19777eaf 100644
--- a/coverage/annotate.py
+++ b/coverage/annotate.py
@@ -2,7 +2,6 @@
import os, re
-from coverage.backward import sorted # pylint: disable=W0622
from coverage.report import Reporter
class AnnotateReporter(Reporter):
diff --git a/coverage/backward.py b/coverage/backward.py
index 7d268545..8237d01b 100644
--- a/coverage/backward.py
+++ b/coverage/backward.py
@@ -8,47 +8,6 @@
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
@@ -164,7 +123,7 @@ else:
def binary_bytes(byte_values):
"""Produce a byte string with the ints from `byte_values`."""
- return "".join([chr(b) for b in 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."""
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index ea112a8b..c311976d 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -2,7 +2,6 @@
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
@@ -565,17 +564,16 @@ class CoverageScript(object):
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
+ 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:
@@ -722,21 +720,18 @@ def main(argv=None):
end = time.clock()
if 0:
print("time: %.3fs" % (end - start))
- except ExceptionDuringRun:
+ except ExceptionDuringRun as err:
# 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:
+ except CoverageException as err:
# A controlled error inside coverage.py: print the message to the user.
- _, err, _ = sys.exc_info()
print(err)
status = ERR
- except SystemExit:
+ except SystemExit as err:
# The user called `sys.exit()`. Exit with their argument, if any.
- _, err, _ = sys.exc_info()
if err.args:
status = err.args[0]
else:
diff --git a/coverage/codeunit.py b/coverage/codeunit.py
index ca1ae5c5..c58e237b 100644
--- a/coverage/codeunit.py
+++ b/coverage/codeunit.py
@@ -52,7 +52,7 @@ class CodeUnit(object):
else:
f = morf
# .pyc files should always refer to a .py instead.
- if f.endswith('.pyc') or f.endswith('.pyo'):
+ if f.endswith(('.pyc', '.pyo')):
f = f[:-1]
elif f.endswith('$py.class'): # Jython
f = f[:-9] + ".py"
diff --git a/coverage/config.py b/coverage/config.py
index 87318ff1..6223afda 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -25,7 +25,7 @@ class HandyConfigParser(configparser.RawConfigParser):
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]
+ word = next(w for w in m.groups() if w is not None)
if word == "$":
return "$"
else:
diff --git a/coverage/control.py b/coverage/control.py
index f75a3dda..fa6fec74 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -3,7 +3,7 @@
import atexit, os, random, socket, sys
from coverage.annotate import AnnotateReporter
-from coverage.backward import string_class, iitems, sorted # pylint: disable=W0622
+from coverage.backward import string_class, iitems
from coverage.codeunit import code_unit_factory, CodeUnit
from coverage.collector import Collector
from coverage.config import CoverageConfig
@@ -98,8 +98,7 @@ class coverage(object):
config_file = ".coveragerc"
try:
self.config.from_file(config_file)
- except ValueError:
- _, err, _ = sys.exc_info()
+ except ValueError as err:
raise CoverageException(
"Couldn't read config file %s: %s" % (config_file, err)
)
@@ -689,12 +688,11 @@ class coverage(object):
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
+ 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()
diff --git a/coverage/data.py b/coverage/data.py
index fb88c5b1..042b6405 100644
--- a/coverage/data.py
+++ b/coverage/data.py
@@ -2,7 +2,7 @@
import os
-from coverage.backward import iitems, pickle, sorted # pylint: disable=W0622
+from coverage.backward import iitems, pickle
from coverage.files import PathAliases
from coverage.misc import file_be_gone
@@ -101,13 +101,13 @@ class CoverageData(object):
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)]
+ (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)]
+ (f, sorted(amap.keys())) for f, amap in iitems(self.arcs)
)
def write_file(self, filename):
@@ -128,11 +128,8 @@ class CoverageData(object):
self.debug.write("Writing data to %r" % (filename,))
# Write the pickle to the file.
- fdata = open(filename, 'wb')
- try:
+ with open(filename, 'wb') as fdata:
pickle.dump(data, fdata, 2)
- finally:
- fdata.close()
def read_file(self, filename):
"""Read the coverage data from `filename`."""
@@ -142,11 +139,8 @@ class CoverageData(object):
"""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:
+ with open(filename, 'rb') as fdata:
data = pickle.load(fdata)
- finally:
- fdata.close()
return data
def _read_file(self, filename):
diff --git a/coverage/debug.py b/coverage/debug.py
index 104f3b1d..6908383d 100644
--- a/coverage/debug.py
+++ b/coverage/debug.py
@@ -41,7 +41,7 @@ def info_formatter(info):
nicely formatted, ready to print.
"""
- label_len = max([len(l) for l, _d in info])
+ label_len = max(len(l) for l, _d in info)
for label, data in info:
if data == []:
data = "-none-"
diff --git a/coverage/execfile.py b/coverage/execfile.py
index f6ebdf79..f90096e9 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -31,35 +31,33 @@ def run_python_module(modulename, args):
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()
+ # 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)
-
- # 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))
+ except ImportError as err:
+ raise NoSource(str(err))
finally:
if openfile:
openfile.close()
@@ -94,7 +92,7 @@ def run_python_file(filename, args, package=None):
try:
# Make a code object somehow.
- if filename.endswith(".pyc") or filename.endswith(".pyo"):
+ if filename.endswith((".pyc", ".pyo")):
code = make_code_from_pyc(filename)
else:
code = make_code_from_py(filename)
@@ -129,10 +127,8 @@ def make_code_from_py(filename):
except IOError:
raise NoSource("No file to run: %r" % filename)
- try:
+ with source_file:
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.
@@ -150,7 +146,7 @@ def make_code_from_pyc(filename):
except IOError:
raise NoCode("No file to run: %r" % filename)
- try:
+ with fpyc:
# First four bytes are a version-specific magic number. It has to
# match or we won't run the file.
magic = fpyc.read(4)
@@ -165,7 +161,5 @@ def make_code_from_pyc(filename):
# The rest of the file is the code object we want.
code = marshal.load(fpyc)
- finally:
- fpyc.close()
return code
diff --git a/coverage/files.py b/coverage/files.py
index 464535a8..94388f96 100644
--- a/coverage/files.py
+++ b/coverage/files.py
@@ -137,7 +137,7 @@ def prep_patterns(patterns):
"""
prepped = []
for p in patterns or []:
- if p.startswith("*") or p.startswith("?"):
+ if p.startswith(("*", "?")):
prepped.append(p)
else:
prepped.append(abs_file(p))
diff --git a/coverage/html.py b/coverage/html.py
index 5242236c..d168e351 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -43,11 +43,8 @@ def data_filename(fname, pkgdir=""):
def data(fname):
"""Return the contents of a data file of ours."""
- data_file = open(data_filename(fname))
- try:
+ with open(data_filename(fname)) as data_file:
return data_file.read()
- finally:
- data_file.close()
class HtmlReporter(Reporter):
@@ -140,11 +137,8 @@ class HtmlReporter(Reporter):
def write_html(self, fname, html):
"""Write `html` to `fname`, properly encoded."""
- fout = open(fname, "wb")
- try:
+ with open(fname, "wb") as fout:
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."""
@@ -156,10 +150,8 @@ class HtmlReporter(Reporter):
def html_file(self, cu, analysis):
"""Generate an HTML file for one source file."""
source_file = cu.source_file()
- try:
+ with source_file:
source = source_file.read()
- finally:
- source_file.close()
# Find out if the file on disk is already correct.
flat_rootname = cu.flat_rootname()
@@ -195,8 +187,7 @@ class HtmlReporter(Reporter):
lines = []
- for lineno, line in enumerate(source_token_lines(source)):
- lineno += 1 # 1-based line numbers.
+ for lineno, line in enumerate(source_token_lines(source), start=1):
# Figure out how to mark this line.
line_class = []
annotate_html = ""
@@ -271,7 +262,7 @@ class HtmlReporter(Reporter):
data("index.html"), self.template_globals
)
- self.totals = sum([f['nums'] for f in self.files])
+ self.totals = sum(f['nums'] for f in self.files)
html = index_tmpl.render({
'arcs': self.arcs,
@@ -310,11 +301,8 @@ class HtmlStatus(object):
usable = False
try:
status_file = os.path.join(directory, self.STATUS_FILE)
- fstatus = open(status_file, "rb")
- try:
+ with open(status_file, "rb") as fstatus:
status = pickle.load(fstatus)
- finally:
- fstatus.close()
except (IOError, ValueError):
usable = False
else:
@@ -339,11 +327,8 @@ class HtmlStatus(object):
'settings': self.settings,
'files': self.files,
}
- fout = open(status_file, "wb")
- try:
+ with open(status_file, "wb") as fout:
pickle.dump(status, fout)
- finally:
- fout.close()
def settings_hash(self):
"""Get the hash of the coverage.py settings."""
diff --git a/coverage/misc.py b/coverage/misc.py
index 0378173f..c88d4ecd 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -3,9 +3,8 @@
import errno
import inspect
import os
-import sys
-from coverage.backward import md5, sorted # pylint: disable=W0622
+from coverage.backward import md5
from coverage.backward import string_class, to_bytes
@@ -59,7 +58,7 @@ def format_lines(statements, lines):
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])
+ return "\n".join("%30s : %s @%d" % (t[3],t[1],t[2]) for t in stack)
def expensive(fn):
@@ -88,7 +87,7 @@ def bool_or_none(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])
+ return "|".join("(%s)" % r for r in regexes)
elif regexes:
return regexes[0]
else:
@@ -99,8 +98,7 @@ 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()
+ except OSError as e:
if e.errno != errno.ENOENT:
raise
diff --git a/coverage/parser.py b/coverage/parser.py
index 7a145a2a..de6590aa 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -1,10 +1,9 @@
"""Code parsing for Coverage."""
-import dis, re, sys, token, tokenize
+import collections, dis, re, token, tokenize
-from coverage.backward import set, sorted, StringIO # pylint: disable=W0622
+from coverage.backward import StringIO
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
@@ -26,13 +25,9 @@ class CodeParser(object):
self.text = text
if not self.text:
try:
- sourcef = open_source(self.filename)
- try:
+ with open_source(self.filename) as sourcef:
self.text = sourcef.read()
- finally:
- sourcef.close()
- except IOError:
- _, err, _ = sys.exc_info()
+ except IOError as err:
raise NoSource(
"No source for code: '%s': %s" % (self.filename, err)
)
@@ -66,13 +61,13 @@ class CodeParser(object):
# Lazily-created ByteParser
self._byte_parser = None
- def _get_byte_parser(self):
+ @property
+ def 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.
@@ -84,9 +79,9 @@ class CodeParser(object):
"""
regex_c = re.compile(join_regex(regexes))
matches = set()
- for i, ltext in enumerate(self.lines):
+ for i, ltext in enumerate(self.lines, start=1):
if regex_c.search(ltext):
- matches.add(i+1)
+ matches.add(i)
return matches
def _raw_parse(self):
@@ -208,8 +203,7 @@ class CodeParser(object):
"""
try:
self._raw_parse()
- except (tokenize.TokenError, IndentationError):
- _, tokerr, _ = sys.exc_info()
+ except (tokenize.TokenError, IndentationError) as tokerr:
msg, lineno = tokerr.args
raise NotPython(
"Couldn't parse '%s' as Python source: '%s' at %s" %
@@ -225,6 +219,7 @@ class CodeParser(object):
return lines, excluded_lines
+ @expensive
def arcs(self):
"""Get information about the arcs available in the code.
@@ -239,8 +234,8 @@ class CodeParser(object):
if fl1 != fl2:
all_arcs.append((fl1, fl2))
return sorted(all_arcs)
- arcs = expensive(arcs)
+ @expensive
def exit_counts(self):
"""Get a mapping from line numbers to count of exits from that line.
@@ -248,7 +243,7 @@ class CodeParser(object):
"""
excluded_lines = self.first_lines(self.excluded)
- exit_counts = {}
+ exit_counts = collections.defaultdict(int)
for l1, l2 in self.arcs():
if l1 < 0:
# Don't ever report -1 as a line number
@@ -259,8 +254,6 @@ class CodeParser(object):
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:
@@ -270,7 +263,6 @@ class CodeParser(object):
exit_counts[l] -= 1
return exit_counts
- exit_counts = expensive(exit_counts)
## Opcodes that guide the ByteParser.
@@ -336,19 +328,15 @@ class ByteParser(object):
else:
if not text:
assert filename, "If no code or text, need a filename"
- sourcef = open_source(filename)
- try:
+ with open_source(filename) as sourcef:
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()
+ except SyntaxError as synerr:
raise NotPython(
"Couldn't parse '%s' as Python source: '%s' at line %d" %
(filename, synerr.msg, synerr.lineno)
@@ -371,7 +359,7 @@ class ByteParser(object):
"""
children = CodeObjects(self.code)
- return [ByteParser(code=c, text=self.text) for c in children]
+ return (ByteParser(code=c, text=self.text) for c in children)
def _bytes_lines(self):
"""Map byte offsets to line numbers in `code`.
@@ -415,7 +403,7 @@ class ByteParser(object):
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]
+ "(%s, %r)" % (dis.opname[b[0]], b[1]) for b in block_stack
)
return "[" + blocks + "]"
@@ -554,9 +542,9 @@ class ByteParser(object):
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])
+ 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])
+ assert all((ex in starts or ex < 0) for ex in ch.exits)
def _arcs(self):
"""Find the executable arcs in the code.
@@ -569,7 +557,7 @@ class ByteParser(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])
+ 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)
diff --git a/coverage/phystokens.py b/coverage/phystokens.py
index 99b1d5ba..e79ce01f 100644
--- a/coverage/phystokens.py
+++ b/coverage/phystokens.py
@@ -1,7 +1,6 @@
"""Better tokenizing for coverage.py."""
import codecs, keyword, re, sys, token, tokenize
-from coverage.backward import set # pylint: disable=W0622
from coverage.parser import generate_tokens
@@ -143,13 +142,8 @@ def source_encoding(source):
# 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'
+ # If no encoding is specified, then the default will be returned.
+ default = 'ascii'
bom_found = False
encoding = None
diff --git a/coverage/results.py b/coverage/results.py
index db6df0d3..0576ae1f 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -1,8 +1,9 @@
"""Results of coverage measurement."""
+import collections
import os
-from coverage.backward import iitems, set, sorted # pylint: disable=W0622
+from coverage.backward import iitems
from coverage.misc import format_lines, join_regex, NoSource
from coverage.parser import CodeParser
@@ -36,9 +37,9 @@ class Analysis(object):
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]
+ 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)])
+ 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()
@@ -112,18 +113,18 @@ class Analysis(object):
"""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]
+ 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 = [
+ 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):
@@ -133,11 +134,11 @@ class Analysis(object):
# 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 = [
+ unpredicted = (
e for e in executed
if e not in possible
and e[0] != e[1]
- ]
+ )
return sorted(unpredicted)
def branch_lines(self):
@@ -148,7 +149,7 @@ class Analysis(object):
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])
+ 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.
@@ -158,11 +159,9 @@ class Analysis(object):
"""
missing = self.arcs_missing()
branch_lines = set(self.branch_lines())
- mba = {}
+ mba = collections.defaultdict(list)
for l1, l2 in missing:
if l1 in branch_lines:
- if l1 not in mba:
- mba[l1] = []
mba[l1].append(l2)
return mba
@@ -210,25 +209,26 @@ class Numbers(object):
self.n_partial_branches = n_partial_branches
self.n_missing_branches = n_missing_branches
+ @classmethod
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):
+ @property
+ def 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):
+ @property
+ def 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):
+ @property
+ def 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) /
@@ -236,9 +236,9 @@ class Numbers(object):
else:
pc_cov = 100.0
return pc_cov
- pc_covered = property(_get_pc_covered)
- def _get_pc_covered_str(self):
+ @property
+ def 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"
@@ -254,15 +254,14 @@ class Numbers(object):
else:
pc = round(pc, self._precision)
return "%.*f" % (self._precision, pc)
- pc_covered_str = property(_get_pc_covered_str)
+ @classmethod
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()
diff --git a/coverage/templite.py b/coverage/templite.py
index e5c0bafe..429a5ccc 100644
--- a/coverage/templite.py
+++ b/coverage/templite.py
@@ -4,8 +4,6 @@
import re
-from coverage.backward import set # pylint: disable=W0622
-
class CodeBuilder(object):
"""Build source code conveniently."""
diff --git a/coverage/version.py b/coverage/version.py
index a43bde80..27c2f6b1 100644
--- a/coverage/version.py
+++ b/coverage/version.py
@@ -1,7 +1,7 @@
"""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
+__version__ = "4.0a0" # see detailed history in CHANGES.txt
__url__ = "http://nedbatchelder.com/code/coverage"
if max(__version__).isalpha():
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 26ac02ad..f5a4c1ba 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -4,7 +4,6 @@ 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):
@@ -97,7 +96,7 @@ class XmlReporter(Reporter):
# Create the 'lines' and 'package' XML elements, which
# are populated later. Note that a package == a directory.
- package_name = rpartition(cu.name, ".")[0]
+ package_name = cu.name.rpartition(".")[0]
className = cu.name
package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0])
@@ -138,8 +137,8 @@ class XmlReporter(Reporter):
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_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
diff --git a/doc/_ext/px_cleaner.py b/doc/_ext/px_cleaner.py
index a5c00ff3..24541207 100644
--- a/doc/_ext/px_cleaner.py
+++ b/doc/_ext/px_cleaner.py
@@ -5,17 +5,11 @@ import sys
def clean_px(fname):
"""Clean a px file."""
- f = open(fname)
- try:
+ with open(fname) as f:
text = f.read()
- finally:
- f.close()
text = text.lstrip()
- f = open(fname, "w")
- try:
+ with open(fname, "w") as f:
f.write(text)
- finally:
- f.close()
def clean_px_files(fnames):
for fname in fnames:
@@ -23,4 +17,3 @@ def clean_px_files(fnames):
if __name__ == '__main__':
clean_px_files(sys.argv[1:])
-
diff --git a/igor.py b/igor.py
index 12ec6c8f..f7879d7c 100644
--- a/igor.py
+++ b/igor.py
@@ -62,11 +62,8 @@ def run_tests_with_coverage(tracer, *nose_args):
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:
+ with open(pth_path, "w") as pth_file:
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())
@@ -161,17 +158,17 @@ def do_check_eol():
checked.add(fname)
line = None
- for n, line in enumerate(open(fname, "rb")):
+ for n, line in enumerate(open(fname, "rb"), start=1):
if crlf:
if "\r" in line:
- print("%s@%d: CR found" % (fname, n+1))
+ print("%s@%d: CR found" % (fname, n))
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))
+ print("%s@%d: trailing whitespace found" % (fname, n))
return
if line is not None and not line.strip():
@@ -216,7 +213,7 @@ def print_banner(label):
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])
+ version += " (pypy %s)" % ".".join(str(v) for v in pypy_version)
print('=== %s %s %s (%s) ===' % (impl, version, label, sys.executable))
diff --git a/lab/parser.py b/lab/parser.py
index ce6902a6..a8e03eec 100644
--- a/lab/parser.py
+++ b/lab/parser.py
@@ -54,13 +54,11 @@ class ParserMain(object):
def one_file(self, options, filename):
"""Process just one file."""
- if options.dis or options.chunks:
- try:
- bp = ByteParser(filename=filename)
- except CoverageException:
- _, err, _ = sys.exc_info()
- print("%s" % (err,))
- return
+ try:
+ bp = ByteParser(filename=filename)
+ except CoverageException as err:
+ print("%s" % (err,))
+ return
if options.dis:
print("Main code:")
@@ -88,8 +86,7 @@ class ParserMain(object):
exit_counts = cp.exit_counts()
- for i, ltext in enumerate(cp.lines):
- lineno = i+1
+ for lineno, ltext in enumerate(cp.lines, start=1):
m0 = m1 = m2 = m3 = a = ' '
if lineno in cp.statement_starts:
m0 = '-'
diff --git a/setup.py b/setup.py
index f0e83e67..e8780f3a 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ 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.
+Coverage.py runs on Pythons 2.6, 2.7, 3.2, 3.3, and PyPy 1.9.
Documentation is at `nedbatchelder.com <%s>`_. Code repository and issue
tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, with a
@@ -54,11 +54,8 @@ 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:
+with open(cov_ver_py) as version_file:
exec(compile(version_file.read(), cov_ver_py, 'exec'))
-finally:
- version_file.close()
doclines = (doc % __url__).splitlines()
classifier_list = classifiers.splitlines()
@@ -118,8 +115,8 @@ ext_errors = (
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
+if sys.platform == 'win32':
+ # distutils.msvc9compiler can raise an IOError when failing to
# find the compiler
ext_errors += (IOError,)
@@ -147,9 +144,9 @@ class ve_build_ext(build_ext):
build_ext.build_extension(self, ext)
except ext_errors:
raise BuildFailed()
- except ValueError:
+ except ValueError as err:
# 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
+ if "'path'" in str(err): # works with both py 2/3
raise BuildFailed()
raise
@@ -189,9 +186,8 @@ def main():
# extension. Try it with, and if it fails, try it without.
try:
setup(**setup_args)
- except BuildFailed:
+ except BuildFailed as exc:
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))
diff --git a/tests/backunittest.py b/tests/backunittest.py
index 30da78eb..0964ab1d 100644
--- a/tests/backunittest.py
+++ b/tests/backunittest.py
@@ -1,8 +1,6 @@
"""Implementations of unittest features from the future."""
-import difflib, re, sys, unittest
-
-from coverage.backward import set # pylint: disable=W0622
+import difflib, re, unittest
def _need(method):
@@ -17,18 +15,6 @@ class TestCase(unittest.TestCase):
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`."""
@@ -57,8 +43,7 @@ class TestCase(unittest.TestCase):
"""
try:
callobj(*args, **kw)
- except excClass:
- _, exc, _ = sys.exc_info()
+ except excClass as exc:
excMsg = str(exc)
if re.search(regexp, excMsg):
# Message provided, and we got the right one: it passes.
diff --git a/tests/coveragetest.py b/tests/coveragetest.py
index f6680cc9..d047a472 100644
--- a/tests/coveragetest.py
+++ b/tests/coveragetest.py
@@ -1,11 +1,10 @@
"""Base test case class for coverage testing."""
import glob, imp, os, random, shlex, shutil, sys, tempfile, textwrap
-import atexit
+import atexit, collections
import coverage
-from coverage.backward import sorted, StringIO # pylint: disable=W0622
-from coverage.backward import to_bytes
+from coverage.backward import StringIO, to_bytes
from coverage.control import _TEST_NAME_FILE
from tests.backtest import run_command
from tests.backunittest import TestCase
@@ -191,11 +190,8 @@ class CoverageTest(TestCase):
os.makedirs(dirs)
# Create the file.
- f = open(filename, 'wb')
- try:
+ with open(filename, 'wb') as f:
f.write(to_bytes(text))
- finally:
- f.close()
return filename
@@ -224,17 +220,16 @@ class CoverageTest(TestCase):
"""
modfile = modname + '.py'
- f = open(modfile, 'r')
for suff in imp.get_suffixes():
if suff[0] == '.py':
break
- try:
+
+ with open(modfile, 'r') as f:
# 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):
@@ -267,10 +262,10 @@ class CoverageTest(TestCase):
# 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, ord(c)-ord('0')) for c in '123456789'))
_arcz_map.update(dict(
- [(c, 10+ord(c)-ord('A')) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
- ))
+ (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.
@@ -306,8 +301,8 @@ class CoverageTest(TestCase):
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"
+ 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="",
@@ -508,8 +503,9 @@ class CoverageTest(TestCase):
self.test_method_made_any_files = False
# Map from class to info about how it ran.
- class_behaviors = {}
+ class_behaviors = collections.defaultdict(ClassBehavior)
+ @classmethod
def report_on_class_behavior(cls):
"""Called at process exit to report on class behavior."""
for test_class, behavior in cls.class_behaviors.items():
@@ -534,14 +530,10 @@ class CoverageTest(TestCase):
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]
+ return self.class_behaviors[self.__class__]
# When the process ends, find out about bad classes.
diff --git a/tests/farm/html/run_partial.py b/tests/farm/html/run_partial.py
index 41e6ba96..eab14411 100644
--- a/tests/farm/html/run_partial.py
+++ b/tests/farm/html/run_partial.py
@@ -24,9 +24,8 @@ contains("html_partial/partial.html",
contains("html_partial/index.html",
"<a href='partial.html'>partial</a>",
)
-if sys.version_info >= (2, 4):
- contains("html_partial/index.html",
- "<span class='pc_cov'>100%</span>"
- )
+contains("html_partial/index.html",
+ "<span class='pc_cov'>100%</span>"
+ )
clean("html_partial")
diff --git a/tests/osinfo.py b/tests/osinfo.py
index 25c3a7c6..a123123c 100644
--- a/tests/osinfo.py
+++ b/tests/osinfo.py
@@ -2,7 +2,7 @@
import sys
-if sys.version_info >= (2, 5) and sys.platform == 'win32':
+if sys.platform == 'win32':
# Windows implementation
def process_ram():
"""How much RAM is this process using? (Windows)"""
@@ -44,11 +44,8 @@ elif sys.platform == 'linux2':
"""Read the /proc/PID/status file to find memory use."""
try:
# get pseudo file /proc/<pid>/status
- t = open('/proc/%d/status' % os.getpid())
- try:
+ with open('/proc/%d/status' % os.getpid()) as t:
v = t.read()
- finally:
- t.close()
except IOError:
return 0 # non-Linux?
# get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
diff --git a/tests/test_arcs.py b/tests/test_arcs.py
index 6268e289..80923f8d 100644
--- a/tests/test_arcs.py
+++ b/tests/test_arcs.py
@@ -88,12 +88,6 @@ class SimpleArcTest(CoverageTest):
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 +
@@ -102,7 +96,7 @@ class SimpleArcTest(CoverageTest):
b = \\
6
""",
- arcz=arcz, arcz_missing="")
+ arcz=".1 15 5-2", arcz_missing="")
def test_if_return(self):
self.check_coverage("""\
@@ -151,33 +145,32 @@ class SimpleArcTest(CoverageTest):
)
-if sys.version_info >= (2, 6):
- class WithTest(CoverageTest):
- """Arc-measuring tests involving context managers."""
+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
+ 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."
- )
+ 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."
- )
+ 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):
@@ -509,9 +502,9 @@ class ExceptionArcTest(CoverageTest):
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
+ # Run this test only on Py2 for now. I hope to fix it on Py3
# eventually...
- if (2, 6) <= sys.version_info < (3,):
+ if sys.version_info < (3, 0):
# "except Exception as e" is crucial here.
def test_bug_212(self):
self.check_coverage("""\
@@ -533,36 +526,34 @@ class ExceptionArcTest(CoverageTest):
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")
+ 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):
diff --git a/tests/test_collector.py b/tests/test_collector.py
index 2714398a..7bd4bebb 100644
--- a/tests/test_collector.py
+++ b/tests/test_collector.py
@@ -4,7 +4,6 @@ import re
import coverage
from coverage.backward import StringIO
-from coverage.backward import set # pylint: disable=W0622
from tests.coveragetest import CoverageTest
@@ -49,7 +48,7 @@ class CollectorTest(CoverageTest):
# duplicates.
trace_lines = [
l for l in debug_out.getvalue().splitlines()
- if l.startswith("Tracing ") or l.startswith("Not tracing ")
+ if l.startswith(("Tracing ", "Not tracing "))
]
filenames = [re.search(r"'[^']+'", l).group() for l in trace_lines]
self.assertEqual(len(filenames), len(set(filenames)))
diff --git a/tests/test_config.py b/tests/test_config.py
index 6d370255..0862d6b2 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
"""Test the config file handling for coverage.py"""
-import sys
import coverage
from coverage.misc import CoverageException
@@ -211,15 +210,14 @@ class ConfigFileTest(CoverageTest):
'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"
- )
+ 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"
+ )
diff --git a/tests/test_coverage.py b/tests/test_coverage.py
index 6de4d0ea..078c66ca 100644
--- a/tests/test_coverage.py
+++ b/tests/test_coverage.py
@@ -839,15 +839,13 @@ class CompoundStatementTest(CoverageTest):
""",
[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_constant_if(self):
+ self.check_coverage("""\
+ if 1:
+ a = 2
+ assert a == 2
+ """,
+ [2,3], "")
def test_while(self):
self.check_coverage("""\
@@ -1510,187 +1508,185 @@ class ExcludeTest(CoverageTest):
[8,9], "", excludes=['#pragma: NO COVER'])
-if sys.version_info >= (2, 4):
- class Py24Test(CoverageTest):
- """Tests of new syntax in Python 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)
+ 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
- @require_int
- def p1(arg):
- return arg*2
+ @boost_by(10)
+ def boosted(arg):
+ return arg*2
- assert p1(10) == 20
- """,
- [1,2,3,4,6,8,10,12], "")
+ assert boosted(10) == 200
+ """,
+ [1,2,3,4,5,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 test_double_function_decorators(self):
- self.check_coverage("""\
- def require_int(func):
+ def boost_by(extra):
+ def decorator(func):
def wrapper(arg):
- assert isinstance(arg, int)
- return func(arg)
+ return extra*func(arg)
return wrapper
+ return decorator
- 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
- @require_int
- @boost_by(10)
- def boosted1(arg):
- return arg*2
+ assert boosted1(10) == 200
- assert boosted1(10) == 200
+ @boost_by(10)
+ @require_int
+ def boosted2(arg):
+ return arg*2
- @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]), "")
- 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]), "")
+class Py25Test(CoverageTest):
+ """Tests of new syntax in Python 2.5."""
-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
- def test_with_statement(self):
- self.check_coverage("""\
- from __future__ import with_statement
+ class Managed:
+ def __enter__(self):
+ desc = "enter"
- class Managed:
- def __enter__(self):
- desc = "enter"
+ def __exit__(self, type, value, tb):
+ desc = "exit"
- def __exit__(self, type, value, tb):
- desc = "exit"
+ m = Managed()
+ with m:
+ desc = "block1a"
+ desc = "block1b"
- m = Managed()
+ try:
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], "")
+ 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")
+ 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):
diff --git a/tests/test_data.py b/tests/test_data.py
index 9c29289d..31578f26 100644
--- a/tests/test_data.py
+++ b/tests/test_data.py
@@ -92,11 +92,8 @@ class DataTest(CoverageTest):
covdata.add_line_data(DATA_1)
covdata.write()
- fdata = open(".coverage", 'rb')
- try:
+ with open(".coverage", 'rb') as fdata:
data = pickle.load(fdata)
- finally:
- fdata.close()
lines = data['lines']
self.assertSameElements(lines.keys(), MEASURED_FILES_1)
@@ -111,11 +108,8 @@ class DataTest(CoverageTest):
covdata.add_arc_data(ARC_DATA_3)
covdata.write()
- fdata = open(".coverage", 'rb')
- try:
+ with open(".coverage", 'rb') as fdata:
data = pickle.load(fdata)
- finally:
- fdata.close()
self.assertSameElements(data['lines'].keys(), [])
arcs = data['arcs']
diff --git a/tests/test_execfile.py b/tests/test_execfile.py
index 24c521bd..ca13d7c8 100644
--- a/tests/test_execfile.py
+++ b/tests/test_execfile.py
@@ -54,11 +54,8 @@ class RunFileTest(CoverageTest):
# 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:
+ with open('nl.py', 'wb') as fpy:
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)
diff --git a/tests/test_farm.py b/tests/test_farm.py
index fee28063..c86983e5 100644
--- a/tests/test_farm.py
+++ b/tests/test_farm.py
@@ -78,10 +78,10 @@ class FarmTestCase(object):
copy run runfunc compare contains doesnt_contain clean skip
""".split()
if self.clean_only:
- glo = dict([(fn, self.noop) for fn in fns])
+ glo = dict((fn, self.noop) for fn in fns)
glo['clean'] = self.clean
else:
- glo = dict([(fn, getattr(self, fn)) for fn in fns])
+ glo = dict((fn, getattr(self, fn)) for fn in fns)
if self.dont_clean: # pragma: not covered
glo['clean'] = self.noop
diff --git a/tests/test_files.py b/tests/test_files.py
index b24e8b8b..230cd092 100644
--- a/tests/test_files.py
+++ b/tests/test_files.py
@@ -4,7 +4,6 @@ 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
diff --git a/tests/test_html.py b/tests/test_html.py
index 06132fb4..f22fdc21 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -177,22 +177,21 @@ class HtmlTitleTest(HtmlTestHelpers, CoverageTest):
self.assertIn("<title>Metrics &amp; stuff!</title>", index)
self.assertIn("<h1>Metrics &amp; 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(
- "<title>&#171;&#964;&#945;&#1041;&#1068;&#8467;&#963;&#187;"
- " numbers", index
- )
- self.assertIn(
- "<h1>&#171;&#964;&#945;&#1041;&#1068;&#8467;&#963;&#187;"
- " numbers", index
- )
+ 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(
+ "<title>&#171;&#964;&#945;&#1041;&#1068;&#8467;&#963;&#187;"
+ " numbers", index
+ )
+ self.assertIn(
+ "<h1>&#171;&#964;&#945;&#1041;&#1068;&#8467;&#963;&#187;"
+ " numbers", index
+ )
def test_title_set_in_args(self):
self.create_initial_files()
diff --git a/tests/test_oddball.py b/tests/test_oddball.py
index 4b18a4ee..eba507be 100644
--- a/tests/test_oddball.py
+++ b/tests/test_oddball.py
@@ -329,43 +329,42 @@ class ExceptionTest(CoverageTest):
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 <arg> is None, return "Void"; otherwise return <arg>
-
- >>> 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], "")
+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 <arg> is None, return "Void"; otherwise return <arg>
+
+ >>> 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'):
diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py
index c1e51f1c..9ff053c4 100644
--- a/tests/test_phystokens.py
+++ b/tests/test_phystokens.py
@@ -29,7 +29,7 @@ class PhysTokensTest(CoverageTest):
"""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])
+ text = "".join(t for _, t in line)
tokenized += text + "\n"
# source_token_lines doesn't preserve trailing spaces, so trim all that
# before comparing.
@@ -86,11 +86,6 @@ if sys.version_info < (3, 0):
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"
@@ -110,11 +105,11 @@ if sys.version_info < (3, 0):
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)
+ self.assertEqual(source_encoding(source), 'ascii')
def test_detect_source_encoding_of_empty_file(self):
# An important edge case.
- self.assertEqual(source_encoding(""), self.default_encoding)
+ self.assertEqual(source_encoding(""), 'ascii')
def test_bom(self):
# A BOM means utf-8.
diff --git a/tests/test_process.py b/tests/test_process.py
index c49d90a9..ddbbafd6 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -35,7 +35,7 @@ class ProcessTest(CoverageTest):
import covmod1
import covmodzip1
a = 1
- print ('done')
+ print('done')
""")
self.assert_doesnt_exist(".coverage")
@@ -52,7 +52,7 @@ class ProcessTest(CoverageTest):
else:
c = 1
d = 1
- print ('done')
+ print('done')
""")
out = self.run_command("coverage -x -p b_or_c.py b")
@@ -88,7 +88,7 @@ class ProcessTest(CoverageTest):
else:
c = 1
d = 1
- print ('done')
+ print('done')
""")
out = self.run_command("coverage -x -p b_or_c.py b")
@@ -128,7 +128,7 @@ class ProcessTest(CoverageTest):
else:
c = 1
d = 1
- print ('done')
+ print('done')
""")
self.make_file(".coveragerc", """\
@@ -270,7 +270,7 @@ class ProcessTest(CoverageTest):
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])
+ 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.
@@ -324,23 +324,20 @@ class ProcessTest(CoverageTest):
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(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)
+ 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
@@ -575,16 +572,13 @@ class ProcessStartupTest(CoverageTest):
g = glob.glob(os.path.join(d, "*.pth"))
if g:
pth_path = os.path.join(d, "subcover.pth")
- pth = open(pth_path, "w")
- try:
+ with open(pth_path, "w") as pth:
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")
diff --git a/tests/test_summary.py b/tests/test_summary.py
index 8035513e..29167bf8 100644
--- a/tests/test_summary.py
+++ b/tests/test_summary.py
@@ -16,7 +16,7 @@ class SummaryTest(CoverageTest):
import covmod1
import covmodzip1
a = 1
- print ('done')
+ 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'))
diff --git a/tests/test_testing.py b/tests/test_testing.py
index c56d8110..64dca617 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -2,11 +2,10 @@
"""Tests that our test infrastructure is really working!"""
import os, sys
-from coverage.backward import to_bytes, rpartition
+from coverage.backward import to_bytes
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`."""
@@ -184,11 +183,11 @@ class CoverageTestTest(CoverageTest):
# 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 = next(l for l in out if "executable:" in l)
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, ":")
+ environ = next(l for l in out if "COV_FOOBAR" in l)
+ _, _, environ = environ.rpartition(":")
self.assertEqual(environ.strip(), "COV_FOOBAR = XYZZY")
diff --git a/tox.ini b/tox.ini
index 7e78ea4a..1b020493 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
-envlist = py25, py26, py27, py31, py32, py33, pypy
+envlist = py26, py27, py32, py33, pypy
[testenv]
commands =