Skip to content

Commit

Permalink
refactor: remove unneeded backward.py shims
Browse files Browse the repository at this point in the history
Removed were:

- StringIO
- configparser
- string_class
- unicode_class
- range
- zip_longest
- get_thread_id
- path_types
- shlex_quote
- reprlib
  • Loading branch information
nedbat committed May 1, 2021
1 parent 9df4345 commit e96ef93
Show file tree
Hide file tree
Showing 16 changed files with 53 additions and 123 deletions.
76 changes: 0 additions & 76 deletions coverage/backward.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,84 +3,8 @@

"""Add things to old Pythons so I can pretend they are newer."""

# This file's purpose is to provide modules to be imported from here.
# pylint: disable=unused-import

import os
import sys

from datetime import datetime


# Pythons 2 and 3 differ on where to get StringIO.
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO

# In py3, ConfigParser was renamed to the more-standard configparser.
# But there's a py3 backport that installs "configparser" in py2, and I don't
# want it because it has annoying deprecation warnings. So try the real py2
# import first.
try:
import ConfigParser as configparser
except ImportError:
import configparser

# What's a string called?
try:
string_class = basestring
except NameError:
string_class = str

# What's a Unicode string called?
try:
unicode_class = unicode
except NameError:
unicode_class = str

# range or xrange?
try:
range = xrange # pylint: disable=redefined-builtin
except NameError:
range = range

try:
from itertools import zip_longest
except ImportError:
from itertools import izip_longest as zip_longest

# Where do we get the thread id from?
try:
from thread import get_ident as get_thread_id
except ImportError:
from threading import get_ident as get_thread_id

try:
os.PathLike
except AttributeError:
# This is Python 2 and 3
path_types = (bytes, string_class, unicode_class)
else:
# 3.6+
path_types = (bytes, str, os.PathLike)

# shlex.quote is new, but there's an undocumented implementation in "pipes",
# who knew!?
try:
from shlex import quote as shlex_quote
except ImportError:
# Useful function, available under a different (undocumented) name
# in Python versions earlier than 3.3.
from pipes import quote as shlex_quote

try:
import reprlib
except ImportError: # pragma: not covered
# We need this on Python 2, but in testing environments, a backport is
# installed, so this import isn't used.
import repr as reprlib

# A function to iterate listlessly over a dict's items, and one to get the
# items as a list.
try:
Expand Down
2 changes: 1 addition & 1 deletion coverage/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys

from coverage import env
from coverage.backward import litems, range # pylint: disable=redefined-builtin
from coverage.backward import litems
from coverage.debug import short_stack
from coverage.disposition import FileDisposition
from coverage.misc import CoverageException, isolate_module
Expand Down
5 changes: 3 additions & 2 deletions coverage/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
"""Config file for coverage.py"""

import collections
import configparser
import copy
import os
import os.path
import re

from coverage import env
from coverage.backward import configparser, iitems, string_class
from coverage.backward import iitems
from coverage.misc import contract, CoverageException, isolate_module
from coverage.misc import substitute_variables

Expand Down Expand Up @@ -247,7 +248,7 @@ def from_args(self, **kwargs):
"""Read config values from `kwargs`."""
for k, v in iitems(kwargs):
if v is not None:
if k in self.MUST_BE_LIST and isinstance(v, string_class):
if k in self.MUST_BE_LIST and isinstance(v, str):
v = [v]
setattr(self, k, v)

Expand Down
6 changes: 3 additions & 3 deletions coverage/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from coverage import env
from coverage.annotate import AnnotateReporter
from coverage.backward import string_class, iitems
from coverage.backward import iitems
from coverage.collector import Collector, CTracer
from coverage.config import read_coverage_config
from coverage.context import should_start_context_test_function, combine_context_switchers
Expand Down Expand Up @@ -465,7 +465,7 @@ def _init_for_start(self):

suffix = self._data_suffix_specified
if suffix or self.config.parallel:
if not isinstance(suffix, string_class):
if not isinstance(suffix, str):
# if data_suffix=True, use .machinename.pid.random
suffix = True
else:
Expand Down Expand Up @@ -812,7 +812,7 @@ def _get_file_reporter(self, morf):
plugin = None
file_reporter = "python"

if isinstance(morf, string_class):
if isinstance(morf, str):
mapped_morf = self._file_mapper(morf)
plugin_name = self._data.file_tracer(mapped_morf)
if plugin_name:
Expand Down
5 changes: 3 additions & 2 deletions coverage/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@
import contextlib
import functools
import inspect
import io
import itertools
import os
import pprint
import reprlib
import sys
try:
import _thread
except ImportError:
import thread as _thread

