Usage

Configuration

To use Sphinx Code Include in a project

  • Create a Sphinx project if you haven’t already (using sphinx-quickstart or otherwise)

  • Add sphinx-code-include to your conf.py

extensions = [
    "code_include.extension",
]

Options

This block shows every option that you can add into a code-include block.

.. code-include :: :func:`module_name.foo`
    :language: python
    :link-at-bottom:
    :link-to-documentation:
    :link-to-source:
    :no-unindent:

Here’s a description of what each option does.

Option

Description

language

The syntax highlight that will be used. Examples of valid input in pygment’s documentation. The default value is “python”

link-at-bottom

Add source code and/or documentation links at the bottom of the block.

link-to-documentation

Add a clickable link to where the source code’s API documentation is.

link-to-source

Add a clickable link to where the source code is from.

no-unindent

If the found source-code has indentation, don’t remove any of it.

Advanced Usage

If you have to use link-to-source, 2 things are required.

  • Your project must be set up for intersphinx.

  • The project that you’re trying to reference must have sphinx.ext.viewcode included in their extensions.

Example Project

sphinx-code-include shows how to use the code-include directive in its own documentation.

This page includes this in its text:

.. code-include :: :mod:`conf`

And this is the conf.py that generates this documentation.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import os

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.coverage',
    'sphinx.ext.doctest',
    'sphinx.ext.extlinks',
    'sphinx.ext.ifconfig',
    'sphinx.ext.napoleon',
    'sphinx.ext.todo',
    'sphinx.ext.viewcode',
]
source_suffix = '.rst'
master_doc = 'index'
project = u'Sphinx Code Include'
year = '2019'
author = u'Colin Kennedy'
copyright = '{0}, {1}'.format(year, author)
version = release = u'1.4.0'

pygments_style = 'trac'
templates_path = ['.']
extlinks = {
    'issue': ('https://github.com/ColinKennedy/sphinx-code-include/issues/%s', '#'),
    'pr': ('https://github.com/ColinKennedy/sphinx-code-include/pull/%s', 'PR #'),
}
# on_rtd is whether we are on readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'

if not on_rtd:  # only set the theme if we're building docs locally
    html_theme = 'sphinx_rtd_theme'

html_use_smartypants = True
html_last_updated_fmt = '%b %d, %Y'
html_split_index = False
html_sidebars = {
   '**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html'],
}
html_short_title = '%s-%s' % (project, version)

napoleon_use_ivar = True
napoleon_use_rtype = False
napoleon_use_param = False


# Add this folder to `sys.path` so that Python can import conf.py.
# Normally we'd never do this. But this is done to show that the
# code-include directive can get the source-code anything that's
# importable.
#
import os
import sys

root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(root, "src"))

extensions += ["code_include.extension", "sphinx.ext.intersphinx", "sphinx_rtd_theme"]

html_theme = "sphinx_rtd_theme"

intersphinx_mapping = {
    "https://requests.kennethreitz.org/en/latest": None,
}




###########################################################################
#          auto-created readthedocs.org specific configuration            #
###########################################################################


#
# The following code was added during an automated build on readthedocs.org
# It is auto created and injected for every build. The result is based on the
# conf.py.tmpl file found in the readthedocs.org codebase:
# https://github.com/rtfd/readthedocs.org/blob/main/readthedocs/doc_builder/templates/doc_builder/conf.py.tmpl
#
# Note: this file shouldn't rely on extra dependencies.

import importlib
import sys
import os.path

# Borrowed from six.
PY3 = sys.version_info[0] == 3
string_types = str if PY3 else basestring

from sphinx import version_info

# Get suffix for proper linking to GitHub
# This is deprecated in Sphinx 1.3+,
# as each page can have its own suffix
if globals().get('source_suffix', False):
    if isinstance(source_suffix, string_types):
        SUFFIX = source_suffix
    elif isinstance(source_suffix, (list, tuple)):
        # Sphinx >= 1.3 supports list/tuple to define multiple suffixes
        SUFFIX = source_suffix[0]
    elif isinstance(source_suffix, dict):
        # Sphinx >= 1.8 supports a mapping dictionary for multiple suffixes
        SUFFIX = list(source_suffix.keys())[0]  # make a ``list()`` for py2/py3 compatibility
    else:
        # default to .rst
        SUFFIX = '.rst'
else:
    SUFFIX = '.rst'

# Add RTD Static Path. Add to the end because it overwrites previous files.
if not 'html_static_path' in globals():
    html_static_path = []
if os.path.exists('_static'):
    html_static_path.append('_static')

# Define this variable in case it's not defined by the user.
# It defaults to `alabaster` which is the default from Sphinx.
# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_theme
html_theme = globals().get('html_theme', 'alabaster')

