9
9
import gc
10
10
from importlib .metadata import metadata
11
11
import os
12
+ from pathlib import Path
12
13
import subprocess
13
14
import sys
14
15
import time
60
61
# (Sphinx looks at variable changes and rewrites all files if some change)
61
62
copyright = (
62
63
f'2012–{ td .year } , MNE Developers. Last updated <time datetime="{ td .isoformat ()} " class="localized">{ td .strftime ("%Y-%m-%d %H:%M %Z" )} </time>\n ' # noqa: E501
63
- '<script type="text/javascript">$(function () { $("time.localized").each(function () { var el = $(this); el.text(new Date(el.attr("datetime")).toLocaleString([], {dateStyle: "medium", timeStyle: "long"})); }); } )</script>'
64
- ) # noqa: E501
64
+ '<script type="text/javascript">$(function () { $("time.localized").each(function () { var el = $(this); el.text(new Date(el.attr("datetime")).toLocaleString([], {dateStyle: "medium", timeStyle: "long"})); }); } )</script>' # noqa: E501
65
+ )
65
66
if os .getenv ("MNE_FULL_DATE" , "false" ).lower () != "true" :
66
67
copyright = f"2012–{ td .year } , MNE Developers. Last updated locally."
67
68
@@ -1636,87 +1637,70 @@ def reset_warnings(gallery_conf, fname):
1636
1637
custom_redirects = {
1637
1638
# Custom redirects (one HTML path to another, relative to outdir)
1638
1639
# can be added here as fr->to key->value mappings
1639
- "install/contributing.html" : "development/contributing.html" ,
1640
- "overview/roadmap.html" : "development/roadmap.html" ,
1641
- "whats_new.html" : "development/whats_new.html" ,
1642
- f"{ tu } /evoked/plot_eeg_erp.html" : f"{ tu } /evoked/30_eeg_erp.html" ,
1643
- f"{ tu } /evoked/plot_whitened.html" : f"{ tu } /evoked/40_whitened.html" ,
1644
- f"{ tu } /misc/plot_modifying_data_inplace.html" : f"{ tu } /intro/15_inplace.html" ,
1645
- f"{ tu } /misc/plot_report.html" : f"{ tu } /intro/70_report.html" ,
1646
- f"{ tu } /misc/plot_seeg.html" : f"{ tu } /clinical/20_seeg.html" ,
1647
- f"{ tu } /misc/plot_ecog.html" : f"{ tu } /clinical/30_ecog.html" ,
1648
- f"{ tu } /{ ml } /plot_receptive_field.html" : f"{ tu } /{ ml } /30_strf.html" ,
1649
- f"{ tu } /{ ml } /plot_sensors_decoding.html" : f"{ tu } /{ ml } /50_decoding.html" ,
1650
- f"{ tu } /{ sm } /plot_background_freesurfer.html" : f"{ tu } /{ fw } /10_background_freesurfer.html" , # noqa E501
1651
- f"{ tu } /{ sm } /plot_source_alignment.html" : f"{ tu } /{ fw } /20_source_alignment.html" ,
1652
- f"{ tu } /{ sm } /plot_forward.html" : f"{ tu } /{ fw } /30_forward.html" ,
1653
- f"{ tu } /{ sm } /plot_eeg_no_mri.html" : f"{ tu } /{ fw } /35_eeg_no_mri.html" ,
1654
- f"{ tu } /{ sm } /plot_background_freesurfer_mne.html" : f"{ tu } /{ fw } /50_background_freesurfer_mne.html" , # noqa E501
1655
- f"{ tu } /{ sm } /plot_fix_bem_in_blender.html" : f"{ tu } /{ fw } /80_fix_bem_in_blender.html" ,
1656
- f"{ tu } /{ sm } /plot_compute_covariance.html" : f"{ tu } /{ fw } /90_compute_covariance.html" ,
1657
- f"{ tu } /{ sm } /plot_object_source_estimate.html" : f"{ tu } /{ nv } /10_stc_class.html" ,
1658
- f"{ tu } /{ sm } /plot_dipole_fit.html" : f"{ tu } /{ nv } /20_dipole_fit.html" ,
1659
- f"{ tu } /{ sm } /plot_mne_dspm_source_localization.html" : f"{ tu } /{ nv } /30_mne_dspm_loreta.html" , # noqa E501
1660
- f"{ tu } /{ sm } /plot_dipole_orientations.html" : f"{ tu } /{ nv } /35_dipole_orientations.html" , # noqa E501
1661
- f"{ tu } /{ sm } /plot_mne_solutions.html" : f"{ tu } /{ nv } /40_mne_fixed_free.html" ,
1662
- f"{ tu } /{ sm } /plot_beamformer_lcmv.html" : f"{ tu } /{ nv } /50_beamformer_lcmv.html" ,
1663
- f"{ tu } /{ sm } /plot_visualize_stc.html" : f"{ tu } /{ nv } /60_visualize_stc.html" ,
1664
- f"{ tu } /{ sm } /plot_eeg_mri_coords.html" : f"{ tu } /{ nv } /70_eeg_mri_coords.html" ,
1665
- f"{ tu } /{ sd } /plot_brainstorm_phantom_elekta.html" : f"{ tu } /{ nv } /80_brainstorm_phantom_elekta.html" , # noqa E501
1666
- f"{ tu } /{ sd } /plot_brainstorm_phantom_ctf.html" : f"{ tu } /{ nv } /85_brainstorm_phantom_ctf.html" , # noqa E501
1667
- f"{ tu } /{ sd } /plot_phantom_4DBTi.html" : f"{ tu } /{ nv } /90_phantom_4DBTi.html" ,
1668
- f"{ tu } /{ sd } /plot_brainstorm_auditory.html" : f"{ tu } /io/60_ctf_bst_auditory.html" ,
1669
- f"{ tu } /{ sd } /plot_sleep.html" : f"{ tu } /clinical/60_sleep.html" ,
1670
- f"{ tu } /{ di } /plot_background_filtering.html" : f"{ tu } /{ pr } /25_background_filtering.html" , # noqa E501
1671
- f"{ tu } /{ di } /plot_background_statistics.html" : f"{ tu } /{ sn } /10_background_stats.html" ,
1672
- f"{ tu } /{ sn } /plot_stats_cluster_erp.html" : f"{ tu } /{ sn } /20_erp_stats.html" ,
1673
- f"{ tu } /{ sn } /plot_stats_cluster_1samp_test_time_frequency.html" : f"{ tu } /{ sn } /40_cluster_1samp_time_freq.html" , # noqa E501
1674
- f"{ tu } /{ sn } /plot_stats_cluster_time_frequency.html" : f"{ tu } /{ sn } /50_cluster_between_time_freq.html" , # noqa E501
1675
- f"{ tu } /{ sn } /plot_stats_spatio_temporal_cluster_sensors.html" : f"{ tu } /{ sn } /75_cluster_ftest_spatiotemporal.html" , # noqa E501
1676
- f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal.html" : f"{ tu } /{ sr } /20_cluster_1samp_spatiotemporal.html" , # noqa E501
1677
- f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal_2samp.html" : f"{ tu } /{ sr } /30_cluster_ftest_spatiotemporal.html" , # noqa E501
1678
- f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal_repeated_measures_anova.html" : f"{ tu } /{ sr } /60_cluster_rmANOVA_spatiotemporal.html" , # noqa E501
1679
- f"{ tu } /{ sr } /plot_stats_cluster_time_frequency_repeated_measures_anova.html" : f"{ tu } /{ sn } /70_cluster_rmANOVA_time_freq.html" , # noqa E501
1680
- f"{ tu } /{ tf } /plot_sensors_time_frequency.html" : f"{ tu } /{ tf } /20_sensors_time_frequency.html" , # noqa E501
1681
- f"{ tu } /{ tf } /plot_ssvep.html" : f"{ tu } /{ tf } /50_ssvep.html" ,
1682
- f"{ tu } /{ si } /plot_creating_data_structures.html" : f"{ tu } /{ si } /10_array_objs.html" ,
1683
- f"{ tu } /{ si } /plot_point_spread.html" : f"{ tu } /{ si } /70_point_spread.html" ,
1684
- f"{ tu } /{ si } /plot_dics.html" : f"{ tu } /{ si } /80_dics.html" ,
1685
- f"{ tu } /{ tf } /plot_eyetracking.html" : f"{ tu } /{ pr } /90_eyetracking_data.html" ,
1686
- f"{ ex } /{ co } /mne_inverse_label_connectivity.html" : f"{ mne_conn } /{ ex } /mne_inverse_label_connectivity.html" , # noqa E501
1687
- f"{ ex } /{ co } /cwt_sensor_connectivity.html" : f"{ mne_conn } /{ ex } /cwt_sensor_connectivity.html" , # noqa E501
1688
- f"{ ex } /{ co } /mixed_source_space_connectivity.html" : f"{ mne_conn } /{ ex } /mixed_source_space_connectivity.html" , # noqa E501
1689
- f"{ ex } /{ co } /mne_inverse_coherence_epochs.html" : f"{ mne_conn } /{ ex } /mne_inverse_coherence_epochs.html" , # noqa E501
1690
- f"{ ex } /{ co } /mne_inverse_connectivity_spectrum.html" : f"{ mne_conn } /{ ex } /mne_inverse_connectivity_spectrum.html" , # noqa E501
1691
- f"{ ex } /{ co } /mne_inverse_envelope_correlation_volume.html" : f"{ mne_conn } /{ ex } /mne_inverse_envelope_correlation_volume.html" , # noqa E501
1692
- f"{ ex } /{ co } /mne_inverse_envelope_correlation.html" : f"{ mne_conn } /{ ex } /mne_inverse_envelope_correlation.html" , # noqa E501
1693
- f"{ ex } /{ co } /mne_inverse_psi_visual.html" : f"{ mne_conn } /{ ex } /mne_inverse_psi_visual.html" , # noqa E501
1694
- f"{ ex } /{ co } /sensor_connectivity.html" : f"{ mne_conn } /{ ex } /sensor_connectivity.html" ,
1695
- f"{ ex } /{ vi } /publication_figure.html" : f"{ tu } /{ vi } /10_publication_figure.html" ,
1696
- f"{ ex } /{ vi } /sensor_noise_level.html" : f"{ tu } /{ pr } /50_artifact_correction_ssp.html" ,
1640
+ "install/contributing" : "development/contributing" ,
1641
+ "overview/cite" : "documentation/cite" ,
1642
+ "overview/get_help" : "help/index" ,
1643
+ "overview/roadmap" : "development/roadmap" ,
1644
+ "whats_new" : "development/whats_new" ,
1645
+ f"{ tu } /evoked/plot_eeg_erp" : f"{ tu } /evoked/30_eeg_erp" ,
1646
+ f"{ tu } /evoked/plot_whitened" : f"{ tu } /evoked/40_whitened" ,
1647
+ f"{ tu } /misc/plot_modifying_data_inplace" : f"{ tu } /intro/15_inplace" ,
1648
+ f"{ tu } /misc/plot_report" : f"{ tu } /intro/70_report" ,
1649
+ f"{ tu } /misc/plot_seeg" : f"{ tu } /clinical/20_seeg" ,
1650
+ f"{ tu } /misc/plot_ecog" : f"{ tu } /clinical/30_ecog" ,
1651
+ f"{ tu } /{ ml } /plot_receptive_field" : f"{ tu } /{ ml } /30_strf" ,
1652
+ f"{ tu } /{ ml } /plot_sensors_decoding" : f"{ tu } /{ ml } /50_decoding" ,
1653
+ f"{ tu } /{ sm } /plot_background_freesurfer" : f"{ tu } /{ fw } /10_background_freesurfer" ,
1654
+ f"{ tu } /{ sm } /plot_source_alignment" : f"{ tu } /{ fw } /20_source_alignment" ,
1655
+ f"{ tu } /{ sm } /plot_forward" : f"{ tu } /{ fw } /30_forward" ,
1656
+ f"{ tu } /{ sm } /plot_eeg_no_mri" : f"{ tu } /{ fw } /35_eeg_no_mri" ,
1657
+ f"{ tu } /{ sm } /plot_background_freesurfer_mne" : f"{ tu } /{ fw } /50_background_freesurfer_mne" , # noqa E501
1658
+ f"{ tu } /{ sm } /plot_fix_bem_in_blender" : f"{ tu } /{ fw } /80_fix_bem_in_blender" ,
1659
+ f"{ tu } /{ sm } /plot_compute_covariance" : f"{ tu } /{ fw } /90_compute_covariance" ,
1660
+ f"{ tu } /{ sm } /plot_object_source_estimate" : f"{ tu } /{ nv } /10_stc_class" ,
1661
+ f"{ tu } /{ sm } /plot_dipole_fit" : f"{ tu } /{ nv } /20_dipole_fit" ,
1662
+ f"{ tu } /{ sm } /plot_mne_dspm_source_localization" : f"{ tu } /{ nv } /30_mne_dspm_loreta" ,
1663
+ f"{ tu } /{ sm } /plot_dipole_orientations" : f"{ tu } /{ nv } /35_dipole_orientations" ,
1664
+ f"{ tu } /{ sm } /plot_mne_solutions" : f"{ tu } /{ nv } /40_mne_fixed_free" ,
1665
+ f"{ tu } /{ sm } /plot_beamformer_lcmv" : f"{ tu } /{ nv } /50_beamformer_lcmv" ,
1666
+ f"{ tu } /{ sm } /plot_visualize_stc" : f"{ tu } /{ nv } /60_visualize_stc" ,
1667
+ f"{ tu } /{ sm } /plot_eeg_mri_coords" : f"{ tu } /{ nv } /70_eeg_mri_coords" ,
1668
+ f"{ tu } /{ sd } /plot_brainstorm_phantom_elekta" : f"{ tu } /{ nv } /80_brainstorm_phantom_elekta" , # noqa E501
1669
+ f"{ tu } /{ sd } /plot_brainstorm_phantom_ctf" : f"{ tu } /{ nv } /85_brainstorm_phantom_ctf" ,
1670
+ f"{ tu } /{ sd } /plot_phantom_4DBTi" : f"{ tu } /{ nv } /90_phantom_4DBTi" ,
1671
+ f"{ tu } /{ sd } /plot_brainstorm_auditory" : f"{ tu } /io/60_ctf_bst_auditory" ,
1672
+ f"{ tu } /{ sd } /plot_sleep" : f"{ tu } /clinical/60_sleep" ,
1673
+ f"{ tu } /{ di } /plot_background_filtering" : f"{ tu } /{ pr } /25_background_filtering" ,
1674
+ f"{ tu } /{ di } /plot_background_statistics" : f"{ tu } /{ sn } /10_background_stats" ,
1675
+ f"{ tu } /{ sn } /plot_stats_cluster_erp" : f"{ tu } /{ sn } /20_erp_stats" ,
1676
+ f"{ tu } /{ sn } /plot_stats_cluster_1samp_test_time_frequency" : f"{ tu } /{ sn } /40_cluster_1samp_time_freq" , # noqa E501
1677
+ f"{ tu } /{ sn } /plot_stats_cluster_time_frequency" : f"{ tu } /{ sn } /50_cluster_between_time_freq" , # noqa E501
1678
+ f"{ tu } /{ sn } /plot_stats_spatio_temporal_cluster_sensors" : f"{ tu } /{ sn } /75_cluster_ftest_spatiotemporal" , # noqa E501
1679
+ f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal" : f"{ tu } /{ sr } /20_cluster_1samp_spatiotemporal" , # noqa E501
1680
+ f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal_2samp" : f"{ tu } /{ sr } /30_cluster_ftest_spatiotemporal" , # noqa E501
1681
+ f"{ tu } /{ sr } /plot_stats_cluster_spatio_temporal_repeated_measures_anova" : f"{ tu } /{ sr } /60_cluster_rmANOVA_spatiotemporal" , # noqa E501
1682
+ f"{ tu } /{ sr } /plot_stats_cluster_time_frequency_repeated_measures_anova" : f"{ tu } /{ sn } /70_cluster_rmANOVA_time_freq" , # noqa E501
1683
+ f"{ tu } /{ tf } /plot_sensors_time_frequency" : f"{ tu } /{ tf } /20_sensors_time_frequency" ,
1684
+ f"{ tu } /{ tf } /plot_ssvep" : f"{ tu } /{ tf } /50_ssvep" ,
1685
+ f"{ tu } /{ si } /plot_creating_data_structures" : f"{ tu } /{ si } /10_array_objs" ,
1686
+ f"{ tu } /{ si } /plot_point_spread" : f"{ tu } /{ si } /70_point_spread" ,
1687
+ f"{ tu } /{ si } /plot_dics" : f"{ tu } /{ si } /80_dics" ,
1688
+ f"{ tu } /{ tf } /plot_eyetracking" : f"{ tu } /{ pr } /90_eyetracking_data" ,
1689
+ f"{ ex } /{ co } /mne_inverse_label_connectivity" : f"{ mne_conn } /{ ex } /mne_inverse_label_connectivity" , # noqa E501
1690
+ f"{ ex } /{ co } /cwt_sensor_connectivity" : f"{ mne_conn } /{ ex } /cwt_sensor_connectivity" ,
1691
+ f"{ ex } /{ co } /mixed_source_space_connectivity" : f"{ mne_conn } /{ ex } /mixed_source_space_connectivity" , # noqa E501
1692
+ f"{ ex } /{ co } /mne_inverse_coherence_epochs" : f"{ mne_conn } /{ ex } /mne_inverse_coherence_epochs" , # noqa E501
1693
+ f"{ ex } /{ co } /mne_inverse_connectivity_spectrum" : f"{ mne_conn } /{ ex } /mne_inverse_connectivity_spectrum" , # noqa E501
1694
+ f"{ ex } /{ co } /mne_inverse_envelope_correlation_volume" : f"{ mne_conn } /{ ex } /mne_inverse_envelope_correlation_volume" , # noqa E501
1695
+ f"{ ex } /{ co } /mne_inverse_envelope_correlation" : f"{ mne_conn } /{ ex } /mne_inverse_envelope_correlation" , # noqa E501
1696
+ f"{ ex } /{ co } /mne_inverse_psi_visual" : f"{ mne_conn } /{ ex } /mne_inverse_psi_visual" ,
1697
+ f"{ ex } /{ co } /sensor_connectivity" : f"{ mne_conn } /{ ex } /sensor_connectivity" ,
1698
+ f"{ ex } /{ vi } /publication_figure" : f"{ tu } /{ vi } /10_publication_figure" ,
1699
+ f"{ ex } /{ vi } /sensor_noise_level" : f"{ tu } /{ pr } /50_artifact_correction_ssp" ,
1697
1700
}
1698
1701
1699
-
1700
- def check_existing_redirect (path ):
1701
- """Make sure existing HTML files are redirects, before overwriting."""
1702
- if os .path .isfile (path ):
1703
- with open (path , "r" ) as fid :
1704
- for _ in range (8 ):
1705
- next (fid )
1706
- line = fid .readline ()
1707
- assert "Page Redirection" in line , line
1708
-
1709
-
1710
- def make_redirects (app , exception ):
1711
- """Make HTML redirects."""
1712
- # https://www.sphinx-doc.org/en/master/extdev/appapi.html
1713
- # Adapted from sphinxcontrib/redirects (BSD-2-Clause)
1714
- if not (
1715
- isinstance (app .builder , sphinx .builders .html .StandaloneHTMLBuilder )
1716
- and exception is None
1717
- ):
1718
- return
1719
- TEMPLATE = """\
1702
+ # Adapted from sphinxcontrib/redirects (BSD-2-Clause)
1703
+ REDIRECT_TEMPLATE = """\
1720
1704
<!DOCTYPE HTML>
1721
1705
<html lang="en-US">
1722
1706
<head>
@@ -1730,66 +1714,104 @@ def make_redirects(app, exception):
1730
1714
<body>
1731
1715
If you are not redirected automatically, follow this <a href='{to}'>link</a>.
1732
1716
</body>
1733
- </html>""" # noqa: E501
1734
- sphinx_gallery_conf = app .config ["sphinx_gallery_conf" ]
1735
- for src_dir , out_dir in zip (
1736
- sphinx_gallery_conf ["examples_dirs" ], sphinx_gallery_conf ["gallery_dirs" ]
1737
- ):
1738
- root = os .path .abspath (os .path .join (app .srcdir , src_dir ))
1717
+ </html>"""
1718
+
1719
+
1720
+ def check_existing_redirect (path ):
1721
+ """Make sure existing HTML files are redirects, before overwriting."""
1722
+ if path .is_file ():
1723
+ with open (path , "r" ) as fid :
1724
+ for _ in range (8 ):
1725
+ next (fid )
1726
+ line = fid .readline ()
1727
+ if "Page Redirection" not in line :
1728
+ raise RuntimeError (
1729
+ "Attempted overwrite of HTML file with a redirect, where the "
1730
+ "original file was not already a redirect."
1731
+ )
1732
+
1733
+
1734
+ def _check_valid_builder (app , exception ):
1735
+ valid_builder = isinstance (app .builder , sphinx .builders .html .StandaloneHTMLBuilder )
1736
+ return valid_builder and exception is None
1737
+
1738
+
1739
+ def make_gallery_redirects (app , exception ):
1740
+ """Make HTML redirects for our sphinx gallery pages."""
1741
+ if not _check_valid_builder (app , exception ):
1742
+ return
1743
+ sg_conf = app .config ["sphinx_gallery_conf" ]
1744
+ for src_dir , out_dir in zip (sg_conf ["examples_dirs" ], sg_conf ["gallery_dirs" ]):
1745
+ root = (Path (app .srcdir ) / src_dir ).resolve ()
1739
1746
fnames = [
1740
- os .path .join (os .path .relpath (dirpath , root ), fname )
1741
- for dirpath , _ , fnames in os .walk (root )
1742
- for fname in fnames
1743
- if fname in needed_plot_redirects
1747
+ pyfile .relative_to (root )
1748
+ for pyfile in root .rglob (r"**/*.py" )
1749
+ if pyfile .name in needed_plot_redirects
1744
1750
]
1745
1751
# plot_ redirects
1746
1752
for fname in fnames :
1747
- dirname = os . path . join (app .outdir , out_dir , os . path . dirname ( fname ))
1748
- to_fname = os . path . splitext ( os . path . basename ( fname ))[ 0 ] + ".html"
1753
+ dirname = Path (app .outdir ) / out_dir / fname . parent
1754
+ to_fname = fname . with_suffix ( ".html" ). name
1749
1755
fr_fname = f"plot_{ to_fname } "
1750
- to_path = os . path . join ( dirname , to_fname )
1751
- fr_path = os . path . join ( dirname , fr_fname )
1752
- assert os . path . isfile ( to_path ), (fname , to_path )
1756
+ to_path = dirname / to_fname
1757
+ fr_path = dirname / fr_fname
1758
+ assert to_path . is_file ( ), (fname , to_path )
1753
1759
with open (fr_path , "w" ) as fid :
1754
- fid .write (TEMPLATE .format (to = to_fname ))
1760
+ fid .write (REDIRECT_TEMPLATE .format (to = to_fname ))
1755
1761
sphinx_logger .info (
1756
1762
f"Added { len (fnames ):3d} HTML plot_* redirects for { out_dir } "
1757
1763
)
1758
- # API redirects
1764
+
1765
+
1766
+ def make_api_redirects (app , exception ):
1767
+ """Make HTML redirects for our API pages."""
1768
+ if not _check_valid_builder (app , exception ):
1769
+ return
1770
+
1759
1771
for page in api_redirects :
1760
1772
fname = f"{ page } .html"
1761
- fr_path = os . path . join (app .outdir , fname )
1762
- to_path = os . path . join (app .outdir , "api" , fname )
1773
+ fr_path = Path (app .outdir ) / fname
1774
+ to_path = Path (app .outdir ) / "api" / fname
1763
1775
# allow overwrite if existing file is just a redirect
1764
1776
check_existing_redirect (fr_path )
1765
1777
with open (fr_path , "w" ) as fid :
1766
- fid .write (TEMPLATE .format (to = to_path ))
1778
+ fid .write (REDIRECT_TEMPLATE .format (to = to_path ))
1767
1779
sphinx_logger .info (f"Added { len (api_redirects ):3d} HTML API redirects" )
1768
- # custom redirects
1769
- for fr , to in custom_redirects .items ():
1770
- if not to .startswith ("http" ):
1771
- assert os .path .isfile (os .path .join (app .outdir , to )), to
1772
- # handle links to sibling folders
1773
- path_parts = to .split ("/" )
1774
- if tu in path_parts :
1775
- path_parts = [".." ] + path_parts [(path_parts .index (tu ) + 1 ) :]
1776
- to = os .path .join (* path_parts )
1777
- assert to .endswith ("html" ), to
1778
- fr_path = os .path .join (app .outdir , fr )
1779
- assert fr_path .endswith ("html" ), fr_path
1780
- # allow overwrite if existing file is just a redirect
1780
+
1781
+
1782
+ def make_custom_redirects (app , exception ):
1783
+ """Make HTML redirects for miscellaneous pages."""
1784
+ if not _check_valid_builder (app , exception ):
1785
+ return
1786
+
1787
+ for _fr , _to in custom_redirects .items ():
1788
+ fr = f"{ _fr } .html"
1789
+ to = f"{ _to } .html"
1790
+ fr_path = Path (app .outdir ) / fr
1781
1791
check_existing_redirect (fr_path )
1782
- # handle folders that no longer exist
1783
- if fr_path .split ("/" )[- 2 ] in (
1792
+ if to .startswith ("http" ):
1793
+ to_path = to
1794
+ else :
1795
+ to_path = Path (app .outdir ) / to
1796
+ assert to_path .is_file (), to_path
1797
+ # recreate folders that no longer exist
1798
+ defunct_gallery_folders = (
1784
1799
"misc" ,
1785
1800
"discussions" ,
1786
1801
"source-modeling" ,
1787
1802
"sample-datasets" ,
1788
1803
"connectivity" ,
1804
+ )
1805
+ parts = fr_path .relative_to (Path (app .outdir )).parts
1806
+ if (
1807
+ len (parts ) > 1 # whats_new violates this
1808
+ and parts [1 ] in defunct_gallery_folders
1809
+ and not fr_path .parent .exists ()
1789
1810
):
1790
- os .makedirs (os .path .dirname (fr_path ), exist_ok = True )
1811
+ os .makedirs (fr_path .parent , exist_ok = True )
1812
+ # write the redirect
1791
1813
with open (fr_path , "w" ) as fid :
1792
- fid .write (TEMPLATE .format (to = to ))
1814
+ fid .write (REDIRECT_TEMPLATE .format (to = to_path ))
1793
1815
sphinx_logger .info (f"Added { len (custom_redirects ):3d} HTML custom redirects" )
1794
1816
1795
1817
@@ -1818,5 +1840,7 @@ def setup(app):
1818
1840
app .connect ("autodoc-process-docstring" , append_attr_meth_examples )
1819
1841
report_scraper .app = app
1820
1842
app .connect ("builder-inited" , report_scraper .copyfiles )
1821
- app .connect ("build-finished" , make_redirects )
1843
+ app .connect ("build-finished" , make_gallery_redirects )
1844
+ app .connect ("build-finished" , make_api_redirects )
1845
+ app .connect ("build-finished" , make_custom_redirects )
1822
1846
app .connect ("build-finished" , make_version )
0 commit comments