summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst12
-rw-r--r--CONTRIBUTORS.txt2
-rw-r--r--Makefile24
-rw-r--r--README.rst3
-rw-r--r--appveyor.yml6
-rw-r--r--ci/github_releases.py138
-rw-r--r--ci/parse_relnotes.py (renamed from ci/upload_relnotes.py)69
-rw-r--r--ci/tidelift_relnotes.py50
-rw-r--r--coverage/backunittest.py2
-rw-r--r--coverage/cmdline.py16
-rw-r--r--coverage/config.py4
-rw-r--r--coverage/control.py22
-rw-r--r--coverage/htmlfiles/pyfile.html8
-rw-r--r--coverage/htmlfiles/style.css144
-rw-r--r--coverage/htmlfiles/style.scss301
-rw-r--r--coverage/multiproc.py2
-rw-r--r--doc/cmd.rst6
-rw-r--r--howto.txt4
-rw-r--r--requirements/dev.pip7
-rw-r--r--requirements/pip.pip5
-rw-r--r--tests/gold/html/Makefile2
-rw-r--r--tests/gold/html/a/a_py.html6
-rw-r--r--tests/gold/html/b_branch/b_py.html8
-rw-r--r--tests/gold/html/bom/2/bom_py.html6
-rw-r--r--tests/gold/html/bom/bom_py.html6
-rw-r--r--tests/gold/html/isolatin1/isolatin1_py.html6
-rw-r--r--tests/gold/html/omit_1/m1_py.html6
-rw-r--r--tests/gold/html/omit_1/m2_py.html6
-rw-r--r--tests/gold/html/omit_1/m3_py.html6
-rw-r--r--tests/gold/html/omit_1/main_py.html6
-rw-r--r--tests/gold/html/omit_2/m2_py.html6
-rw-r--r--tests/gold/html/omit_2/m3_py.html6
-rw-r--r--tests/gold/html/omit_2/main_py.html6
-rw-r--r--tests/gold/html/omit_3/m3_py.html6
-rw-r--r--tests/gold/html/omit_3/main_py.html6
-rw-r--r--tests/gold/html/omit_4/m1_py.html6
-rw-r--r--tests/gold/html/omit_4/m3_py.html6
-rw-r--r--tests/gold/html/omit_4/main_py.html6
-rw-r--r--tests/gold/html/omit_5/m1_py.html6
-rw-r--r--tests/gold/html/omit_5/main_py.html6
-rw-r--r--tests/gold/html/other/blah_blah_other_py.html6
-rw-r--r--tests/gold/html/other/here_py.html6
-rw-r--r--tests/gold/html/partial/partial_py.html8
-rw-r--r--tests/gold/html/styled/a_py.html6
-rw-r--r--tests/gold/html/styled/style.css144
-rw-r--r--tests/gold/html/unicode/unicode_py.html6
-rw-r--r--tests/test_cmdline.py18
-rw-r--r--tests/test_config.py14
-rw-r--r--tests/test_phystokens.py2
-rw-r--r--tox.ini2
50 files changed, 811 insertions, 344 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index b63ad42b..4c5bdcab 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -24,7 +24,17 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`.
Unreleased
----------
-Nothing yet.
+- The HTML report has been redesigned by Victor Salvino. There is now a dark
+ mode, the code text is larger, and system san serif fonts are used.
+
+- The ``coverage report`` and ``coverage html`` commands now accept a
+ ``--precision`` option to control the number of decimal points displayed.
+ Thanks, Teake Nutma.
+
+- TOML configuration files with non-ASCII characters would cause errors on
+ Windows (`issue 990`_). This is now fixed.
+
+.. _issue 990: https://github.com/nedbat/coveragepy/issues/990
.. _changes_51:
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index a3cc9be7..c418a049 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -127,9 +127,11 @@ Stephen Finucane
Steve Leonard
Steve Peak
S. Y. Lee
+Teake Nutma
Ted Wexler
Thijs Triemstra
Titus Brown
+Victor Salvino
Ville Skyttä
Yury Selivanov
Zac Hatfield-Dodds
diff --git a/Makefile b/Makefile
index e1675d9b..64eab8be 100644
--- a/Makefile
+++ b/Makefile
@@ -133,17 +133,17 @@ WEBHOME = ~/web/stellated/
WEBSAMPLE = $(WEBHOME)/files/sample_coverage_html
WEBSAMPLEBETA = $(WEBHOME)/files/sample_coverage_html_beta
-docreqs:
+$(DOCPYTHON):
tox -q -e doc --notest
-dochtml: docreqs ## Build the docs HTML output.
+dochtml: $(DOCBIN) ## Build the docs HTML output.
$(DOCBIN)/python doc/check_copied_from.py doc/*.rst
$(SPHINXBUILD) -b html doc doc/_build/html
docdev: dochtml ## Build docs, and auto-watch for changes.
PATH=$(DOCBIN):$(PATH) $(SPHINXAUTOBUILD) -b html doc doc/_build/html
-docspell: docreqs
+docspell: $(DOCBIN)
$(SPHINXBUILD) -b spelling doc doc/_spell
publish:
@@ -156,7 +156,19 @@ publishbeta:
mkdir -p $(WEBSAMPLEBETA)
cp doc/sample_html_beta/*.* $(WEBSAMPLEBETA)
-upload_relnotes: docreqs ## Upload parsed release notes to Tidelift.
+CHANGES_MD = /tmp/rst_rst/changes.md
+RELNOTES_JSON = /tmp/relnotes.json
+
+$(CHANGES_MD): CHANGES.rst $(DOCBIN)
$(SPHINXBUILD) -b rst doc /tmp/rst_rst
- pandoc -frst -tmarkdown_strict --atx-headers /tmp/rst_rst/changes.rst > /tmp/rst_rst/changes.md
- python ci/upload_relnotes.py /tmp/rst_rst/changes.md pypi/coverage
+ pandoc -frst -tmarkdown_strict --atx-headers --wrap=none /tmp/rst_rst/changes.rst > $(CHANGES_MD)
+
+relnotes_json: $(RELNOTES_JSON)
+$(RELNOTES_JSON): $(CHANGES_MD)
+ $(DOCBIN)/python ci/parse_relnotes.py /tmp/rst_rst/changes.md $(RELNOTES_JSON)
+
+tidelift_relnotes: $(RELNOTES_JSON) ## Upload parsed release notes to Tidelift.
+ $(DOCBIN)/python ci/tidelift_relnotes.py $(RELNOTES_JSON) pypi/coverage
+
+github_releases: $(RELNOTES_JSON) ## Update GitHub releases.
+ $(DOCBIN)/python ci/github_releases.py $(RELNOTES_JSON) nedbat/coveragepy
diff --git a/README.rst b/README.rst
index 4534bc92..50ae4f79 100644
--- a/README.rst
+++ b/README.rst
@@ -9,7 +9,7 @@ Code coverage testing for Python.
| |license| |versions| |status|
| |ci-status| |win-ci-status| |docs| |codecov|
-| |kit| |format| |repos|
+| |kit| |format| |repos| |downloads|
| |stars| |forks| |contributors|
| |tidelift| |twitter-coveragepy| |twitter-nedbat|
@@ -38,7 +38,6 @@ For Enterprise
--------------
.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logo_small.png
- :width: 75
:alt: Tidelift
:target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme
diff --git a/appveyor.yml b/appveyor.yml
index 76e21dad..35c670a1 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -131,11 +131,9 @@ install:
# Check that we have the expected version and architecture for Python
- "python -c \"import struct, sys; print('{}\\n{}-bit'.format(sys.version, struct.calcsize('P') * 8))\""
- # Upgrade to the latest version of pip to avoid it displaying warnings
+ # Upgrade to the right version of pip to avoid it displaying warnings
# about it being out of date.
- - "python -m pip install --disable-pip-version-check --upgrade pip"
- # And upgrade virtualenv to get the latest pip inside .tox virtualenvs.
- - "python -m pip install --disable-pip-version-check --upgrade virtualenv"
+ - "python -m pip install --disable-pip-version-check -r requirements/pip.pip"
# Install requirements.
- "%CMD_IN_ENV% pip install -r requirements/ci.pip"
diff --git a/ci/github_releases.py b/ci/github_releases.py
new file mode 100644
index 00000000..1c7ee604
--- /dev/null
+++ b/ci/github_releases.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+"""
+Upload release notes into GitHub releases.
+"""
+
+import json
+import shlex
+import subprocess
+import sys
+
+import pkg_resources
+import requests
+
+
+RELEASES_URL = "https://api.github.com/repos/{repo}/releases"
+
+def run_command(cmd):
+ """
+ Run a command line (with no shell).
+
+ Returns a tuple:
+ bool: true if the command succeeded.
+ str: the output of the command.
+
+ """
+ proc = subprocess.run(
+ shlex.split(cmd),
+ shell=False,
+ check=False,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ output = proc.stdout.decode("utf-8")
+ succeeded = proc.returncode == 0
+ return succeeded, output
+
+def does_tag_exist(tag_name):
+ """
+ Does `tag_name` exist as a tag in git?
+ """
+ return run_command(f"git rev-parse --verify {tag_name}")[0]
+
+def check_ok(resp):
+ """
+ Check that the Requests response object was successful.
+
+ Raise an exception if not.
+ """
+ if not resp:
+ print(f"text: {resp.text!r}")
+ resp.raise_for_status()
+
+def github_paginated(session, url):
+ """
+ Get all the results from a paginated GitHub url.
+ """
+ while True:
+ resp = session.get(url)
+ check_ok(resp)
+ yield from resp.json()
+ next_link = resp.links.get("next", None)
+ if not next_link:
+ break
+ url = next_link["url"]
+
+def get_releases(session, repo):
+ """
+ Get all the releases from a name/project repo.
+
+ Returns:
+ A dict mapping tag names to release dictionaries.
+ """
+ url = RELEASES_URL.format(repo=repo)
+ releases = { r['tag_name']: r for r in github_paginated(session, url) }
+ return releases
+
+def release_for_relnote(relnote):
+ """
+ Turn a release note dict into the data needed by GitHub for a release.
+ """
+ tag = f"coverage-{relnote['version']}"
+ return {
+ "tag_name": tag,
+ "name": tag,
+ "body": relnote["text"],
+ "draft": False,
+ "prerelease": relnote["prerelease"],
+ }
+
+def create_release(session, repo, relnote):
+ """
+ Create a new GitHub release.
+ """
+ print(f"Creating {relnote['version']}")
+ data = release_for_relnote(relnote)
+ resp = session.post(RELEASES_URL.format(repo=repo), json=data)
+ check_ok(resp)
+
+def update_release(session, url, relnote):
+ """
+ Update an existing GitHub release.
+ """
+ print(f"Updating {relnote['version']}")
+ data = release_for_relnote(relnote)
+ resp = session.patch(url, json=data)
+ check_ok(resp)
+
+def update_github_releases(json_filename, repo):
+ """
+ Read the json file, and create or update releases in GitHub.
+ """
+ gh_session = requests.Session()
+ releases = get_releases(gh_session, repo)
+ if 0: # if you need to delete all the releases!
+ for release in releases.values():
+ print(release["tag_name"])
+ resp = gh_session.delete(release["url"])
+ check_ok(resp)
+ return
+
+ with open(json_filename) as jf:
+ relnotes = json.load(jf)
+ relnotes.sort(key=lambda rel: pkg_resources.parse_version(rel["version"]))
+ for relnote in relnotes:
+ tag = "coverage-" + relnote["version"]
+ if not does_tag_exist(tag):
+ continue
+ exists = tag in releases
+ if not exists:
+ create_release(gh_session, repo, relnote)
+ else:
+ release = releases[tag]
+ if release["body"] != relnote["text"]:
+ url = release["url"]
+ update_release(gh_session, url, relnote)
+
+if __name__ == "__main__":
+ update_github_releases(*sys.argv[1:]) # pylint: disable=no-value-for-parameter
diff --git a/ci/upload_relnotes.py b/ci/parse_relnotes.py
index 630f4d0a..d19e6d60 100644
--- a/ci/upload_relnotes.py
+++ b/ci/parse_relnotes.py
@@ -1,26 +1,20 @@
#!/usr/bin/env python3
"""
-Upload CHANGES.md to Tidelift as Markdown chunks
+Parse CHANGES.md into a JSON structure.
-Put your Tidelift API token in a file called tidelift.token alongside this
-program, for example:
+Run with two arguments: the .md file to parse, and the JSON file to write:
- user/n3IwOpxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc2ZwE4
-
-Run with two arguments: the .md file to parse, and the Tidelift package name:
-
- python upload_relnotes.py CHANGES.md pypi/coverage
+ python parse_relnotes.py CHANGES.md relnotes.json
Every section that has something that looks like a version number in it will
-be uploaded as the release notes for that version.
+be recorded as the release notes for that version.
"""
-import os.path
+import json
import re
import sys
-import requests
class TextChunkBuffer:
"""Hold onto text chunks until needed."""
@@ -82,6 +76,14 @@ def sections(parsed_data):
yield (*header, "\n".join(text))
+def refind(regex, text):
+ """Find a regex in some text, and return the matched text, or None."""
+ m = re.search(regex, text)
+ if m:
+ return m.group()
+ else:
+ return None
+
def relnotes(mdlines):
r"""Yield (version, text) pairs from markdown lines.
@@ -91,32 +93,23 @@ def relnotes(mdlines):
"""
for _, htext, text in sections(parse_md(mdlines)):
- m_version = re.search(r"\d+\.\d[^ ]*", htext)
- if m_version:
- version = m_version.group()
- yield version, text
-
-def update_release_note(package, version, text):
- """Update the release notes for one version of a package."""
- url = f"https://api.tidelift.com/external-api/lifting/{package}/release-notes/{version}"
- token_file = os.path.join(os.path.dirname(__file__), "tidelift.token")
- with open(token_file) as ftoken:
- token = ftoken.read().strip()
- headers = {
- "Authorization": f"Bearer: {token}",
- }
- req_args = dict(url=url, data=text.encode('utf8'), headers=headers)
- result = requests.post(**req_args)
- if result.status_code == 409:
- result = requests.put(**req_args)
- print(f"{version}: {result.status_code}")
-
-def parse_and_upload(md_filename, package):
- """Main function: parse markdown and upload to Tidelift."""
- with open(md_filename) as f:
- markdown = f.read()
- for version, text in relnotes(markdown.splitlines(True)):
- update_release_note(package, version, text)
+ version = refind(r"\d+\.\d[^ ]*", htext)
+ if version:
+ prerelease = any(c in version for c in "abc")
+ when = refind(r"\d+-\d+-\d+", htext)
+ yield {
+ "version": version,
+ "text": text,
+ "prerelease": prerelease,
+ "when": when,
+ }
+
+def parse(md_filename, json_filename):
+ """Main function: parse markdown and write JSON."""
+ with open(md_filename) as mf:
+ markdown = mf.read()
+ with open(json_filename, "w") as jf:
+ json.dump(list(relnotes(markdown.splitlines(True))), jf, indent=4)
if __name__ == "__main__":
- parse_and_upload(*sys.argv[1:]) # pylint: disable=no-value-for-parameter
+ parse(*sys.argv[1:]) # pylint: disable=no-value-for-parameter
diff --git a/ci/tidelift_relnotes.py b/ci/tidelift_relnotes.py
new file mode 100644
index 00000000..bc3a37d4
--- /dev/null
+++ b/ci/tidelift_relnotes.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+"""
+Upload release notes from a JSON file to Tidelift as Markdown chunks
+
+Put your Tidelift API token in a file called tidelift.token alongside this
+program, for example:
+
+ user/n3IwOpxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc2ZwE4
+
+Run with two arguments: the JSON file of release notes, and the Tidelift
+package name:
+
+ python tidelift_relnotes.py relnotes.json pypi/coverage
+
+Every section that has something that looks like a version number in it will
+be uploaded as the release notes for that version.
+
+"""
+
+import json
+import os.path
+import sys
+
+import requests
+
+
+def update_release_note(package, version, text):
+ """Update the release notes for one version of a package."""
+ url = f"https://api.tidelift.com/external-api/lifting/{package}/release-notes/{version}"
+ token_file = os.path.join(os.path.dirname(__file__), "tidelift.token")
+ with open(token_file) as ftoken:
+ token = ftoken.read().strip()
+ headers = {
+ "Authorization": f"Bearer: {token}",
+ }
+ req_args = dict(url=url, data=text.encode('utf8'), headers=headers)
+ result = requests.post(**req_args)
+ if result.status_code == 409:
+ result = requests.put(**req_args)
+ print(f"{version}: {result.status_code}")
+
+def upload(json_filename, package):
+ """Main function: parse markdown and upload to Tidelift."""
+ with open(json_filename) as jf:
+ relnotes = json.load(jf)
+ for relnote in relnotes:
+ update_release_note(package, relnote["version"], relnote["text"])
+
+if __name__ == "__main__":
+ upload(*sys.argv[1:]) # pylint: disable=no-value-for-parameter
diff --git a/coverage/backunittest.py b/coverage/backunittest.py
index 078f48cc..123bb2a1 100644
--- a/coverage/backunittest.py
+++ b/coverage/backunittest.py
@@ -18,7 +18,7 @@ class TestCase(unittest.TestCase):
`unittest` doesn't have them.
"""
- # pylint: disable=arguments-differ, deprecated-method
+ # pylint: disable=signature-differs, deprecated-method
if not unittest_has('assertCountEqual'):
def assertCountEqual(self, *args, **kwargs):
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index 23ebd8f5..d557ddf1 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -146,6 +146,13 @@ class Opts(object):
"to be run as 'python -m' would run it."
),
)
+ precision = optparse.make_option(
+ '', '--precision', action='store', metavar='N', type=int,
+ help=(
+ "Number of digits after the decimal point to display for "
+ "reported coverage percentages."
+ ),
+ )
rcfile = optparse.make_option(
'', '--rcfile', action='store',
help=(
@@ -203,6 +210,7 @@ class CoverageOptionParser(optparse.OptionParser, object):
omit=None,
contexts=None,
parallel_mode=None,
+ precision=None,
pylib=None,
rcfile=True,
show_missing=None,
@@ -358,6 +366,7 @@ CMDS = {
Opts.ignore_errors,
Opts.include,
Opts.omit,
+ Opts.precision,
Opts.show_contexts,
Opts.skip_covered,
Opts.skip_empty,
@@ -395,6 +404,7 @@ CMDS = {
Opts.ignore_errors,
Opts.include,
Opts.omit,
+ Opts.precision,
Opts.show_missing,
Opts.skip_covered,
Opts.skip_empty,
@@ -583,6 +593,7 @@ class CoverageScript(object):
show_missing=options.show_missing,
skip_covered=options.skip_covered,
skip_empty=options.skip_empty,
+ precision=options.precision,
**report_args
)
elif options.action == "annotate":
@@ -594,6 +605,7 @@ class CoverageScript(object):
skip_covered=options.skip_covered,
skip_empty=options.skip_empty,
show_contexts=options.show_contexts,
+ precision=options.precision,
**report_args
)
elif options.action == "xml":
@@ -807,7 +819,7 @@ HELP_TOPICS = {
""",
'minimum_help': """\
- Code coverage for Python. Use '{program_name} help' for help.
+ Code coverage for Python, version {__version__} {extension_modifier}. Use '{program_name} help' for help.
""",
'version': """\
@@ -858,8 +870,8 @@ if _profile: # pragma: debugging
def main(argv=None): # pylint: disable=function-redefined
"""A wrapper around main that profiles."""
+ profiler = SimpleLauncher.launch()
try:
- profiler = SimpleLauncher.launch()
return original_main(argv)
finally:
data, _ = profiler.query(re_filter='coverage', max_records=100)
diff --git a/coverage/config.py b/coverage/config.py
index 7876052b..6d336d1f 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -72,7 +72,7 @@ class HandyConfigParser(configparser.RawConfigParser):
d[opt] = self.get(section, opt)
return d
- def get(self, section, option, *args, **kwargs): # pylint: disable=arguments-differ
+ def get(self, section, option, *args, **kwargs):
"""Get a value, replacing environment variables also.
The arguments are the same as `RawConfigParser.get`, but in the found
@@ -325,7 +325,7 @@ class CoverageConfig(object):
if used:
self.config_file = os.path.abspath(filename)
- with open(filename) as f:
+ with open(filename, "rb") as f:
self._config_contents = f.read()
return used
diff --git a/coverage/control.py b/coverage/control.py
index 2b8c3d26..c2f40e70 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -829,7 +829,7 @@ class Coverage(object):
def report(
self, morfs=None, show_missing=None, ignore_errors=None,
file=None, omit=None, include=None, skip_covered=None,
- contexts=None, skip_empty=None,
+ contexts=None, skip_empty=None, precision=None,
):
"""Write a textual summary report to `file`.
@@ -857,6 +857,9 @@ class Coverage(object):
expressions (using :func:`re.search <python:re.search>`) will be
included in the report.
+ `precision` is the number of digits to display after the decimal
+ point for percentages.
+
All of the arguments default to the settings read from the
:ref:`configuration file <config>`.
@@ -868,12 +871,15 @@ class Coverage(object):
.. versionadded:: 5.0
The `contexts` and `skip_empty` parameters.
+ .. versionadded:: 5.2
+ The `precision` parameter.
+
"""
with override_config(
self,
ignore_errors=ignore_errors, report_omit=omit, report_include=include,
show_missing=show_missing, skip_covered=skip_covered,
- report_contexts=contexts, skip_empty=skip_empty,
+ report_contexts=contexts, skip_empty=skip_empty, precision=precision,
):
reporter = SummaryReporter(self)
return reporter.report(morfs, outfile=file)
@@ -899,10 +905,12 @@ class Coverage(object):
reporter = AnnotateReporter(self)
reporter.report(morfs, directory=directory)
- def html_report(self, morfs=None, directory=None, ignore_errors=None,
- omit=None, include=None, extra_css=None, title=None,
- skip_covered=None, show_contexts=None, contexts=None,
- skip_empty=None):
+ def html_report(
+ self, morfs=None, directory=None, ignore_errors=None,
+ omit=None, include=None, extra_css=None, title=None,
+ skip_covered=None, show_contexts=None, contexts=None,
+ skip_empty=None, precision=None,
+ ):
"""Generate an HTML report.
The HTML is written to `directory`. The file "index.html" is the
@@ -930,7 +938,7 @@ class Coverage(object):
ignore_errors=ignore_errors, report_omit=omit, report_include=include,
html_dir=directory, extra_css=extra_css, html_title=title,
skip_covered=skip_covered, show_contexts=show_contexts, report_contexts=contexts,
- skip_empty=skip_empty,
+ skip_empty=skip_empty, precision=precision,
):
reporter = HtmlReporter(self)
return reporter.report(morfs)
diff --git a/coverage/htmlfiles/pyfile.html b/coverage/htmlfiles/pyfile.html
index eb0f99c8..ec0f416f 100644
--- a/coverage/htmlfiles/pyfile.html
+++ b/coverage/htmlfiles/pyfile.html
@@ -33,12 +33,12 @@
<h2 class="stats">
{{nums.n_statements}} statements &nbsp;
- <span class="{{category.run}} shortkey_r button_toggle_run">{{nums.n_executed}} run</span>
- <span class="{{category.mis}} shortkey_m button_toggle_mis">{{nums.n_missing}} missing</span>
- <span class="{{category.exc}} shortkey_x button_toggle_exc">{{nums.n_excluded}} excluded</span>
+ <button type="button" class="{{category.run}} shortkey_r button_toggle_run" title="Toggle lines run">{{nums.n_executed}} run</button>
+ <button type="button" class="{{category.mis}} shortkey_m button_toggle_mis" title="Toggle lines missing">{{nums.n_missing}} missing</button>
+ <button type="button" class="{{category.exc}} shortkey_x button_toggle_exc" title="Toggle lines excluded">{{nums.n_excluded}} excluded</button>
{% if has_arcs %}
- <span class="{{category.par}} shortkey_p button_toggle_par">{{nums.n_partial_branches}} partial</span>
+ <button type="button" class="{{category.par}} shortkey_p button_toggle_par" title="Toggle lines partially run">{{nums.n_partial_branches}} partial</button>
{% endif %}
</h2>
</div>
diff --git a/coverage/htmlfiles/style.css b/coverage/htmlfiles/style.css
index e8ff5765..5a79a2e7 100644
--- a/coverage/htmlfiles/style.css
+++ b/coverage/htmlfiles/style.css
@@ -4,11 +4,15 @@
/* Don't edit this .css file. Edit the .scss file instead! */
html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; }
-body { font-family: georgia, serif; font-size: 1em; }
+body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 1em; background: #fff; color: #000; }
+@media (prefers-color-scheme: dark) { body { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { body { color: #eee; } }
html > body { font-size: 16px; }
-p { font-size: .75em; line-height: 1.33333333em; }
+a:active, a:focus { outline: 2px dashed #007acc; }
+
+p { font-size: .875em; line-height: 1.4em; }
table { border-collapse: collapse; }
@@ -22,35 +26,53 @@ a.nav { text-decoration: none; color: inherit; }
a.nav:hover { text-decoration: underline; color: inherit; }
#header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; }
+@media (prefers-color-scheme: dark) { #header { background: black; } }
+@media (prefers-color-scheme: dark) { #header { border-color: #333; } }
-.indexfile #footer { margin: 1em 3em; }
+.indexfile #footer { margin: 1rem 3rem; }
-.pyfile #footer { margin: 1em 1em; }
+.pyfile #footer { margin: 1rem 1rem; }
-#footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; }
+#footer .content { padding: 0; color: #666; font-style: italic; }
+@media (prefers-color-scheme: dark) { #footer .content { color: #aaa; } }
-#index { margin: 1em 0 0 3em; }
+#index { margin: 1rem 0 0 3rem; }
-#header .content { padding: 1em 3rem; }
+#header .content { padding: 1rem 3rem; }
h1 { font-size: 1.25em; display: inline-block; }
-#filter_container { display: inline-block; float: right; margin: 0 2em 0 0; }
-#filter_container input { width: 10em; }
+#filter_container { float: right; margin: 0 2em 0 0; }
+#filter_container input { width: 10em; padding: 0.2em 0.5em; border: 2px solid #ccc; background: #fff; color: #000; }
+@media (prefers-color-scheme: dark) { #filter_container input { border-color: #444; } }
+@media (prefers-color-scheme: dark) { #filter_container input { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { #filter_container input { color: #eee; } }
+#filter_container input:focus { border-color: #007acc; }
h2.stats { margin-top: .5em; font-size: 1em; }
-.stats span { border: 1px solid; border-radius: .1em; padding: .1em .5em; margin: 0 .1em; cursor: pointer; border-color: #ccc #999 #999 #ccc; }
-.stats span.run { background: #eeffee; }
-.stats span.run.show_run { border-color: #999 #ccc #ccc #999; background: #ddffdd; }
-.stats span.mis { background: #ffeeee; }
-.stats span.mis.show_mis { border-color: #999 #ccc #ccc #999; background: #ffdddd; }
-.stats span.exc { background: #f7f7f7; }
-.stats span.exc.show_exc { border-color: #999 #ccc #ccc #999; background: #eeeeee; }
-.stats span.par { background: #ffffd5; }
-.stats span.par.show_par { border-color: #999 #ccc #ccc #999; background: #ffffaa; }
-
-#source p .annotate.long, .help_panel { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; box-shadow: #cccccc .2em .2em .2em; color: #333; padding: .25em .5em; }
+.stats button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; color: inherit; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; }
+@media (prefers-color-scheme: dark) { .stats button { border-color: #444; } }
+.stats button:active, .stats button:focus { outline: 2px dashed #007acc; }
+.stats button:active, .stats button:focus { outline: 2px dashed #007acc; }
+.stats button.run { background: #eeffee; }
+@media (prefers-color-scheme: dark) { .stats button.run { background: #373d29; } }
+.stats button.run.show_run { background: #dfd; border: 2px solid #00dd00; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.run.show_run { background: #373d29; } }
+.stats button.mis { background: #ffeeee; }
+@media (prefers-color-scheme: dark) { .stats button.mis { background: #4b1818; } }
+.stats button.mis.show_mis { background: #fdd; border: 2px solid #ff0000; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.mis.show_mis { background: #4b1818; } }
+.stats button.exc { background: #f7f7f7; }
+@media (prefers-color-scheme: dark) { .stats button.exc { background: #333; } }
+.stats button.exc.show_exc { background: #eee; border: 2px solid #808080; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.exc.show_exc { background: #333; } }
+.stats button.par { background: #ffffd5; }
+@media (prefers-color-scheme: dark) { .stats button.par { background: #650; } }
+.stats button.par.show_par { background: #ffa; border: 2px solid #dddd00; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.par.show_par { background: #650; } }
+
+#source p .annotate.long, .help_panel { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; color: #333; padding: .25em .5em; }
#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; }
@@ -58,41 +80,57 @@ h2.stats { margin-top: .5em; font-size: 1em; }
.help_panel { padding: .5em; border: 1px solid #883; }
.help_panel .legend { font-style: italic; margin-bottom: 1em; }
-.indexfile .help_panel { width: 20em; height: 4em; }
-.pyfile .help_panel { width: 16em; height: 8em; }
+.indexfile .help_panel { width: 20em; min-height: 4em; }
+.pyfile .help_panel { width: 16em; min-height: 8em; }
#panel_icon { float: right; cursor: pointer; }
.keyhelp { margin: .75em; }
-.keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; }
+.keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-weight: bold; background: #eee; }
-#source { padding: 1em 0 1em 3rem; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; }
+#source { padding: 1em 0 1em 3rem; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
#source p { position: relative; white-space: pre; }
#source p * { box-sizing: border-box; }
-#source p .n { float: left; text-align: right; width: 3rem; box-sizing: border-box; margin-left: -3rem; padding-right: 1em; color: #999999; font-family: verdana, sans-serif; }
-#source p .n a { text-decoration: none; color: #999999; font-size: .8333em; line-height: 1em; }
-#source p .n a:hover { text-decoration: underline; color: #999999; }
+#source p .n { float: left; text-align: right; width: 3rem; box-sizing: border-box; margin-left: -3rem; padding-right: 1em; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n { color: #777; } }
+#source p .n a { text-decoration: none; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n a { color: #777; } }
+#source p .n a:hover { text-decoration: underline; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n a:hover { color: #777; } }
#source p.highlight .n { background: #ffdd00; }
-#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid white; }
+#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid #fff; }
+@media (prefers-color-scheme: dark) { #source p .t { border-color: #1e1e1e; } }
#source p .t:hover { background: #f2f2f2; }
+@media (prefers-color-scheme: dark) { #source p .t:hover { background: #282828; } }
#source p .t:hover ~ .r .annotate.long { display: block; }
-#source p .t .com { color: green; font-style: italic; line-height: 1px; }
+#source p .t .com { color: #008000; font-style: italic; line-height: 1px; }
+@media (prefers-color-scheme: dark) { #source p .t .com { color: #6A9955; } }
#source p .t .key { font-weight: bold; line-height: 1px; }
-#source p .t .str { color: #000080; }
+#source p .t .str { color: #0451A5; }
+@media (prefers-color-scheme: dark) { #source p .t .str { color: #9CDCFE; } }
#source p.mis .t { border-left: 0.2em solid #ff0000; }
-#source p.mis.show_mis .t { background: #ffdddd; }
+#source p.mis.show_mis .t { background: #fdd; }
+@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t { background: #4b1818; } }
#source p.mis.show_mis .t:hover { background: #f2d2d2; }
-#source p.run .t { border-left: 0.2em solid #00ff00; }
-#source p.run.show_run .t { background: #ddffdd; }
+@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } }
+#source p.run .t { border-left: 0.2em solid #00dd00; }
+#source p.run.show_run .t { background: #dfd; }
+@media (prefers-color-scheme: dark) { #source p.run.show_run .t { background: #373d29; } }
#source p.run.show_run .t:hover { background: #d2f2d2; }
+@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } }
#source p.exc .t { border-left: 0.2em solid #808080; }
-#source p.exc.show_exc .t { background: #eeeeee; }
+#source p.exc.show_exc .t { background: #eee; }
+@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t { background: #333; } }
#source p.exc.show_exc .t:hover { background: #e2e2e2; }
-#source p.par .t { border-left: 0.2em solid #eeee99; }
-#source p.par.show_par .t { background: #ffffaa; }
+@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } }
+#source p.par .t { border-left: 0.2em solid #dddd00; }
+#source p.par.show_par .t { background: #ffa; }
+@media (prefers-color-scheme: dark) { #source p.par.show_par .t { background: #650; } }
#source p.par.show_par .t:hover { background: #f2f2a2; }
-#source p .r { position: absolute; top: 0; right: 2.5em; font-family: verdana, sans-serif; }
-#source p .annotate { font-family: georgia; color: #666; padding-right: .5em; }
+@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } }
+#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
+#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; }
+@media (prefers-color-scheme: dark) { #source p .annotate { color: #ddd; } }
#source p .annotate.short:hover ~ .long { display: block; }
#source p .annotate.long { width: 30em; right: 2.5em; }
#source p input { display: none; }
@@ -103,22 +141,32 @@ h2.stats { margin-top: .5em; font-size: 1em; }
#source p input:checked ~ .r label.ctx::before { content: "▼ "; }
#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; }
#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; }
-#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: verdana, sans-serif; white-space: nowrap; background: #aaeeff; border-radius: .25em; margin-right: 1.75em; }
+@media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } }
+#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #aaeeff; border-radius: .25em; margin-right: 1.75em; }
#source p .ctxs span { display: block; text-align: right; }
+#index { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 0.875em; }
#index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; }
+@media (prefers-color-scheme: dark) { #index td, #index th { border-color: #333; } }
#index td.left, #index th.left { padding-left: 0; }
#index td.right, #index th.right { padding-right: 0; }
#index td.name, #index th.name { text-align: left; width: auto; }
-#index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; }
-#index th:hover { background: #eee; border-bottom: 1px solid #999; }
-#index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; white-space: nowrap; background: #eee; }
+#index th { font-style: italic; color: #333; cursor: pointer; }
+@media (prefers-color-scheme: dark) { #index th { color: #ddd; } }
+#index th:hover { background: #eee; }
+@media (prefers-color-scheme: dark) { #index th:hover { background: #333; } }
+#index th.headerSortDown, #index th.headerSortUp { white-space: nowrap; background: #eee; }
+@media (prefers-color-scheme: dark) { #index th.headerSortDown, #index th.headerSortUp { background: #333; } }
#index th.headerSortDown:after { content: " ↓"; }
#index th.headerSortUp:after { content: " ↑"; }
-#index td.name a { text-decoration: none; color: #000; }
+#index td.name a { text-decoration: none; color: inherit; }
#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; }
-#index tr.file:hover { background: #eeeeee; }
-#index tr.file:hover td.name { text-decoration: underline; color: #000; }
-
-#scroll_marker { position: fixed; right: 0; top: 0; width: 16px; height: 100%; background: white; border-left: 1px solid #eee; will-change: transform; }
-#scroll_marker .marker { background: #ddd; position: absolute; min-height: 3px; width: 100%; }
+#index tr.file:hover { background: #eee; }
+@media (prefers-color-scheme: dark) { #index tr.file:hover { background: #333; } }
+#index tr.file:hover td.name { text-decoration: underline; color: inherit; }
+
+#scroll_marker { position: fixed; right: 0; top: 0; width: 16px; height: 100%; background: #fff; border-left: 1px solid #eee; will-change: transform; }
+@media (prefers-color-scheme: dark) { #scroll_marker { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { #scroll_marker { border-color: #333; } }
+#scroll_marker .marker { background: #ccc; position: absolute; min-height: 3px; width: 100%; }
+@media (prefers-color-scheme: dark) { #scroll_marker .marker { background: #444; } }
diff --git a/coverage/htmlfiles/style.scss b/coverage/htmlfiles/style.scss
index 901cccc4..b3c63e75 100644
--- a/coverage/htmlfiles/style.scss
+++ b/coverage/htmlfiles/style.scss
@@ -8,6 +8,9 @@
// When working on the file, this command is useful:
// sass --watch --style=compact --sourcemap=none --no-cache coverage/htmlfiles/style.scss:htmlcov/style.css
+//
+// OR you can process sass purely in python with `pip install pysass`, then:
+// pysassc --style=compact coverage/htmlfiles/style.scss coverage/htmlfiles/style.css
// Ignore this comment, it's for the CSS output file:
/* Don't edit this .css file. Edit the .scss file instead! */
@@ -15,6 +18,82 @@
// Dimensions
$left-gutter: 3rem;
+
+//
+// Declare colors and variables
+//
+
+$font-normal: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+$font-code: SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+
+$off-button-lighten: 50%;
+$hover-dark-amt: 95%;
+
+$focus-color: #007acc;
+
+$mis-color: #ff0000;
+$run-color: #00dd00;
+$exc-color: #808080;
+$par-color: #dddd00;
+
+$light-bg: #fff;
+$light-fg: #000;
+$light-gray1: #f8f8f8;
+$light-gray2: #eee;
+$light-gray3: #ccc;
+$light-gray4: #999;
+$light-gray5: #666;
+$light-gray6: #333;
+$light-pln-bg: $light-bg;
+$light-mis-bg: #fdd;
+$light-run-bg: #dfd;
+$light-exc-bg: $light-gray2;
+$light-par-bg: #ffa;
+$light-token-com: #008000;
+$light-token-str: #0451A5;
+
+$dark-bg: #1e1e1e;
+$dark-fg: #eee;
+$dark-gray1: #222;
+$dark-gray2: #333;
+$dark-gray3: #444;
+$dark-gray4: #777;
+$dark-gray5: #aaa;
+$dark-gray6: #ddd;
+$dark-pln-bg: $dark-bg;
+$dark-mis-bg: #4b1818;
+$dark-run-bg: #373d29;
+$dark-exc-bg: $dark-gray2;
+$dark-par-bg: #650;
+$dark-token-com: #6A9955;
+$dark-token-str: #9CDCFE;
+
+//
+// Mixins and utilities
+//
+@mixin background-dark($color) {
+ @media (prefers-color-scheme: dark) {
+ background: $color;
+ }
+}
+@mixin color-dark($color) {
+ @media (prefers-color-scheme: dark) {
+ color: $color;
+ }
+}
+@mixin border-color-dark($color) {
+ @media (prefers-color-scheme: dark) {
+ border-color: $color;
+ }
+}
+
+// Add visual outline to navigable elements on focus improve accessibility.
+@mixin focus-border {
+ &:active, &:focus {
+ outline: 2px dashed $focus-color;
+ }
+}
+
// Page-wide styles
html, body, h1, h2, h3, p, table, td, th {
margin: 0;
@@ -29,18 +108,25 @@ html, body, h1, h2, h3, p, table, td, th {
// Set baseline grid to 16 pt.
body {
- font-family: georgia, serif;
+ font-family: $font-normal;
font-size: 1em;
+ background: $light-bg;
+ color: $light-fg;
+ @include background-dark($dark-bg);
+ @include color-dark($dark-fg);
}
html>body {
font-size: 16px;
}
-// Set base font size to 12/16
+a {
+ @include focus-border;
+}
+
p {
- font-size: .75em; // 12/16
- line-height: 1.33333333em; // 16/12
+ font-size: .875em;
+ line-height: 1.4em;
}
table {
@@ -70,34 +156,35 @@ a.nav {
// Page structure
#header {
- background: #f8f8f8;
+ background: $light-gray1;
+ @include background-dark(black);
width: 100%;
- border-bottom: 1px solid #eee;
+ border-bottom: 1px solid $light-gray2;
+ @include border-color-dark($dark-gray2);
}
.indexfile #footer {
- margin: 1em 3em;
+ margin: 1rem 3rem;
}
.pyfile #footer {
- margin: 1em 1em;
+ margin: 1rem 1rem;
}
#footer .content {
padding: 0;
- font-size: 85%;
- font-family: verdana, sans-serif;
- color: #666666;
+ color: $light-gray5;
+ @include color-dark($dark-gray5);
font-style: italic;
}
#index {
- margin: 1em 0 0 3em;
+ margin: 1rem 0 0 3rem;
}
// Header styles
#header .content {
- padding: 1em $left-gutter;
+ padding: 1rem $left-gutter;
}
h1 {
@@ -106,61 +193,81 @@ h1 {
}
#filter_container {
- display: inline-block;
float: right;
margin: 0 2em 0 0;
input {
width: 10em;
+ padding: 0.2em 0.5em;
+ border: 2px solid $light-gray3;
+ background: $light-bg;
+ color: $light-fg;
+ @include border-color-dark($dark-gray3);
+ @include background-dark($dark-bg);
+ @include color-dark($dark-fg);
+ &:focus {
+ border-color: $focus-color;
+ }
}
}
-$pln-color: #ffffff;
-$mis-color: #ffdddd;
-$run-color: #ddffdd;
-$exc-color: #eeeeee;
-$par-color: #ffffaa;
-
-$off-button-lighten: 50%;
-
h2.stats {
margin-top: .5em;
font-size: 1em;
}
-.stats span {
+.stats button {
+ font-family: inherit;
+ font-size: inherit;
border: 1px solid;
- border-radius: .1em;
+ border-radius: .2em;
+ color: inherit;
padding: .1em .5em;
- margin: 0 .1em;
+ margin: 1px calc(.1em + 1px);
cursor: pointer;
- border-color: #ccc #999 #999 #ccc;
+ border-color: $light-gray3;
+ @include border-color-dark($dark-gray3);
+ @include focus-border;
+
+ @include focus-border;
&.run {
- background: mix($run-color, #fff, $off-button-lighten);
+ background: mix($light-run-bg, $light-bg, $off-button-lighten);
+ @include background-dark($dark-run-bg);
&.show_run {
- border-color: #999 #ccc #ccc #999;
- background: $run-color;
+ background: $light-run-bg;
+ @include background-dark($dark-run-bg);
+ border: 2px solid $run-color;
+ margin: 0 .1em;
}
}
&.mis {
- background: mix($mis-color, #fff, $off-button-lighten);
+ background: mix($light-mis-bg, $light-bg, $off-button-lighten);
+ @include background-dark($dark-mis-bg);
&.show_mis {
- border-color: #999 #ccc #ccc #999;
- background: $mis-color;
+ background: $light-mis-bg;
+ @include background-dark($dark-mis-bg);
+ border: 2px solid $mis-color;
+ margin: 0 .1em;
}
}
&.exc {
- background: mix($exc-color, #fff, $off-button-lighten);
+ background: mix($light-exc-bg, $light-bg, $off-button-lighten);
+ @include background-dark($dark-exc-bg);
&.show_exc {
- border-color: #999 #ccc #ccc #999;
- background: $exc-color;
+ background: $light-exc-bg;
+ @include background-dark($dark-exc-bg);
+ border: 2px solid $exc-color;
+ margin: 0 .1em;
}
}
&.par {
- background: mix($par-color, #fff, $off-button-lighten);
+ background: mix($light-par-bg, $light-bg, $off-button-lighten);
+ @include background-dark($dark-par-bg);
&.show_par {
- border-color: #999 #ccc #ccc #999;
- background: $par-color;
+ background: $light-par-bg;
+ @include background-dark($dark-par-bg);
+ border: 2px solid $par-color;
+ margin: 0 .1em;
}
}
}
@@ -173,7 +280,6 @@ h2.stats {
background: #ffffcc;
border: 1px solid #888;
border-radius: .2em;
- box-shadow: #cccccc .2em .2em .2em;
color: #333;
padding: .25em .5em;
}
@@ -207,12 +313,12 @@ h2.stats {
.indexfile & {
width: 20em;
- height: 4em;
+ min-height: 4em;
}
.pyfile & {
width: 16em;
- height: 8em;
+ min-height: 8em;
}
}
@@ -228,7 +334,7 @@ h2.stats {
border: 1px solid black;
border-color: #888 #333 #333 #888;
padding: .1em .35em;
- font-family: monospace;
+ font-family: $font-code;
font-weight: bold;
background: #eee;
}
@@ -236,13 +342,6 @@ h2.stats {
// Source file styles
-$hover-dark-amt: 95%;
-$pln-hover-color: mix($pln-color, #000, $hover-dark-amt);
-$mis-hover-color: mix($mis-color, #000, $hover-dark-amt);
-$run-hover-color: mix($run-color, #000, $hover-dark-amt);
-$exc-hover-color: mix($exc-color, #000, $hover-dark-amt);
-$par-hover-color: mix($par-color, #000, $hover-dark-amt);
-
// The slim bar at the left edge of the source lines, colored by coverage.
$border-indicator-width: .2em;
@@ -250,7 +349,7 @@ $context-panel-color: #aaeeff;
#source {
padding: 1em 0 1em $left-gutter;
- font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-family: $font-code;
p {
// position relative makes position:absolute pop-ups appear in the right place.
@@ -268,17 +367,17 @@ $context-panel-color: #aaeeff;
box-sizing: border-box;
margin-left: -$left-gutter;
padding-right: 1em;
- color: #999999;
- font-family: verdana, sans-serif;
+ color: $light-gray4;
+ @include color-dark($dark-gray4);
a {
text-decoration: none;
- color: #999999;
- font-size: .8333em; // 10/12
- line-height: 1em;
+ color: $light-gray4;
+ @include color-dark($dark-gray4);
&:hover {
text-decoration: underline;
- color: #999999;
+ color: $light-gray4;
+ @include color-dark($dark-gray4);
}
}
}
@@ -293,10 +392,12 @@ $context-panel-color: #aaeeff;
box-sizing: border-box;
margin-left: -.5em;
padding-left: .5em - $border-indicator-width;
- border-left: $border-indicator-width solid white;
+ border-left: $border-indicator-width solid $light-bg;
+ @include border-color-dark($dark-bg);
&:hover {
- background: $pln-hover-color;
+ background: mix($light-pln-bg, $light-fg, $hover-dark-amt);
+ @include background-dark(mix($dark-pln-bg, $dark-fg, $hover-dark-amt));
& ~ .r .annotate.long {
display: block;
@@ -305,7 +406,8 @@ $context-panel-color: #aaeeff;
// Syntax coloring
.com {
- color: green;
+ color: $light-token-com;
+ @include color-dark($dark-token-com);
font-style: italic;
line-height: 1px;
}
@@ -314,62 +416,71 @@ $context-panel-color: #aaeeff;
line-height: 1px;
}
.str {
- color: #000080;
+ color: $light-token-str;
+ @include color-dark($dark-token-str);
}
}
&.mis {
.t {
- border-left: $border-indicator-width solid #ff0000;
+ border-left: $border-indicator-width solid $mis-color;
}
&.show_mis .t {
- background: $mis-color;
+ background: $light-mis-bg;
+ @include background-dark($dark-mis-bg);
&:hover {
- background: $mis-hover-color;
+ background: mix($light-mis-bg, $light-fg, $hover-dark-amt);
+ @include background-dark(mix($dark-mis-bg, $dark-fg, $hover-dark-amt));
}
}
}
&.run {
.t {
- border-left: $border-indicator-width solid #00ff00;
+ border-left: $border-indicator-width solid $run-color;
}
&.show_run .t {
- background: $run-color;
+ background: $light-run-bg;
+ @include background-dark($dark-run-bg);
&:hover {
- background: $run-hover-color;
+ background: mix($light-run-bg, $light-fg, $hover-dark-amt);
+ @include background-dark(mix($dark-run-bg, $dark-fg, $hover-dark-amt));
}
}
}
&.exc {
.t {
- border-left: $border-indicator-width solid #808080;
+ border-left: $border-indicator-width solid $exc-color;
}
&.show_exc .t {
- background: $exc-color;
+ background: $light-exc-bg;
+ @include background-dark($dark-exc-bg);
&:hover {
- background: $exc-hover-color;
+ background: mix($light-exc-bg, $light-fg, $hover-dark-amt);
+ @include background-dark(mix($dark-exc-bg, $dark-fg, $hover-dark-amt));
}
}
}
&.par {
.t {
- border-left: $border-indicator-width solid #eeee99;
+ border-left: $border-indicator-width solid $par-color;
}
&.show_par .t {
- background: $par-color;
+ background: $light-par-bg;
+ @include background-dark($dark-par-bg);
&:hover {
- background: $par-hover-color;
+ background: mix($light-par-bg, $light-fg, $hover-dark-amt);
+ @include background-dark(mix($dark-par-bg, $dark-fg, $hover-dark-amt));
}
}
@@ -379,12 +490,13 @@ $context-panel-color: #aaeeff;
position: absolute;
top: 0;
right: 2.5em;
- font-family: verdana, sans-serif;
+ font-family: $font-normal;
}
.annotate {
- font-family: georgia;
- color: #666;
+ font-family: $font-normal;
+ color: $light-gray5;
+ @include color-dark($dark-gray6);
padding-right: .5em;
&.short:hover ~ .long {
@@ -432,7 +544,8 @@ $context-panel-color: #aaeeff;
}
label.ctx {
- color: #999;
+ color: $light-gray4;
+ @include color-dark($dark-gray4);
display: inline-block;
padding: 0 .5em;
font-size: .8333em; // 10/12
@@ -444,7 +557,7 @@ $context-panel-color: #aaeeff;
overflow-y: hidden;
transition: all .2s;
padding: 0 .5em;
- font-family: verdana, sans-serif;
+ font-family: $font-normal;
white-space: nowrap;
background: $context-panel-color;
border-radius: .25em;
@@ -460,11 +573,15 @@ $context-panel-color: #aaeeff;
// index styles
#index {
+ font-family: $font-normal;
+ font-size: 0.875em;
+
td, th {
text-align: right;
width: 5em;
padding: .25em .5em;
- border-bottom: 1px solid #eee;
+ border-bottom: 1px solid $light-gray2;
+ @include border-color-dark($dark-gray2);
&.left {
padding-left: 0;
}
@@ -478,17 +595,17 @@ $context-panel-color: #aaeeff;
}
th {
font-style: italic;
- color: #333;
- border-bottom: 1px solid #ccc;
+ color: $light-gray6;
+ @include color-dark($dark-gray6);
cursor: pointer;
&:hover {
- background: #eee;
- border-bottom: 1px solid #999;
+ background: $light-gray2;
+ @include background-dark($dark-gray2);
}
&.headerSortDown, &.headerSortUp {
- border-bottom: 1px solid #000;
white-space: nowrap;
- background: #eee;
+ background: $light-gray2;
+ @include background-dark($dark-gray2);
}
&.headerSortDown:after {
content: " ↓";
@@ -499,7 +616,7 @@ $context-panel-color: #aaeeff;
}
td.name a {
text-decoration: none;
- color: #000;
+ color: inherit;
}
tr.total td,
@@ -509,10 +626,11 @@ $context-panel-color: #aaeeff;
border-bottom: none;
}
tr.file:hover {
- background: #eeeeee;
+ background: $light-gray2;
+ @include background-dark($dark-gray2);
td.name {
text-decoration: underline;
- color: #000;
+ color: inherit;
}
}
}
@@ -524,12 +642,15 @@ $context-panel-color: #aaeeff;
top: 0;
width: 16px;
height: 100%;
- background: white;
- border-left: 1px solid #eee;
+ background: $light-bg;
+ border-left: 1px solid $light-gray2;
+ @include background-dark($dark-bg);
+ @include border-color-dark($dark-gray2);
will-change: transform; // for faster scrolling of fixed element in Chrome
.marker {
- background: #ddd;
+ background: $light-gray3;
+ @include background-dark($dark-gray3);
position: absolute;
min-height: 3px;
width: 100%;
diff --git a/coverage/multiproc.py b/coverage/multiproc.py
index 2931b3be..0afcb0c9 100644
--- a/coverage/multiproc.py
+++ b/coverage/multiproc.py
@@ -28,7 +28,7 @@ original_bootstrap = OriginalProcess._bootstrap
class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-method
"""A replacement for multiprocess.Process that starts coverage."""
- def _bootstrap(self, *args, **kwargs): # pylint: disable=arguments-differ
+ def _bootstrap(self, *args, **kwargs): # pylint: disable=signature-differs
"""Wrapper around _bootstrap to start coverage."""
try:
from coverage import Coverage # avoid circular import
diff --git a/doc/cmd.rst b/doc/cmd.rst
index cbbb26bb..31ae6e01 100644
--- a/doc/cmd.rst
+++ b/doc/cmd.rst
@@ -371,6 +371,9 @@ If you have :ref:`recorded contexts <contexts>`, the ``--contexts`` option lets
you choose which contexts to report on. See :ref:`context_reporting` for
details.
+The ``--precision`` option controls the number of digits displayed after the
+decimal point in coverage percentages, defaulting to none.
+
Other common reporting options are described above in :ref:`cmd_reporting`.
@@ -418,6 +421,9 @@ The ``--skip-covered`` switch will skip any file with 100% coverage, letting
you focus on the files that still need attention. The ``--skip-empty`` switch
will skip any file with no executable statements.
+The ``--precision`` option controls the number of digits displayed after the
+decimal point in coverage percentages, defaulting to none.
+
If you have :ref:`recorded contexts <contexts>`, the ``--contexts`` option lets
you choose which contexts to report on, and the ``--show-contexts`` option will
annotate lines with the contexts that ran them. See :ref:`context_reporting`
diff --git a/howto.txt b/howto.txt
index 3653e830..203a119f 100644
--- a/howto.txt
+++ b/howto.txt
@@ -74,7 +74,9 @@
- add an "Unreleased" section to the top.
- git push
- Update Tidelift:
- - make upload_relnotes
+ - make tidelift_relnotes
+- Update GitHub releases:
+ - make github_releases
- Update readthedocs
- IF NOT PRE-RELEASE:
- update git "stable" branch to point to latest release
diff --git a/requirements/dev.pip b/requirements/dev.pip
index a11729cd..96591414 100644
--- a/requirements/dev.pip
+++ b/requirements/dev.pip
@@ -4,8 +4,7 @@
# Requirements for doing local development work on coverage.py.
# https://requires.io/github/nedbat/coveragepy/requirements/
-pip==20.0.2
-virtualenv==16.7.9
+-r pip.pip
pluggy==0.13.1
@@ -15,9 +14,9 @@ pluggy==0.13.1
# for linting.
greenlet==0.4.15
-pylint==2.4.4
+pylint==2.5.2
check-manifest==0.40
-readme_renderer==24.0
+readme_renderer==26.0
# for kitting.
requests==2.22.0
diff --git a/requirements/pip.pip b/requirements/pip.pip
new file mode 100644
index 00000000..71c7f213
--- /dev/null
+++ b/requirements/pip.pip
@@ -0,0 +1,5 @@
+# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
+
+pip==20.0.2
+virtualenv==16.7.9
diff --git a/tests/gold/html/Makefile b/tests/gold/html/Makefile
index fa98714e..604ece7a 100644
--- a/tests/gold/html/Makefile
+++ b/tests/gold/html/Makefile
@@ -7,7 +7,7 @@ help:
complete: ## Copy support files into directories so the HTML can be viewed properly.
@for sub in *; do \
- if [[ -f $$sub/index.html ]]; then \
+ if [ -f "$$sub/index.html" ]; then \
echo Copying into $$sub ; \
cp -n support/* $$sub ; \
fi ; \
diff --git a/tests/gold/html/a/a_py.html b/tests/gold/html/a/a_py.html
index 2ce52414..d534c6a3 100644
--- a/tests/gold/html/a/a_py.html
+++ b/tests/gold/html/a/a_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
3 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">1 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">1 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/b_branch/b_py.html b/tests/gold/html/b_branch/b_py.html
index ce8bb875..67a1b83b 100644
--- a/tests/gold/html/b_branch/b_py.html
+++ b/tests/gold/html/b_branch/b_py.html
@@ -22,10 +22,10 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
17 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">14 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">3 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
- <span class="par run show_par shortkey_p button_toggle_par">4 partial</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">14 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">3 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
+ <button type="button" class="par run show_par shortkey_p button_toggle_par" title="Toggle lines partially run">4 partial</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/bom/2/bom_py.html b/tests/gold/html/bom/2/bom_py.html
index 3d1c98fb..74f4f2fe 100644
--- a/tests/gold/html/bom/2/bom_py.html
+++ b/tests/gold/html/bom/2/bom_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
7 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">5 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">2 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">5 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">2 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/bom/bom_py.html b/tests/gold/html/bom/bom_py.html
index 635f8b51..10b84ede 100644
--- a/tests/gold/html/bom/bom_py.html
+++ b/tests/gold/html/bom/bom_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
7 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">5 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">2 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">5 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">2 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/isolatin1/isolatin1_py.html b/tests/gold/html/isolatin1/isolatin1_py.html
index 9c12c445..b344bad6 100644
--- a/tests/gold/html/isolatin1/isolatin1_py.html
+++ b/tests/gold/html/isolatin1/isolatin1_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_1/m1_py.html b/tests/gold/html/omit_1/m1_py.html
index 60923930..57584495 100644
--- a/tests/gold/html/omit_1/m1_py.html
+++ b/tests/gold/html/omit_1/m1_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_1/m2_py.html b/tests/gold/html/omit_1/m2_py.html
index de060f32..e8c1791d 100644
--- a/tests/gold/html/omit_1/m2_py.html
+++ b/tests/gold/html/omit_1/m2_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_1/m3_py.html b/tests/gold/html/omit_1/m3_py.html
index 76a91a4a..e714d47f 100644
--- a/tests/gold/html/omit_1/m3_py.html
+++ b/tests/gold/html/omit_1/m3_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_1/main_py.html b/tests/gold/html/omit_1/main_py.html
index 9f242537..28173d12 100644
--- a/tests/gold/html/omit_1/main_py.html
+++ b/tests/gold/html/omit_1/main_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
8 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">8 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">8 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_2/m2_py.html b/tests/gold/html/omit_2/m2_py.html
index de060f32..e8c1791d 100644
--- a/tests/gold/html/omit_2/m2_py.html
+++ b/tests/gold/html/omit_2/m2_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_2/m3_py.html b/tests/gold/html/omit_2/m3_py.html
index 76a91a4a..e714d47f 100644
--- a/tests/gold/html/omit_2/m3_py.html
+++ b/tests/gold/html/omit_2/m3_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_2/main_py.html b/tests/gold/html/omit_2/main_py.html
index 9f242537..28173d12 100644
--- a/tests/gold/html/omit_2/main_py.html
+++ b/tests/gold/html/omit_2/main_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
8 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">8 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">8 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_3/m3_py.html b/tests/gold/html/omit_3/m3_py.html
index 76a91a4a..e714d47f 100644
--- a/tests/gold/html/omit_3/m3_py.html
+++ b/tests/gold/html/omit_3/m3_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_3/main_py.html b/tests/gold/html/omit_3/main_py.html
index 9f242537..28173d12 100644
--- a/tests/gold/html/omit_3/main_py.html
+++ b/tests/gold/html/omit_3/main_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
8 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">8 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">8 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_4/m1_py.html b/tests/gold/html/omit_4/m1_py.html
index 60923930..57584495 100644
--- a/tests/gold/html/omit_4/m1_py.html
+++ b/tests/gold/html/omit_4/m1_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_4/m3_py.html b/tests/gold/html/omit_4/m3_py.html
index 76a91a4a..e714d47f 100644
--- a/tests/gold/html/omit_4/m3_py.html
+++ b/tests/gold/html/omit_4/m3_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_4/main_py.html b/tests/gold/html/omit_4/main_py.html
index 9f242537..28173d12 100644
--- a/tests/gold/html/omit_4/main_py.html
+++ b/tests/gold/html/omit_4/main_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
8 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">8 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">8 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_5/m1_py.html b/tests/gold/html/omit_5/m1_py.html
index 60923930..57584495 100644
--- a/tests/gold/html/omit_5/m1_py.html
+++ b/tests/gold/html/omit_5/m1_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/omit_5/main_py.html b/tests/gold/html/omit_5/main_py.html
index 9f242537..28173d12 100644
--- a/tests/gold/html/omit_5/main_py.html
+++ b/tests/gold/html/omit_5/main_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
8 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">8 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">8 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/other/blah_blah_other_py.html b/tests/gold/html/other/blah_blah_other_py.html
index d3a4ebfc..8f0309d4 100644
--- a/tests/gold/html/other/blah_blah_other_py.html
+++ b/tests/gold/html/other/blah_blah_other_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
1 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">1 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">1 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/other/here_py.html b/tests/gold/html/other/here_py.html
index df2715d6..c2f6b5f1 100644
--- a/tests/gold/html/other/here_py.html
+++ b/tests/gold/html/other/here_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
4 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">3 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">1 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">3 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">1 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/partial/partial_py.html b/tests/gold/html/partial/partial_py.html
index f004808a..abd755d0 100644
--- a/tests/gold/html/partial/partial_py.html
+++ b/tests/gold/html/partial/partial_py.html
@@ -22,10 +22,10 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
7 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">7 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">1 excluded</span>
- <span class="par run show_par shortkey_p button_toggle_par">1 partial</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">7 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">1 excluded</button>
+ <button type="button" class="par run show_par shortkey_p button_toggle_par" title="Toggle lines partially run">1 partial</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/styled/a_py.html b/tests/gold/html/styled/a_py.html
index 4687e464..7b6f9dcd 100644
--- a/tests/gold/html/styled/a_py.html
+++ b/tests/gold/html/styled/a_py.html
@@ -23,9 +23,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
3 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">1 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">1 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/gold/html/styled/style.css b/tests/gold/html/styled/style.css
index e8ff5765..5a79a2e7 100644
--- a/tests/gold/html/styled/style.css
+++ b/tests/gold/html/styled/style.css
@@ -4,11 +4,15 @@
/* Don't edit this .css file. Edit the .scss file instead! */
html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; }
-body { font-family: georgia, serif; font-size: 1em; }
+body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 1em; background: #fff; color: #000; }
+@media (prefers-color-scheme: dark) { body { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { body { color: #eee; } }
html > body { font-size: 16px; }
-p { font-size: .75em; line-height: 1.33333333em; }
+a:active, a:focus { outline: 2px dashed #007acc; }
+
+p { font-size: .875em; line-height: 1.4em; }
table { border-collapse: collapse; }
@@ -22,35 +26,53 @@ a.nav { text-decoration: none; color: inherit; }
a.nav:hover { text-decoration: underline; color: inherit; }
#header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; }
+@media (prefers-color-scheme: dark) { #header { background: black; } }
+@media (prefers-color-scheme: dark) { #header { border-color: #333; } }
-.indexfile #footer { margin: 1em 3em; }
+.indexfile #footer { margin: 1rem 3rem; }
-.pyfile #footer { margin: 1em 1em; }
+.pyfile #footer { margin: 1rem 1rem; }
-#footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; }
+#footer .content { padding: 0; color: #666; font-style: italic; }
+@media (prefers-color-scheme: dark) { #footer .content { color: #aaa; } }
-#index { margin: 1em 0 0 3em; }
+#index { margin: 1rem 0 0 3rem; }
-#header .content { padding: 1em 3rem; }
+#header .content { padding: 1rem 3rem; }
h1 { font-size: 1.25em; display: inline-block; }
-#filter_container { display: inline-block; float: right; margin: 0 2em 0 0; }
-#filter_container input { width: 10em; }
+#filter_container { float: right; margin: 0 2em 0 0; }
+#filter_container input { width: 10em; padding: 0.2em 0.5em; border: 2px solid #ccc; background: #fff; color: #000; }
+@media (prefers-color-scheme: dark) { #filter_container input { border-color: #444; } }
+@media (prefers-color-scheme: dark) { #filter_container input { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { #filter_container input { color: #eee; } }
+#filter_container input:focus { border-color: #007acc; }
h2.stats { margin-top: .5em; font-size: 1em; }
-.stats span { border: 1px solid; border-radius: .1em; padding: .1em .5em; margin: 0 .1em; cursor: pointer; border-color: #ccc #999 #999 #ccc; }
-.stats span.run { background: #eeffee; }
-.stats span.run.show_run { border-color: #999 #ccc #ccc #999; background: #ddffdd; }
-.stats span.mis { background: #ffeeee; }
-.stats span.mis.show_mis { border-color: #999 #ccc #ccc #999; background: #ffdddd; }
-.stats span.exc { background: #f7f7f7; }
-.stats span.exc.show_exc { border-color: #999 #ccc #ccc #999; background: #eeeeee; }
-.stats span.par { background: #ffffd5; }
-.stats span.par.show_par { border-color: #999 #ccc #ccc #999; background: #ffffaa; }
-
-#source p .annotate.long, .help_panel { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; box-shadow: #cccccc .2em .2em .2em; color: #333; padding: .25em .5em; }
+.stats button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; color: inherit; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; }
+@media (prefers-color-scheme: dark) { .stats button { border-color: #444; } }
+.stats button:active, .stats button:focus { outline: 2px dashed #007acc; }
+.stats button:active, .stats button:focus { outline: 2px dashed #007acc; }
+.stats button.run { background: #eeffee; }
+@media (prefers-color-scheme: dark) { .stats button.run { background: #373d29; } }
+.stats button.run.show_run { background: #dfd; border: 2px solid #00dd00; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.run.show_run { background: #373d29; } }
+.stats button.mis { background: #ffeeee; }
+@media (prefers-color-scheme: dark) { .stats button.mis { background: #4b1818; } }
+.stats button.mis.show_mis { background: #fdd; border: 2px solid #ff0000; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.mis.show_mis { background: #4b1818; } }
+.stats button.exc { background: #f7f7f7; }
+@media (prefers-color-scheme: dark) { .stats button.exc { background: #333; } }
+.stats button.exc.show_exc { background: #eee; border: 2px solid #808080; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.exc.show_exc { background: #333; } }
+.stats button.par { background: #ffffd5; }
+@media (prefers-color-scheme: dark) { .stats button.par { background: #650; } }
+.stats button.par.show_par { background: #ffa; border: 2px solid #dddd00; margin: 0 .1em; }
+@media (prefers-color-scheme: dark) { .stats button.par.show_par { background: #650; } }
+
+#source p .annotate.long, .help_panel { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; color: #333; padding: .25em .5em; }
#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; }
@@ -58,41 +80,57 @@ h2.stats { margin-top: .5em; font-size: 1em; }
.help_panel { padding: .5em; border: 1px solid #883; }
.help_panel .legend { font-style: italic; margin-bottom: 1em; }
-.indexfile .help_panel { width: 20em; height: 4em; }
-.pyfile .help_panel { width: 16em; height: 8em; }
+.indexfile .help_panel { width: 20em; min-height: 4em; }
+.pyfile .help_panel { width: 16em; min-height: 8em; }
#panel_icon { float: right; cursor: pointer; }
.keyhelp { margin: .75em; }
-.keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; }
+.keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-weight: bold; background: #eee; }
-#source { padding: 1em 0 1em 3rem; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; }
+#source { padding: 1em 0 1em 3rem; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
#source p { position: relative; white-space: pre; }
#source p * { box-sizing: border-box; }
-#source p .n { float: left; text-align: right; width: 3rem; box-sizing: border-box; margin-left: -3rem; padding-right: 1em; color: #999999; font-family: verdana, sans-serif; }
-#source p .n a { text-decoration: none; color: #999999; font-size: .8333em; line-height: 1em; }
-#source p .n a:hover { text-decoration: underline; color: #999999; }
+#source p .n { float: left; text-align: right; width: 3rem; box-sizing: border-box; margin-left: -3rem; padding-right: 1em; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n { color: #777; } }
+#source p .n a { text-decoration: none; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n a { color: #777; } }
+#source p .n a:hover { text-decoration: underline; color: #999; }
+@media (prefers-color-scheme: dark) { #source p .n a:hover { color: #777; } }
#source p.highlight .n { background: #ffdd00; }
-#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid white; }
+#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid #fff; }
+@media (prefers-color-scheme: dark) { #source p .t { border-color: #1e1e1e; } }
#source p .t:hover { background: #f2f2f2; }
+@media (prefers-color-scheme: dark) { #source p .t:hover { background: #282828; } }
#source p .t:hover ~ .r .annotate.long { display: block; }
-#source p .t .com { color: green; font-style: italic; line-height: 1px; }
+#source p .t .com { color: #008000; font-style: italic; line-height: 1px; }
+@media (prefers-color-scheme: dark) { #source p .t .com { color: #6A9955; } }
#source p .t .key { font-weight: bold; line-height: 1px; }
-#source p .t .str { color: #000080; }
+#source p .t .str { color: #0451A5; }
+@media (prefers-color-scheme: dark) { #source p .t .str { color: #9CDCFE; } }
#source p.mis .t { border-left: 0.2em solid #ff0000; }
-#source p.mis.show_mis .t { background: #ffdddd; }
+#source p.mis.show_mis .t { background: #fdd; }
+@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t { background: #4b1818; } }
#source p.mis.show_mis .t:hover { background: #f2d2d2; }
-#source p.run .t { border-left: 0.2em solid #00ff00; }
-#source p.run.show_run .t { background: #ddffdd; }
+@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } }
+#source p.run .t { border-left: 0.2em solid #00dd00; }
+#source p.run.show_run .t { background: #dfd; }
+@media (prefers-color-scheme: dark) { #source p.run.show_run .t { background: #373d29; } }
#source p.run.show_run .t:hover { background: #d2f2d2; }
+@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } }
#source p.exc .t { border-left: 0.2em solid #808080; }
-#source p.exc.show_exc .t { background: #eeeeee; }
+#source p.exc.show_exc .t { background: #eee; }
+@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t { background: #333; } }
#source p.exc.show_exc .t:hover { background: #e2e2e2; }
-#source p.par .t { border-left: 0.2em solid #eeee99; }
-#source p.par.show_par .t { background: #ffffaa; }
+@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } }
+#source p.par .t { border-left: 0.2em solid #dddd00; }
+#source p.par.show_par .t { background: #ffa; }
+@media (prefers-color-scheme: dark) { #source p.par.show_par .t { background: #650; } }
#source p.par.show_par .t:hover { background: #f2f2a2; }
-#source p .r { position: absolute; top: 0; right: 2.5em; font-family: verdana, sans-serif; }
-#source p .annotate { font-family: georgia; color: #666; padding-right: .5em; }
+@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } }
+#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
+#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; }
+@media (prefers-color-scheme: dark) { #source p .annotate { color: #ddd; } }
#source p .annotate.short:hover ~ .long { display: block; }
#source p .annotate.long { width: 30em; right: 2.5em; }
#source p input { display: none; }
@@ -103,22 +141,32 @@ h2.stats { margin-top: .5em; font-size: 1em; }
#source p input:checked ~ .r label.ctx::before { content: "▼ "; }
#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; }
#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; }
-#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: verdana, sans-serif; white-space: nowrap; background: #aaeeff; border-radius: .25em; margin-right: 1.75em; }
+@media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } }
+#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #aaeeff; border-radius: .25em; margin-right: 1.75em; }
#source p .ctxs span { display: block; text-align: right; }
+#index { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 0.875em; }
#index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; }
+@media (prefers-color-scheme: dark) { #index td, #index th { border-color: #333; } }
#index td.left, #index th.left { padding-left: 0; }
#index td.right, #index th.right { padding-right: 0; }
#index td.name, #index th.name { text-align: left; width: auto; }
-#index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; }
-#index th:hover { background: #eee; border-bottom: 1px solid #999; }
-#index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; white-space: nowrap; background: #eee; }
+#index th { font-style: italic; color: #333; cursor: pointer; }
+@media (prefers-color-scheme: dark) { #index th { color: #ddd; } }
+#index th:hover { background: #eee; }
+@media (prefers-color-scheme: dark) { #index th:hover { background: #333; } }
+#index th.headerSortDown, #index th.headerSortUp { white-space: nowrap; background: #eee; }
+@media (prefers-color-scheme: dark) { #index th.headerSortDown, #index th.headerSortUp { background: #333; } }
#index th.headerSortDown:after { content: " ↓"; }
#index th.headerSortUp:after { content: " ↑"; }
-#index td.name a { text-decoration: none; color: #000; }
+#index td.name a { text-decoration: none; color: inherit; }
#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; }
-#index tr.file:hover { background: #eeeeee; }
-#index tr.file:hover td.name { text-decoration: underline; color: #000; }
-
-#scroll_marker { position: fixed; right: 0; top: 0; width: 16px; height: 100%; background: white; border-left: 1px solid #eee; will-change: transform; }
-#scroll_marker .marker { background: #ddd; position: absolute; min-height: 3px; width: 100%; }
+#index tr.file:hover { background: #eee; }
+@media (prefers-color-scheme: dark) { #index tr.file:hover { background: #333; } }
+#index tr.file:hover td.name { text-decoration: underline; color: inherit; }
+
+#scroll_marker { position: fixed; right: 0; top: 0; width: 16px; height: 100%; background: #fff; border-left: 1px solid #eee; will-change: transform; }
+@media (prefers-color-scheme: dark) { #scroll_marker { background: #1e1e1e; } }
+@media (prefers-color-scheme: dark) { #scroll_marker { border-color: #333; } }
+#scroll_marker .marker { background: #ccc; position: absolute; min-height: 3px; width: 100%; }
+@media (prefers-color-scheme: dark) { #scroll_marker .marker { background: #444; } }
diff --git a/tests/gold/html/unicode/unicode_py.html b/tests/gold/html/unicode/unicode_py.html
index 46722961..a4218bcc 100644
--- a/tests/gold/html/unicode/unicode_py.html
+++ b/tests/gold/html/unicode/unicode_py.html
@@ -22,9 +22,9 @@
<img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
<h2 class="stats">
2 statements &nbsp;
- <span class="run shortkey_r button_toggle_run">2 run</span>
- <span class="mis show_mis shortkey_m button_toggle_mis">0 missing</span>
- <span class="exc show_exc shortkey_x button_toggle_exc">0 excluded</span>
+ <button type="button" class="run shortkey_r button_toggle_run" title="Toggle lines run">2 run</button>
+ <button type="button" class="mis show_mis shortkey_m button_toggle_mis" title="Toggle lines missing">0 missing</button>
+ <button type="button" class="exc show_exc shortkey_x button_toggle_exc" title="Toggle lines excluded">0 excluded</button>
</h2>
</div>
</div>
diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py
index f5e8e96a..2406d93d 100644
--- a/tests/test_cmdline.py
+++ b/tests/test_cmdline.py
@@ -37,11 +37,11 @@ class BaseCmdLineTest(CoverageTest):
_defaults.Coverage().html_report(
directory=None, ignore_errors=None, include=None, omit=None, morfs=[],
skip_covered=None, show_contexts=None, title=None, contexts=None,
- skip_empty=None,
+ skip_empty=None, precision=None,
)
_defaults.Coverage().report(
ignore_errors=None, include=None, omit=None, morfs=[],
- show_missing=None, skip_covered=None, contexts=None, skip_empty=None,
+ show_missing=None, skip_covered=None, contexts=None, skip_empty=None, precision=None,
)
_defaults.Coverage().xml_report(
ignore_errors=None, include=None, omit=None, morfs=[], outfile=None,
@@ -49,7 +49,7 @@ class BaseCmdLineTest(CoverageTest):
)
_defaults.Coverage().json_report(
ignore_errors=None, include=None, omit=None, morfs=[], outfile=None,
- contexts=None, pretty_print=None, show_contexts=None
+ contexts=None, pretty_print=None, show_contexts=None,
)
_defaults.Coverage(
cover_pylib=None, data_suffix=None, timid=None, branch=None,
@@ -324,6 +324,11 @@ class CmdLineTest(BaseCmdLineTest):
cov.load()
cov.html_report(morfs=["mod1", "mod2", "mod3"])
""")
+ self.cmd_executes("html --precision=3", """\
+ cov = Coverage()
+ cov.load()
+ cov.html_report(precision=3)
+ """)
self.cmd_executes("html --title=Hello_there", """\
cov = Coverage()
cov.load()
@@ -367,6 +372,11 @@ class CmdLineTest(BaseCmdLineTest):
cov.load()
cov.report(morfs=["mod1", "mod2", "mod3"])
""")
+ self.cmd_executes("report --precision=7", """\
+ cov = Coverage()
+ cov.load()
+ cov.report(precision=7)
+ """)
self.cmd_executes("report --skip-covered", """\
cov = Coverage()
cov.load()
@@ -781,7 +791,7 @@ class CmdLineStdoutTest(BaseCmdLineTest):
def test_minimum_help(self):
self.command_line("")
out = self.stdout()
- self.assertIn("Code coverage for Python.", out)
+ self.assertIn("Code coverage for Python", out)
self.assertLess(out.count("\n"), 4)
def test_version(self):
diff --git a/tests/test_config.py b/tests/test_config.py
index 51d9b9ef..89ecb17c 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -3,6 +3,7 @@
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
"""Test the config file handling for coverage.py"""
+
from collections import OrderedDict
import mock
@@ -62,6 +63,8 @@ class ConfigTest(CoverageTest):
# A .coveragerc file will be read into the configuration.
self.make_file("pyproject.toml", """\
# This is just a bogus toml file for testing.
+ [tool.somethingelse]
+ authors = ["Joe D'Ávila <joe@gmail.com>"]
[tool.coverage.run]
concurrency = ["a", "b"]
timid = true
@@ -70,20 +73,23 @@ class ConfigTest(CoverageTest):
[tool.coverage.report]
precision = 3
fail_under = 90.5
+ [tool.coverage.html]
+ title = "tabblo & «ταБЬℓσ»"
[tool.coverage.plugins.a_plugin]
hello = "world"
""")
cov = coverage.Coverage(config_file="pyproject.toml")
self.assertTrue(cov.config.timid)
self.assertFalse(cov.config.branch)
- self.assertEqual(cov.config.concurrency, ["a", "b"])
- self.assertEqual(cov.config.data_file, ".hello_kitty.data")
- self.assertEqual(cov.config.plugins, ["plugins.a_plugin"])
+ self.assertEqual(cov.config.concurrency, [u"a", u"b"])
+ self.assertEqual(cov.config.data_file, u".hello_kitty.data")
+ self.assertEqual(cov.config.plugins, [u"plugins.a_plugin"])
self.assertEqual(cov.config.precision, 3)
+ self.assertEqual(cov.config.html_title, u"tabblo & «ταБЬℓσ»")
self.assertAlmostEqual(cov.config.fail_under, 90.5)
self.assertEqual(
cov.config.get_plugin_options("plugins.a_plugin"),
- {'hello': 'world'}
+ {u"hello": u"world"}
)
# Test that our class doesn't reject integers when loading floats
diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py
index 6f38fc94..1256694a 100644
--- a/tests/test_phystokens.py
+++ b/tests/test_phystokens.py
@@ -285,5 +285,5 @@ class CompileUnicodeTest(CoverageTest):
def test_double_coding_declaration(self):
# Build this string in a weird way so that actual vim's won't try to
# interpret it...
- uni = u"# -*- coding:utf-8 -*-\n# v" "im: fileencoding=utf-8\n"
+ uni = u"# -*- coding:utf-8 -*-\n# v" + "im: fileencoding=utf-8\n"
self.assert_compile_unicode(uni)
diff --git a/tox.ini b/tox.ini
index 57c4d4bc..fbdc2132 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,8 +14,8 @@ extras =
deps =
# Check here for what might be out of date:
# https://requires.io/github/nedbat/coveragepy/requirements/
+ -r requirements/pip.pip
-r requirements/pytest.pip
- pip==20.0.2
setuptools==41.4.0
# gevent 1.3 causes a failure: https://github.com/nedbat/coveragepy/issues/663
py{27,35,36}: gevent==1.2.2