Skip to content

Commit

Permalink
fix: cache busting on HTML report support files
Browse files Browse the repository at this point in the history
  • Loading branch information
nedbat committed Apr 24, 2024
1 parent 0c60b8f commit 63a8a75
Show file tree
Hide file tree
Showing 77 changed files with 660 additions and 625 deletions.
4 changes: 3 additions & 1 deletion CHANGES.rst
Expand Up @@ -23,7 +23,9 @@ upgrading your version of coverage.py.
Unreleased
----------

Nothing yet.
- Support files (JavaScript and CSS) referenced by the HTML report now have
hashes added to their names to ensure updated files are used instead of stale
cached copies.


.. scriv-start-here
Expand Down
48 changes: 29 additions & 19 deletions coverage/html.py
Expand Up @@ -12,7 +12,6 @@
import json
import os
import re
import shutil
import string

from dataclasses import dataclass, field
Expand Down Expand Up @@ -238,11 +237,7 @@ def __init__(self, cov: Coverage) -> None:

title = self.config.html_title

self.extra_css: str | None
if self.config.extra_css:
self.extra_css = os.path.basename(self.config.extra_css)
else:
self.extra_css = None
self.extra_css = bool(self.config.extra_css)

self.data = self.coverage.get_data()
self.has_arcs = self.data.has_arcs()
Expand Down Expand Up @@ -270,6 +265,7 @@ def __init__(self, cov: Coverage) -> None:
"extra_css": self.extra_css,
"has_arcs": self.has_arcs,
"show_contexts": self.config.show_contexts,
"statics": {},

# Constants for all reports.
# These css classes determine which lines are highlighted by default.
Expand Down Expand Up @@ -323,6 +319,9 @@ def report(self, morfs: Iterable[TMorf] | None) -> float:
if not have_data:
raise NoDataError("No data to report.")

self.make_directory()
self.make_local_static_report_files()

if files_to_report:
for ftr1, ftr2 in zip(files_to_report[:-1], files_to_report[1:]):
ftr1.next_html = ftr2.html_filename
Expand All @@ -347,7 +346,6 @@ def report(self, morfs: Iterable[TMorf] | None) -> float:
# Write function and class index pages.
self.write_region_index_pages(files_to_report)

