Skip to content

Commit

Permalink
Merge pull request #49 from lincolnloop/47-markdown-generation-issues
Browse files Browse the repository at this point in the history
 Fix Markdown Generation Differences From V4
  • Loading branch information
dchukhin authored Oct 7, 2024
2 parents 96b8c8f + 5988e81 commit 80c031d
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ Change Log
==========

5.0.1 (Unreleased)
==================
========================

- Support reading TOML files via ``tomllib`` on Python 3.11+
- Update Markdown generation, so that output matches v4 output

5.0.0 (13 August 2024)
========================
Expand Down
37 changes: 26 additions & 11 deletions goodconf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,27 @@ def _find_file(filename: str, require: bool = True) -> str | None:
return os.path.abspath(filename)


def _fieldinfo_to_str(field_info: FieldInfo) -> str:
"""
Return the string representation of a pydantic.fields.FieldInfo.
"""
if isinstance(field_info.annotation, type) and not isinstance(
field_info.annotation, GenericAlias
):
# For annotation like <class 'int'>, we use its name ("int").
field_type = field_info.annotation.__name__
else:
if str(field_info.annotation).startswith("typing."):
# For annotation like typing.Literal['a', 'b'], we use
# its string representation, but without "typing." ("Literal['a', 'b']").
field_type = str(field_info.annotation)[len("typing.") :]
else:
# For annotation like list[str], we use its string
# representation ("list[str]").
field_type = field_info.annotation
return field_type


def initial_for_field(name: str, field_info: FieldInfo) -> Any:
try:
json_schema_extra = field_info.json_schema_extra or {}
Expand Down Expand Up @@ -296,18 +317,12 @@ def generate_markdown(cls) -> str:
if field_info.description:
lines.append(f" * description: {field_info.description}")
# We want to append a line with the field_info type, and sometimes
# field_info.annotation looks the way we want, like
# 'typing.Literal['a', 'b']', but other times, it includes some extra
# text, like '<class 'bool'>'. Therefore, we have some logic to make
# the type show up the way we want.
field_type = (
field_info.annotation.__name__
if isinstance(field_info.annotation, type)
and not isinstance(field_info.annotation, GenericAlias)
else field_info.annotation
)
# field_info.annotation looks the way we want, like 'list[str]', but
# other times, it includes some extra text, like '<class 'bool'>'.
# Therefore, we have some logic to make the type show up the way we want.
field_type = _fieldinfo_to_str(field_info)
lines.append(f" * type: `{field_type}`")
if field_info.default is not None:
if field_info.default not in [None, PydanticUndefined]:
lines.append(f" * default: `{field_info.default}`")
return "\n".join(lines)

Expand Down
4 changes: 3 additions & 1 deletion tests/test_goodconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ def test_generate_markdown_types():
class TestConf(GoodConf):
a: Literal["a", "b"] = Field(default="a")
b: list[str] = Field()
c: None

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


def test_generate_markdown_required():
Expand Down

0 comments on commit 80c031d

Please sign in to comment.