|
a |
|
b/Docs/conf.py |
|
|
1 |
# -- Project information ----------------------------------------------------- |
|
|
2 |
import os |
|
|
3 |
import re |
|
|
4 |
import subprocess |
|
|
5 |
import sys |
|
|
6 |
from datetime import datetime |
|
|
7 |
from pathlib import Path |
|
|
8 |
|
|
|
9 |
sys.path.insert(0, os.path.abspath("exts")) |
|
|
10 |
sys.path.insert(0, os.path.abspath("tools")) |
|
|
11 |
|
|
|
12 |
|
|
|
13 |
current_year = os.environ.get("YEAR", datetime.now().year) |
|
|
14 |
|
|
|
15 |
|
|
|
16 |
project = "AMMR" |
|
|
17 |
copyright = f"{current_year}, AnyBody Technology" |
|
|
18 |
author = "AnyBody Technology" |
|
|
19 |
# language = "fr" # For testing language translations |
|
|
20 |
|
|
|
21 |
|
|
|
22 |
def tagged_commit(): |
|
|
23 |
"""Check if we are on a tagged commit""" |
|
|
24 |
try: |
|
|
25 |
subprocess.check_call( |
|
|
26 |
["git", "describe", "--tags", "--exact-match", "HEAD"], |
|
|
27 |
stdout=subprocess.DEVNULL, |
|
|
28 |
stderr=subprocess.DEVNULL, |
|
|
29 |
) |
|
|
30 |
except subprocess.CalledProcessError: |
|
|
31 |
return False |
|
|
32 |
else: |
|
|
33 |
return True |
|
|
34 |
|
|
|
35 |
|
|
|
36 |
if tags.has("offline"): |
|
|
37 |
# building offline version |
|
|
38 |
pass |
|
|
39 |
|
|
|
40 |
|
|
|
41 |
if not tagged_commit() and not tags.has("offline"): |
|
|
42 |
tags.add("draft") |
|
|
43 |
|
|
|
44 |
# `todo` and `todoList` produce output, else they produce nothing. |
|
|
45 |
todo_include_todos = tags.has("draft") |
|
|
46 |
|
|
|
47 |
|
|
|
48 |
master_doc = "index" |
|
|
49 |
|
|
|
50 |
# -- General configuration --------------------------------------------------- |
|
|
51 |
|
|
|
52 |
# Add any Sphinx extension module names here, as strings. They can be |
|
|
53 |
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
|
|
54 |
# ones. |
|
|
55 |
extensions = [ |
|
|
56 |
"sphinx.ext.intersphinx", |
|
|
57 |
"sphinx.ext.viewcode", |
|
|
58 |
"sphinx.ext.intersphinx", |
|
|
59 |
"sphinx.ext.todo", |
|
|
60 |
"sphinx.ext.mathjax", |
|
|
61 |
"sphinx.ext.githubpages", |
|
|
62 |
"myst_parser", |
|
|
63 |
"ammr_directives", |
|
|
64 |
"sphinxext.opengraph", |
|
|
65 |
"sphinx_design", |
|
|
66 |
"sphinx_togglebutton", |
|
|
67 |
"sphinx_copybutton", |
|
|
68 |
|
|
|
69 |
# "sphinxcontrib.youtube", |
|
|
70 |
# "sphinx_copybutton", |
|
|
71 |
# "sphinx_design", |
|
|
72 |
# "sphinx_examples", |
|
|
73 |
# "sphinx_tabs.tabs", |
|
|
74 |
# "sphinx_togglebutton", |
|
|
75 |
# "sphinxcontrib.bibtex", |
|
|
76 |
# "sphinxext.opengraph", |
|
|
77 |
# For the kitchen sink |
|
|
78 |
# "sphinx.ext.todo", |
|
|
79 |
] |
|
|
80 |
|
|
|
81 |
|
|
|
82 |
myst_enable_extensions = [ |
|
|
83 |
"colon_fence", |
|
|
84 |
"deflist", |
|
|
85 |
"fieldlist", |
|
|
86 |
"dollarmath", |
|
|
87 |
"amsmath", |
|
|
88 |
"html_image", |
|
|
89 |
"substitution", |
|
|
90 |
"attrs_inline", |
|
|
91 |
] |
|
|
92 |
|
|
|
93 |
# Add any paths that contain templates here, relative to this directory. |
|
|
94 |
# templates_path = ["_templates"] |
|
|
95 |
|
|
|
96 |
|
|
|
97 |
source_suffix = [".rst", ".md"] |
|
|
98 |
|
|
|
99 |
# List of patterns, relative to source directory, that match files and |
|
|
100 |
# directories to ignore when looking for source files. |
|
|
101 |
# This pattern also affects html_static_path and html_extra_path. |
|
|
102 |
exclude_patterns = [ |
|
|
103 |
"_build", |
|
|
104 |
"README.md", |
|
|
105 |
"Thumbs.db", |
|
|
106 |
".DS_Store", |
|
|
107 |
"exts", |
|
|
108 |
"auto_examples", |
|
|
109 |
".pixi", |
|
|
110 |
] |
|
|
111 |
|
|
|
112 |
# The name of the Pygments (syntax highlighting) style to use. |
|
|
113 |
highlight_language = "AnyScriptDoc" |
|
|
114 |
pygments_style = "AnyScript" |
|
|
115 |
|
|
|
116 |
ams_version = os.environ.get("AMS_VERSION", "8.1.0") |
|
|
117 |
if not re.match(r"^\d\.\d\.\d", ams_version): |
|
|
118 |
raise ValueError("Wrong format for AMS version, environment variable") |
|
|
119 |
ams_version_short = ams_version.rpartition(".")[0] |
|
|
120 |
ams_version_x = ams_version_short + ".x" |
|
|
121 |
|
|
|
122 |
|
|
|
123 |
ammr_version = os.environ.get("AMMR_VERSION", None) |
|
|
124 |
if ammr_version is None: |
|
|
125 |
AMMR_VERSION_RE = re.compile(r'.*AMMR_VERSION\s"(?P<version>.*)"') |
|
|
126 |
with open("../AMMR.version.any") as fh: |
|
|
127 |
match = AMMR_VERSION_RE.search(fh.read()) |
|
|
128 |
if match: |
|
|
129 |
ammr_version = match.groupdict()["version"] |
|
|
130 |
else: |
|
|
131 |
raise Exception("Could not parse AMMR version") |
|
|
132 |
|
|
|
133 |
|
|
|
134 |
if not re.match(r"^\d\.\d\.\d", ammr_version): |
|
|
135 |
raise ValueError("Wrong format for AMMR version, environment variable") |
|
|
136 |
|
|
|
137 |
ammr_version_short = ammr_version.rpartition(".")[0] |
|
|
138 |
|
|
|
139 |
rst_epilog = f""" |
|
|
140 |
|
|
|
141 |
.. |AMS| replace:: AnyBody Modeling System™ |
|
|
142 |
.. |AMS_VERSION_X| replace:: {ams_version_x} |
|
|
143 |
.. |AMS_VERSION| replace:: {ams_version} |
|
|
144 |
.. |AMS_VERSION_SHORT| replace:: {ams_version_short} |
|
|
145 |
.. |AMMR_VERSION_SHORT| replace:: {ammr_version_short} |
|
|
146 |
.. |AMMR_VERSION| replace:: {ammr_version} |
|
|
147 |
.. |AMMR_DEMO_INST_DIR| replace:: :literal:`~/Documents/{ams_version_x}/AMMR.v{ammr_version}-Demo` |
|
|
148 |
.. |CURRENT_YEAR| replace:: {current_year} |
|
|
149 |
.. |WHAT_IS_NEW| replace:: :ref:`What's new in AMMR {ammr_version} <whats-new>` |
|
|
150 |
.. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.10527958.svg |
|
|
151 |
:target: https://doi.org/10.5281/zenodo.10527958 |
|
|
152 |
""" |
|
|
153 |
|
|
|
154 |
myst_substitutions = { |
|
|
155 |
"AMS": "AnyBody Modeling System™", |
|
|
156 |
"AMS_VERSION_X": ams_version_x, |
|
|
157 |
"AMS_VERSION": ams_version_x, |
|
|
158 |
"AMS_VERSION_SHORT": ams_version_short, |
|
|
159 |
"AMMR_VERSION_SHORT": ams_version_short, |
|
|
160 |
"AMMR_VERSION": ammr_version, |
|
|
161 |
"CURRENT_YEAR": current_year, |
|
|
162 |
"AMMR_DEMO_INST_DIR": f"`~/Documents/{ams_version_x}/AMMR.v{ammr_version}-Demo`", |
|
|
163 |
"DOI": "[](https://doi.org/10.5281/zenodo.10527958)", |
|
|
164 |
"WHAT_IS_NEW": f"{{ref}}`What's new in AMMR {ammr_version} <whats-new>`", |
|
|
165 |
"WHAT_IS_NEW2": f"{{material-outlined}}`update;1em` New in AMMR {ammr_version}", |
|
|
166 |
} |
|
|
167 |
|
|
|
168 |
|
|
|
169 |
no_index = """ |
|
|
170 |
.. meta:: |
|
|
171 |
:robots: noindex |
|
|
172 |
""" |
|
|
173 |
myst_html_meta = {} |
|
|
174 |
|
|
|
175 |
if tags.has("draft"): |
|
|
176 |
rst_epilog = rst_epilog + no_index |
|
|
177 |
myst_html_meta["robots"] = "noindex" |
|
|
178 |
|
|
|
179 |
github_doc_root = "https://github.com/AnyBody/ammr/tree/master/Docs" |
|
|
180 |
|
|
|
181 |
version = f"{ammr_version_short}" |
|
|
182 |
# The full version, including alpha/beta/rc tags. |
|
|
183 |
release = f"{ammr_version}" |
|
|
184 |
|
|
|
185 |
if tags.has("draft") and not release.endswith("beta"): |
|
|
186 |
release = release + "-beta" |
|
|
187 |
|
|
|
188 |
|
|
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
|
192 |
# suppress_warnings = ["myst.domains", "ref.ref"] |
|
|
193 |
|
|
|
194 |
numfig = True |
|
|
195 |
|
|
|
196 |
|
|
|
197 |
|
|
|
198 |
# -- Options for HTML output ------------------------------------------------- |
|
|
199 |
|
|
|
200 |
# The theme to use for HTML and HTML Help pages. See the documentation for |
|
|
201 |
# a list of builtin themes. |
|
|
202 |
# |
|
|
203 |
html_theme = "sphinx_book_theme" |
|
|
204 |
# html_logo = "_static/logo-wide.svg" |
|
|
205 |
html_title = f"{project} v{release} Documentation" |
|
|
206 |
html_copy_source = False |
|
|
207 |
# html_favicon = "_static/logo-square.svg" |
|
|
208 |
html_last_updated_fmt = "" |
|
|
209 |
|
|
|
210 |
# html_sidebars = { |
|
|
211 |
# "reference/blog/*": [ |
|
|
212 |
# "navbar-logo.html", |
|
|
213 |
# "search-field.html", |
|
|
214 |
# "ablog/postcard.html", |
|
|
215 |
# "ablog/recentposts.html", |
|
|
216 |
# "ablog/tagcloud.html", |
|
|
217 |
# "ablog/categories.html", |
|
|
218 |
# "ablog/archives.html", |
|
|
219 |
# "sbt-sidebar-nav.html", |
|
|
220 |
# ] |
|
|
221 |
# } |
|
|
222 |
# Add any paths that contain custom static files (such as style sheets) here, |
|
|
223 |
# relative to this directory. They are copied after the builtin static files, |
|
|
224 |
# so a file named "default.css" will overwrite the builtin "default.css". |
|
|
225 |
html_static_path = ["_static", "body/_static"] |
|
|
226 |
html_css_files = ["_static/custom.css"] |
|
|
227 |
|
|
|
228 |
|
|
|
229 |
html_logo = "_static/AMMR.svg" |
|
|
230 |
html_favicon = "_static/favicon.ico" |
|
|
231 |
|
|
|
232 |
|
|
|
233 |
html_theme_options = { |
|
|
234 |
"path_to_docs": "Docs", |
|
|
235 |
"repository_url": "https://github.com/anybody/ammr", |
|
|
236 |
"repository_branch": "master", |
|
|
237 |
"use_edit_page_button": True, |
|
|
238 |
"use_source_button": True, |
|
|
239 |
"use_issues_button": False, |
|
|
240 |
"use_repository_button": True, |
|
|
241 |
"use_download_button": False, |
|
|
242 |
|
|
|
243 |
"home_page_in_toc": False, |
|
|
244 |
"show_toc_level": 1, |
|
|
245 |
|
|
|
246 |
"pygment_light_style": "AnyScript", |
|
|
247 |
"pygment_dark_style": "stata-dark", |
|
|
248 |
|
|
|
249 |
|
|
|
250 |
# "use_sidenotes": True, |
|
|
251 |
# "announcement": ( |
|
|
252 |
# "⚠️The latest release refactored our HTML, " |
|
|
253 |
# "so double-check your custom CSS rules!⚠️" |
|
|
254 |
# ), |
|
|
255 |
"logo": { |
|
|
256 |
"image_dark": "_static/AMMR.svg", |
|
|
257 |
# "text": html_title, # Uncomment to try text with logo |
|
|
258 |
}, |
|
|
259 |
"icon_links": [ |
|
|
260 |
# { |
|
|
261 |
# "name": "AnyBody Technology", |
|
|
262 |
# "url": "https://anybodytech.com/", |
|
|
263 |
# # "icon": "_static/ebp-logo.png", |
|
|
264 |
# "type": "local", |
|
|
265 |
# }, |
|
|
266 |
# { |
|
|
267 |
# "name": "GitHub", |
|
|
268 |
# "url": "https://github.com/anybody/ammr", |
|
|
269 |
# "icon": "fa-brands fa-github", |
|
|
270 |
# }, |
|
|
271 |
], |
|
|
272 |
# For testing |
|
|
273 |
# "use_fullscreen_button": False, |
|
|
274 |
# "home_page_in_toc": True, |
|
|
275 |
# "extra_footer": "<a href='https://google.com'>Test</a>", # DEPRECATED KEY |
|
|
276 |
# "show_navbar_depth": 2, |
|
|
277 |
# Testing layout areas |
|
|
278 |
# "navbar_start": ["test.html"], |
|
|
279 |
# "navbar_center": ["test.html"], |
|
|
280 |
# "navbar_end": ["test.html"], |
|
|
281 |
# "navbar_persistent": ["test.html"], |
|
|
282 |
# "footer_start": ["test.html"], |
|
|
283 |
# "footer_end": ["test.html"] |
|
|
284 |
} |
|
|
285 |
|
|
|
286 |
bibtex_bibfiles = ["references.bib"] |
|
|
287 |
# To test that style looks good with common bibtex config |
|
|
288 |
bibtex_reference_style = "author_year" |
|
|
289 |
bibtex_default_style = "plain" |
|
|
290 |
numpydoc_show_class_members = False # for automodule:: urllib.parse stub file issue |
|
|
291 |
linkcheck_ignore = [ |
|
|
292 |
"http://someurl/release", # This is a fake link |
|
|
293 |
"https://doi.org", # These don't resolve properly and cause SSL issues |
|
|
294 |
] |
|
|
295 |
|
|
|
296 |
|
|
|
297 |
|
|
|
298 |
intersphinx_mapping = {} |
|
|
299 |
if tags.has("offline"): |
|
|
300 |
# Todo. Find a way to link to offline html versions. |
|
|
301 |
intersphinx_mapping["tutorials"] = ("https://anyscript.org/tutorials/", None) |
|
|
302 |
else: |
|
|
303 |
if tags.has("draft"): |
|
|
304 |
intersphinx_mapping["tutorials"] = ( |
|
|
305 |
"https://anyscript.org/tutorials/beta/", |
|
|
306 |
None, |
|
|
307 |
) |
|
|
308 |
else: |
|
|
309 |
intersphinx_mapping["tutorials"] = ("https://anyscript.org/tutorials/", None) |
|
|
310 |
|
|
|
311 |
|
|
|
312 |
|
|
|
313 |
# sphinxext.opengraph |
|
|
314 |
# ogp_social_cards = { |
|
|
315 |
# "image": "_static/logo-square.png", |
|
|
316 |
# } |
|
|
317 |
|
|
|
318 |
ogp_site_url = "https://anyscript.org/" |
|
|
319 |
ogp_site_name = "AMMR Documentation" |
|
|
320 |
ogp_image = "https://anyscript.org/ammr/_static/AMMR_Logo.png" |
|
|
321 |
ogp_use_first_image = True # if not found defaults to 'ogp_image' |
|
|
322 |
|
|
|
323 |
|
|
|
324 |
# Generate gallery files |
|
|
325 |
import frontmatter |
|
|
326 |
import jinja2 |
|
|
327 |
|
|
|
328 |
gallery = {} |
|
|
329 |
galleryfolders = [x for x in Path("Applications").iterdir() if x.is_dir()] |
|
|
330 |
for folder in galleryfolders: |
|
|
331 |
gallery[folder] = [] |
|
|
332 |
for file in sorted(folder.glob("*.md"), key=lambda x: x.name.upper()): |
|
|
333 |
post = frontmatter.load(file) |
|
|
334 |
if "gallery_title" in post: |
|
|
335 |
gallery[folder].append( |
|
|
336 |
{ |
|
|
337 |
"doc": file.with_suffix("").as_posix(), |
|
|
338 |
"title": post["gallery_title"], |
|
|
339 |
"image": post["gallery_image"], |
|
|
340 |
} |
|
|
341 |
) |
|
|
342 |
|
|
|
343 |
|
|
|
344 |
with open("Applications/gallery.txt.jinja2") as fh: |
|
|
345 |
gallery_template = jinja2.Template(fh.read()) |
|
|
346 |
|
|
|
347 |
for folder, section in gallery.items(): |
|
|
348 |
gallery_txt = folder / "gallery.txt" |
|
|
349 |
content = gallery_template.render(examples=section) |
|
|
350 |
with open(gallery_txt, encoding="utf8") as fh: |
|
|
351 |
previous_content = fh.read() |
|
|
352 |
if content != previous_content: |
|
|
353 |
with open(gallery_txt, "w", encoding="utf8") as fh: |
|
|
354 |
fh.write(content) |
|
|
355 |
|
|
|
356 |
# Run the python file "tools/generate_class_template_docs.py" |
|
|
357 |
# to generate the class template documentation |
|
|
358 |
|
|
|
359 |
import generate_class_template_docs |
|
|
360 |
|
|
|
361 |
generate_class_template_docs.run_all() |
|
|
362 |
|
|
|
363 |
|
|
|
364 |
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" |
|
|
365 |
|
|
|
366 |
linkcheck_ignore = [ |
|
|
367 |
r".*linkcheck_ignore", |
|
|
368 |
"https://doi.org/10.1115/1.4037100", # asme.org prevents the linkcheck |
|
|
369 |
"https://doi.org/10.1115/1.4052115", # asme.org prevents the linkcheck |
|
|
370 |
"https://dx.doi.org/10.1115/1.4001678", # asme.org prevents the linkcheck |
|
|
371 |
"https://dx.doi.org/10.1115/1.4029258", # asme.org prevents the linkcheck |
|
|
372 |
"https://doi.org/10.1080/10255842.2020.1851367", # tandfonline.com prevents the linkcheck |
|
|
373 |
"https://dx.doi.org/10.1002/jor.20255", # wiley.com prevents the linkcheck |
|
|
374 |
"https://doi.org/10.1016/j.clinbiomech.2006.10.003", # clinbiomech.com prevents the linkcheck |
|
|
375 |
"https://doi.org/10.1002/jor.25267", # wiley.com prevents the linkcheck |
|
|
376 |
"https://web.archive.org*", # web.archive.org is currently down due to hacking atacks |
|
|
377 |
"https://doi.org/10.5281/zenodo.15094590", # version not released yet |
|
|
378 |
] |
|
|
379 |
|
|
|
380 |
linkcheck_allowed_redirects = { |
|
|
381 |
"https://doi.org.*": ".*", |
|
|
382 |
"https://dx.doi.org.*": ".*", |
|
|
383 |
"https://www.anybodytech.com/download/anybodysetup.*": ".*", |
|
|
384 |
} |
|
|
385 |
|
|
|
386 |
def setup(app): |
|
|
387 |
... |