self.make_local_static_report_files()
return (
self.index_pages["file"].totals.n_statements
and self.index_pages["file"].totals.pc_covered
Expand All @@ -359,24 +357,40 @@ def make_directory(self) -> None:
if not os.listdir(self.directory):
self.directory_was_empty = True

def copy_static_file(self, src: str, slug: str = "") -> None:
"""Copy a static file into the output directory with cache busting."""
with open(src, "rb") as f:
text = f.read()
h = Hasher()
h.update(text)
cache_bust = h.hexdigest()[:8]
src_base = os.path.basename(src)
dest = src_base.replace(".", f"_cb_{cache_bust}.")
if not slug:
slug = src_base.replace(".", "_")
self.template_globals["statics"][slug] = dest # type: ignore
with open(os.path.join(self.directory, dest), "wb") as f:
f.write(text)

def make_local_static_report_files(self) -> None:
"""Make local instances of static files for HTML report."""

# The files we provide must always be copied.
for static in self.STATIC_FILES:
shutil.copyfile(data_filename(static), os.path.join(self.directory, static))
self.copy_static_file(data_filename(static))

# The user may have extra CSS they want copied.
if self.extra_css:
assert self.config.extra_css is not None
self.copy_static_file(self.config.extra_css, slug="extra_css")

# Only write the .gitignore file if the directory was originally empty.
# .gitignore can't be copied from the source tree because it would
# prevent the static files from being checked in.
# .gitignore can't be copied from the source tree because if it was in
# the source tree, it would stop the static files from being checked in.
if self.directory_was_empty:
with open(os.path.join(self.directory, ".gitignore"), "w") as fgi:
fgi.write("# Created by coverage.py\n*\n")

# The user may have extra CSS they want copied.
if self.extra_css:
assert self.config.extra_css is not None
shutil.copyfile(self.config.extra_css, os.path.join(self.directory, self.extra_css))

def should_report(self, analysis: Analysis, index_page: IndexPage) -> bool:
"""Determine if we'll report this file or region."""
# Get the numbers for this file.
Expand Down Expand Up @@ -407,8 +421,6 @@ def write_html_page(self, ftr: FileToReport) -> None:
only does page summary bookkeeping.
"""
self.make_directory()

# Find out if the page on disk is already correct.
if self.incr.can_skip_file(self.data, ftr.fr, ftr.rootname):
self.index_pages["file"].summaries.append(self.incr.index_info(ftr.rootname))
Expand Down Expand Up @@ -501,8 +513,6 @@ def write_html_page(self, ftr: FileToReport) -> None:

def write_file_index_page(self, first_html: str, final_html: str) -> None:
"""Write the file index page for this report."""
self.make_directory()

index_file = self.write_index_page(
self.index_pages["file"],
first_html=first_html,
Expand Down
10 changes: 5 additions & 5 deletions coverage/htmlfiles/index.html
Expand Up @@ -6,12 +6,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{ title|escape }}</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="icon" sizes="32x32" href="{{ statics.favicon_32_png }}">
<link rel="stylesheet" href="{{ statics.style_css }}" type="text/css">
{% if extra_css %}
<link rel="stylesheet" href="{{ extra_css }}" type="text/css">
<link rel="stylesheet" href="{{ statics.extra_css }}" type="text/css">
{% endif %}
<script src="coverage_html.js" defer></script>
<script src="{{ statics.coverage_html_js }}" defer></script>
</head>
<body class="indexfile">

Expand All @@ -24,7 +24,7 @@ <h1>{{ title|escape }}:
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="{{ statics.keybd_closed_png }}" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down
10 changes: 5 additions & 5 deletions coverage/htmlfiles/pyfile.html
Expand Up @@ -6,10 +6,10 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for {{relative_filename|escape}}: {{nums.pc_covered_str}}%</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="icon" sizes="32x32" href="{{ statics.favicon_32_png }}">
<link rel="stylesheet" href="{{ statics.style_css }}" type="text/css">
{% if extra_css %}
<link rel="stylesheet" href="{{ extra_css }}" type="text/css">
<link rel="stylesheet" href="{{ statics.extra_css }}" type="text/css">
{% endif %}

{% if contexts_json %}
Expand All @@ -18,7 +18,7 @@
</script>
{% endif %}

<script src="coverage_html.js" defer></script>
<script src="{{ statics.coverage_html_js }}" defer></script>
</head>
<body class="pyfile">

Expand All @@ -32,7 +32,7 @@ <h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="{{ statics.keybd_closed_png }}" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down
16 changes: 8 additions & 8 deletions tests/gold/html/a/a_py.html
Expand Up @@ -3,9 +3,9 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage for a.py: 67%</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<script src="coverage_html.js" defer></script>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_606408f0.js" defer></script>
</head>
<body class="pyfile">
<header>
Expand All @@ -17,7 +17,7 @@ <h1>
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down Expand Up @@ -64,8 +64,8 @@ <h2>
<a id="indexLink" class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a id="nextFileLink" class="nav" href="index.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
<aside class="hidden">
<button type="button" class="button_next_chunk" data-shortcut="j"></button>
Expand Down Expand Up @@ -93,8 +93,8 @@ <h2>
<a class="nav" href="index.html">&Hat; index</a> &nbsp; &nbsp;
<a class="nav" href="index.html">&#xbb; next</a>
&nbsp; &nbsp; &nbsp;
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
</footer>
Expand Down
16 changes: 8 additions & 8 deletions tests/gold/html/a/class_index.html
Expand Up @@ -3,9 +3,9 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage report</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<script src="coverage_html.js" defer></script>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_606408f0.js" defer></script>
</head>
<body class="indexfile">
<header>
Expand All @@ -16,7 +16,7 @@ <h1>Coverage report:
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down Expand Up @@ -54,8 +54,8 @@ <h2>
<a class="button current">Classes</a>
</h2>
<p class="text">
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
</header>
Expand Down Expand Up @@ -99,8 +99,8 @@ <h2>
<footer>
<div class="content">
<p>
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
<aside class="hidden">
Expand Down
16 changes: 8 additions & 8 deletions tests/gold/html/a/function_index.html
Expand Up @@ -3,9 +3,9 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage report</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<script src="coverage_html.js" defer></script>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_606408f0.js" defer></script>
</head>
<body class="indexfile">
<header>
Expand All @@ -16,7 +16,7 @@ <h1>Coverage report:
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down Expand Up @@ -54,8 +54,8 @@ <h2>
<a class="button" href="class_index.html">Classes</a>
</h2>
<p class="text">
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
</header>
Expand Down Expand Up @@ -99,8 +99,8 @@ <h2>
<footer>
<div class="content">
<p>
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
<aside class="hidden">
Expand Down
16 changes: 8 additions & 8 deletions tests/gold/html/a/index.html
Expand Up @@ -3,9 +3,9 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Coverage report</title>
<link rel="icon" sizes="32x32" href="favicon_32.png">
<link rel="stylesheet" href="style.css" type="text/css">
<script src="coverage_html.js" defer></script>
<link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
<link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
<script src="coverage_html_cb_606408f0.js" defer></script>
</head>
<body class="indexfile">
<header>
Expand All @@ -16,7 +16,7 @@ <h1>Coverage report:
<aside id="help_panel_wrapper">
<input id="help_panel_state" type="checkbox">
<label for="help_panel_state">
<img id="keyboard_icon" src="keybd_closed.png" alt="Show/hide keyboard shortcuts">
<img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
</label>
<div id="help_panel">
<p class="legend">Shortcuts on this page</p>
Expand Down Expand Up @@ -53,8 +53,8 @@ <h2>
<a class="button" href="class_index.html">Classes</a>
</h2>
<p class="text">
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
</header>
Expand Down Expand Up @@ -95,8 +95,8 @@ <h2>
<footer>
<div class="content">
<p>
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.0a1.dev1">coverage.py v7.5.0a1.dev1</a>,
created at 2024-04-21 10:39 -0400
<a class="nav" href="https://coverage.readthedocs.io/en/7.5.1a0.dev1">coverage.py v7.5.1a0.dev1</a>,
created at 2024-04-24 09:22 -0400
</p>
</div>
<aside class="hidden">
Expand Down

0 comments on commit 63a8a75

Please sign in to comment.