1import urllib.request
2from io import BytesIO
3import os
4from pathlib import Path
5
6
7def download_or_cache(url, version):
8    """
9    Get bytes from the given url or local cache.
10
11    Parameters
12    ----------
13    url : str
14        The url to download.
15    sha : str
16        The sha256 of the file.
17
18    Returns
19    -------
20    BytesIO
21        The file loaded into memory.
22    """
23    cache_dir = _get_xdg_cache_dir()
24
25    if cache_dir is not None:  # Try to read from cache.
26        try:
27            data = (cache_dir / version).read_bytes()
28        except IOError:
29            pass
30        else:
31            return BytesIO(data)
32
33    with urllib.request.urlopen(
34        urllib.request.Request(url, headers={"User-Agent": ""})
35    ) as req:
36        data = req.read()
37
38    if cache_dir is not None:  # Try to cache the downloaded file.
39        try:
40            cache_dir.mkdir(parents=True, exist_ok=True)
41            with open(cache_dir / version, "xb") as fout:
42                fout.write(data)
43        except IOError:
44            pass
45
46    return BytesIO(data)
47
48
49def _get_xdg_cache_dir():
50    """
51    Return the XDG cache directory.
52
53    See https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
54    """
55    cache_dir = os.environ.get("XDG_CACHE_HOME")
56    if not cache_dir:
57        cache_dir = os.path.expanduser("~/.cache")
58        if cache_dir.startswith("~/"):  # Expansion failed.
59            return None
60    return Path(cache_dir, "matplotlib")
61
62
63if __name__ == "__main__":
64    data = {
65        "v3.4.2": "4743323",
66        "v3.4.1": "4649959",
67        "v3.4.0": "4638398",
68        "v3.3.4": "4475376",
69        "v3.3.3": "4268928",
70        "v3.3.2": "4030140",
71        "v3.3.1": "3984190",
72        "v3.3.0": "3948793",
73        "v3.2.2": "3898017",
74        "v3.2.1": "3714460",
75        "v3.2.0": "3695547",
76        "v3.1.3": "3633844",
77        "v3.1.2": "3563226",
78        "v3.1.1": "3264781",
79        "v3.1.0": "2893252",
80        "v3.0.3": "2577644",
81        "v3.0.2": "1482099",
82        "v3.0.1": "1482098",
83        "v2.2.5": "3633833",
84        "v3.0.0": "1420605",
85        "v2.2.4": "2669103",
86        "v2.2.3": "1343133",
87        "v2.2.2": "1202077",
88        "v2.2.1": "1202050",
89        "v2.2.0": "1189358",
90        "v2.1.2": "1154287",
91        "v2.1.1": "1098480",
92        "v2.1.0": "1004650",
93        "v2.0.2": "573577",
94        "v2.0.1": "570311",
95        "v2.0.0": "248351",
96        "v1.5.3": "61948",
97        "v1.5.2": "56926",
98        "v1.5.1": "44579",
99        "v1.5.0": "32914",
100        "v1.4.3": "15423",
101        "v1.4.2": "12400",
102        "v1.4.1": "12287",
103        "v1.4.0": "11451",
104    }
105    doc_dir = Path(__file__).parent.parent.absolute() / "doc"
106    target_dir = doc_dir / "_static/zenodo_cache"
107    citing = doc_dir / "citing.rst"
108    target_dir.mkdir(exist_ok=True, parents=True)
109    header = []
110    footer = []
111    with open(citing, "r") as fin:
112        target = header
113        for ln in fin:
114            if target is not None:
115                target.append(ln.rstrip())
116            if ln.strip() == ".. START OF AUTOGENERATED":
117                target.extend(["", ""])
118                target = None
119            if ln.strip() == ".. END OF AUTOGENERATED":
120                target = footer
121                target.append(ln)
122
123    with open(citing, "w") as fout:
124        fout.write("\n".join(header))
125        for version, doi in data.items():
126            svg_path = target_dir / f"{doi}.svg"
127            if not svg_path.exists():
128                url = f"https://zenodo.org/badge/doi/10.5281/zenodo.{doi}.svg"
129                payload = download_or_cache(url, f"{doi}.svg")
130                with open(svg_path, "xb") as svgout:
131                    svgout.write(payload.read())
132            fout.write(
133                f"""
134{version}
135   .. image:: _static/zenodo_cache/{doi}.svg
136      :target:  https://doi.org/10.5281/zenodo.{doi}"""
137            )
138        fout.write("\n\n")
139        fout.write("\n".join(footer))
140        fout.write('\n')
141