Search code examples
pythonflaskpython-sphinxdocumentation-generation

Sphinx autoflask only makes one page for all the endpoints


I've inherited a project and am using Sphinx for the first time. I've got a app.py that has all my api endpoints and when you make documentation you have all the api.add_resources wrapped in a function.

from resources.recipes import GetRecipes, RecipeList, 
from resources.employees import Chefs, Servers, Admin  

def make_port():
   api = Api(app)
   
   api.add_resource(GetRecipes, '/getrecipes/<:string:recipetype>')
   api.add_resource(RecipeList, '/allrecipes/<:string:recipetype>')
   api.add_resource(Chefs, '/chefs/<:string:name>')
   api.add_resource(Servers, '/servers/<:string:name>')
   api.add_resource(Admin, '/admin/<:string:name>') 

   return app

then I have my app.rst in my docs folder

API Documentation
=================

Summary
-------

.. qrefflask:: app:make_port()
    :undoc-static:

API Details
-----------

.. autoflask:: app:make_port()
   :endpoints: getRecipes, RecipeList, Chefs, Servers, Admin
   :undoc-static

When I make the doc It only makes one single page with all the endpoints on it. I've tried just importing the folder 'resources/employees, recources/recipes into the modules.rst

.. toctree::
   : maxdepth: 4

   app
   resources/employees
   resources/recipes

but it doesn't turn out the same way.

What I'd like to do is organize the endpoints manually as some endpoints are similiar enough to be grouped together.

I'm pretty new to this project and sphinx and I've not been able to figure it out with the Sphinx Documentation.


Solution

  • I had the structure completely wrong.

    First thing I had to do was create a folder. I named it api. I moved the app.rst into the api folder though It works building it without it.

    Then I made my desired pages inside the api/.. folder.

    docs
        |_api
             |_recipes.rst
             |_employees.rst
    

    then I structured the rst folder to have the endpoints I wanted for that page.

    Employee API
    =========
    
    .. qrefflask:: app:make_port()
       :endpoints: Chefs, Servers, Admin
       :undoc-static:
    
    Chefs Endpoints
    ^^^^^^^^^^^^^^^
    
    .. autoflask:: app:make_port()
       :endpoints: Chefs
    
    ----
    Servers Endpoints
    ^^^^^^^^^^^^^^^^^^^
    
    .. autoflask:: app:make_port()
       :endpoints: servers
    
    ----
    
    Admin Employee Endpoints
    ^^^^^^^^^^^^^^^^^^^^^
    
    .. autoflask:: app:make_port()
       :endpoints: admin
    
    ----
    
    
    

    Because I had so many endpoints I make a python script that would take a txt file and create the rst files for me.

    I made a folder called scripts with a subdir of endpoints and put my txt files in there

    docs
        |_api
             |_recipes.rst
             |_employees.rst
        |_scripts
             |_endpoints
                        |_employees.txt
                        |_recipes.txt
             |_endpoint_generator.py
    
    

    the txt file just needs to have the endpoints on different lines

    employees.txt
    
    Chefs
    Servers
    Admin
    

    Here is the endpoint_generator.py if anyone needs it.

    import os
    
    # Directory containing input text files
    input_dir = "endpoints"
    
    # Directory to save generated RST files
    output_dir = "../api"
    
    # Check if the input directory exists
    if not os.path.exists(input_dir):
        print(f"Error: Directory '{input_dir}' does not exist.")
        exit()
    
    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Get a list of all .txt files in the input directory
    input_files = [f for f in os.listdir(input_dir) if f.endswith('.txt')]
    
    # Process each input file
    for input_filename in input_files:
        # Construct full path to input file
        input_filepath = os.path.join(input_dir, input_filename)
    
        # Determine output file name (without extension)
        output_filename = os.path.splitext(input_filename)[0]
    
        # Read endpoint names from the input file
        endpoints = []
        with open(input_filepath, "r") as f:
            for line in f:
                endpoint = line.strip()
                if endpoint:  # Skip empty lines
                    endpoints.append(endpoint.lower())
    
        # Start building the RST content
        rst_content = ""
    
        rst_content += f"{output_filename.capitalize()} API\n"
        rst_content += "=" * len(output_filename) + "====\n\n"
    
        api_table_list = ",".join(str(x) for x in endpoints)
        rst_content += f".. qrefflask:: app:make_port()\n   :endpoints: {api_table_list} \n   :undoc-static:\n\n"
    
        # Loop through each endpoint
        for endpoint in endpoints:
            # Add section title for the endpoint
            rst_content += f"{endpoint.capitalize()} Endpoints\n"
            rst_content += "^" * len(f"{endpoint} Endpoints") + "\n\n"
    
            # Add autoflask directive with the endpoint
            rst_content += ".. autoflask:: app:make_port()\n"
            rst_content += f"   :endpoints: {endpoint}\n\n"
    
            # Add separator after each endpoint except the last one
            if endpoint != endpoints[-1]:
                rst_content += "----\n\n"
    
        # Construct output file path in the output directory
        output_file_path = os.path.join(output_dir, f"{output_filename}.rst")
    
        # Write the generated content to the output file
        with open(output_file_path, "w") as f:
            f.write(rst_content)
    
        print(f"Endpoints RST file '{output_file_path}' generated successfully!")
    
    print("All endpoints RST files generated in directory 'api/'.")
    

    and finally I had to edit the index.rst file adding in the pages.

    .. toctree::
       :maxdepth: 4
    
       api/employees
       api/recipes
    

    I hope this helps someone in the future!