from coverage.backward import reprlib, StringIO
from coverage.misc import isolate_module

os = isolate_module(os)
Expand Down Expand Up @@ -86,7 +87,7 @@ def write(self, msg):
class DebugControlString(DebugControl):
"""A `DebugControl` that writes to a StringIO, for testing."""
def __init__(self, options):
super(DebugControlString, self).__init__(options, StringIO())
super(DebugControlString, self).__init__(options, io.StringIO())

def get_output(self):
"""Get the output text from the `DebugControl`."""
Expand Down
6 changes: 3 additions & 3 deletions coverage/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import types

from coverage import env
from coverage.backward import to_bytes, unicode_class
from coverage.backward import to_bytes

ISOLATED_MODULES = {}

Expand Down Expand Up @@ -71,7 +71,7 @@ def new_contract(*args, **kwargs):

# Define contract words that PyContract doesn't have.
new_contract('bytes', lambda v: isinstance(v, bytes))
new_contract('unicode', lambda v: isinstance(v, unicode_class))
new_contract('unicode', lambda v: isinstance(v, str))

def one_of(argnames):
"""Ensure that only one of the argnames is non-None."""
Expand Down Expand Up @@ -204,7 +204,7 @@ def __init__(self):
def update(self, v):
"""Add `v` to the hash, recursively if needed."""
self.md5.update(to_bytes(str(type(v))))
if isinstance(v, unicode_class):
if isinstance(v, str):
self.md5.update(v.encode('utf8'))
elif isinstance(v, bytes):
self.md5.update(v)
Expand Down
4 changes: 3 additions & 1 deletion coverage/numbits.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"""
import json

from coverage.backward import byte_to_int, bytes_to_ints, binary_bytes, zip_longest
from itertools import zip_longest

from coverage.backward import byte_to_int, bytes_to_ints, binary_bytes
from coverage.misc import contract, new_contract

def _to_blob(b):
Expand Down
5 changes: 2 additions & 3 deletions coverage/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
import tokenize

from coverage import env
from coverage.backward import range # pylint: disable=redefined-builtin
from coverage.backward import bytes_to_ints, string_class
from coverage.backward import bytes_to_ints
from coverage.bytecode import code_objects
from coverage.debug import short_stack
from coverage.misc import contract, join_regex, new_contract, nice_pair, one_of
Expand Down Expand Up @@ -1206,7 +1205,7 @@ def _is_simple_value(value):
"""Is `value` simple enough to be displayed on a single line?"""
return (
value in [None, [], (), {}, set()] or
isinstance(value, (string_class, int, float))
isinstance(value, (str, int, float))
)

def ast_dump(node, depth=0):
Expand Down
17 changes: 9 additions & 8 deletions coverage/sqldata.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
import re
import sqlite3
import sys
import threading
import zlib

from coverage.backward import get_thread_id, iitems, to_bytes, to_string
from coverage.backward import iitems, to_bytes, to_string
from coverage.debug import NoDebugging, SimpleReprMixin, clipped_repr
from coverage.files import PathAliases
from coverage.misc import CoverageException, contract, file_be_gone, filename_suffix, isolate_module
Expand Down Expand Up @@ -244,7 +245,7 @@ def _create_db(self):
"""
if self._debug.should('dataio'):
self._debug.write("Creating data file {!r}".format(self._filename))
self._dbs[get_thread_id()] = db = SqliteDb(self._filename, self._debug)
self._dbs[threading.get_ident()] = db = SqliteDb(self._filename, self._debug)
with db:
db.executescript(SCHEMA)
db.execute("insert into coverage_schema (version) values (?)", (SCHEMA_VERSION,))
Expand All @@ -261,12 +262,12 @@ def _open_db(self):
"""Open an existing db file, and read its metadata."""
if self._debug.should('dataio'):
self._debug.write("Opening data file {!r}".format(self._filename))
self._dbs[get_thread_id()] = SqliteDb(self._filename, self._debug)
self._dbs[threading.get_ident()] = SqliteDb(self._filename, self._debug)
self._read_db()

def _read_db(self):
"""Read the metadata from a database so that we are ready to use it."""
with self._dbs[get_thread_id()] as db:
with self._dbs[threading.get_ident()] as db:
try:
schema_version, = db.execute_one("select version from coverage_schema")
except Exception as exc:
Expand All @@ -292,15 +293,15 @@ def _read_db(self):

