Skip to content

Commit 049ec48

Browse files
authored
Temp fix decade-long Sphinx bug breaking our CSS during partial rebuilds (#2496)
* Add temp fix for Sphinx failing to copy static files * Gate the temp fix feature behind a dev-machine specific file * Move the temp fix into a contained script file + update .gitignore comment * Remove extraneous commits + add annotations and docstrings * Fix broken URL link in docstring * Extra safety for when we notice we shouldn't run * Fix some pathing stuff + test with ./make.py serve * Fix paths * Update top-of-file docstring * Fix dirs
1 parent 7be16ce commit 049ec48

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ temp/
5858
.python-version
5959

6060
.flake8
61+
62+
# pending: Sphinx 8.1.4 + deps are verified as working with Arcade
63+
# see util/sphinx_static_file_temp_fix.py
64+
.ENABLE_DEVMACHINE_SPHINX_STATIC_FIX

doc/conf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
HERE = Path(__file__).resolve()
3030
REPO_LOCAL_ROOT = HERE.parent.parent
31+
3132
ARCADE_MODULE = REPO_LOCAL_ROOT / "arcade"
3233
UTIL_DIR = REPO_LOCAL_ROOT / "util"
3334

@@ -88,14 +89,17 @@ def run_util(filename, run_name="__main__", init_globals=None):
8889

8990
runpy.run_path(full_str, **kwargs)
9091

92+
# Temp fix for Sphinx not copying static files # pending: post-3.0 refactor
93+
# Enable by creating a .ENABLE_DEVMACHINE_SPHINX_STATIC_FIX
94+
run_util("sphinx_static_file_temp_fix.py")
95+
9196
# Make thumbnails for the example code screenshots
9297
run_util("generate_example_thumbnails.py")
9398
# Create a tabular representation of the resources with embeds
9499
run_util("create_resources_listing.py", init_globals=RESOURCE_GLOBALS)
95100
# Run the generate quick API index script
96101
run_util('../util/update_quick_index.py')
97102

98-
99103
autodoc_inherit_docstrings = False
100104
autodoc_default_options = {
101105
'members': True,
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Gets 3.0 out the door by temp fixing Sphinx rebuild not copying CSS.
4+
5+
IMPORTANT: ONLY LOCAL DEVELOPER MACHINES NEED THIS!
6+
7+
## Who should use this?
8+
9+
If `./make.py clean` seems like the only way to get `./make.py html` or
10+
`./make.py serve` to serve your modified CSS, then yes, it's for you.
11+
12+
## How do I use this?
13+
14+
1. `cd` to the repo root
15+
2. `touch .ENABLE_DEVMACHINE_SPHINX_STATIC_FIX`
16+
3. `./make.py html` with working CSS change updates copying
17+
18+
## When should I be careful?
19+
20+
Keep the following in mind:
21+
22+
1. It is a temp fix which *seems* to work with both:
23+
24+
* `./make.py html`
25+
* `./make.py serve`
26+
27+
3. No real config options other on/off via file presence
28+
29+
## What's Broken in Sphinx?
30+
31+
1. Sphinx has a long-standing bug which fails to copy static files
32+
https://github.com/sphinx-doc/sphinx/issues/1810
33+
34+
2. The fix is slated for 8.2.0 and the fix PR merged on Jan 13, 2025:
35+
https://github.com/sphinx-doc/sphinx/pull/13236
36+
37+
3. No, Arcade 3.0 **will not wait** for the following:
38+
39+
1. Sphinx 3.2.0 to ship the fix for the problem
40+
2. Themes to become compatible
41+
3. Plugins to become compatible
42+
4. Our customizations to be tested with all of the above
43+
44+
"""
45+
46+
import sys
47+
import logging
48+
from pathlib import Path
49+
from sphinx import __version__ as sphinx_version
50+
51+
UTIL_DIR = Path(__file__).parent.resolve()
52+
REPO_ROOT = UTIL_DIR.parent.resolve()
53+
54+
# Ensure we get utility & Arcade imports first
55+
sys.path.insert(0, str(REPO_ROOT))
56+
57+
log = logging.getLogger(__name__)
58+
59+
DOC_DIR = REPO_ROOT / "doc"
60+
STATIC_SOURCE_DIR = DOC_DIR / "_static"
61+
62+
ENABLE_DEVMACHINE_SPHINX_STATIC_FIX = REPO_ROOT / ".ENABLE_DEVMACHINE_SPHINX_STATIC_FIX"
63+
64+
BUILD_DIR = REPO_ROOT / "build"
65+
BUILD_HTML_DIR = BUILD_DIR / "html"
66+
BUILD_STATIC_DIR = BUILD_HTML_DIR / "_static"
67+
BUILD_CSS_DIR = BUILD_STATIC_DIR / "css"
68+
69+
STATIC_CSS_DIR = STATIC_SOURCE_DIR / "css"
70+
force_copy_on_change = { # pending: sphinx >= 8.1.4
71+
source_file: BUILD_CSS_DIR / source_file.name
72+
for source_file in STATIC_CSS_DIR.glob("*.css")
73+
}
74+
75+
76+
def force_sync(src: Path, dest: Path, dry: bool = False) -> None:
77+
"""Sync a single file from ``src`` to ``dest``.
78+
79+
Caveats:
80+
81+
1. Assumes both are `pathlib.Path` instances
82+
2. Assumes both are small
83+
3. Fails hard when a file isn't found
84+
85+
"""
86+
if sphinx_version >= '8.1.4':
87+
log.warning(
88+
'Sphinx >= 8.1.4 may patch broken _static copy\n'
89+
' (see https://github.com/sphinx-doc/sphinx/issues/1810)')
90+
try:
91+
if src.read_text() != dest.read_text():
92+
if dry:
93+
log.info(f" DRY : {src} was out of date, but dry run left it as-is!")
94+
# shutil.copyfile(src, dest)
95+
else:
96+
log.info(f" SYNC: {src} was out of date!")
97+
98+
else:
99+
log.info(f" SKIP: {src} is current!")
100+
except Exception as e:
101+
log.error(f" FAIL: {src} failed: {e}")
102+
raise e
103+
104+
105+
def main():
106+
if not ENABLE_DEVMACHINE_SPHINX_STATIC_FIX.exists():
107+
log.info(f"SKIP: Force-sync found no {ENABLE_DEVMACHINE_SPHINX_STATIC_FIX} file!")
108+
return
109+
elif not BUILD_HTML_DIR.exists():
110+
log.info(f"SKIP: {BUILD_HTML_DIR} does not exist yet.")
111+
return
112+
113+
log.info(f"SYNC: Force-sync enable file found")
114+
for src, dest in force_copy_on_change.items():
115+
force_sync(src, dest)
116+
117+
118+
if __name__ == "__main__":
119+
main()

0 commit comments

Comments
 (0)