Automatically document BaseSettings environment variables #9673
Replies: 4 comments 3 replies
-
I would wrap it into a typer command, super nice, thank you! Another idea that came to mind, is to auto-generate a .env.dist |
Beta Was this translation helpful? Give feedback.
-
For pydantic 2, replace for prop in settings_class.schema()["properties"].values():
rows.append(
[
"`" + list(prop["env_names"])[0].upper() + "`",
prop["type"],
prop.get("default", ""),
prop.get("description", ""),
]
) with for k, v in settings_class.model_json_schema()["properties"].items():
rows.append(
[
"`" + k.upper() + "`",
v["type"],
v.get("default", ""),
v.get("description", ""),
]
) |
Beta Was this translation helpful? Give feedback.
-
Thank you for your snippets! I modified it to take care of the list of settings classes and append them to the markdown tables one by one. Codefrom pathlib import Path
from typing import Sequence
from pydantic_settings import BaseSettings
def get_env_vars_md(
settings_class: type[BaseSettings],
):
"""
Create a markdown table describing the environment variables read by
`settings_class` and insert it in a markdown file between the
`start_of_region` string and the `end_of_region` string.
"""
title = settings_class.__name__
headers = ["Variable", "Type", "Default", "Description"]
rows = []
for k, v in settings_class.model_json_schema()["properties"].items():
type = (
v["type"]
if "type" in v
else ", ".join(map(lambda x: x["type"], v["anyOf"]))
)
rows.append(
[
"`" + k.upper() + "`",
type,
v.get("default", ""),
v.get("description", ""),
]
)
table = make_markdown_table(title, [headers] + rows)
return table
# https://gist.github.com/ohmerhe/b8ed8113cc20ed8bc9193c12b3a315c4
def make_markdown_table(title: str, rows: Sequence[Sequence[str]]) -> str:
"""
Take table, with headers given as first row, and return markdown string.
Ex Input:
[["Name", "Age", "Height"],
["Jake", 20, "5'10"],
["Mary", 21, "5'7"]]
"""
if len(rows) == 0 or len(rows[0]) == 0:
return ""
markdown = "\n"
markdown += f"### {title}\n\n"
markdown += "|" + "|".join(rows[0]) + "|\n"
markdown += "|" + "|".join(["--------------"] * len(rows[0])) + "|\n"
for row in rows[1:]:
markdown += "|" + "|".join(str(x) for x in row) + "|\n"
return markdown
# Modify this to suit your environment. Update the list of classes
from common.config import *
documentation = [
MySettingsClass,
]
tables = []
for settings_class in documentation:
table = get_env_vars_md(
settings_class=settings_class,
)
tables.append(table)
markdown_file_path = "README.md"
start_of_region: str = "<!-- begin env -->"
end_of_region: str = "<!-- end env -->"
path_obj = Path(markdown_file_path)
old_file_contents = path_obj.read_text()
tables_str = "\n".join(tables)
new_file_contents = (
old_file_contents[: old_file_contents.index(start_of_region) + len(start_of_region)]
+ tables_str
+ old_file_contents[old_file_contents.index(end_of_region) :]
)
path_obj.write_text(new_file_contents) |
Beta Was this translation helpful? Give feedback.
-
Hey Thank you for sharing this! i want to do the same but not for a settings class, but instead i need to retreive the parameters infos (type, description, type) from composite or reuseable template files and put them in a table automatically in Readme.md |
Beta Was this translation helpful? Give feedback.
-
Below is a function
print_env_vars_in_file
that takes your settings class (inheriting fromBaseSettings
), generates a markdown table that lists the name, type, default value, and description (set withpydantic.Field
) of each environment variable, and writes it in a specified location in a markdown file. For example, you can run it in CI/CD to make sure your documentation stays updated.Example:
If this is the settings class,
the table will be
APP_NAME
ADMIN_EMAIL
ITEMS_PER_USER
Beta Was this translation helpful? Give feedback.
All reactions