def _connect(self):
"""Get the SqliteDb object to use."""
if get_thread_id() not in self._dbs:
if threading.get_ident() not in self._dbs:
if os.path.exists(self._filename):
self._open_db()
else:
self._create_db()
return self._dbs[get_thread_id()]
return self._dbs[threading.get_ident()]

def __nonzero__(self):
if (get_thread_id() not in self._dbs and not os.path.exists(self._filename)):
if (threading.get_ident() not in self._dbs and not os.path.exists(self._filename)):
return False
try:
with self._connect() as con:
Expand Down Expand Up @@ -357,7 +358,7 @@ def loads(self, data):
"Unrecognized serialization: {!r} (head of {} bytes)".format(data[:40], len(data))
)
script = to_string(zlib.decompress(data[1:]))
self._dbs[get_thread_id()] = db = SqliteDb(self._filename, self._debug)
self._dbs[threading.get_ident()] = db = SqliteDb(self._filename, self._debug)
with db:
db.executescript(script)
self._read_db()
Expand Down
4 changes: 2 additions & 2 deletions coverage/tomlconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

"""TOML configuration support for coverage.py"""

import configparser
import io
import os
import re

from coverage import env
from coverage.backward import configparser, path_types
from coverage.misc import CoverageException, substitute_variables

# TOML support is an install-time extra option.
Expand Down Expand Up @@ -37,7 +37,7 @@ def __init__(self, our_file):
def read(self, filenames):
# RawConfigParser takes a filename or list of filenames, but we only
# ever call this with a single filename.
assert isinstance(filenames, path_types)
assert isinstance(filenames, (bytes, str, os.PathLike))
filename = filenames
if env.PYVERSION >= (3, 6):
filename = os.fspath(filename)
Expand Down
9 changes: 5 additions & 4 deletions tests/coveragetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datetime
import difflib
import glob
import io
import os
import os.path
import random
Expand All @@ -18,7 +19,7 @@

import coverage
from coverage import env
from coverage.backward import StringIO, import_local_file, string_class, shlex_quote
from coverage.backward import import_local_file
from coverage.cmdline import CoverageScript

from tests.helpers import arcs_to_arcz_repr, arcz_to_arcs, assert_count_equal
Expand Down Expand Up @@ -176,7 +177,7 @@ def check_coverage(
assert False, "None of the lines choices matched %r" % (statements,)

missing_formatted = analysis.missing_formatted()
if isinstance(missing, string_class):
if isinstance(missing, str):
msg = "{!r} != {!r}".format(missing_formatted, missing)
assert missing_formatted == missing, msg
else:
Expand All @@ -202,7 +203,7 @@ def check_coverage(
assert False, msg

if report:
frep = StringIO()
frep = io.StringIO()
cov.report(mod, file=frep, show_missing=True)
rep = " ".join(frep.getvalue().split("\n")[2].split()[1:])
assert report == rep, "{!r} != {!r}".format(report, rep)
Expand Down Expand Up @@ -380,7 +381,7 @@ def run_command_status(self, cmd):
else:
command_words = [command_name]

cmd = " ".join([shlex_quote(w) for w in command_words] + command_args)
cmd = " ".join([shlex.quote(w) for w in command_words] + command_args)

# Add our test modules directory to PYTHONPATH. I'm sure there's too
# much path munging here, but...
Expand Down
7 changes: 4 additions & 3 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import fnmatch
import glob
import io
import os
import os.path
import re
Expand All @@ -16,7 +17,7 @@

import coverage
from coverage import env
from coverage.backward import code_object, import_local_file, StringIO
from coverage.backward import code_object, import_local_file
from coverage.data import line_counts
from coverage.files import abs_file, relative_filename
from coverage.misc import CoverageException
Expand Down Expand Up @@ -945,7 +946,7 @@ def coverage_usepkgs(self, **kwargs):
cov.start()
import usepkgs # pragma: nested # pylint: disable=import-error, unused-import
cov.stop() # pragma: nested
report = StringIO()
report = io.StringIO()
cov.report(file=report, **kwargs)
return report.getvalue()

Expand Down Expand Up @@ -1070,7 +1071,7 @@ def pretend_to_be_pytestcov(self, append):
self.start_import_stop(cov, "prog")
cov.combine()
cov.save()
report = StringIO()
report = io.StringIO()
cov.report(show_missing=None, ignore_errors=True, file=report, skip_covered=None,
skip_empty=None)
assert report.getvalue() == textwrap.dedent("""\
Expand Down
Loading

0 comments on commit e96ef93

Please sign in to comment.