|
48 | 48 | def setup(app):
|
49 | 49 | RedirectFrom.app = app
|
50 | 50 | app.add_directive("redirect-from", RedirectFrom)
|
| 51 | + app.connect("env-before-read-docs", _setup_redirects) |
| 52 | + app.connect("env-merge-info", _merge_redirects) |
| 53 | + app.connect("env-purge-doc", _purge_redirects) |
51 | 54 | app.connect("build-finished", _generate_redirects)
|
52 | 55 |
|
| 56 | + metadata = {'parallel_read_safe': True} |
| 57 | + return metadata |
| 58 | + |
53 | 59 |
|
54 | 60 | class RedirectFrom(Directive):
|
55 | 61 | required_arguments = 1
|
56 |
| - redirects = {} |
57 | 62 |
|
58 | 63 | def run(self):
|
59 | 64 | redirected_doc, = self.arguments
|
60 | 65 | env = self.app.env
|
61 | 66 | builder = self.app.builder
|
62 | 67 | current_doc = env.path2doc(self.state.document.current_source)
|
63 | 68 | redirected_reldoc, _ = env.relfn2path(redirected_doc, current_doc)
|
64 |
| - if redirected_reldoc in self.redirects: |
| 69 | + if redirected_reldoc in env._redirects: |
65 | 70 | raise ValueError(
|
66 | 71 | f"{redirected_reldoc} is already noted as redirecting to "
|
67 |
| - f"{self.redirects[redirected_reldoc]}") |
68 |
| - self.redirects[redirected_reldoc] = builder.get_relative_uri( |
| 72 | + f"{env._redirects[redirected_reldoc]}") |
| 73 | + env._redirects[redirected_reldoc] = builder.get_relative_uri( |
69 | 74 | redirected_reldoc, current_doc)
|
70 | 75 | return []
|
71 | 76 |
|
72 | 77 |
|
| 78 | +def _setup_redirects(app, env, docnames): |
| 79 | + if not hasattr(env, "_redirects"): |
| 80 | + env._redirects = {} |
| 81 | + |
| 82 | + |
| 83 | +def _merge_redirects(app, env, docnames, other): |
| 84 | + for src, dst in other._redirects.items(): |
| 85 | + if src not in env._redirects: |
| 86 | + env._redirects[src] = dst |
| 87 | + elif env._redirects[src] != dst: |
| 88 | + raise ValueError(f"{src} is already noted as redirecting to {dst}") |
| 89 | + |
| 90 | + |
| 91 | +def _purge_redirects(app, env, docname): |
| 92 | + env._redirects.clear() |
| 93 | + |
| 94 | + |
73 | 95 | def _generate_redirects(app, exception):
|
74 | 96 | builder = app.builder
|
75 | 97 | if builder.name != "html" or exception:
|
76 | 98 | return
|
77 |
| - for k, v in RedirectFrom.redirects.items(): |
| 99 | + for k, v in app.env._redirects.items(): |
78 | 100 | p = Path(app.outdir, k + builder.out_suffix)
|
79 | 101 | if p.is_file():
|
80 | 102 | logger.warning(f'A redirect-from directive is trying to create '
|
|
0 commit comments