summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-05-01 13:02:31 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-05-01 13:30:39 -0400
commit9df434550a499c16e9fd26cfb9627837bfdc02a5 (patch)
tree5619ea3c3bec05d04363a66ced9c7ebffcefb1df /coverage
parent3fe17c1f2244c07cf9d0f9e3609392c2ad441db1 (diff)
downloadpython-coveragepy-git-9df434550a499c16e9fd26cfb9627837bfdc02a5.tar.gz
refactor: remove code explicitly choosing between py2 and py3
Diffstat (limited to 'coverage')
-rw-r--r--coverage/backward.py68
-rw-r--r--coverage/cmdline.py4
-rw-r--r--coverage/env.py4
-rw-r--r--coverage/execfile.py6
-rw-r--r--coverage/files.py20
-rw-r--r--coverage/html.py3
-rw-r--r--coverage/misc.py3
-rw-r--r--coverage/numbits.py16
-rw-r--r--coverage/parser.py7
-rw-r--r--coverage/phystokens.py110
-rw-r--r--coverage/pytracer.py2
-rw-r--r--coverage/report.py6
-rw-r--r--coverage/sqldata.py17
-rw-r--r--coverage/summary.py5
-rw-r--r--coverage/templite.py7
-rw-r--r--coverage/xmlreport.py6
16 files changed, 41 insertions, 243 deletions
diff --git a/coverage/backward.py b/coverage/backward.py
index 779cd661..da839d71 100644
--- a/coverage/backward.py
+++ b/coverage/backward.py
@@ -11,8 +11,6 @@ import sys
from datetime import datetime
-from coverage import env
-
# Pythons 2 and 3 differ on where to get StringIO.
try:
@@ -119,51 +117,27 @@ else:
return iter(seq).next
# 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 env.PY3:
- def to_bytes(s):
- """Convert string `s` to bytes."""
- return s.encode('utf8')
-
- def to_string(b):
- """Convert bytes `b` to 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):
- """Turn a byte indexed from a bytes object into an int."""
- return byte
-
- def bytes_to_ints(bytes_value):
- """Turn a bytes object into a sequence of ints."""
- # In Python 3, 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 string."""
- 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):
- """Turn a byte indexed from a bytes object into an int."""
- return ord(byte)
-
- def bytes_to_ints(bytes_value):
- """Turn a bytes object into a sequence of ints."""
- for byte in bytes_value:
- yield ord(byte)
-
+# get them right.
+def to_bytes(s):
+ """Convert string `s` to bytes."""
+ return s.encode('utf8')
+
+def to_string(b):
+ """Convert bytes `b` to 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):
+ """Turn a byte indexed from a bytes object into an int."""
+ return byte
+
+def bytes_to_ints(bytes_value):
+ """Turn a bytes object into a sequence of ints."""
+ # In Python 3, iterating bytes gives ints.
+ return bytes_value
try:
# In Python 2.x, the builtins were in __builtin__
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index a27e7d98..fa473509 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -20,7 +20,7 @@ from coverage.collector import CTracer
from coverage.data import line_counts
from coverage.debug import info_formatter, info_header, short_stack
from coverage.execfile import PyRunner
-from coverage.misc import BaseCoverageException, ExceptionDuringRun, NoSource, output_encoding
+from coverage.misc import BaseCoverageException, ExceptionDuringRun, NoSource
from coverage.results import should_fail_under
@@ -878,8 +878,6 @@ def main(argv=None):
except BaseCoverageException as err:
# A controlled error inside coverage.py: print the message to the user.
msg = err.args[0]
- if env.PY2:
- msg = msg.encode(output_encoding())
print(msg)
status = ERR
except SystemExit as err:
diff --git a/coverage/env.py b/coverage/env.py
index adce7989..f0d98a27 100644
--- a/coverage/env.py
+++ b/coverage/env.py
@@ -20,13 +20,11 @@ IRONPYTHON = (platform.python_implementation() == "IronPython")
# Python versions. We amend version_info with one more value, a zero if an
# official version, or 1 if built from source beyond an official version.
PYVERSION = sys.version_info + (int(platform.python_version()[-1] == "+"),)
-PY2 = PYVERSION < (3, 0)
PY3 = PYVERSION >= (3, 0)
if PYPY:
PYPYVERSION = sys.pypy_version_info
-PYPY2 = PYPY and PY2
PYPY3 = PYPY and PY3
# Python behavior.
@@ -40,8 +38,6 @@ class PYBEHAVIOR(object):
# Is "if __debug__" optimized away?
if PYPY3:
optimize_if_debug = True
- elif PYPY2:
- optimize_if_debug = False
else:
optimize_if_debug = not pep626
diff --git a/coverage/execfile.py b/coverage/execfile.py
index 29409d51..fd6846e0 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -182,9 +182,6 @@ class PyRunner(object):
else:
raise NoSource("Can't find '__main__' module in '%s'" % self.arg0)
- if env.PY2:
- self.arg0 = os.path.abspath(self.arg0)
-
# Make a spec. I don't know if this is the right way to do it.
try:
import importlib.machinery
@@ -197,8 +194,7 @@ class PyRunner(object):
self.package = ""
self.loader = DummyLoader("__main__")
else:
- if env.PY3:
- self.loader = DummyLoader("__main__")
+ self.loader = DummyLoader("__main__")
self.arg0 = python_reported_file(self.arg0)
diff --git a/coverage/files.py b/coverage/files.py
index d6826830..f7272bd7 100644
--- a/coverage/files.py
+++ b/coverage/files.py
@@ -13,7 +13,6 @@ import re
import sys
from coverage import env
-from coverage.backward import unicode_class
from coverage.misc import contract, CoverageException, join_regex, isolate_module
@@ -105,8 +104,6 @@ if env.WINDOWS:
def actual_path(path):
"""Get the actual path of `path`, including the correct case."""
- if env.PY2 and isinstance(path, unicode_class):
- path = path.encode(sys.getfilesystemencoding())
if path in _ACTUAL_PATH_CACHE:
return _ACTUAL_PATH_CACHE[path]
@@ -143,19 +140,10 @@ else:
return filename
-if env.PY2:
- @contract(returns='unicode')
- def unicode_filename(filename):
- """Return a Unicode version of `filename`."""
- if isinstance(filename, str):
- encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
- filename = filename.decode(encoding, "replace")
- return filename
-else:
- @contract(filename='unicode', returns='unicode')
- def unicode_filename(filename):
- """Return a Unicode version of `filename`."""
- return filename
+@contract(filename='unicode', returns='unicode')
+def unicode_filename(filename):
+ """Return a Unicode version of `filename`."""
+ return filename
@contract(returns='unicode')
diff --git a/coverage/html.py b/coverage/html.py
index 0dfee7ca..b48bb80b 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -10,7 +10,6 @@ import re
import shutil
import coverage
-from coverage import env
from coverage.backward import iitems, SimpleNamespace, format_local_datetime
from coverage.data import add_data_to_hash
from coverage.files import flat_rootname
@@ -182,8 +181,6 @@ class HtmlReporter(object):
self.skip_empty= self.config.skip_empty
title = self.config.html_title
- if env.PY2:
- title = title.decode("utf8")
if self.config.extra_css:
self.extra_css = os.path.basename(self.config.extra_css)
diff --git a/coverage/misc.py b/coverage/misc.py
index 034e288e..44d1cdf8 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -71,8 +71,7 @@ if USE_CONTRACTS:
# Define contract words that PyContract doesn't have.
new_contract('bytes', lambda v: isinstance(v, bytes))
- if env.PY3:
- new_contract('unicode', lambda v: isinstance(v, unicode_class))
+ new_contract('unicode', lambda v: isinstance(v, unicode_class))
def one_of(argnames):
"""Ensure that only one of the argnames is non-None."""
diff --git a/coverage/numbits.py b/coverage/numbits.py
index 6ca96fbc..7205b9f1 100644
--- a/coverage/numbits.py
+++ b/coverage/numbits.py
@@ -15,22 +15,14 @@ the future. Use these functions to work with those binary blobs of data.
"""
import json
-from coverage import env
from coverage.backward import byte_to_int, bytes_to_ints, binary_bytes, zip_longest
from coverage.misc import contract, new_contract
-if env.PY3:
- def _to_blob(b):
- """Convert a bytestring into a type SQLite will accept for a blob."""
- return b
+def _to_blob(b):
+ """Convert a bytestring into a type SQLite will accept for a blob."""
+ return b
- new_contract('blob', lambda v: isinstance(v, bytes))
-else:
- def _to_blob(b):
- """Convert a bytestring into a type SQLite will accept for a blob."""
- return buffer(b) # pylint: disable=undefined-variable
-
- new_contract('blob', lambda v: isinstance(v, buffer)) # pylint: disable=undefined-variable
+new_contract('blob', lambda v: isinstance(v, bytes))
@contract(nums='Iterable', returns='blob')
diff --git a/coverage/parser.py b/coverage/parser.py
index 09362da3..6280129c 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -105,8 +105,6 @@ class PythonParser(object):
"""
combined = join_regex(regexes)
- if env.PY2:
- combined = combined.decode("utf8")
regex_c = re.compile(combined)
matches = set()
for i, ltext in enumerate(self.lines, start=1):
@@ -1119,7 +1117,7 @@ class AstArcAnalyzer(object):
start = to_top = self.line_for_node(node.test)
constant_test = self.is_constant_expr(node.test)
top_is_body0 = False
- if constant_test and (env.PY3 or constant_test == "Num"):
+ if constant_test:
top_is_body0 = True
if env.PYBEHAVIOR.keep_constant_test:
top_is_body0 = False
@@ -1196,8 +1194,7 @@ class AstArcAnalyzer(object):
_code_object__GeneratorExp = _make_oneline_code_method("generator expression")
_code_object__DictComp = _make_oneline_code_method("dictionary comprehension")
_code_object__SetComp = _make_oneline_code_method("set comprehension")
- if env.PY3:
- _code_object__ListComp = _make_oneline_code_method("list comprehension")
+ _code_object__ListComp = _make_oneline_code_method("list comprehension")
if AST_DUMP: # pragma: debugging
diff --git a/coverage/phystokens.py b/coverage/phystokens.py
index 54378b3b..7556d310 100644
--- a/coverage/phystokens.py
+++ b/coverage/phystokens.py
@@ -3,15 +3,12 @@
"""Better tokenizing for coverage.py."""
-import codecs
import keyword
import re
-import sys
import token
import tokenize
-from coverage import env
-from coverage.backward import iternext, unicode_class
+from coverage.backward import iternext
from coverage.misc import contract
@@ -154,102 +151,7 @@ generate_tokens = CachedTokenizer().generate_tokens
COOKIE_RE = re.compile(r"^[ \t]*#.*coding[:=][ \t]*([-\w.]+)", flags=re.MULTILINE)
@contract(source='bytes')
-def _source_encoding_py2(source):
- """Determine the encoding for `source`, according to PEP 263.
-
- `source` is a byte string, the text of the program.
-
- Returns a string, the name of the encoding.
-
- """
- assert isinstance(source, bytes)
-
- # Do this so the detect_encode code we copied will work.
- readline = iternext(source.splitlines(True))
-
- # This is mostly code adapted from Py3.2's tokenize module.
-
- 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.
- 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 behavior 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 behavior 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
-
-
-@contract(source='bytes')
-def _source_encoding_py3(source):
+def source_encoding(source):
"""Determine the encoding for `source`, according to PEP 263.
`source` is a byte string: the text of the program.
@@ -261,12 +163,6 @@ def _source_encoding_py3(source):
return tokenize.detect_encoding(readline)[0]
-if env.PY3:
- source_encoding = _source_encoding_py3
-else:
- source_encoding = _source_encoding_py2
-
-
@contract(source='unicode')
def compile_unicode(source, filename, mode):
"""Just like the `compile` builtin, but works on any Unicode string.
@@ -280,8 +176,6 @@ def compile_unicode(source, filename, mode):
"""
source = neuter_encoding_declaration(source)
- if env.PY2 and isinstance(filename, unicode_class):
- filename = filename.encode(sys.getfilesystemencoding(), "replace")
code = compile(source, filename, mode)
return code
diff --git a/coverage/pytracer.py b/coverage/pytracer.py
index 8b81cf0e..ccc913a8 100644
--- a/coverage/pytracer.py
+++ b/coverage/pytracer.py
@@ -11,8 +11,6 @@ from coverage import env
# We need the YIELD_VALUE opcode below, in a comparison-friendly form.
YIELD_VALUE = dis.opmap['YIELD_VALUE']
-if env.PY2:
- YIELD_VALUE = chr(YIELD_VALUE)
# When running meta-coverage, this file can try to trace itself, which confuses
# everything. Don't trace ourselves.
diff --git a/coverage/report.py b/coverage/report.py
index 9dfc8f5e..0ddb5e10 100644
--- a/coverage/report.py
+++ b/coverage/report.py
@@ -4,7 +4,6 @@
"""Reporter foundation for coverage.py."""
import sys
-from coverage import env
from coverage.files import prep_patterns, FnmatchMatcher
from coverage.misc import CoverageException, NoSource, NotPython, ensure_dir_for_file, file_be_gone
@@ -27,10 +26,7 @@ def render_report(output_path, reporter, morfs):
# HTMLReport does this using the Report plumbing because
# its task is more complex, being multiple files.
ensure_dir_for_file(output_path)
- open_kwargs = {}
- if env.PY3:
- open_kwargs["encoding"] = "utf8"
- outfile = open(output_path, "w", **open_kwargs)
+ outfile = open(output_path, "w", encoding="utf-8")
file_to_close = outfile
try:
diff --git a/coverage/sqldata.py b/coverage/sqldata.py
index 205c56c0..62df6508 100644
--- a/coverage/sqldata.py
+++ b/coverage/sqldata.py
@@ -16,7 +16,6 @@ import sqlite3
import sys
import zlib
-from coverage import env
from coverage.backward import get_thread_id, iitems, to_bytes, to_string
from coverage.debug import NoDebugging, SimpleReprMixin, clipped_repr
from coverage.files import PathAliases
@@ -1002,20 +1001,6 @@ class SqliteDb(SimpleReprMixin):
if self.con is not None:
return
- # SQLite on Windows on py2 won't open a file if the filename argument
- # has non-ascii characters in it. Opening a relative file name avoids
- # a problem if the current directory has non-ascii.
- filename = self.filename
- if env.WINDOWS and env.PY2:
- try:
- filename = os.path.relpath(self.filename)
- except ValueError:
- # ValueError can be raised under Windows when os.getcwd() returns a
- # folder from a different drive than the drive of self.filename in
- # which case we keep the original value of self.filename unchanged,
- # hoping that we won't face the non-ascii directory problem.
- pass
-
# It can happen that Python switches threads while the tracer writes
# data. The second thread will also try to write to the data,
# effectively causing a nested context. However, given the idempotent
@@ -1023,7 +1008,7 @@ class SqliteDb(SimpleReprMixin):
# is not a problem.
if self.debug:
self.debug.write("Connecting to {!r}".format(self.filename))
- self.con = sqlite3.connect(filename, check_same_thread=False)
+ self.con = sqlite3.connect(self.filename, check_same_thread=False)
self.con.create_function('REGEXP', 2, _regexp)
# This pragma makes writing faster. It disables rollbacks, but we never need them.
diff --git a/coverage/summary.py b/coverage/summary.py
index 65f80470..d526d0bc 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -5,10 +5,9 @@
import sys
-from coverage import env
from coverage.report import get_analysis_to_report
from coverage.results import Numbers
-from coverage.misc import CoverageException, output_encoding
+from coverage.misc import CoverageException
class SummaryReporter(object):
@@ -27,8 +26,6 @@ class SummaryReporter(object):
def writeout(self, line):
"""Write a line to the output, adding a newline."""
- if env.PY2:
- line = line.encode(output_encoding())
self.outfile.write(line.rstrip())
self.outfile.write("\n")
diff --git a/coverage/templite.py b/coverage/templite.py
index 7d4024e0..82673886 100644
--- a/coverage/templite.py
+++ b/coverage/templite.py
@@ -12,8 +12,6 @@ http://aosabook.org/en/500L/a-template-engine.html
import re
-from coverage import env
-
class TempliteSyntaxError(ValueError):
"""Raised when a template has a syntax error."""
@@ -137,10 +135,7 @@ class Templite(object):
code.add_line("result = []")
code.add_line("append_result = result.append")
code.add_line("extend_result = result.extend")
- if env.PY2:
- code.add_line("to_str = unicode")
- else:
- code.add_line("to_str = str")
+ code.add_line("to_str = str")
buffered = []
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 6d012ee6..470e991c 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -10,7 +10,6 @@ import sys
import time
import xml.dom.minidom
-from coverage import env
from coverage import __url__, __version__, files
from coverage.backward import iitems
from coverage.misc import isolate_module
@@ -228,7 +227,4 @@ class XmlReporter(object):
def serialize_xml(dom):
"""Serialize a minidom node to XML."""
- out = dom.toprettyxml()
- if env.PY2:
- out = out.encode("utf8")
- return out
+ return dom.toprettyxml()