mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-06 20:16:53 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
72ad6dc953
commit
f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions
|
|
@ -1,8 +1,6 @@
|
|||
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
||||
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
|
||||
|
||||
"""HTML reporting for coverage.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import collections
|
||||
|
|
@ -13,20 +11,31 @@ import os
|
|||
import re
|
||||
import shutil
|
||||
import string
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterable, TYPE_CHECKING, cast
|
||||
from typing import Any
|
||||
from typing import cast
|
||||
from typing import Iterable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import coverage
|
||||
from coverage.data import CoverageData, add_data_to_hash
|
||||
from coverage.data import add_data_to_hash
|
||||
from coverage.data import CoverageData
|
||||
from coverage.exceptions import NoDataError
|
||||
from coverage.files import flat_rootname
|
||||
from coverage.misc import ensure_dir, file_be_gone, Hasher, isolate_module, format_local_datetime
|
||||
from coverage.misc import human_sorted, plural, stdout_link
|
||||
from coverage.misc import ensure_dir
|
||||
from coverage.misc import file_be_gone
|
||||
from coverage.misc import format_local_datetime
|
||||
from coverage.misc import Hasher
|
||||
from coverage.misc import human_sorted
|
||||
from coverage.misc import isolate_module
|
||||
from coverage.misc import plural
|
||||
from coverage.misc import stdout_link
|
||||
from coverage.report_core import get_analysis_to_report
|
||||
from coverage.results import Analysis, Numbers
|
||||
from coverage.results import Analysis
|
||||
from coverage.results import Numbers
|
||||
from coverage.templite import Templite
|
||||
from coverage.types import TLineNo, TMorf
|
||||
from coverage.types import TLineNo
|
||||
from coverage.types import TMorf
|
||||
from coverage.version import __url__
|
||||
|
||||
|
||||
|
|
@ -56,7 +65,7 @@ os = isolate_module(os)
|
|||
def data_filename(fname: str) -> str:
|
||||
"""Return the path to an "htmlfiles" data file of ours.
|
||||
"""
|
||||
static_dir = os.path.join(os.path.dirname(__file__), "htmlfiles")
|
||||
static_dir = os.path.join(os.path.dirname(__file__), 'htmlfiles')
|
||||
static_filename = os.path.join(static_dir, fname)
|
||||
return static_filename
|
||||
|
||||
|
|
@ -69,9 +78,9 @@ def read_data(fname: str) -> str:
|
|||
|
||||
def write_html(fname: str, html: str) -> None:
|
||||
"""Write `html` to `fname`, properly encoded."""
|
||||
html = re.sub(r"(\A\s+)|(\s+$)", "", html, flags=re.MULTILINE) + "\n"
|
||||
with open(fname, "wb") as fout:
|
||||
fout.write(html.encode("ascii", "xmlcharrefreplace"))
|
||||
html = re.sub(r'(\A\s+)|(\s+$)', '', html, flags=re.MULTILINE) + '\n'
|
||||
with open(fname, 'wb') as fout:
|
||||
fout.write(html.encode('ascii', 'xmlcharrefreplace'))
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -86,11 +95,11 @@ class LineData:
|
|||
context_list: list[str]
|
||||
short_annotations: list[str]
|
||||
long_annotations: list[str]
|
||||
html: str = ""
|
||||
html: str = ''
|
||||
context_str: str | None = None
|
||||
annotate: str | None = None
|
||||
annotate_long: str | None = None
|
||||
css_class: str = ""
|
||||
css_class: str = ''
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -104,7 +113,7 @@ class FileData:
|
|||
class HtmlDataGeneration:
|
||||
"""Generate structured data to be turned into HTML reports."""
|
||||
|
||||
EMPTY = "(empty)"
|
||||
EMPTY = '(empty)'
|
||||
|
||||
def __init__(self, cov: Coverage) -> None:
|
||||
self.coverage = cov
|
||||
|
|
@ -112,8 +121,8 @@ class HtmlDataGeneration:
|
|||
data = self.coverage.get_data()
|
||||
self.has_arcs = data.has_arcs()
|
||||
if self.config.show_contexts:
|
||||
if data.measured_contexts() == {""}:
|
||||
self.coverage._warn("No contexts were measured")
|
||||
if data.measured_contexts() == {''}:
|
||||
self.coverage._warn('No contexts were measured')
|
||||
data.set_query_contexts(self.config.report_contexts)
|
||||
|
||||
def data_for_file(self, fr: FileReporter, analysis: Analysis) -> FileData:
|
||||
|
|
@ -129,47 +138,49 @@ class HtmlDataGeneration:
|
|||
|
||||
for lineno, tokens in enumerate(fr.source_token_lines(), start=1):
|
||||
# Figure out how to mark this line.
|
||||
category = ""
|
||||
category = ''
|
||||
short_annotations = []
|
||||
long_annotations = []
|
||||
|
||||
if lineno in analysis.excluded:
|
||||
category = "exc"
|
||||
category = 'exc'
|
||||
elif lineno in analysis.missing:
|
||||
category = "mis"
|
||||
category = 'mis'
|
||||
elif self.has_arcs and lineno in missing_branch_arcs:
|
||||
category = "par"
|
||||
category = 'par'
|
||||
for b in missing_branch_arcs[lineno]:
|
||||
if b < 0:
|
||||
short_annotations.append("exit")
|
||||
short_annotations.append('exit')
|
||||
else:
|
||||
short_annotations.append(str(b))
|
||||
long_annotations.append(fr.missing_arc_description(lineno, b, arcs_executed))
|
||||
elif lineno in analysis.statements:
|
||||
category = "run"
|
||||
category = 'run'
|
||||
|
||||
contexts = []
|
||||
contexts_label = ""
|
||||
contexts_label = ''
|
||||
context_list = []
|
||||
if category and self.config.show_contexts:
|
||||
contexts = human_sorted(c or self.EMPTY for c in contexts_by_lineno.get(lineno, ()))
|
||||
if contexts == [self.EMPTY]:
|
||||
contexts_label = self.EMPTY
|
||||
else:
|
||||
contexts_label = f"{len(contexts)} ctx"
|
||||
contexts_label = f'{len(contexts)} ctx'
|
||||
context_list = contexts
|
||||
|
||||
lines.append(LineData(
|
||||
tokens=tokens,
|
||||
number=lineno,
|
||||
category=category,
|
||||
statement=(lineno in analysis.statements),
|
||||
contexts=contexts,
|
||||
contexts_label=contexts_label,
|
||||
context_list=context_list,
|
||||
short_annotations=short_annotations,
|
||||
long_annotations=long_annotations,
|
||||
))
|
||||
lines.append(
|
||||
LineData(
|
||||
tokens=tokens,
|
||||
number=lineno,
|
||||
category=category,
|
||||
statement=(lineno in analysis.statements),
|
||||
contexts=contexts,
|
||||
contexts_label=contexts_label,
|
||||
context_list=context_list,
|
||||
short_annotations=short_annotations,
|
||||
long_annotations=long_annotations,
|
||||
),
|
||||
)
|
||||
|
||||
file_data = FileData(
|
||||
relative_filename=fr.relative_filename(),
|
||||
|
|
@ -182,15 +193,17 @@ class HtmlDataGeneration:
|
|||
|
||||
class FileToReport:
|
||||
"""A file we're considering reporting."""
|
||||
|
||||
def __init__(self, fr: FileReporter, analysis: Analysis) -> None:
|
||||
self.fr = fr
|
||||
self.analysis = analysis
|
||||
self.rootname = flat_rootname(fr.relative_filename())
|
||||
self.html_filename = self.rootname + ".html"
|
||||
self.html_filename = self.rootname + '.html'
|
||||
|
||||
|
||||
HTML_SAFE = string.ascii_letters + string.digits + "!#$%'()*+,-./:;=?@[]^_`{|}~"
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
def encode_int(n: int) -> str:
|
||||
"""Create a short HTML-safe string from an integer, using HTML_SAFE."""
|
||||
|
|
@ -201,7 +214,7 @@ def encode_int(n: int) -> str:
|
|||
while n:
|
||||
n, t = divmod(n, len(HTML_SAFE))
|
||||
r.append(HTML_SAFE[t])
|
||||
return "".join(r)
|
||||
return ''.join(r)
|
||||
|
||||
|
||||
class HtmlReporter:
|
||||
|
|
@ -210,11 +223,11 @@ class HtmlReporter:
|
|||
# These files will be copied from the htmlfiles directory to the output
|
||||
# directory.
|
||||
STATIC_FILES = [
|
||||
"style.css",
|
||||
"coverage_html.js",
|
||||
"keybd_closed.png",
|
||||
"keybd_open.png",
|
||||
"favicon_32.png",
|
||||
'style.css',
|
||||
'coverage_html.js',
|
||||
'keybd_closed.png',
|
||||
'keybd_open.png',
|
||||
'favicon_32.png',
|
||||
]
|
||||
|
||||
def __init__(self, cov: Coverage) -> None:
|
||||
|
|
@ -253,29 +266,29 @@ class HtmlReporter:
|
|||
|
||||
self.template_globals = {
|
||||
# Functions available in the templates.
|
||||
"escape": escape,
|
||||
"pair": pair,
|
||||
"len": len,
|
||||
'escape': escape,
|
||||
'pair': pair,
|
||||
'len': len,
|
||||
|
||||
# Constants for this report.
|
||||
"__url__": __url__,
|
||||
"__version__": coverage.__version__,
|
||||
"title": title,
|
||||
"time_stamp": format_local_datetime(datetime.datetime.now()),
|
||||
"extra_css": self.extra_css,
|
||||
"has_arcs": self.has_arcs,
|
||||
"show_contexts": self.config.show_contexts,
|
||||
'__url__': __url__,
|
||||
'__version__': coverage.__version__,
|
||||
'title': title,
|
||||
'time_stamp': format_local_datetime(datetime.datetime.now()),
|
||||
'extra_css': self.extra_css,
|
||||
'has_arcs': self.has_arcs,
|
||||
'show_contexts': self.config.show_contexts,
|
||||
|
||||
# Constants for all reports.
|
||||
# These css classes determine which lines are highlighted by default.
|
||||
"category": {
|
||||
"exc": "exc show_exc",
|
||||
"mis": "mis show_mis",
|
||||
"par": "par run show_par",
|
||||
"run": "run",
|
||||
'category': {
|
||||
'exc': 'exc show_exc',
|
||||
'mis': 'mis show_mis',
|
||||
'par': 'par run show_par',
|
||||
'run': 'run',
|
||||
},
|
||||
}
|
||||
self.pyfile_html_source = read_data("pyfile.html")
|
||||
self.pyfile_html_source = read_data('pyfile.html')
|
||||
self.source_tmpl = Templite(self.pyfile_html_source, self.template_globals)
|
||||
|
||||
def report(self, morfs: Iterable[TMorf] | None) -> float:
|
||||
|
|
@ -303,17 +316,17 @@ class HtmlReporter:
|
|||
|
||||
for i, ftr in enumerate(files_to_report):
|
||||
if i == 0:
|
||||
prev_html = "index.html"
|
||||
prev_html = 'index.html'
|
||||
else:
|
||||
prev_html = files_to_report[i - 1].html_filename
|
||||
if i == len(files_to_report) - 1:
|
||||
next_html = "index.html"
|
||||
next_html = 'index.html'
|
||||
else:
|
||||
next_html = files_to_report[i + 1].html_filename
|
||||
self.write_html_file(ftr, prev_html, next_html)
|
||||
|
||||
if not self.all_files_nums:
|
||||
raise NoDataError("No data to report.")
|
||||
raise NoDataError('No data to report.')
|
||||
|
||||
self.totals = cast(Numbers, sum(self.all_files_nums))
|
||||
|
||||
|
|
@ -322,7 +335,7 @@ class HtmlReporter:
|
|||
first_html = files_to_report[0].html_filename
|
||||
final_html = files_to_report[-1].html_filename
|
||||
else:
|
||||
first_html = final_html = "index.html"
|
||||
first_html = final_html = 'index.html'
|
||||
self.index_file(first_html, final_html)
|
||||
|
||||
self.make_local_static_report_files()
|
||||
|
|
@ -344,8 +357,8 @@ class HtmlReporter:
|
|||
# .gitignore can't be copied from the source tree because it would
|
||||
# prevent 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")
|
||||
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:
|
||||
|
|
@ -401,29 +414,29 @@ class HtmlReporter:
|
|||
# Build the HTML for the line.
|
||||
html_parts = []
|
||||
for tok_type, tok_text in ldata.tokens:
|
||||
if tok_type == "ws":
|
||||
if tok_type == 'ws':
|
||||
html_parts.append(escape(tok_text))
|
||||
else:
|
||||
tok_html = escape(tok_text) or " "
|
||||
tok_html = escape(tok_text) or ' '
|
||||
html_parts.append(f'<span class="{tok_type}">{tok_html}</span>')
|
||||
ldata.html = "".join(html_parts)
|
||||
ldata.html = ''.join(html_parts)
|
||||
if ldata.context_list:
|
||||
encoded_contexts = [
|
||||
encode_int(context_codes[c_context]) for c_context in ldata.context_list
|
||||
]
|
||||
code_width = max(len(ec) for ec in encoded_contexts)
|
||||
ldata.context_str = (
|
||||
str(code_width)
|
||||
+ "".join(ec.ljust(code_width) for ec in encoded_contexts)
|
||||
str(code_width) +
|
||||
''.join(ec.ljust(code_width) for ec in encoded_contexts)
|
||||
)
|
||||
else:
|
||||
ldata.context_str = ""
|
||||
ldata.context_str = ''
|
||||
|
||||
if ldata.short_annotations:
|
||||
# 202F is NARROW NO-BREAK SPACE.
|
||||
# 219B is RIGHTWARDS ARROW WITH STROKE.
|
||||
ldata.annotate = ", ".join(
|
||||
f"{ldata.number} ↛ {d}"
|
||||
ldata.annotate = ', '.join(
|
||||
f'{ldata.number} ↛ {d}'
|
||||
for d in ldata.short_annotations
|
||||
)
|
||||
else:
|
||||
|
|
@ -434,10 +447,10 @@ class HtmlReporter:
|
|||
if len(longs) == 1:
|
||||
ldata.annotate_long = longs[0]
|
||||
else:
|
||||
ldata.annotate_long = "{:d} missed branches: {}".format(
|
||||
ldata.annotate_long = '{:d} missed branches: {}'.format(
|
||||
len(longs),
|
||||
", ".join(
|
||||
f"{num:d}) {ann_long}"
|
||||
', '.join(
|
||||
f'{num:d}) {ann_long}'
|
||||
for num, ann_long in enumerate(longs, start=1)
|
||||
),
|
||||
)
|
||||
|
|
@ -447,24 +460,24 @@ class HtmlReporter:
|
|||
css_classes = []
|
||||
if ldata.category:
|
||||
css_classes.append(
|
||||
self.template_globals["category"][ldata.category], # type: ignore[index]
|
||||
self.template_globals['category'][ldata.category], # type: ignore[index]
|
||||
)
|
||||
ldata.css_class = " ".join(css_classes) or "pln"
|
||||
ldata.css_class = ' '.join(css_classes) or 'pln'
|
||||
|
||||
html_path = os.path.join(self.directory, ftr.html_filename)
|
||||
html = self.source_tmpl.render({
|
||||
**file_data.__dict__,
|
||||
"contexts_json": contexts_json,
|
||||
"prev_html": prev_html,
|
||||
"next_html": next_html,
|
||||
'contexts_json': contexts_json,
|
||||
'prev_html': prev_html,
|
||||
'next_html': next_html,
|
||||
})
|
||||
write_html(html_path, html)
|
||||
|
||||
# Save this file's information for the index file.
|
||||
index_info: IndexInfoDict = {
|
||||
"nums": ftr.analysis.numbers,
|
||||
"html_filename": ftr.html_filename,
|
||||
"relative_filename": ftr.fr.relative_filename(),
|
||||
'nums': ftr.analysis.numbers,
|
||||
'html_filename': ftr.html_filename,
|
||||
'relative_filename': ftr.fr.relative_filename(),
|
||||
}
|
||||
self.file_summaries.append(index_info)
|
||||
self.incr.set_index_info(ftr.rootname, index_info)
|
||||
|
|
@ -472,30 +485,30 @@ class HtmlReporter:
|
|||
def index_file(self, first_html: str, final_html: str) -> None:
|
||||
"""Write the index.html file for this report."""
|
||||
self.make_directory()
|
||||
index_tmpl = Templite(read_data("index.html"), self.template_globals)
|
||||
index_tmpl = Templite(read_data('index.html'), self.template_globals)
|
||||
|
||||
skipped_covered_msg = skipped_empty_msg = ""
|
||||
skipped_covered_msg = skipped_empty_msg = ''
|
||||
if self.skipped_covered_count:
|
||||
n = self.skipped_covered_count
|
||||
skipped_covered_msg = f"{n} file{plural(n)} skipped due to complete coverage."
|
||||
skipped_covered_msg = f'{n} file{plural(n)} skipped due to complete coverage.'
|
||||
if self.skipped_empty_count:
|
||||
n = self.skipped_empty_count
|
||||
skipped_empty_msg = f"{n} empty file{plural(n)} skipped."
|
||||
skipped_empty_msg = f'{n} empty file{plural(n)} skipped.'
|
||||
|
||||
html = index_tmpl.render({
|
||||
"files": self.file_summaries,
|
||||
"totals": self.totals,
|
||||
"skipped_covered_msg": skipped_covered_msg,
|
||||
"skipped_empty_msg": skipped_empty_msg,
|
||||
"first_html": first_html,
|
||||
"final_html": final_html,
|
||||
'files': self.file_summaries,
|
||||
'totals': self.totals,
|
||||
'skipped_covered_msg': skipped_covered_msg,
|
||||
'skipped_empty_msg': skipped_empty_msg,
|
||||
'first_html': first_html,
|
||||
'final_html': final_html,
|
||||
})
|
||||
|
||||
index_file = os.path.join(self.directory, "index.html")
|
||||
index_file = os.path.join(self.directory, 'index.html')
|
||||
write_html(index_file, html)
|
||||
|
||||
print_href = stdout_link(index_file, f"file://{os.path.abspath(index_file)}")
|
||||
self.coverage._message(f"Wrote HTML report to {print_href}")
|
||||
print_href = stdout_link(index_file, f'file://{os.path.abspath(index_file)}')
|
||||
self.coverage._message(f'Wrote HTML report to {print_href}')
|
||||
|
||||
# Write the latest hashes for next time.
|
||||
self.incr.write()
|
||||
|
|
@ -504,12 +517,12 @@ class HtmlReporter:
|
|||
class IncrementalChecker:
|
||||
"""Logic and data to support incremental reporting."""
|
||||
|
||||
STATUS_FILE = "status.json"
|
||||
STATUS_FILE = 'status.json'
|
||||
STATUS_FORMAT = 2
|
||||
NOTE = (
|
||||
"This file is an internal implementation detail to speed up HTML report"
|
||||
+ " generation. Its format can change at any time. You might be looking"
|
||||
+ " for the JSON report: https://coverage.rtfd.io/cmd.html#cmd-json"
|
||||
'This file is an internal implementation detail to speed up HTML report' +
|
||||
' generation. Its format can change at any time. You might be looking' +
|
||||
' for the JSON report: https://coverage.rtfd.io/cmd.html#cmd-json'
|
||||
)
|
||||
|
||||
# The data looks like:
|
||||
|
|
@ -545,7 +558,7 @@ class IncrementalChecker:
|
|||
|
||||
def reset(self) -> None:
|
||||
"""Initialize to empty. Causes all files to be reported."""
|
||||
self.globals = ""
|
||||
self.globals = ''
|
||||
self.files: dict[str, FileInfoDict] = {}
|
||||
|
||||
def read(self) -> None:
|
||||
|
|
@ -559,17 +572,17 @@ class IncrementalChecker:
|
|||
usable = False
|
||||
else:
|
||||
usable = True
|
||||
if status["format"] != self.STATUS_FORMAT:
|
||||
if status['format'] != self.STATUS_FORMAT:
|
||||
usable = False
|
||||
elif status["version"] != coverage.__version__:
|
||||
elif status['version'] != coverage.__version__:
|
||||
usable = False
|
||||
|
||||
if usable:
|
||||
self.files = {}
|
||||
for filename, fileinfo in status["files"].items():
|
||||
fileinfo["index"]["nums"] = Numbers(*fileinfo["index"]["nums"])
|
||||
for filename, fileinfo in status['files'].items():
|
||||
fileinfo['index']['nums'] = Numbers(*fileinfo['index']['nums'])
|
||||
self.files[filename] = fileinfo
|
||||
self.globals = status["globals"]
|
||||
self.globals = status['globals']
|
||||
else:
|
||||
self.reset()
|
||||
|
||||
|
|
@ -578,19 +591,19 @@ class IncrementalChecker:
|
|||
status_file = os.path.join(self.directory, self.STATUS_FILE)
|
||||
files = {}
|
||||
for filename, fileinfo in self.files.items():
|
||||
index = fileinfo["index"]
|
||||
index["nums"] = index["nums"].init_args() # type: ignore[typeddict-item]
|
||||
index = fileinfo['index']
|
||||
index['nums'] = index['nums'].init_args() # type: ignore[typeddict-item]
|
||||
files[filename] = fileinfo
|
||||
|
||||
status = {
|
||||
"note": self.NOTE,
|
||||
"format": self.STATUS_FORMAT,
|
||||
"version": coverage.__version__,
|
||||
"globals": self.globals,
|
||||
"files": files,
|
||||
'note': self.NOTE,
|
||||
'format': self.STATUS_FORMAT,
|
||||
'version': coverage.__version__,
|
||||
'globals': self.globals,
|
||||
'files': files,
|
||||
}
|
||||
with open(status_file, "w") as fout:
|
||||
json.dump(status, fout, separators=(",", ":"))
|
||||
with open(status_file, 'w') as fout:
|
||||
json.dump(status, fout, separators=(',', ':'))
|
||||
|
||||
def check_global_data(self, *data: Any) -> None:
|
||||
"""Check the global data that can affect incremental reporting."""
|
||||
|
|
@ -609,7 +622,7 @@ class IncrementalChecker:
|
|||
`rootname` is the name being used for the file.
|
||||
"""
|
||||
m = Hasher()
|
||||
m.update(fr.source().encode("utf-8"))
|
||||
m.update(fr.source().encode('utf-8'))
|
||||
add_data_to_hash(data, fr.filename, m)
|
||||
this_hash = m.hexdigest()
|
||||
|
||||
|
|
@ -624,19 +637,19 @@ class IncrementalChecker:
|
|||
|
||||
def file_hash(self, fname: str) -> str:
|
||||
"""Get the hash of `fname`'s contents."""
|
||||
return self.files.get(fname, {}).get("hash", "") # type: ignore[call-overload]
|
||||
return self.files.get(fname, {}).get('hash', '') # type: ignore[call-overload]
|
||||
|
||||
def set_file_hash(self, fname: str, val: str) -> None:
|
||||
"""Set the hash of `fname`'s contents."""
|
||||
self.files.setdefault(fname, {})["hash"] = val # type: ignore[typeddict-item]
|
||||
self.files.setdefault(fname, {})['hash'] = val # type: ignore[typeddict-item]
|
||||
|
||||
def index_info(self, fname: str) -> IndexInfoDict:
|
||||
"""Get the information for index.html for `fname`."""
|
||||
return self.files.get(fname, {}).get("index", {}) # type: ignore
|
||||
return self.files.get(fname, {}).get('index', {}) # type: ignore
|
||||
|
||||
def set_index_info(self, fname: str, info: IndexInfoDict) -> None:
|
||||
"""Set the information for index.html for `fname`."""
|
||||
self.files.setdefault(fname, {})["index"] = info # type: ignore[typeddict-item]
|
||||
self.files.setdefault(fname, {})['index'] = info # type: ignore[typeddict-item]
|
||||
|
||||
|
||||
# Helpers for templates and generating HTML
|
||||
|
|
@ -648,9 +661,9 @@ def escape(t: str) -> str:
|
|||
|
||||
"""
|
||||
# Convert HTML special chars into HTML entities.
|
||||
return t.replace("&", "&").replace("<", "<")
|
||||
return t.replace('&', '&').replace('<', '<')
|
||||
|
||||
|
||||
def pair(ratio: tuple[int, int]) -> str:
|
||||
"""Format a pair of numbers so JavaScript can read them in an attribute."""
|
||||
return "{} {}".format(*ratio)
|
||||
return '{} {}'.format(*ratio)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue