Skip to content
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

DO NOT MERGE feat: sphinx plugin to get docs outside the main tree #293

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions docs/_ext/include_all_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
A Sphinx extension to allow the inclusion of documents that are outside of the main docs directory.

Before building, look in the entire repository (minus the main docs directory) for any .rst files. Symlink these files
inside the main docs directory so they are visible to Sphinx and can be included in index.rst. After the build, removes
the directory containing all the symlinks.

Requires new config values:
repo_root: the absolute path of the root of the repository
symlink_sub_dir: the name of the subdirectory in which to put the symlinks. Default "symlinks"
"""

import shutil
from os import mkdir, path, symlink, walk

from sphinx.util import logging

logger = logging.getLogger(__name__)


def should_remove_dir(subdir):
"""
Determine if we should skip a directory

Parameters:
subdir - a directory returned from os.walk

Returns:
True if the directory is only for generated files or should otherwise be ignored
"""
return subdir in ["build", "dist", ".tox", ".github", ".git", ".idea", '__pycache__'] or subdir.endswith("egg-info")


def rm_symlinks(app, exception):
"""
Remove the symlink directory
"""
srcdir = app.srcdir
symlink_dir = app.config.symlink_sub_dir
shutil.rmtree(path.join(srcdir, symlink_dir))


def create_symlinks(app, config):
"""
Create symlinks
:param app:
:param config:
:return:
"""
srcdir = app.srcdir
symlink_dir = config.symlink_sub_dir
try:
mkdir(path.join(srcdir, symlink_dir))
except FileExistsError:
logger.error(f"Cannot create directory for symlinks. Directory {symlink_dir} already exists in {srcdir}")
raise
for root, dirs, files in walk(config.repo_root, topdown=True):
# if we're in a subdirectory of the root docs folder, we can already access all the docs here, so skip
if path.commonpath([srcdir, root]) == srcdir:
continue

[dirs.remove(d) for d in list(dirs) if should_remove_dir(d)]

try:
# if necessary, make the new subdir for these symlinks
if not root == config.repo_root:
new_dir = path.join(srcdir, symlink_dir, path.relpath(root, start=config.repo_root))
mkdir(new_dir)
except FileExistsError:
logger.info(f"Not making new subdir for {root}, subdir already exists")
pass

for doc_file in files:
# only adds rsts for now
if doc_file.endswith('.rst'):
# full_path will be an absolute path like /path/to/repo/app/docs/mydoc.rst
full_path = path.join(root, doc_file)

# eg app/docs/mydoc.rst
relative_to_repo_root = path.relpath(full_path, start=config.repo_root)

# add the relative path to the doc source directory, eg docs/app/docs/mydoc.rst
symlink_path = path.join(srcdir, symlink_dir, relative_to_repo_root)
try:
symlink(full_path, symlink_path)
except FileExistsError:
logger.warn(f"Cannot create {symlink_path}, file already exists")
pass


def setup(app):
"""
Entry point into Sphinx
"""
app.add_config_value("repo_root", "", 'html', [str])
app.add_config_value("symlink_sub_dir", "symlinks", 'html', [str])
app.connect('config-inited', create_symlinks)
app.connect('build-finished', rm_symlinks)

return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
7 changes: 6 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def get_version(*file_paths):

REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(REPO_ROOT)
sys.path.append("./_ext")

VERSION = get_version('../edx_django_utils', '__init__.py')

Expand Down Expand Up @@ -67,7 +68,8 @@ def get_version(*file_paths):
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.ifconfig',
'sphinx.ext.napoleon'
'sphinx.ext.napoleon',
'include_all_files',
]

# A list of warning types to suppress arbitrary warning messages.
Expand Down Expand Up @@ -469,6 +471,9 @@ def get_version(*file_paths):
#
# epub_use_index = True

repo_root = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..'))
symlink_sub_dir = "symlinks"


# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
Expand Down
24 changes: 12 additions & 12 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,38 @@ EdX utilities for Django Application development.
:maxdepth: 1
:caption: Monitoring Decisions

monitoring/decisions/0001-monitoring-by-code-owner
monitoring/decisions/0002-custom-monitoring-language
monitoring/decisions/0003-code-owner-for-celery-tasks
monitoring/decisions/0004-code-owner-theme-and-squad
symlinks/edx_django_utils/monitoring/docs/decisions/0001-monitoring-by-code-owner
symlinks/edx_django_utils/monitoring/docs/decisions/0002-custom-monitoring-language
symlinks/edx_django_utils/monitoring/docs/decisions/0003-code-owner-for-celery-tasks
symlinks/edx_django_utils/monitoring/docs/decisions/0004-code-owner-theme-and-squad

.. toctree::
:maxdepth: 1
:caption: Monitoring How-Tos

monitoring/how_tos/add_code_owner_custom_attribute_to_an_ida
monitoring/how_tos/using_custom_attributes
monitoring/how_tos/search_new_relic_nrql
monitoring/how_tos/update_monitoring_for_squad_or_theme_changes
symlinks/edx_django_utils/monitoring/docs/how_tos/add_code_owner_custom_attribute_to_an_ida
symlinks/edx_django_utils/monitoring/docs/how_tos/using_custom_attributes
symlinks/edx_django_utils/monitoring/docs/how_tos/search_new_relic_nrql
symlinks/edx_django_utils/monitoring/docs/how_tos/update_monitoring_for_squad_or_theme_changes

.. toctree::
:maxdepth: 1
:caption: Plugins README

plugins/readme
symlinks/edx_django_utils/plugins/README

.. toctree::
:maxdepth: 1
:caption: Plugins Decisions

plugins/decisions/0001-plugin-contexts
symlinks/edx_django_utils/plugins/docs/decisions/0001-plugin-contexts

.. toctree::
:maxdepth: 1
:caption: Plugins How-Tos

plugins/how_tos/how_to_enable_plugins_for_an_ida
plugins/how_tos/how_to_create_a_plugin_app
symlinks/edx_django_utils/plugins/docs/how_tos/how_to_enable_plugins_for_an_ida
symlinks/edx_django_utils/plugins/docs/how_tos/how_to_create_a_plugin_app


Indices and tables
Expand Down
30 changes: 0 additions & 30 deletions docs/monitoring/README.rst

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion docs/monitoring/how_tos/search_new_relic_nrql.rst

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion docs/monitoring/how_tos/using_custom_attributes.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/plugins/decisions/0001-plugin-contexts.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/plugins/how_tos/how_to_create_a_plugin_app.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/plugins/how_tos/how_to_enable_plugins_for_an_ida.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/plugins/readme.rst

This file was deleted.

4 changes: 2 additions & 2 deletions edx_django_utils/plugins/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ into a containing Django project.
Enable Plugins in an IDA
------------------------

See :doc:`instructions to enable plugins for an IDA <how_tos/how_to_enable_plugins_for_an_ida>`.
See :doc:`instructions to enable plugins for an IDA <docs/how_tos/how_to_enable_plugins_for_an_ida>`.

Creating a Plugin App
---------------------

See :doc:`how to create a plugin app <how_tos/how_to_create_a_plugin_app>`.
See :doc:`how to create a plugin app <docs/how_tos/how_to_create_a_plugin_app>`.

.. note:: Do not use this plugin framework for required apps. Instead, explicitly add your required app to the ``INSTALLED_APPS`` of the IDA.

Expand Down