#Add project information to the template context.
context = {
    'html_theme': html_theme,
    'current_version': "stable",
    'version_slug': "stable",
    'MEDIA_URL': "https://media.readthedocs.org/",
    'STATIC_URL': "https://assets.readthedocs.org/static/",
    'PRODUCTION_DOMAIN': "readthedocs.org",
    'proxied_static_path': "/_/static/",
    'versions': [
    ("latest", "/en/latest/"),
    ("stable", "/en/stable/"),
    ("v1.1.0", "/en/v1.1.0/"),
    ("issues-9-add_better_logging", "/en/issues-9-add_better_logging/"),
    ],
    'downloads': [ 
    ("pdf", "//sphinx-code-include.readthedocs.io/_/downloads/en/stable/pdf/"),
    ("html", "//sphinx-code-include.readthedocs.io/_/downloads/en/stable/htmlzip/"),
    ("epub", "//sphinx-code-include.readthedocs.io/_/downloads/en/stable/epub/"),
    ],
    'subprojects': [ 
    ],
    'slug': 'sphinx-code-include',
    'name': u'sphinx-code-include',
    'rtd_language': u'en',
    'programming_language': u'words',
    'canonical_url': '',
    'analytics_code': 'None',
    'single_version': False,
    'conf_py_path': '/docs/',
    'api_host': 'https://readthedocs.org',
    'github_user': 'ColinKennedy',
    'proxied_api_host': '/_',
    'github_repo': 'sphinx-code-include',
    'github_version': 'be20e6c67fc81b79c425b733e536c8ca07c15a66',
    'display_github': True,
    'bitbucket_user': 'None',
    'bitbucket_repo': 'None',
    'bitbucket_version': 'be20e6c67fc81b79c425b733e536c8ca07c15a66',
    'display_bitbucket': False,
    'gitlab_user': 'None',
    'gitlab_repo': 'None',
    'gitlab_version': 'be20e6c67fc81b79c425b733e536c8ca07c15a66',
    'display_gitlab': False,
    'READTHEDOCS': True,
    'using_theme': (html_theme == "default"),
    'new_theme': (html_theme == "sphinx_rtd_theme"),
    'source_suffix': SUFFIX,
    'ad_free': False,
    'docsearch_disabled': False,
    'user_analytics_code': '',
    'global_analytics_code': 'UA-17997319-1',
    'commit': 'be20e6c6',
}

# For sphinx >=1.8 we can use html_baseurl to set the canonical URL.
# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_baseurl
if version_info >= (1, 8):
    if not globals().get('html_baseurl'):
        html_baseurl = context['canonical_url']
    context['canonical_url'] = None





if 'html_context' in globals():
    for key in context:
        if key not in html_context:
            html_context[key] = context[key]
else:
    html_context = context

# Add custom RTD extension
if 'extensions' in globals():
    # Insert at the beginning because it can interfere
    # with other extensions.
    # See https://github.com/rtfd/readthedocs.org/pull/4054
    extensions.insert(0, "readthedocs_ext.readthedocs")
else:
    extensions = ["readthedocs_ext.readthedocs"]

# Add External version warning banner to the external version documentation
if 'tag' == 'external':
    extensions.insert(1, "readthedocs_ext.external_version_warning")
    readthedocs_vcs_url = 'None'
    readthedocs_build_url = 'https://readthedocs.org/projects/sphinx-code-include/builds/23773231/'

project_language = 'en'

# User's Sphinx configurations
language_user = globals().get('language', None)
latex_engine_user = globals().get('latex_engine', None)
latex_elements_user = globals().get('latex_elements', None)

# Remove this once xindy gets installed in Docker image and XINDYOPS
# env variable is supported
# https://github.com/rtfd/readthedocs-docker-images/pull/98
latex_use_xindy = False

chinese = any([
    language_user in ('zh_CN', 'zh_TW'),
    project_language in ('zh_CN', 'zh_TW'),
])

japanese = any([
    language_user == 'ja',
    project_language == 'ja',
])

if chinese:
    latex_engine = latex_engine_user or 'xelatex'

    latex_elements_rtd = {
        'preamble': '\\usepackage[UTF8]{ctex}\n',
    }
    latex_elements = latex_elements_user or latex_elements_rtd
elif japanese:
    latex_engine = latex_engine_user or 'platex'

# Make sure our build directory is always excluded
exclude_patterns = globals().get('exclude_patterns', [])
exclude_patterns.extend(['_build'])

Notice intersphinx_mapping towards the bottom. This attribute must be set up to point to your other project. intersphinx_mapping cannot be empty. In our case, we’ll point it to some external Sphinx project.

.. code-include :: :func:`requests.get`

And this is what the block above renders as:

def get(url, params=None, **kwargs):
    r"""Sends a GET request.

    :param url: URL for the new :class:`Request` object.
    :param params: (optional) Dictionary, list of tuples or bytes to send
        in the query string for the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request("get", url, params=params, **kwargs)

Notice that requests.get is actually using a different theme than this documentation’s theme but it still renders with the correct color scheme.

And of course, you can refer to objects in your current project using code-include, too.

.. code-include :: :func:`code_include.helper.memoize`
def memoize(function):
    """Wrap a function with this decorator to cache its results.

    Reference:
        http://code.activestate.com/recipes/578231-probably-the-fastest-memoization-decorator-in-the-/#c1

    Args:
        function (callable):
            Some Python callable will become cache-able by this function.

    Returns:
        :class:`MemoDict`:
            A per-function instance gets called only once for a set of
            arguments once.

    """

    class MemoDict(dict):
        """A class that stores a function and caches each unique function call."""

        def __init__(self, function):
            super(MemoDict, self).__init__()

            self.function = function

        def __call__(self, *args):
            return self[args]

        def __missing__(self, key):
            ret = self[key] = self.function(*key)

            return ret

    return MemoDict(function)

Advanced Customization - Pre-Processor Function

You have total control over how source-code is rendered in your Sphinx project. Say, for example, you want to get source-code of a function but you want to remove the function’s docstring, or delete its comments.

Note

code_include_preprocessor is only run if your code comes from another Sphinx project. If the source-code that you’re targetting comes from imported content then the pre-processor is ignored.

Add a function called code_include_preprocessor to your conf.py

def code_include_preprocessor(soup):
    """`soup` is a :class:`bs4.element.Tag` object."""
    pass

code-include brings in the source-code from projects as HTML tags. This function lets you directly access and modify those tags before it gets converted into raw text. So you’re free to change whatever you want and it will be applied to every code-include directive.