Skip to content

Commit

Permalink
Fix up markdown output
Browse files Browse the repository at this point in the history
  • Loading branch information
ipmb committed Feb 10, 2024
1 parent 9759ab3 commit 7522656
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Change Log
==========

Unreleased
==========

- Fixed type display in Markdown generation
- Changed markdown output format (trailing spaces were problematic).

3.0.1 (30 June 2023)
====================

Expand Down
35 changes: 30 additions & 5 deletions goodconf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@ def file_config_settings_source(settings: BaseSettings) -> Dict[str, Any]:
return values


def type_to_str(tp: Type[Any]) -> str:
"""String representation of a type."""
print(tp)
origin = get_origin(tp)
if origin is None: # Simple type or a specific value in Literal
if hasattr(tp, "__name__"):
return tp.__name__
return repr(
tp
) # Use repr for values to get their string representation properly

args = get_args(tp)

if (
origin is Union and len(args) == 2 and type(None) in args
): # Handle Optional as a special case
non_none_args = [arg for arg in args if arg is not type(None)]
return f"Optional[{type_to_str(non_none_args[0])}]"

if origin: # Generic or special type like Union, Literal, etc.
type_name = origin.__name__
args_str = ", ".join(type_to_str(arg) for arg in args)
return f"{type_name}[{args_str}]"
return str(tp) # Fallback for any other type


class GoodConf(BaseSettings):
def __init__(self, load: bool = False, **kwargs):
"""
Expand Down Expand Up @@ -229,13 +255,12 @@ def generate_markdown(cls) -> str:
for k, v in cls.__fields__.items():
lines.append(f"* **{k}** ")
if v.required:
lines[-1] = lines[-1] + "_REQUIRED_ "
lines[-1] = lines[-1] + "_REQUIRED_"
if v.field_info.description:
lines.append(f" {v.field_info.description} ")
type_ = v.type_ == v.type_.__name__ if v.outer_type_ else v.outer_type_
lines.append(f" type: `{type_}` ")
lines.append(f" * description: {v.field_info.description}")
lines.append(f" * type: `{type_to_str(v.outer_type_)}`")
if v.default is not None:
lines.append(f" default: `{v.default}` ")
lines.append(f" * default: `{v.default}`")
return "\n".join(lines)

def django_manage(self, args: Optional[List[str]] = None):
Expand Down
18 changes: 15 additions & 3 deletions tests/test_goodconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import re
from textwrap import dedent
from typing import Optional
from typing import Optional, Literal

import pytest
from pydantic import Field, ValidationError
Expand Down Expand Up @@ -133,14 +133,26 @@ class TestConf(GoodConf):

mkdn = TestConf.generate_markdown()
# Not sure on final format, just do some basic smoke tests
assert help_ in mkdn
assert f" * description: {help_}" in mkdn.splitlines()


def test_generate_markdown_default_false():
class TestConf(GoodConf):
a: bool = Field(default=False)

assert "False" in TestConf.generate_markdown()
lines = TestConf.generate_markdown().splitlines()
assert " * type: `bool`" in lines
assert " * default: `False`" in lines


def test_generate_markdown_types():
class TestConf(GoodConf):
a: Literal["a", "b"] = Field(default="a")
b: list[str] = Field()

lines = TestConf.generate_markdown().splitlines()
assert " * type: `Literal['a', 'b']`" in lines
assert " * type: `list[str]`" in lines


def test_undefined():
Expand Down

0 comments on commit 7522656

Please sign in to comment.