diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 44420685..423378a6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,8 @@ -## What does this pull request do? +## Summary of Changes -## Relevant Github ticket(s)? +## Related GitHub Issue(s) +## Additional Context for Reviewers + diff --git a/docs/_config.yml b/docs/_config.yml index be75c751..4dccd8ab 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -40,7 +40,7 @@ sphinx: - numpydoc - sphinx.ext.mathjax local_extensions: - ext_linkcode: _ext + linkcode: _ext config: autosummary_generate: True bibtex_reference_style: author_year diff --git a/docs/_ext/ext_linkcode.py b/docs/_ext/linkcode.py similarity index 80% rename from docs/_ext/ext_linkcode.py rename to docs/_ext/linkcode.py index c26de7a5..6ec36560 100644 --- a/docs/_ext/ext_linkcode.py +++ b/docs/_ext/linkcode.py @@ -10,10 +10,8 @@ if TYPE_CHECKING: from types import ModuleType -def linkcode_resolve( - domain: str, - info: dict -) -> str | None: + +def linkcode_resolve(domain: str, info: dict) -> str | None: """ Implementation of linkcode_resolve from the Sphinx extension sphinx.ext.linkcode. For more information, see: @@ -39,20 +37,20 @@ def linkcode_resolve( """ # Base path pointing to GitHub source code. - url_base: str = 'https://github.com/casact/chainladder-python/blob/master/' + url_base: str = "https://github.com/casact/chainladder-python/blob/master/" # Get the language information. - if domain != 'py': + if domain != "py": return None - if not info['module']: + if not info["module"]: return None # Extract the module. - mod: ModuleType = importlib.import_module(info['module']) + mod: ModuleType = importlib.import_module(info["module"]) obj: ModuleType = mod # Extract the part. - for part in info['fullname'].split('.'): + for part in info["fullname"].split("."): obj: type = getattr(obj, part) # Unwrap any decorators. @@ -63,27 +61,24 @@ def linkcode_resolve( # If the source file cannot be found, return the URL pointing to a .py file named after the module. if source_file is None: - filename: str = info['module'].replace('.', '/') + filename: str = info["module"].replace(".", "/") return url_base + "%s.py" % filename # Extract the lines and locate the starting line position. source_lines, start_line = inspect.getsourcelines(obj) # Get the root path. - root_path: str = os.path.abspath( - os.path.join(cl.__file__, '..', '..') - ) + root_path: str = os.path.abspath(os.path.join(cl.__file__, "..", "..")) # Construct a relative path using the source file path, enforce forward slash in case running on Windows. - rel_path: str = os.path.relpath(source_file, root_path).replace(os.sep, '/') + rel_path: str = os.path.relpath(source_file, root_path).replace(os.sep, "/") # Extract the ending line. end_line: int = start_line + len(source_lines) - 1 # Construct the URL by appending the relative path, starting, and ending lines to the base URL. - return url_base + '%s#L%d-L%d' % ( - rel_path, start_line, end_line - ) + return url_base + "%s#L%d-L%d" % (rel_path, start_line, end_line) + def setup(app) -> None: """ diff --git a/docs/_ext/tests/test_ext_linkcode.py b/docs/_ext/tests/test_ext_linkcode.py index 1bdee5bc..1e94afd1 100644 --- a/docs/_ext/tests/test_ext_linkcode.py +++ b/docs/_ext/tests/test_ext_linkcode.py @@ -1,4 +1,4 @@ -from docs._ext.ext_linkcode import linkcode_resolve # noqa +from linkcode import linkcode_resolve def test_linkcode_resolve_url_lines() -> None: """ diff --git a/docs/conf.py b/docs/conf.py index e40572f6..40e4f4a7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,88 +1,44 @@ -# jupyter-book config sphinx . -author = "" -bibtex_bibfiles = ["./library/references.bib"] -comments_config = {"hypothesis": False, "utterances": False} -copyright = "2023" -exclude_patterns = [ - "**.ipynb_checkpoints", - ".DS_Store", - "Thumbs.db", - "_build", - "templates", -] -execution_allow_errors = False -execution_excludepatterns = [] -execution_in_temp = False -execution_timeout = 30 -extensions = [ - "sphinx_design", - "sphinx_togglebutton", - "sphinx_copybutton", - "myst_nb", - "jupyter_book", - "sphinx_thebe", - "sphinx_comments", - "sphinx_external_toc", - "sphinx.ext.doctest", - "sphinx.ext.intersphinx", - "sphinx_book_theme", - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "numpydoc", - "sphinx.ext.mathjax", - "sphinxcontrib.bibtex", - "sphinx_jupyterbook_latex", - "sphinx_copybutton", - "sphinx_design", -] +import sys +from pathlib import Path +_DOCS_EXT_DIR = Path(__file__).resolve().parent / '_ext' +_p = str(_DOCS_EXT_DIR) +if _p not in sys.path: + sys.path.insert(0, _p) + +############################################################################### +# Auto-generated by `jupyter-book config` +# If you wish to continue using _config.yml, make edits to that file and +# re-generate this one. +############################################################################### +author = 'John Bogaardt, Kenneth Hsu, et. al.' +autosummary_generate = True +bibtex_bibfiles = ['library/references.bib'] +bibtex_reference_style = 'author_year' +comments_config = {'hypothesis': False, 'utterances': False} +copyright = '2023' +exclude_patterns = ['**.ipynb_checkpoints', '.DS_Store', 'Thumbs.db', '_build'] +extensions = ['sphinx_togglebutton', 'sphinx_copybutton', 'myst_nb', 'jupyter_book', 'sphinx_thebe', 'sphinx_comments', 'sphinx_external_toc', 'sphinx.ext.intersphinx', 'sphinx_design', 'sphinx_book_theme', 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.doctest', 'sphinx.ext.linkcode', 'numpydoc', 'sphinx.ext.mathjax', 'linkcode', 'sphinxcontrib.bibtex', 'sphinx_jupyterbook_latex', 'sphinx_multitoc_numbering'] external_toc_exclude_missing = False -external_toc_path = "_toc.yml" -html_permalinks = True -html_permalinks_icon = "ΒΆ" -html_baseurl = "" -html_favicon = "" -html_logo = "./images/logo.png" -html_sourcelink_suffix = "" -html_theme = "sphinx_book_theme" -html_theme_options = { - "search_bar_text": "Search this book...", - "launch_buttons": { - "notebook_interface": "classic", - "binderhub_url": "https://mybinder.org", - "jupyterhub_url": "", - "thebe": False, - "colab_url": "", - }, - "path_to_docs": "docs", - "repository_url": "https://github.com/casact/chainladder-python", - "repository_branch": "master", - "google_analytics_id": "", - "extra_navbar": 'Powered by Jupyter Book', - "extra_footer": "", - "home_page_in_toc": True, - "use_repository_button": True, - "use_edit_page_button": False, - "use_issues_button": True, -} -html_title = "Reserving in Python" -jupyter_cache = "" -jupyter_execute_notebooks = "force" -language = "en" -latex_engine = "pdflatex" -myst_enable_extensions = ["colon_fence", "dollarmath", "linkify", "substitution"] -myst_url_schemes = ["mailto", "http", "https"] -nb_output_stderr = "show" +external_toc_path = '_toc.yml' +html_baseurl = '' +html_favicon = '' +html_logo = 'images/logo.png' +html_sourcelink_suffix = '' +html_theme = 'sphinx_book_theme' +html_theme_options = {'search_bar_text': 'Search this book...', 'launch_buttons': {'notebook_interface': 'classic', 'binderhub_url': '', 'jupyterhub_url': '', 'thebe': False, 'colab_url': '', 'deepnote_url': ''}, 'path_to_docs': 'docs', 'repository_url': 'https://github.com/casact/chainladder-python', 'repository_branch': 'master', 'extra_footer': '', 'home_page_in_toc': True, 'announcement': '', 'analytics': {'google_analytics_id': '', 'plausible_analytics_domain': '', 'plausible_analytics_url': 'https://plausible.io/js/script.js'}, 'use_repository_button': True, 'use_edit_page_button': False, 'use_issues_button': True} +html_title = 'Chainladder - Python' +latex_engine = 'pdflatex' +myst_enable_extensions = ['html_admonition', 'colon_fence', 'dollarmath', 'linkify', 'substitution'] +myst_url_schemes = ['mailto', 'http', 'https'] +nb_execution_allow_errors = False +nb_execution_cache_path = '' +nb_execution_excludepatterns = [] +nb_execution_in_temp = False +nb_execution_mode = 'force' +nb_execution_timeout = 30 +nb_output_stderr = 'show' numfig = True -panels_add_bootstrap_css = False -pygments_style = "sphinx" -suppress_warnings = ["myst.domains"] +pygments_style = 'sphinx' +suppress_warnings = ['myst.domains'] use_jupyterbook_latex = True use_multitoc_numbering = True -autosummary_generate = True -nbsphinx_kernel_name = "cl_docs" - - -import chainladder as cl - -version = cl.__version__ -release = cl.__version__ diff --git a/docs/prep_sphinx_conf.py b/docs/prep_sphinx_conf.py new file mode 100644 index 00000000..ca7cfb7e --- /dev/null +++ b/docs/prep_sphinx_conf.py @@ -0,0 +1,30 @@ +""" +Prepend docs/_ext to sys.path in conf.py. + +`jupyter-book config sphinx` lists local extensions but does not emit this path, +so standalone Sphinx (e.g. Read the Docs) cannot import them. Run after generating conf.py. +""" +from pathlib import Path + +CONF = Path(__file__).resolve().parent / "conf.py" +MARKER = "_DOCS_EXT_DIR = Path(__file__).resolve().parent / '_ext'" + +BLOCK = """import sys +from pathlib import Path +_DOCS_EXT_DIR = Path(__file__).resolve().parent / '_ext' +_p = str(_DOCS_EXT_DIR) +if _p not in sys.path: + sys.path.insert(0, _p) + +""" + + +def main() -> None: + text = CONF.read_text(encoding="utf8") + if MARKER in text: + return + CONF.write_text(BLOCK + text, encoding="utf8") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index 45cb9cd2..36f050c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,6 +88,7 @@ all = [ [tool.pytest.ini_options] testpaths = ["chainladder/*", "docs/_ext"] +pythonpath = ["docs/_ext"] [tool.setuptools] include-package-data = true diff --git a/readthedocs.yaml b/readthedocs.yaml index e4a484af..bcb94429 100644 --- a/readthedocs.yaml +++ b/readthedocs.yaml @@ -9,8 +9,8 @@ build: python: "3.11" jobs: pre_build: - # Generate on-the-fly Sphinx configuration from Jupyter Book's _config.yml - "jupyter-book config sphinx docs/" + - "python docs/prep_sphinx_conf.py" python: install: