🌐 AI搜索 & 代理 主页
Skip to content
Prev Previous commit
Next Next commit
Use quoute-style=preserve
  • Loading branch information
AA-Turner committed Jul 19, 2024
commit a599ef7a3b3c028bd720089c4a223fc77481ab90
2 changes: 1 addition & 1 deletion Doc/.ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ignore = [

[format]
preview = true
quote-style = "single"
quote-style = "preserve"
docstring-code-format = true
exclude = [
"tools/extensions/lexers/*",
Expand Down
4 changes: 2 additions & 2 deletions Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@
repository_url = repository_url.removesuffix('.git')
html_context = {
'is_deployment_preview': is_deployment_preview,
'repository_url': repository_url if repository_url else None,
'repository_url': repository_url or None,
'pr_id': os.getenv('READTHEDOCS_VERSION'),
'enable_analytics': os.getenv('PYTHON_DOCS_ENABLE_ANALYTICS'),
}
Expand Down Expand Up @@ -524,7 +524,7 @@
# The coverage checker will ignore all C items whose names match these regexes
# (using re.match) -- the keys must be the same as in coverage_c_regexes.
coverage_ignore_c_items = {
# 'cfunction': [...]
# 'cfunction': [...]
}


Expand Down
132 changes: 66 additions & 66 deletions Doc/tools/check-warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,66 +20,66 @@
# Exclude these whether they're dirty or clean,
# because they trigger a rebuild of dirty files.
EXCLUDE_FILES = {
'Doc/whatsnew/changelog.rst',
"Doc/whatsnew/changelog.rst",
}

# Subdirectories of Doc/ to exclude.
EXCLUDE_SUBDIRS = {
'.env',
'.venv',
'env',
'includes',
'venv',
".env",
".venv",
"env",
"includes",
"venv",
}

# Regex pattern to match the parts of a Sphinx warning
WARNING_PATTERN = re.compile(
r'(?P<file>([A-Za-z]:[\\/])?[^:]+):(?P<line>\d+): WARNING: (?P<msg>.+)'
r"(?P<file>([A-Za-z]:[\\/])?[^:]+):(?P<line>\d+): WARNING: (?P<msg>.+)"
)

# Regex pattern to match the line numbers in a Git unified diff
DIFF_PATTERN = re.compile(
r'^@@ -(?P<linea>\d+)(?:,(?P<removed>\d+))? \+(?P<lineb>\d+)(?:,(?P<added>\d+))? @@',
r"^@@ -(?P<linea>\d+)(?:,(?P<removed>\d+))? \+(?P<lineb>\d+)(?:,(?P<added>\d+))? @@",
flags=re.MULTILINE,
)


def get_diff_files(ref_a: str, ref_b: str, filter_mode: str = '') -> set[Path]:
def get_diff_files(ref_a: str, ref_b: str, filter_mode: str = "") -> set[Path]:
"""List the files changed between two Git refs, filtered by change type."""
added_files_result = subprocess.run(
[
'git',
'diff',
f'--diff-filter={filter_mode}',
'--name-only',
f'{ref_a}...{ref_b}',
'--',
"git",
"diff",
f"--diff-filter={filter_mode}",
"--name-only",
f"{ref_a}...{ref_b}",
"--",
],
stdout=subprocess.PIPE,
check=True,
text=True,
encoding='UTF-8',
encoding="UTF-8",
)

added_files = added_files_result.stdout.strip().split('\n')
added_files = added_files_result.stdout.strip().split("\n")
return {Path(file.strip()) for file in added_files if file.strip()}


def get_diff_lines(ref_a: str, ref_b: str, file: Path) -> list[int]:
"""List the lines changed between two Git refs for a specific file."""
diff_output = subprocess.run(
[
'git',
'diff',
'--unified=0',
f'{ref_a}...{ref_b}',
'--',
"git",
"diff",
"--unified=0",
f"{ref_a}...{ref_b}",
"--",
str(file),
],
stdout=subprocess.PIPE,
check=True,
text=True,
encoding='UTF-8',
encoding="UTF-8",
)

# Scrape line offsets + lengths from diff and convert to line numbers
Expand All @@ -89,7 +89,7 @@ def get_diff_lines(ref_a: str, ref_b: str, file: Path) -> list[int]:
line_match.groupdict(default=1) for line_match in line_matches
]
line_ints = [
(int(match_value['lineb']), int(match_value['added']))
(int(match_value["lineb"]), int(match_value["added"]))
for match_value in line_match_values
]
line_ranges = [
Expand Down Expand Up @@ -136,7 +136,7 @@ def filter_warnings_by_diff(
) -> list[re.Match[str]]:
"""Filter the passed per-file warnings to just those on changed lines."""
diff_lines = get_diff_lines(ref_a, ref_b, file)
with file.open(encoding='UTF-8') as file_obj:
with file.open(encoding="UTF-8") as file_obj:
paragraphs = get_para_line_numbers(file_obj)
touched_paras = [
para_lines
Expand All @@ -145,12 +145,12 @@ def filter_warnings_by_diff(
]
touched_para_lines = set(itertools.chain(*touched_paras))
warnings_infile = [
warning for warning in warnings if str(file) in warning['file']
warning for warning in warnings if str(file) in warning["file"]
]
warnings_touched = [
warning
for warning in warnings_infile
if int(warning['line']) in touched_para_lines
if int(warning["line"]) in touched_para_lines
]
return warnings_touched

Expand All @@ -160,7 +160,7 @@ def process_touched_warnings(
) -> list[re.Match[str]]:
"""Filter a list of Sphinx warnings to those affecting touched lines."""
added_files, modified_files = tuple(
get_diff_files(ref_a, ref_b, filter_mode=mode) for mode in ('A', 'M')
get_diff_files(ref_a, ref_b, filter_mode=mode) for mode in ("A", "M")
)

warnings_added = filter_and_parse_warnings(warnings, added_files)
Expand All @@ -169,7 +169,7 @@ def process_touched_warnings(
modified_files_warned = {
file
for file in modified_files
if any(str(file) in warning['file'] for warning in warnings_modified)
if any(str(file) in warning["file"] for warning in warnings_modified)
}

warnings_modified_touched = [
Expand All @@ -184,7 +184,7 @@ def process_touched_warnings(


def annotate_diff(
warnings: list[str], ref_a: str = 'main', ref_b: str = 'HEAD'
warnings: list[str], ref_a: str = "main", ref_b: str = "HEAD"
) -> None:
"""
Convert Sphinx warning messages to GitHub Actions for changed paragraphs.
Expand All @@ -198,12 +198,12 @@ def annotate_diff(
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message
"""
warnings_touched = process_touched_warnings(warnings, ref_a, ref_b)
print('Emitting doc warnings matching modified lines:')
print("Emitting doc warnings matching modified lines:")
for warning in warnings_touched:
print('::warning file={file},line={line}::{msg}'.format_map(warning))
print("::warning file={file},line={line}::{msg}".format_map(warning))
print(warning[0])
if not warnings_touched:
print('None')
print("None")


def fail_if_regression(
Expand All @@ -217,19 +217,19 @@ def fail_if_regression(
"""
all_rst = {
str(rst)
for rst in Path('Doc/').rglob('*.rst')
for rst in Path("Doc/").rglob("*.rst")
if rst.parts[1] not in EXCLUDE_SUBDIRS
}
should_be_clean = all_rst - files_with_expected_nits - EXCLUDE_FILES
problem_files = sorted(should_be_clean & files_with_nits)
if problem_files:
print('\nError: must not contain warnings:\n')
print("\nError: must not contain warnings:\n")
for filename in problem_files:
print(filename)
for warning in warnings:
if filename in warning:
if match := WARNING_PATTERN.fullmatch(warning):
print(' {line}: {msg}'.format_map(match))
print(" {line}: {msg}".format_map(match))
return -1
return 0

Expand All @@ -243,10 +243,10 @@ def fail_if_improved(
"""
files_with_no_nits = files_with_expected_nits - files_with_nits
if files_with_no_nits:
print('\nCongratulations! You improved:\n')
print("\nCongratulations! You improved:\n")
for filename in sorted(files_with_no_nits):
print(filename)
print('\nPlease remove from Doc/tools/.nitignore\n')
print("\nPlease remove from Doc/tools/.nitignore\n")
return -1
return 0

Expand All @@ -255,15 +255,15 @@ def fail_if_new_news_nit(warnings: list[str], threshold: int) -> int:
"""
Ensure no warnings are found in the NEWS file before a given line number.
"""
news_nits = (warning for warning in warnings if '/build/NEWS:' in warning)
news_nits = (warning for warning in warnings if "/build/NEWS:" in warning)

# Nits found before the threshold line
new_news_nits = [
nit for nit in news_nits if int(nit.split(':')[1]) <= threshold
nit for nit in news_nits if int(nit.split(":")[1]) <= threshold
]

if new_news_nits:
print('\nError: new NEWS nits:\n')
print("\nError: new NEWS nits:\n")
for warning in new_news_nits:
print(warning)
return -1
Expand All @@ -274,58 +274,58 @@ def fail_if_new_news_nit(warnings: list[str], threshold: int) -> int:
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
'--annotate-diff',
nargs='*',
metavar=('BASE_REF', 'HEAD_REF'),
help='Add GitHub Actions annotations on the diff for warnings on '
'lines changed between the given refs (main and HEAD, by default)',
"--annotate-diff",
nargs="*",
metavar=("BASE_REF", "HEAD_REF"),
help="Add GitHub Actions annotations on the diff for warnings on "
"lines changed between the given refs (main and HEAD, by default)",
)
parser.add_argument(
'--fail-if-regression',
action='store_true',
help='Fail if known-good files have warnings',
"--fail-if-regression",
action="store_true",
help="Fail if known-good files have warnings",
)
parser.add_argument(
'--fail-if-improved',
action='store_true',
help='Fail if new files with no nits are found',
"--fail-if-improved",
action="store_true",
help="Fail if new files with no nits are found",
)
parser.add_argument(
'--fail-if-new-news-nit',
metavar='threshold',
"--fail-if-new-news-nit",
metavar="threshold",
type=int,
nargs='?',
nargs="?",
const=NEWS_NIT_THRESHOLD,
help='Fail if new NEWS nit found before threshold line number',
help="Fail if new NEWS nit found before threshold line number",
)

args = parser.parse_args(argv)
if args.annotate_diff is not None and len(args.annotate_diff) > 2:
parser.error(
'--annotate-diff takes between 0 and 2 ref args, not '
f'{len(args.annotate_diff)} {tuple(args.annotate_diff)}'
"--annotate-diff takes between 0 and 2 ref args, not "
f"{len(args.annotate_diff)} {tuple(args.annotate_diff)}"
)
exit_code = 0

wrong_directory_msg = 'Must run this script from the repo root'
if not Path('Doc').exists() or not Path('Doc').is_dir():
wrong_directory_msg = "Must run this script from the repo root"
if not Path("Doc").exists() or not Path("Doc").is_dir():
raise RuntimeError(wrong_directory_msg)

with Path('Doc/sphinx-warnings.txt').open(encoding='UTF-8') as f:
with Path("Doc/sphinx-warnings.txt").open(encoding="UTF-8") as f:
warnings = f.read().splitlines()

cwd = str(Path.cwd()) + os.path.sep
files_with_nits = {
warning.removeprefix(cwd).split(':')[0]
warning.removeprefix(cwd).split(":")[0]
for warning in warnings
if 'Doc/' in warning
if "Doc/" in warning
}

with Path('Doc/tools/.nitignore').open(encoding='UTF-8') as clean_files:
with Path("Doc/tools/.nitignore").open(encoding="UTF-8") as clean_files:
files_with_expected_nits = {
filename.strip()
for filename in clean_files
if filename.strip() and not filename.startswith('#')
if filename.strip() and not filename.startswith("#")
}

if args.annotate_diff is not None:
Expand All @@ -347,5 +347,5 @@ def main(argv: list[str] | None = None) -> int:
return exit_code


if __name__ == '__main__':
if __name__ == "__main__":
sys.exit(main())
10 changes: 5 additions & 5 deletions Doc/tools/extensions/lexers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

def setup(app):
# Used for highlighting Parser/Python.asdl in library/ast.rst
app.add_lexer('asdl', ASDLLexer)
app.add_lexer("asdl", ASDLLexer)
# Used for highlighting Grammar/python.gram in reference/grammar.rst
app.add_lexer('peg', PEGLexer)
app.add_lexer("peg", PEGLexer)

return {
'version': '1.0',
'parallel_read_safe': True,
'parallel_write_safe': True,
"version": "1.0",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
Loading