diff --git a/config/url_fixups.yaml b/config/url_fixups.yaml new file mode 100644 index 0000000..2294bc4 --- /dev/null +++ b/config/url_fixups.yaml @@ -0,0 +1,100 @@ +# Heart URL-fixup rules — the live-check's "immune memory" (Heart#53/#75). +# Each rule rewrites a known-bad URL pattern to its known-good form when the +# URL sweep proposes fixes. Pure instance policy: an adopting fork replaces +# this file with their own accumulated fixups (or empties it). +# +# pattern: a Python regex; replacement may use backrefs (\1). +rewrites: +- pattern: hhttps:// + replacement: https:// + description: hhttps:// typo +- pattern: (github\.com|githubusercontent\.com)/Jammy2211/(autolens_workspace|autogalaxy_workspace|autofit_workspace) + replacement: \1/PyAutoLabs/\2 + description: Jammy2211/ → PyAutoLabs/ +- pattern: (github\.com|githubusercontent\.com)/Jammy2211/(PyAutoArray|PyAutoLens|PyAutoGalaxy) + replacement: \1/PyAutoLabs/\2 + description: Jammy2211/ → PyAutoLabs/ +- pattern: (github\.com|githubusercontent\.com)/(?:Jammy2211|rhayes777)/(PyAutoFit|PyAutoConf) + replacement: \1/PyAutoLabs/\2 + description: Jammy2211|rhayes777/{PyAutoFit,PyAutoConf} → PyAutoLabs/... +- pattern: (github\.com|githubusercontent\.com)/rhayes777/PyAutoGalaxy + replacement: \1/PyAutoLabs/PyAutoGalaxy + description: rhayes777/PyAutoGalaxy → PyAutoLabs/PyAutoGalaxy +- pattern: /blob/release/ + replacement: /blob/main/ + description: /blob/release/ → /blob/main/ +- pattern: /tree/release/ + replacement: /tree/main/ + description: /tree/release/ → /tree/main/ +- pattern: github\.com/joshspeagle/[Nn]autilus + replacement: github.com/johannesulf/nautilus + description: joshspeagle/nautilus → johannesulf/nautilus +- pattern: github\.com/rhayes777/PyAutoBuild + replacement: github.com/PyAutoLabs/PyAutoBuild + description: rhayes777/PyAutoBuild → PyAutoLabs/PyAutoBuild +- pattern: www\.sphinx-doc\.org/en/main + replacement: www.sphinx-doc.org/en/master + description: sphinx-doc /en/main → /en/master +- pattern: github\.com/bokeh/bokeh/blob/main/CODE_OF_CONDUCT\.md + replacement: github.com/bokeh/bokeh/blob/main/docs/CODE_OF_CONDUCT.md + description: bokeh CoC moved to /docs/ +- pattern: https?://github\.com/numfocus/numfocus/blob/main/manual/numfocus-coc\.md(#the-short-version)? + replacement: https://numfocus.org/code-of-conduct + description: numfocus CoC → numfocus.org/code-of-conduct +- pattern: Fiterence_anti-harassment + replacement: Conference_anti-harassment + description: Fiterence → Conference (typo) +- pattern: (colab\.research\.google\.com/github/PyAutoLabs/autofit_workspace/blob/[^/]+/)start_here\.ipynb + replacement: \1notebooks/overview/overview_1_the_basics.ipynb + description: autofit_workspace Colab badge → notebooks/overview/overview_1_the_basics.ipynb +- pattern: (colab\.research\.google\.com/github/PyAutoLabs/autogalaxy_workspace/blob/[^/]+/)start_here\.ipynb + replacement: \1notebooks/imaging/start_here.ipynb + description: autogalaxy_workspace Colab badge → notebooks/imaging/start_here.ipynb +- pattern: (colab\.research\.google\.com/github/PyAutoLabs/autolens_workspace/blob/[^/]+/)start_here\.ipynb + replacement: \1notebooks/imaging/start_here.ipynb + description: autolens_workspace Colab badge → notebooks/imaging/start_here.ipynb +- pattern: autofit_workspace/blob/main/notebooks/overview/simple/fit\.ipynb + replacement: autofit_workspace/blob/main/notebooks/overview/overview_1_the_basics.ipynb + description: autofit_workspace simple/fit → overview_1_the_basics +- pattern: autofit_workspace/blob/main/notebooks/overview/complex/fit\.ipynb + replacement: autofit_workspace/blob/main/notebooks/overview/overview_2_scientific_workflow.ipynb + description: autofit_workspace complex/fit → overview_2_scientific_workflow +- pattern: autofit_workspace/blob/main/notebooks/overview/(simple|complex)/result\.ipynb + replacement: autofit_workspace/blob/main/notebooks/cookbooks/result.ipynb + description: autofit_workspace overview/*/result → cookbooks/result +- pattern: autofit_workspace/tree/main/notebooks/overview/simplee + replacement: autofit_workspace/tree/main/notebooks/overview + description: autofit_workspace simplee typo → overview +- pattern: pyautofit\.readthedocs\.io/en/latest/cookbooks/cookbook_1_basics\.html + replacement: pyautofit.readthedocs.io/en/latest/cookbooks/model.html + description: PyAutoFit cookbook_1_basics → cookbooks/model +- pattern: pyautofit\.readthedocs\.io/en/latest/overview/model_fit\.html + replacement: pyautofit.readthedocs.io/en/latest/overview/the_basics.html + description: PyAutoFit overview/model_fit → overview/the_basics +- pattern: pyautofit\.readthedocs\.io/en/latest/overview/model_complex\.html + replacement: pyautofit.readthedocs.io/en/latest/cookbooks/model.html + description: PyAutoFit overview/model_complex → cookbooks/model +- pattern: pyautofit\.readthedocs\.io/en/latest/overview/non_linear_search\.html + replacement: pyautofit.readthedocs.io/en/latest/cookbooks/search.html + description: PyAutoFit overview/non_linear_search → cookbooks/search +- pattern: pyautofit\.readthedocs\.io/en/latest/overview/result\.html + replacement: pyautofit.readthedocs.io/en/latest/cookbooks/result.html + description: PyAutoFit overview/result → cookbooks/result +- pattern: (autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/modeling/imaging/features/(multi_gaussian_expansion|shapelets|linear_light_profiles|pixelization|extra_galaxies|operated_light_profile|sky_background)\.ipynb + replacement: \1/blob/main/notebooks/imaging/features/\2/modeling.ipynb + description: workspaces modeling/imaging/features/.ipynb → imaging/features//modeling.ipynb +- pattern: (autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/multi/modeling/features/(wavelength_dependence|same_wavelength|dataset_offsets|one_by_one|imaging_and_interferometer|pixelization)\.ipynb + replacement: \1/blob/main/notebooks/multi/features/\2/modeling.ipynb + description: workspaces multi/modeling/features/.ipynb → multi/features//modeling.ipynb +- pattern: (autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/multi/modeling/start_here\.ipynb + replacement: \1/blob/main/notebooks/multi/start_here.ipynb + description: workspaces multi/modeling/start_here → multi/start_here +- pattern: autolens_workspace/blob/main/notebooks/imaging/features/shapelets/ + replacement: autolens_workspace/blob/main/notebooks/imaging/features/advanced/shapelets/ + description: autolens shapelets under imaging/features/advanced/ +- pattern: (autogalaxy_workspace|autolens_workspace|autofit_workspace)/tree/main/notebooks/plot + replacement: \1/tree/main/notebooks/guides/plot + description: workspaces tree/main/notebooks/plot → notebooks/guides/plot +- pattern: raw\.githubusercontent\.com/(?:rhayes777|PyAutoLabs)/PyAutoFit/feature/docs_update/ + replacement: raw.githubusercontent.com/PyAutoLabs/PyAutoFit/main/ + description: PyAutoFit docs_update branch images → PyAutoLabs/main diff --git a/heart/checks/url_check_live.py b/heart/checks/url_check_live.py index df4d718..2a5b99a 100644 --- a/heart/checks/url_check_live.py +++ b/heart/checks/url_check_live.py @@ -83,108 +83,22 @@ class Result: locations: list[Location] = field(default_factory=list) -KNOWN_PATTERN_REWRITES: list[tuple[re.Pattern[str], str, str]] = [ - # (regex, replacement, description) - (re.compile(r"hhttps://"), "https://", "hhttps:// typo"), - (re.compile( - r"(github\.com|githubusercontent\.com)/Jammy2211/" - r"(autolens_workspace|autogalaxy_workspace|autofit_workspace)" - ), r"\1/PyAutoLabs/\2", "Jammy2211/ → PyAutoLabs/"), - (re.compile( - r"(github\.com|githubusercontent\.com)/Jammy2211/" - r"(PyAutoArray|PyAutoLens|PyAutoGalaxy)" - ), r"\1/PyAutoLabs/\2", "Jammy2211/ → PyAutoLabs/"), - (re.compile(r"(github\.com|githubusercontent\.com)/(?:Jammy2211|rhayes777)/(PyAutoFit|PyAutoConf)"), - r"\1/PyAutoLabs/\2", "Jammy2211|rhayes777/{PyAutoFit,PyAutoConf} → PyAutoLabs/..."), - (re.compile(r"(github\.com|githubusercontent\.com)/rhayes777/PyAutoGalaxy"), - r"\1/PyAutoLabs/PyAutoGalaxy", "rhayes777/PyAutoGalaxy → PyAutoLabs/PyAutoGalaxy"), - (re.compile(r"/blob/release/"), "/blob/main/", "/blob/release/ → /blob/main/"), - (re.compile(r"/tree/release/"), "/tree/main/", "/tree/release/ → /tree/main/"), - (re.compile(r"github\.com/joshspeagle/[Nn]autilus"), - "github.com/johannesulf/nautilus", "joshspeagle/nautilus → johannesulf/nautilus"), - (re.compile(r"github\.com/rhayes777/PyAutoBuild"), - "github.com/PyAutoLabs/PyAutoBuild", "rhayes777/PyAutoBuild → PyAutoLabs/PyAutoBuild"), - (re.compile(r"www\.sphinx-doc\.org/en/main"), - "www.sphinx-doc.org/en/master", "sphinx-doc /en/main → /en/master"), - (re.compile(r"github\.com/bokeh/bokeh/blob/main/CODE_OF_CONDUCT\.md"), - "github.com/bokeh/bokeh/blob/main/docs/CODE_OF_CONDUCT.md", - "bokeh CoC moved to /docs/"), - (re.compile( - r"https?://github\.com/numfocus/numfocus/blob/main/manual/numfocus-coc\.md" - r"(#the-short-version)?" - ), "https://numfocus.org/code-of-conduct", - "numfocus CoC → numfocus.org/code-of-conduct"), - (re.compile(r"Fiterence_anti-harassment"), "Conference_anti-harassment", - "Fiterence → Conference (typo)"), - (re.compile( - r"(colab\.research\.google\.com/github/PyAutoLabs/autofit_workspace/blob/[^/]+/)start_here\.ipynb" - ), r"\1notebooks/overview/overview_1_the_basics.ipynb", - "autofit_workspace Colab badge → notebooks/overview/overview_1_the_basics.ipynb"), - (re.compile( - r"(colab\.research\.google\.com/github/PyAutoLabs/autogalaxy_workspace/blob/[^/]+/)start_here\.ipynb" - ), r"\1notebooks/imaging/start_here.ipynb", - "autogalaxy_workspace Colab badge → notebooks/imaging/start_here.ipynb"), - (re.compile( - r"(colab\.research\.google\.com/github/PyAutoLabs/autolens_workspace/blob/[^/]+/)start_here\.ipynb" - ), r"\1notebooks/imaging/start_here.ipynb", - "autolens_workspace Colab badge → notebooks/imaging/start_here.ipynb"), - (re.compile(r"autofit_workspace/blob/main/notebooks/overview/simple/fit\.ipynb"), - "autofit_workspace/blob/main/notebooks/overview/overview_1_the_basics.ipynb", - "autofit_workspace simple/fit → overview_1_the_basics"), - (re.compile(r"autofit_workspace/blob/main/notebooks/overview/complex/fit\.ipynb"), - "autofit_workspace/blob/main/notebooks/overview/overview_2_scientific_workflow.ipynb", - "autofit_workspace complex/fit → overview_2_scientific_workflow"), - (re.compile(r"autofit_workspace/blob/main/notebooks/overview/(simple|complex)/result\.ipynb"), - "autofit_workspace/blob/main/notebooks/cookbooks/result.ipynb", - "autofit_workspace overview/*/result → cookbooks/result"), - (re.compile(r"autofit_workspace/tree/main/notebooks/overview/simplee"), - "autofit_workspace/tree/main/notebooks/overview", - "autofit_workspace simplee typo → overview"), - (re.compile(r"pyautofit\.readthedocs\.io/en/latest/cookbooks/cookbook_1_basics\.html"), - "pyautofit.readthedocs.io/en/latest/cookbooks/model.html", - "PyAutoFit cookbook_1_basics → cookbooks/model"), - (re.compile(r"pyautofit\.readthedocs\.io/en/latest/overview/model_fit\.html"), - "pyautofit.readthedocs.io/en/latest/overview/the_basics.html", - "PyAutoFit overview/model_fit → overview/the_basics"), - (re.compile(r"pyautofit\.readthedocs\.io/en/latest/overview/model_complex\.html"), - "pyautofit.readthedocs.io/en/latest/cookbooks/model.html", - "PyAutoFit overview/model_complex → cookbooks/model"), - (re.compile(r"pyautofit\.readthedocs\.io/en/latest/overview/non_linear_search\.html"), - "pyautofit.readthedocs.io/en/latest/cookbooks/search.html", - "PyAutoFit overview/non_linear_search → cookbooks/search"), - (re.compile(r"pyautofit\.readthedocs\.io/en/latest/overview/result\.html"), - "pyautofit.readthedocs.io/en/latest/cookbooks/result.html", - "PyAutoFit overview/result → cookbooks/result"), - (re.compile( - r"(autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/" - r"modeling/imaging/features/(multi_gaussian_expansion|shapelets|" - r"linear_light_profiles|pixelization|extra_galaxies|operated_light_profile|" - r"sky_background)\.ipynb" - ), r"\1/blob/main/notebooks/imaging/features/\2/modeling.ipynb", - "workspaces modeling/imaging/features/.ipynb → imaging/features//modeling.ipynb"), - (re.compile( - r"(autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/" - r"multi/modeling/features/(wavelength_dependence|same_wavelength|dataset_offsets|" - r"one_by_one|imaging_and_interferometer|pixelization)\.ipynb" - ), r"\1/blob/main/notebooks/multi/features/\2/modeling.ipynb", - "workspaces multi/modeling/features/.ipynb → multi/features//modeling.ipynb"), - (re.compile( - r"(autogalaxy_workspace|autolens_workspace)/blob/main/notebooks/" - r"multi/modeling/start_here\.ipynb" - ), r"\1/blob/main/notebooks/multi/start_here.ipynb", - "workspaces multi/modeling/start_here → multi/start_here"), - (re.compile(r"autolens_workspace/blob/main/notebooks/imaging/features/shapelets/"), - "autolens_workspace/blob/main/notebooks/imaging/features/advanced/shapelets/", - "autolens shapelets under imaging/features/advanced/"), - (re.compile( - r"(autogalaxy_workspace|autolens_workspace|autofit_workspace)/tree/main/notebooks/plot" - ), r"\1/tree/main/notebooks/guides/plot", - "workspaces tree/main/notebooks/plot → notebooks/guides/plot"), - (re.compile( - r"raw\.githubusercontent\.com/(?:rhayes777|PyAutoLabs)/PyAutoFit/feature/docs_update/" - ), "raw.githubusercontent.com/PyAutoLabs/PyAutoFit/main/", - "PyAutoFit docs_update branch images → PyAutoLabs/main"), -] +def _load_pattern_rewrites() -> list[tuple[re.Pattern[str], str, str]]: + """The known URL-fixup rules, from config/url_fixups.yaml (Heart policy — + the sweep's accumulated immune memory; adopter-replaceable). Strict: the + file is in-repo, so a missing/broken file fails loudly.""" + import yaml + + path = Path(__file__).resolve().parents[2] / "config" / "url_fixups.yaml" + rules = yaml.safe_load(path.read_text())["rewrites"] + return [ + (re.compile(r["pattern"]), r["replacement"], r["description"]) + for r in rules + ] + + +KNOWN_PATTERN_REWRITES: list[tuple[re.Pattern[str], str, str]] = _load_pattern_rewrites() + _TOOL_DIR_ABS = Path(__file__).resolve().parent # PyAutoBuild/autobuild