DEV Community

Cover image for Zero to Docs Hero: Create a Python Documentation Generator with GPT-5
Ayush kumar
Ayush kumar

Posted on

Zero to Docs Hero: Create a Python Documentation Generator with GPT-5

If you’ve ever found yourself dreading the task of writing docstrings or README files, you’re not alone.
Documentation is essential — but let’s face it, it’s not the most glamorous part of coding. What if you could take your Python code, click a button, and instantly get clean, PEP-257-compliant docstrings and professional Markdown documentation?

In this guide, you’ll build an Interactive Documentation Generator — a Streamlit web app that works with your code directly.
Upload a .py file, paste your code, or even fetch a raw GitHub file, and watch as GPT-5 turns it into polished docs you can download in seconds.
No more procrastination, no more messy README files — just instant clarity for your future self and your team.

Prerequisites

Before we dive in, make sure you have:

  • Python 3.11+ installed (check with python3 --version)
  • pip 24+ installed (check with pip --version)
  • An OpenAI API key from the OpenAI dashboard
  • Basic familiarity with running Python scripts
  • A willingness to never manually write docstrings again

Step 1: Check Python & pip versions

python3 --version
pip --version
Enter fullscreen mode Exit fullscreen mode

If you see output like your screenshot:

  • Python 3.11.x or newer → ✅ OK
  • pip 24.x or newer → ✅ OK
  • This confirms your environment can run the Interactive Documentation Generator project.

Step 2: Create & activate a virtual environment

mkdir docsgen && cd docsgen
python -m venv venv
source venv/bin/activate   # For Windows use: venv\Scripts\activate

Enter fullscreen mode Exit fullscreen mode
  • mkdir docsgen && cd docsgen → Makes a new project folder and enters it
  • python -m venv venv → Creates an isolated Python environment named venv
  • source venv/bin/activate → Activates the environment (you’ll see (venv) in your terminal)

Now your dependencies will be installed only for this project, keeping your system clean.

Step 3: Install Required Dependencies

Run:

pip install streamlit openai python-dotenv

Enter fullscreen mode Exit fullscreen mode

What these do:

  • streamlit → For creating the interactive web UI
  • openai → To access GPT-5 (or any other OpenAI model) for doc generation
  • python-dotenv → For securely loading your API keys from a .env file

After this step, your environment is ready to start coding the documentation generator.

Step 4: Upgrade the OpenAI SDK

# make sure your virtual env is active: (venv) in the prompt
pip install --upgrade openai

Enter fullscreen mode Exit fullscreen mode

Verify the install:

pip show openai

Enter fullscreen mode Exit fullscreen mode

You should see something like:

Name: openai
Version: 1.99.x
Location: .../venv/lib/python3.11/site-packages

Enter fullscreen mode Exit fullscreen mode

Why this matters: we’re using the new 1.x SDK (from openai import OpenAI + client.chat.completions.create(...)).
Older code (openai.ChatCompletion.create) will break.

Step 5: Add your API key

Create a file named .env in the project root:

Inside .env, add:

OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxx

Enter fullscreen mode Exit fullscreen mode

Replace sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx with your actual API key from the OpenAI dashboard.

Step 6: Write the Python Script

In your project root, create a file named app.py.

Add the following code:

# app.py — Interactive Documentation Generator (single file)

import os
import tempfile
import requests
import streamlit as st
from dotenv import load_dotenv
from openai import OpenAI

# ---------- Setup ----------
load_dotenv()
API_KEY = os.getenv("OPENAI_API_KEY")
if not API_KEY:
    st.stop()  # fails fast with clear message
client = OpenAI(api_key=API_KEY)

st.set_page_config(page_title="Interactive Doc Generator", layout="wide")
st.title("📄 Interactive Documentation Generator (GPT-5)")

st.caption("Upload a .py file, paste code, or fetch a raw GitHub .py URL. "
           "Then click **Generate** to get docstrings + Markdown.")

# ---------- Session state (so values survive reruns) ----------
if "code" not in st.session_state:
    st.session_state.code = ""
if "output" not in st.session_state:
    st.session_state.output = ""
if "updated_code" not in st.session_state:
    st.session_state.updated_code = ""

# ---------- Inputs ----------
st.markdown("## 1) Provide your code")
c1, c2 = st.columns([1, 1])

with c1:
    uploaded_file = st.file_uploader("Upload a `.py` file", type=["py"])

with c2:
    repo_url = st.text_input("Or enter a GitHub **raw** .py URL")
    st.caption("Example: https://raw.githubusercontent.com/user/repo/branch/path/file.py")

default_example = (
    "def hello(name):\n"
    "    return f\"Hello, {name}!\"\n\n"
    "class Greeter:\n"
    "    def greet(self, name):\n"
    "        return hello(name)\n"
)

st.markdown("#### Or paste code below")
pasted_code = st.text_area(
    "Paste Python code",
    value=st.session_state.code or default_example,
    height=220,
    label_visibility="visible",
)

# Resolve `code`
code = ""
if uploaded_file is not None:
    try:
        code = uploaded_file.read().decode("utf-8")
        st.success("✅ Loaded code from uploaded file")
    except Exception as e:
        st.error(f"Could not read file: {e}")
elif repo_url.strip():
    try:
        r = requests.get(repo_url.strip(), timeout=20)
        r.raise_for_status()
        code = r.text
        st.success("✅ Loaded code from GitHub URL")
    except Exception as e:
        st.error(f"Failed to fetch from URL: {e}")
else:
    code = pasted_code

# Persist for next rerun
st.session_state.code = code

