Skip to content

Commit 98c2726

Browse files
authored
Merge pull request #1529 from scylladb/fix-multiversion-3.4
1 parent 70269ba commit 98c2726

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

extensions/sphinx-multiversion/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
author="Jan Holthuis",
2222
author_email="holthuis.jan@googlemail.com",
2323
url="https://holzhaus.github.io/sphinx-multiversion/",
24-
version="0.3.3",
24+
version="0.3.4",
2525
install_requires=["sphinx >= 2.1"],
2626
license="BSD",
2727
packages=["sphinx_multiversion"],

extensions/sphinx-multiversion/sphinx_multiversion/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from .main import main
33
from .sphinx import setup
44

5-
__version__ = "0.3.3"
5+
__version__ = "0.3.4"
66

77
__all__ = [
88
"setup",

extensions/sphinx-multiversion/sphinx_multiversion/main.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,86 @@ def working_dir(path):
3232
os.chdir(prev_cwd)
3333

3434

35+
def extract_custom_config_vars(confpath, var_names):
36+
"""
37+
Extract custom config variables from conf.py for each branch/tag.
38+
39+
Needed because some variables (like myst_substitutions) aren't registered
40+
with Sphinx's config system and won't be available via Config.read().
41+
42+
This ensures each version gets its own values by executing that version's conf.py.
43+
44+
Args:
45+
confpath: Path to directory containing conf.py
46+
var_names: List of variable names to extract (e.g., ["myst_substitutions"])
47+
48+
Returns:
49+
dict: {var_name: value} for requested variables (None if not found)
50+
"""
51+
conf_file = os.path.join(confpath, "conf.py")
52+
if not os.path.exists(conf_file):
53+
return {var_name: None for var_name in var_names}
54+
55+
logger = logging.getLogger(__name__)
56+
57+
try:
58+
with open(conf_file, "r", encoding="utf-8") as f:
59+
content = f.read()
60+
61+
# Execute conf.py in a minimal namespace
62+
namespace = {
63+
"__file__": conf_file,
64+
"__name__": "__main__",
65+
"__builtins__": __builtins__,
66+
}
67+
68+
# Change to confpath directory so relative imports work
69+
old_cwd = os.getcwd()
70+
old_path = sys.path.copy()
71+
try:
72+
os.chdir(confpath)
73+
sys.path.insert(0, confpath)
74+
75+
# Try to execute the whole file
76+
try:
77+
exec(content, namespace)
78+
except (ImportError, ModuleNotFoundError) as import_err:
79+
# If imports fail, try partial execution by skipping import lines
80+
logger.debug(
81+
"Import failed in %s: %s, trying partial execution",
82+
conf_file,
83+
import_err,
84+
)
85+
86+
lines = content.split("\n")
87+
partial_namespace = namespace.copy()
88+
for i, line in enumerate(lines):
89+
try:
90+
# Skip import lines that might fail
91+
if line.strip().startswith(("import ", "from ")):
92+
continue
93+
exec("\n".join(lines[: i + 1]), partial_namespace)
94+
# Stop early if we've found all requested variables
95+
if all(var in partial_namespace for var in var_names):
96+
namespace = partial_namespace
97+
break
98+
except Exception as _e:
99+
continue
100+
101+
# Extract requested variables
102+
return {var_name: namespace.get(var_name) for var_name in var_names}
103+
104+
finally:
105+
os.chdir(old_cwd)
106+
sys.path = old_path
107+
108+
except Exception as err:
109+
logger.warning(
110+
"Failed to extract custom config variables from %s: %s", conf_file, err
111+
)
112+
return {var_name: None for var_name in var_names}
113+
114+
35115
def load_sphinx_config_worker(q, confpath, confoverrides, add_defaults):
36116
try:
37117
with working_dir(confpath):
@@ -309,7 +389,8 @@ def main(argv=None):
309389
current_sourcedir = os.path.join(repopath, sourcedir)
310390
project = sphinx_project.Project(current_sourcedir, source_suffixes)
311391

312-
myst_substitutions = getattr(current_config, "myst_substitutions", {})
392+
custom_vars = extract_custom_config_vars(confpath, ["myst_substitutions"])
393+
myst_substitutions = custom_vars.get("myst_substitutions") or {}
313394

314395
metadata[gitref.name] = {
315396
"name": gitref.name,

0 commit comments

Comments
 (0)