-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Examples page #7
Merged
Merged
Changes from 66 commits
Commits
Show all changes
113 commits
Select commit
Hold shift + click to select a range
b1d05ba
Add openmm cookbook
Yoshanuikabundi 6ee79d7
Examples progress
Yoshanuikabundi 413c1a7
Remove sphinx_gallery
Yoshanuikabundi 75f45dc
Add gitpython to lint environment
Yoshanuikabundi 45e6bd3
Remove nbsphinx_prolog
Yoshanuikabundi d8f197e
Download zip files with notebooks and files, not just notebooks
Yoshanuikabundi cd59e3e
Pre-processing notebooks basically works
Yoshanuikabundi 7479768
Execute notebooks in parallel and only update changed notebooks
Yoshanuikabundi 08dfb53
Set INTERCHANGE_EXPERIMENTAL and simplify delay code
Yoshanuikabundi 2bacdde
Notes to self
Yoshanuikabundi d773f31
Interim fixes for extension
Yoshanuikabundi 7926fb4
Fix module stuff
Yoshanuikabundi 96dbb8f
Clean up removed notebooks and download latest release examples
Yoshanuikabundi a214387
Get the sphinx extension building the processed stuff
Yoshanuikabundi 2c92744
Proof of concept gallery
Yoshanuikabundi 975fa72
Simplify code and fix warnings
Yoshanuikabundi ac0a263
Fix css in cookbook
Yoshanuikabundi 79f2e8a
Finish transition to MyST-NB
Yoshanuikabundi 97a2705
Temporary fix for NGLView widgets.
Yoshanuikabundi 7215221
Process all notebooks in single folder
Yoshanuikabundi b7a46e1
Refactor towards caching notebooks on Git branch
Yoshanuikabundi 7fbaac3
Avoid unnecessary API requests AKA Generators are cool & I am a nerd
Yoshanuikabundi fa6b6b9
Order Sphinx hooks chronologically
Yoshanuikabundi 0c956e7
Application -> Sphinx
Yoshanuikabundi 23912d3
Typos
Yoshanuikabundi 7071026
Merge branch 'cookbook_gha' into examples
Yoshanuikabundi 3a644c8
Merge branch 'main' into examples
Yoshanuikabundi f8d3a90
Fix colab link generation
Yoshanuikabundi 1b50d0f
Download cache if pre-processed notebooks are missing
Yoshanuikabundi 69f9d21
Print out git version
Yoshanuikabundi a851793
Troubleshooting improvements for broken examples
Yoshanuikabundi eea7e04
Remove unnecessary + redundant remove_notebooks function
Yoshanuikabundi 9d15655
Ping github in sphinx extension to test RTD internet access
Yoshanuikabundi 512e8bd
Try multiping
Yoshanuikabundi 4ed8dea
Remove ping test
Yoshanuikabundi 3492931
Try cloning in RTD hook
Yoshanuikabundi 8975f9c
Simplify git command
Yoshanuikabundi 86a5b81
mv -> rsync
Yoshanuikabundi c09b28a
Install rsync + git
Yoshanuikabundi 870fb42
Remove ls command
Yoshanuikabundi 1746529
Don't print git version
Yoshanuikabundi 5fde2ab
Fix include_css_files()
Yoshanuikabundi d3a993c
Remove unused imports
Yoshanuikabundi 625736d
Move notebook grid CSS out of extension
Yoshanuikabundi 5c8be5a
Update lint environment
Yoshanuikabundi 0b8f567
Merge branch 'main' into examples
Yoshanuikabundi 26f49bf
Exclude examples from link checker
Yoshanuikabundi fe95db1
Remove annoying print statement
Yoshanuikabundi 7c3604b
Debug link check ignore conf
Yoshanuikabundi 23cb681
Move linkcheck exclusions to sphinx extension
Yoshanuikabundi d3bdbce
Fix linkcheck exclusions
Yoshanuikabundi ff4b45b
Tell MyST-NB about codelinter
Yoshanuikabundi bf28b5c
Merge branch 'main' into examples
Yoshanuikabundi fd77c1e
Parse tag out of repo list
Yoshanuikabundi 25c9e3e
Copy thumbnails correctly
Yoshanuikabundi d3e1308
Get thumbnails into gallery
Yoshanuikabundi 6adbb09
Break up _cookbook.py
Yoshanuikabundi ba7ac0a
Formatting
Yoshanuikabundi a26c0a0
Pin nglview>=3.0.6 and remove JS included therein
Yoshanuikabundi 42ba5b3
Initial category support
Yoshanuikabundi 618337f
Rejib cache paths
Yoshanuikabundi ebdadbe
Add fragmenter and reminder for QCSubmit
Yoshanuikabundi 5a9423d
Disable fragmenter for now
Yoshanuikabundi 5c3bf09
Move zipped notebooks to source directory
Yoshanuikabundi 1a822b1
Support categories in cookbook
Yoshanuikabundi 9f17df0
Tweak categories and switch to new interchange branch
Yoshanuikabundi 9576cd6
Print env in rtd and update TK/Interchange
Yoshanuikabundi 4d30f76
Try and enable custom widgets in colab
Yoshanuikabundi 189bbd9
Support branch/pr caches and update main every night
Yoshanuikabundi d76f3aa
Fix inputs
Yoshanuikabundi 4087b98
Ergonomics
Yoshanuikabundi 0b2b619
Ensure deploy subdirectory exists
Yoshanuikabundi 532e455
Fix ergonomics
Yoshanuikabundi 1b4b9bb
Add --ignore-unmatch
Yoshanuikabundi 6969dff
Use multiline string in .readthedocs.yaml
Yoshanuikabundi 1de772a
Use old-style test in readthedocs.yaml
Yoshanuikabundi d86b2d6
String equality in .readthedocs.yaml
Yoshanuikabundi 6336d79
Debug rtd with ls
Yoshanuikabundi 0823436
Try ls --tree
Yoshanuikabundi 0c423ea
Work around absence of --tree
Yoshanuikabundi c1b4b81
Fix cache download path
Yoshanuikabundi 222a143
Debug rtd
Yoshanuikabundi 553b56b
Try apt-get tree
Yoshanuikabundi 30ff339
Fix source path?
Yoshanuikabundi f610d71
Move glob outside of quotes
Yoshanuikabundi b1cdd08
Simplify .readthedocs.yaml
Yoshanuikabundi 620964c
Include branch in colab link
Yoshanuikabundi 03d1d40
Update colab links in Sphinx extension
Yoshanuikabundi d565d10
Consolidate code between .readthedocs.yaml and python
Yoshanuikabundi 90231a6
Fix argument handling in proc_examples.py
Yoshanuikabundi 5b13759
Fix import
Yoshanuikabundi c17a1c7
Swap quotes
Yoshanuikabundi b155ab9
Try backtick shell expansion
Yoshanuikabundi 56fad31
Use shell logic in .readthedocs.yaml
Yoshanuikabundi 139b9a4
Clean up PR cache when closed
Yoshanuikabundi 7d43834
Trigger RTD build when cache is updated (except in PRs)
Yoshanuikabundi 0c28089
Merge branch 'main' into examples
Yoshanuikabundi f60ed11
Clarify description
Yoshanuikabundi 7143205
Single quotes
Yoshanuikabundi fa10eee
Show source repository in gallery
Yoshanuikabundi b45fdb2
Style top-of-notebook links
Yoshanuikabundi 90effe8
Add experimental warnings and improve styling
Yoshanuikabundi 3ed8f85
Newline in css
Yoshanuikabundi 33b77bb
globals -> globals_
Yoshanuikabundi 8ed4661
Switch run_notebook.sh to use jupyterlab
Yoshanuikabundi 0689914
Add installation instructions
Yoshanuikabundi a2b33a9
zip -> tgz
Yoshanuikabundi 3c53bfe
Add CLI example for run_notebook.sh
Yoshanuikabundi 52d05dc
Simplify
Yoshanuikabundi 457ae4b
Fix old imports
Yoshanuikabundi 0350a44
More robust run_notebook.sh
Yoshanuikabundi dfcc8de
Migrate to setup-micromamba
Yoshanuikabundi 708dc2e
ZIP -> .TGZ in install instructions
Yoshanuikabundi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
build/ | ||
|
||
# Cookbook files | ||
source/examples/ | ||
source/_cookbook/ | ||
|
||
# Python stuff | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
"""Implementation of the cookbook Sphinx extension""" | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
import json | ||
from os import stat | ||
from pathlib import Path | ||
import shutil | ||
|
||
from sphinx.application import Sphinx | ||
from sphinx.config import Config | ||
|
||
from .github import download_dir | ||
from .notebook import ( | ||
insert_cell, | ||
get_metadata, | ||
find_notebooks, | ||
notebook_zip, | ||
set_metadata, | ||
) | ||
from .globals import ( | ||
EXEC_IPYNB_ROOT, | ||
REPO_EXAMPLES_DIR, | ||
CACHE_BRANCH, | ||
COLAB_IPYNB_ROOT, | ||
OPENFF_DOCS_ROOT, | ||
ZIPPED_IPYNB_ROOT, | ||
GITHUB_REPOS, | ||
) | ||
|
||
|
||
def inject_tags_index(notebook: dict) -> dict: | ||
"""Inject an `index` directive containing the notebook's metadata tags""" | ||
|
||
tags = get_metadata(notebook, "tags", ["untagged"]) | ||
|
||
return insert_cell( | ||
notebook, | ||
cell_type="markdown", | ||
source=[ | ||
f"```{{index}} {', '.join(tags)}", | ||
f"```", | ||
], | ||
) | ||
|
||
|
||
def inject_links(app: Sphinx, notebook: dict, docpath: Path) -> dict: | ||
user, repo, *path = str(docpath.relative_to(EXEC_IPYNB_ROOT)).split("/") | ||
path = "/".join(path) | ||
|
||
tag = get_metadata(notebook, "src_repo_tag", "main") | ||
|
||
github_uri = ( | ||
f"https://github.com/{user}/{repo}/blob/{tag}/{REPO_EXAMPLES_DIR}/{path}" | ||
) | ||
|
||
# TODO: Test colab | ||
colab_path = COLAB_IPYNB_ROOT.relative_to(OPENFF_DOCS_ROOT) / user / repo / path | ||
colab_uri = f"https://colab.research.google.com/github/openforcefield/openff-docs/blob/{CACHE_BRANCH}/{colab_path}" | ||
|
||
zip_path = notebook_zip(docpath).relative_to(app.srcdir) | ||
|
||
return insert_cell( | ||
notebook, | ||
cell_type="markdown", | ||
source=[ | ||
f"[Download Notebook](path:/{zip_path})", | ||
f"[View in GitHub]({github_uri})", | ||
f"[Open in Google Colab]({colab_uri})", | ||
], | ||
) | ||
|
||
|
||
def process_notebook(app: Sphinx, docname: str, source: list[str]): | ||
docpath = Path(app.env.doc2path(docname)) | ||
if docpath.suffix != ".ipynb": | ||
return | ||
|
||
notebook = json.loads(source[0]) | ||
|
||
notebook = inject_links(app, notebook, docpath) | ||
notebook = inject_tags_index(notebook) | ||
|
||
# Tell Sphinx we don't expect this notebook to show up in a toctree | ||
set_metadata(notebook, "orphan", True) | ||
|
||
source[0] = json.dumps(notebook) | ||
|
||
|
||
def download_cached_notebooks(app: Sphinx, config: Config): | ||
""" | ||
Download notebooks from the cache iff they do not exist. | ||
|
||
Note that the cache is not checked for changes; if you want to refresh the | ||
cache, you must manually delete it. | ||
""" | ||
for directory in [ | ||
COLAB_IPYNB_ROOT, | ||
EXEC_IPYNB_ROOT, | ||
ZIPPED_IPYNB_ROOT, | ||
]: | ||
for repo in GITHUB_REPOS: | ||
repo, _, tag = repo.partition("#") | ||
repo_directory = directory / repo | ||
if not repo_directory.exists(): | ||
download_dir( | ||
"openforcefield/openff-docs", | ||
str(repo_directory.relative_to(OPENFF_DOCS_ROOT)), | ||
repo_directory, | ||
refspec=CACHE_BRANCH, | ||
) | ||
|
||
# Exclude notebooks from linkcheck | ||
config["linkcheck_exclude_documents"].extend( | ||
str(doc.relative_to(app.srcdir)) for doc in Path(EXEC_IPYNB_ROOT).glob("**/*") | ||
) | ||
|
||
|
||
def find_notebook_docnames(app, env, docnames): | ||
"""Find the downloaded notebooks and make sure Sphinx sees them""" | ||
for path in find_notebooks(EXEC_IPYNB_ROOT): | ||
docname = env.project.path2doc(str(path)) | ||
docnames.append(docname) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
from pathlib import Path | ||
|
||
from sphinx.environment import BuildEnvironment | ||
from sphinx.util.docutils import SphinxDirective | ||
import sphinx.addnodes | ||
import docutils.nodes | ||
from sphinx.writers.html5 import HTML5Translator | ||
from docutils.parsers.rst.directives import choice | ||
from sphinx.application import Sphinx | ||
|
||
from ._cookbook import find_notebooks | ||
from .globals import EXEC_IPYNB_ROOT | ||
from .utils import flatten | ||
|
||
|
||
class CookbookDirective(SphinxDirective): | ||
""" | ||
Directive to draw thumbnails of the cookbook. | ||
|
||
The "categories" option specifies the categories of notebooks that should be | ||
included in this cookbook. It is a comma-separated string listing category | ||
names. Omitting this option will include all categories. The | ||
names "uncategorized" and "other" are special; "uncategorized" is applied | ||
to any notebook without a category, whereas "other" will include all | ||
categories not rendered in a cookbook somewhere else on the same page as | ||
the current directive (possibly including "uncategorized"). | ||
""" | ||
|
||
optional_arguments = 1 | ||
option_spec = { | ||
"categories": lambda x: [ | ||
s.strip().lower().replace("-", "_") for s in str(x).split(",") | ||
], | ||
} | ||
has_content = False | ||
|
||
def run(self): | ||
node = CookbookNode(categories=self.options.get("categories", [])) | ||
|
||
for path in find_notebooks(EXEC_IPYNB_ROOT): | ||
entry = CookbookEntryNode.from_path(self.env, path) | ||
node.append(entry) | ||
|
||
return [node] | ||
|
||
|
||
class CookbookNode(docutils.nodes.Element): | ||
"""Docutils node representing the cookbook directive""" | ||
|
||
def __init__( | ||
self, | ||
categories: list[str] | None = None, | ||
*args, | ||
**kwargs, | ||
): | ||
self.categories: list[str] = categories if categories else [] | ||
self.children: list[CookbookEntryNode] | ||
return super().__init__(*args, **kwargs) | ||
|
||
@staticmethod | ||
def visit(translator: HTML5Translator, node: "CookbookNode"): | ||
"""Render the CookbookNode in HTML""" | ||
translator.body.append("<div class='notebook-grid'>") | ||
|
||
@staticmethod | ||
def depart(translator: HTML5Translator, node: "CookbookNode"): | ||
"""Render the CookbookNode in HTML""" | ||
translator.body.append("</div>") | ||
|
||
|
||
class CookbookEntryNode(docutils.nodes.Element): | ||
def __init__( | ||
self, | ||
docname: str, | ||
thumbnail_uri: str = "https://openforcefield.org/about/branding/img/openforcefield_v2_full-color.png", | ||
*args, | ||
**kwargs, | ||
): | ||
"""The absolute path to the notebook.""" | ||
self.docname: str = docname | ||
"""The docname of the notebook.""" | ||
self.uri: str | None = None | ||
"""URI of the built notebook.""" | ||
self.title: str | None = None | ||
"""Title of the notebook.""" | ||
|
||
super().__init__(*args, **kwargs) | ||
|
||
self.append( | ||
docutils.nodes.image( | ||
"", | ||
uri=thumbnail_uri, | ||
alt="", | ||
candidates={"?": ""}, | ||
classes=["output", "image_png"], | ||
) | ||
) | ||
|
||
@classmethod | ||
def from_path(cls, env: BuildEnvironment, path: Path) -> "CookbookEntryNode": | ||
docname = env.path2doc(str(path)) | ||
|
||
if docname is None: | ||
raise ValueError( | ||
f"path {path} is not a document in this Sphinx environment.", | ||
) | ||
|
||
if path.with_name("thumbnail.png").is_file(): | ||
thumbnail_uri = str(path.with_name("thumbnail.png").relative_to(env.srcdir)) | ||
return cls(docname=docname, thumbnail_uri=thumbnail_uri) | ||
|
||
return cls(docname=docname) | ||
|
||
@staticmethod | ||
def visit(translator: HTML5Translator, node: CookbookNode): | ||
"""Render the CookbookEntryNode in HTML""" | ||
translator.body.extend( | ||
[ | ||
f"<a class='notebook-grid-elem' href={node.uri}>", | ||
] | ||
) | ||
|
||
@staticmethod | ||
def depart(translator: HTML5Translator, node: CookbookNode): | ||
"""Render the CookbookEntryNode in HTML""" | ||
translator.body.extend( | ||
[ | ||
"<div class='caption'>", | ||
node.title, | ||
"</div>", | ||
"</a>", | ||
] | ||
) | ||
|
||
|
||
def proc_cookbook_toctree( | ||
app: Sphinx, | ||
doctree: sphinx.addnodes.document, | ||
docname: str, | ||
): | ||
"""Update the cookbook with URIs and titles""" | ||
metadata = app.env.metadata | ||
|
||
cookbook_nodes = [*doctree.findall(CookbookNode)] | ||
|
||
# Get the categories that are in a cookbook directive on this page | ||
categories_on_page = {*flatten(node.categories for node in cookbook_nodes)} | ||
|
||
for cookbook_node in cookbook_nodes: | ||
cookbook_categories = cookbook_node.categories | ||
|
||
if cookbook_categories: | ||
# "uncategorised" is a special category for notebooks whose metadata | ||
# doesn't specify a category | ||
cookbook_entries_with_categories = ( | ||
(entry, metadata[entry.docname].get("category", "uncategorized")) | ||
for entry in cookbook_node.children | ||
) | ||
# "other" is a special category for cookbook directives that should | ||
# include all notebooks not rendered in any other category on the | ||
# current page. | ||
# TODO: Make this all notebooks not rendered in the entire project? | ||
cookbook_node.children = [ | ||
entry | ||
for entry, entry_category in cookbook_entries_with_categories | ||
if entry_category in cookbook_categories | ||
or ( | ||
"other" in cookbook_categories | ||
and entry_category not in categories_on_page | ||
) | ||
] | ||
|
||
for entry in cookbook_node.children: | ||
entry.title = app.env.titles[entry.docname].astext() | ||
if entry.title == "<no title>": | ||
entry.title = Path(entry.docname).stem.replace("_", " ") | ||
|
||
entry.uri = app.builder.get_relative_uri(docname, entry.docname) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0.3.7 is released, which should work, and with any luck the tarballs will actually be online in an hour or two from me writing this comment