0

Summary of the Issue

I am using a fork of a popular package, scikit-learn, (yes I need a fork for specific technical reasons) that has a documentation hosted with Sphinx. I want to simultaneously use the fork I have and scikit-learn itself, so I release the fork under a different namespace sklearn_fork, so I can use it for my own specific purposes.

However, I still want the Sphinx docs to render properly. The issue is that in the fork, I find+replace all instances of "~sklearn.utils.*" with for example "~sklearn_fork.utils.*", which basically makes Sphinx not able to find the necessary reference.

Is there a way for me to dynamically add code into my conf.py, so that way all references for "sklearn_fork" are mapped to "sklearn"?

Basically what I would want is to do the following:

1. <search for all instances of "`sklearn_fork.*`">

2. <replace those instances with "`sklearn.*`">

3. <run Sphinx as is>

Example

As an example, say we have a docstring that had the following find+replaced from "sklearn" to "sklearn_fork".

class OriginalClass:
   """
   ...
 
   Inside this docstring, there is a sentence that has    
   the following :func:`~sklearn_fork.utils.Bunch`, or
    something like `sklearn_fork.pipeline.Pipeline`, which I 
    want to replace.
   """

Now I want to reverse that during the Sphinx build. by replacing the docstring so what Sphinx sees is the following:

class OriginalClass:
   """
   ...
 
   Inside this docstring, there is a sentence that has    
   the following :func:`~sklearn.utils.Bunch`, or
    something like `sklearn.pipeline.Pipeline`, which I 
    want to replace.
   """
ajl123
  • 1,172
  • 5
  • 17
  • 40

1 Answers1

0

Turns out autodoc has a autodoc-process-docstring event, which processes the docstring, so you can write a custom function that does this substitution for you. Here is a solution I found that works where you can use re.sub function to replace all instances of "sklearn_fork" with "sklearn" dynamically in your conf.py file.

This helps one generally process docstrings that have this issue.

import re

def replace_sklearn_fork_with_sklearn(app, what, name, obj, options, lines):
    """
    This function replaces all instances of 'sklearn_fork' with 'sklearn'
    in the docstring content.
    """
    # Convert the list of lines to a string
    content = "\n".join(lines)
    
    # Use regular expressions to replace 'sklearn_fork' with 'sklearn'
    content = re.sub(r'`~sklearn_fork\.', r'`~sklearn.', content)
    content = re.sub(r'`sklearn_fork\.', r'`sklearn.', content)
    
    # Convert the modified string back to a list of lines
    lines[:] = content.split("\n")

def setup(app):
    app.connect("autodoc-process-docstring", replace_sklearn_fork_with_sklearn)
ajl123
  • 1,172
  • 5
  • 17
  • 40