|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +# Authors: The MNE-Python contributors. |
| 4 | +# License: BSD-3-Clause |
| 5 | +# Copyright the MNE-Python contributors. |
| 6 | + |
| 7 | +import re |
| 8 | +from importlib.metadata import metadata |
| 9 | +from pathlib import Path |
| 10 | + |
| 11 | +from mne.utils import _pl, warn |
| 12 | + |
| 13 | +README_PATH = Path(__file__).parents[2] / "README.rst" |
| 14 | +BEGIN = ".. ↓↓↓ BEGIN CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↓↓↓" |
| 15 | +END = ".. ↑↑↑ END CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↑↑↑" |
| 16 | + |
| 17 | +CORE_DEPS_URLS = { |
| 18 | + "Python": "https://www.python.org", |
| 19 | + "NumPy": "https://numpy.org", |
| 20 | + "SciPy": "https://scipy.org", |
| 21 | + "Matplotlib": "https://matplotlib.org", |
| 22 | + "Pooch": "https://www.fatiando.org/pooch/latest/", |
| 23 | + "tqdm": "https://tqdm.github.io", |
| 24 | + "Jinja2": "https://palletsprojects.com/p/jinja/", |
| 25 | + "decorator": "https://github.com/micheles/decorator", |
| 26 | + "lazy-loader": "https://pypi.org/project/lazy_loader", |
| 27 | + "packaging": "https://packaging.pypa.io/en/stable/", |
| 28 | +} |
| 29 | + |
| 30 | + |
| 31 | +def _prettify_pin(pin): |
| 32 | + if pin is None: |
| 33 | + return "" |
| 34 | + pins = pin.split(",") |
| 35 | + replacements = { |
| 36 | + "<=": " ≤ ", |
| 37 | + ">=": " ≥ ", |
| 38 | + "<": " < ", |
| 39 | + ">": " > ", |
| 40 | + } |
| 41 | + for old, new in replacements.items(): |
| 42 | + pins = [p.replace(old, new) for p in pins] |
| 43 | + pins = reversed(pins) |
| 44 | + return ",".join(pins) |
| 45 | + |
| 46 | + |
| 47 | +# get the dependency info |
| 48 | +py_pin = metadata("mne").get("Requires-Python") |
| 49 | +all_deps = metadata("mne").get_all("Requires-Dist") |
| 50 | +core_deps = [f"python{py_pin}", *[dep for dep in all_deps if "extra ==" not in dep]] |
| 51 | +pattern = re.compile(r"(?P<name>[A-Za-z_\-\d]+)(?P<pin>[<>=]+.*)?") |
| 52 | +core_deps_pins = { |
| 53 | + dep["name"]: _prettify_pin(dep["pin"]) for dep in map(pattern.match, core_deps) |
| 54 | +} |
| 55 | +# don't show upper pin on NumPy (not important for users, just devs) |
| 56 | +new_pin = core_deps_pins["numpy"].split(",") |
| 57 | +new_pin.remove(" < 3") |
| 58 | +core_deps_pins["numpy"] = new_pin[0] |
| 59 | + |
| 60 | +# make sure our URLs dict is minimal and complete |
| 61 | +missing_urls = set(core_deps_pins) - {dep.lower() for dep in CORE_DEPS_URLS} |
| 62 | +extra_urls = {dep.lower() for dep in CORE_DEPS_URLS} - set(core_deps_pins) |
| 63 | +update_msg = ( |
| 64 | + "please update `CORE_DEPS_URLS` mapping in `tools/hooks/sync_dependencies.py`." |
| 65 | +) |
| 66 | +if missing_urls: |
| 67 | + _s = _pl(missing_urls) |
| 68 | + raise RuntimeError( |
| 69 | + f"Missing URL{_s} for package{_s} {', '.join(missing_urls)}; {update_msg}" |
| 70 | + ) |
| 71 | +if extra_urls: |
| 72 | + _s = _pl(extra_urls) |
| 73 | + warn(f"Superfluous URL{_s} for package{_s} {', '.join(extra_urls)}; {update_msg}") |
| 74 | + |
| 75 | +# construct the rST |
| 76 | +core_deps_bullets = [ |
| 77 | + f"- `{key} <{url}>`__{core_deps_pins[key.lower()]}" |
| 78 | + for key, url in CORE_DEPS_URLS.items() |
| 79 | +] |
| 80 | +core_deps_rst = "\n" + "\n".join(core_deps_bullets) + "\n" |
| 81 | + |
| 82 | +# rewrite the README file |
| 83 | +lines = README_PATH.read_text("utf-8").splitlines() |
| 84 | +out_lines = list() |
| 85 | +skip = False |
| 86 | +for line in lines: |
| 87 | + if line.strip() == BEGIN: |
| 88 | + skip = True |
| 89 | + out_lines.append(line) |
| 90 | + out_lines.append(core_deps_rst) |
| 91 | + if line.strip() == END: |
| 92 | + skip = False |
| 93 | + if not skip: |
| 94 | + out_lines.append(line) |
| 95 | +README_PATH.write_text("\n".join(out_lines) + "\n", encoding="utf-8") |
0 commit comments