diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2021-05-01 13:02:31 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2021-05-01 13:30:39 -0400 |
commit | 9df434550a499c16e9fd26cfb9627837bfdc02a5 (patch) | |
tree | 5619ea3c3bec05d04363a66ced9c7ebffcefb1df /coverage | |
parent | 3fe17c1f2244c07cf9d0f9e3609392c2ad441db1 (diff) | |
download | python-coveragepy-git-9df434550a499c16e9fd26cfb9627837bfdc02a5.tar.gz |
refactor: remove code explicitly choosing between py2 and py3
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/backward.py | 68 | ||||
-rw-r--r-- | coverage/cmdline.py | 4 | ||||
-rw-r--r-- | coverage/env.py | 4 | ||||
-rw-r--r-- | coverage/execfile.py | 6 | ||||
-rw-r--r-- | coverage/files.py | 20 | ||||
-rw-r--r-- | coverage/html.py | 3 | ||||
-rw-r--r-- | coverage/misc.py | 3 | ||||
-rw-r--r-- | coverage/numbits.py | 16 | ||||
-rw-r--r-- | coverage/parser.py | 7 | ||||
-rw-r--r-- | coverage/phystokens.py | 110 | ||||
-rw-r--r-- | coverage/pytracer.py | 2 | ||||
-rw-r--r-- | coverage/report.py | 6 | ||||
-rw-r--r-- | coverage/sqldata.py | 17 | ||||
-rw-r--r-- | coverage/summary.py | 5 | ||||
-rw-r--r-- | coverage/templite.py | 7 | ||||
-rw-r--r-- | coverage/xmlreport.py | 6 |
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() |