Skip to content

Commit

Permalink
Deduplicate redirects (#7757)
Browse files Browse the repository at this point in the history
* feat: Add duplicate redirect detection in Sphinx setup

* refactor: Simplify duplicate redirect detection and add return value

* feat: Add logging of redirect warnings to warnings.log file

* fix: Move warnings.log to build directory

* feat: Add script to detect duplicate redirects in conf.py

* Add script to detect redirect duplication
  • Loading branch information
cwarnermm authored Feb 26, 2025
1 parent 184a7e5 commit 32d62f6
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
84 changes: 84 additions & 0 deletions scripts/detect-duplicate-redirects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3

"""
Script to detect duplicate redirects in conf.py
"""

import os
import sys
from collections import defaultdict

def load_redirects():
"""Load redirects dictionary from conf.py"""
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'source'))
import conf
return conf.redirects

def find_duplicate_redirects(redirects):
"""
Analyze redirects dictionary for duplicates
Returns tuple of (duplicate_sources, sources_to_same_target)
"""
# Track sources that map to the same target
target_to_sources = defaultdict(list)
# Track duplicate sources
source_to_targets = defaultdict(list)

for source, target in redirects.items():
# Track this source->target mapping
source_to_targets[source].append(target)
# Track this target's source
target_to_sources[target].append(source)

# Find duplicates
duplicate_sources = {
source: targets
for source, targets in source_to_targets.items()
if len(targets) > 1
}

sources_to_same_target = {
target: sources
for target, sources in target_to_sources.items()
if len(sources) > 1
}

return duplicate_sources, sources_to_same_target

def write_warnings(duplicate_sources, sources_to_same_target):
"""Write warning messages to warnings.log"""
os.makedirs('build', exist_ok=True)

with open('build/warnings.log', 'a') as log:
if duplicate_sources:
warning = "\nDuplicate sources found (same source maps to multiple targets):\n"
log.write(warning)
print(warning)

for source, targets in duplicate_sources.items():
msg = f"Source: {source}\n"
msg += f"Maps to multiple targets: {targets}\n"
log.write(msg)
print(msg)

if sources_to_same_target:
warning = "\nMultiple sources map to same target:\n"
log.write(warning)
print(warning)

for target, sources in sources_to_same_target.items():
msg = f"Target: {target}\n"
msg += f"Has multiple sources: {sources}\n"
log.write(msg)
print(msg)

def main():
redirects = load_redirects()
duplicate_sources, sources_to_same_target = find_duplicate_redirects(redirects)
write_warnings(duplicate_sources, sources_to_same_target)

# Return non-zero exit code if duplicates found
return 1 if duplicate_sources else 0

if __name__ == '__main__':
sys.exit(main())
39 changes: 39 additions & 0 deletions source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,46 @@
from sphinx.application import Sphinx


def find_duplicate_redirects(redirects):
# Track sources that map to the same target
target_to_sources = {}
# Track duplicate sources
duplicate_sources = {}

# Open warnings log file in build directory
with open("build/warnings.log", "w") as log:
for source, target in redirects.items():
# Check for duplicate sources
if source in duplicate_sources:
warning = f"\nDuplicate redirect found:\n"
warning += f"Source: {source}\n"
warning += f"Already maps to: {duplicate_sources[source]}\n"
warning += f"Also maps to: {target}\n"
log.write(warning)
print(warning)
else:
duplicate_sources[source] = target

# Track sources mapping to same target
if target in target_to_sources:
target_to_sources[target].append(source)
else:
target_to_sources[target] = [source]

# Log sources that map to the same target
for target, sources in target_to_sources.items():
if len(sources) > 1:
warning = f"\nMultiple sources map to same target:\n"
warning += f"Target: {target}\n"
warning += f"Sources: {sources}\n"
log.write(warning)
print(warning)

return len(duplicate_sources) == len(redirects)

def setup(_: Sphinx):
# Check for duplicate redirects when Sphinx builds
find_duplicate_redirects(redirects)
return


Expand Down

0 comments on commit 32d62f6

Please sign in to comment.