st.markdown("---")
st.markdown("## 2) Options")

opt1, opt2, opt3 = st.columns([1, 1, 1])
with opt1:
    output_format = st.radio(
        "Output format",
        options=["Docstrings Only", "Markdown Only", "Both"],
        index=2,
    )
with opt2:
    model = st.selectbox("Model", ["gpt-5-chat-latest", "gpt-4o"], index=0)
with opt3:
    temperature = st.slider("Creativity (temperature)", 0.0, 1.0, 0.2, 0.1)

SYSTEM_PROMPT_MAP = {
    "Docstrings Only": (
        "You are a senior Python documentation assistant. Add or improve PEP-257 docstrings "
        "for all public functions/classes/methods. Return ONLY updated Python code (no markdown)."
    ),
    "Markdown Only": (
        "You are a senior Python documentation assistant. Produce Markdown docs for the code with sections: "
        "Overview, API Reference (params/returns/raises), How It Works, and Example Usage."
    ),
    "Both": (
        "You are a senior Python documentation assistant. First, output updated Python code with PEP-257 "
        "docstrings only. Then print this exact delimiter line:\n"
        "-----DOCS_DELIMITER-----\n"
        "After the delimiter, output Markdown docs (Overview, API Reference, How It Works, Example Usage)."
    ),
}

# ---------- Action buttons ----------
go = st.button("⚡ Generate", type="primary", use_container_width=True)

# ---------- Generate ----------
if go:
    if not code.strip():
        st.warning("Please upload, paste, or fetch some Python code first.")
    else:
        with st.spinner("Generating documentation with GPT…"):
            try:
                resp = client.chat.completions.create(
                    model=model,
                    temperature=temperature,
                    messages=[
                        {"role": "system", "content": SYSTEM_PROMPT_MAP[output_format]},
                        {"role": "user", "content": code},
                    ],
                )
                content = resp.choices[0].message.content.strip()

                updated_code, docs = "", ""
                if output_format == "Both":
                    if "-----DOCS_DELIMITER-----" in content:
                        updated_code, docs = content.split("-----DOCS_DELIMITER-----", 1)
                    else:
                        # Fallback if model forgot delimiter: try to guess
                        updated_code, docs = content, ""
                elif output_format == "Docstrings Only":
                    updated_code = content
                else:  # Markdown Only
                    docs = content

                st.session_state.updated_code = updated_code.strip()
                st.session_state.output = docs.strip()

            except Exception as e:
                st.error(f"OpenAI error: {e}")

# ---------- Results ----------
st.markdown("---")
st.markdown("## 3) Results")

if st.session_state.updated_code:
    st.subheader("✅ Updated Code with Docstrings")
    st.code(st.session_state.updated_code, language="python")
    st.download_button(
        "⬇️ Download updated code (.py)",
        data=st.session_state.updated_code,
        file_name="updated_with_docstrings.py",
        mime="text/x-python",
        use_container_width=True,
    )

if st.session_state.output:
    st.subheader("📘 Generated Markdown Documentation")
    st.markdown(st.session_state.output)
    st.download_button(
        "⬇️ Download docs (.md)",
        data=st.session_state.output,
        file_name="DOCUMENTATION.md",
        mime="text/markdown",
        use_container_width=True,
    )

if not st.session_state.updated_code and not st.session_state.output:
    st.info("👆 Provide code and click **Generate** to see results here.")
Enter fullscreen mode Exit fullscreen mode

This script:

  • Loads OpenAI API key from .env using dotenv.
  • Sets up a Streamlit web app titled Interactive Documentation Generator.
  • Accepts Python code input via file upload, text paste, or GitHub raw .py URL.
  • Lets user choose output format — docstrings only, markdown only, or both.
  • Optionally loads sample code for quick testing.
  • Displays the original code before processing.
  • Sends code + instructions to GPT-5 to generate docstrings, markdown docs, or both.
  • Shows generated documentation in the Streamlit UI.
  • Allows downloading the docs as a .md file.
  • Handles errors gracefully with clear messages.

Step 7: Run it

streamlit run app.py

Enter fullscreen mode Exit fullscreen mode

Once it starts, you’ll see something like this in your terminal:

You can now view your Streamlit app in your browser.

Local URL: http://localhost:8501
Network URL: http://<your-local-ip>:8501

Enter fullscreen mode Exit fullscreen mode

Step 8: Check App

Now open your browser and visit:

http://localhost:8501
Enter fullscreen mode Exit fullscreen mode

You’ll see your Interactive Documentation Generator ready to go.
Upload a .py file, paste code, or give a GitHub raw link — and watch GPT-5 instantly create clean docstrings, Markdown docs, and examples.

Step 9: Generate docs (and download)

  • In the app, paste or upload your .py file (or paste a GitHub raw URL).
  • Pick Output format → Docstrings Only, Markdown Only, or Both.
  • Click ⚡ Generate.
  • Scroll to Results:

Updated Code with Docstrings → preview + Download updated code (.py)
Generated Markdown Documentation → preview + Download docs (.md)

  • That’s it—you’ve got docstrings + a clean Markdown doc in seconds.







Conclusion

By the end of this tutorial, you’ve got a fully functional, single-file Python app that transforms any script into beautifully documented code.
No more guessing what a function does six months later — now your code tells its own story.
Whether you use it for personal projects, client work, or open-source contributions, this tool will save you time, improve code readability, and make your repositories shine.

Now the only question is — will you spend your next coding break actually coding, or finally generating those docs you’ve been putting off? With this setup, you can do both at the same time.

Top comments (0)