Skip to content

Commit

Permalink
feat: Nested settings are now documented in the output of `--about --…
Browse files Browse the repository at this point in the history
…format=markdown` (#2263)
  • Loading branch information
edgarrmondragon committed Mar 6, 2024
1 parent e0b120d commit cc05280
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 27 deletions.
83 changes: 61 additions & 22 deletions singer_sdk/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,60 @@ def format_about(self, about_info: AboutInfo) -> str:
class MarkdownFormatter(AboutFormatter, format_name="markdown"):
"""About formatter for Markdown output."""

def _generate_property_row(
self,
name: str,
schema: dict[str, t.Any],
*,
required: bool,
parent_name: str | None = None,
) -> t.Generator[str, None, None]:
"""Generate a row for this property and for nested properties, if any.
Args:
name: The property name.
schema: The property schema.
required: Whether the property is required to be present.
parent_name: The parent property name, if any.
Yields:
One markdown table row for the setting, and one for each sub-property.
"""
setting_name = f"{parent_name}.{name}" if parent_name else name
md_description = schema.get("description", "").replace("\n", "<BR/>")
yield (
f"| {setting_name} "
f"| {'True' if required else 'False':8} "
f"| {schema.get('default', 'None'):7} "
f"| {md_description:11} |"
)
if "properties" in schema:
yield from self._generate_property_rows(schema, parent_name=setting_name)

def _generate_property_rows(
self,
schema: dict[str, t.Any],
*,
parent_name: str = "",
) -> t.Generator[str, None, None]:
"""Generate a row for each property in the schema.
Args:
schema: A JSON object schema.
parent_name: The parent property name, if any.
Yields:
One markdown table row for each property.
"""
required_settings = schema.get("required", [])
for name, sub_schema in schema.get("properties", {}).items():
yield from self._generate_property_row(
name,
sub_schema,
required=name in required_settings,
parent_name=parent_name,
)

def format_about(self, about_info: AboutInfo) -> str:
"""Render about information.
Expand All @@ -173,18 +227,8 @@ def format_about(self, about_info: AboutInfo) -> str:
Returns:
A formatted string.
"""
max_setting_len = max(len(k) for k in about_info.settings["properties"])

# Set table base for markdown
table_base = (
f"| {'Setting':{max_setting_len}}| Required | Default | Description |\n"
f"|:{'-' * max_setting_len}|:--------:|:-------:|:------------|\n"
)

# Empty list for string parts
md_list = []
# Get required settings for table
required_settings = about_info.settings.get("required", [])

# Iterate over Dict to set md
md_list.append(
Expand All @@ -201,19 +245,14 @@ def format_about(self, about_info: AboutInfo) -> str:
md_list.append(capabilities)

setting = "## Settings\n\n"

for k, v in about_info.settings.get("properties", {}).items():
md_description = v.get("description", "").replace("\n", "<BR/>")
table_base += (
f"| {k}{' ' * (max_setting_len - len(k))}"
f"| {'True' if k in required_settings else 'False':8} | "
f"{v.get('default', 'None'):7} | "
f"{md_description:11} |\n"
)

setting += table_base
settings_table = (
"| Setting | Required | Default | Description |\n"
"|:--------|:--------:|:-------:|:------------|\n"
)
settings_table += "\n".join(self._generate_property_rows(about_info.settings))
setting += settings_table
setting += (
"\n"
"\n\n"
+ "\n".join(
[
"A full list of supported settings and capabilities "
Expand Down
10 changes: 10 additions & 0 deletions tests/core/test_about.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ def about_info() -> AboutInfo:
"type": "string",
"description": "API key for the tap to use.",
},
"complex_setting": {
"type": "object",
"description": "A complex setting, with sub-settings.",
"properties": {
"sub_setting": {
"type": "string",
"description": "A sub-setting.",
}
},
},
},
"required": ["api_key"],
},
Expand Down
10 changes: 10 additions & 0 deletions tests/snapshots/about_format/json.snap.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
"api_key": {
"type": "string",
"description": "API key for the tap to use."
},
"complex_setting": {
"type": "object",
"description": "A complex setting, with sub-settings.",
"properties": {
"sub_setting": {
"type": "string",
"description": "A sub-setting."
}
}
}
},
"required": [
Expand Down
10 changes: 6 additions & 4 deletions tests/snapshots/about_format/markdown.snap.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ Built with the [Meltano Singer SDK](https://sdk.meltano.com).

## Settings

| Setting | Required | Default | Description |
|:----------|:--------:|:-------:|:------------|
| start_date| False | None | Start date for the tap to extract data from. |
| api_key | True | None | API key for the tap to use. |
| Setting | Required | Default | Description |
|:--------|:--------:|:-------:|:------------|
| start_date | False | None | Start date for the tap to extract data from. |
| api_key | True | None | API key for the tap to use. |
| complex_setting | False | None | A complex setting, with sub-settings. |
| complex_setting.sub_setting | False | None | A sub-setting. |

A full list of supported settings and capabilities is available by running: `tap-example --about`

Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots/about_format/text.snap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ Version: 0.1.1
SDK Version: 1.0.0
Supported Python Versions: ['3.6', '3.7', '3.8']
Capabilities: [catalog, discover, state]
Settings: {'properties': {'start_date': {'type': 'string', 'format': 'date-time', 'description': 'Start date for the tap to extract data from.'}, 'api_key': {'type': 'string', 'description': 'API key for the tap to use.'}}, 'required': ['api_key']}
Settings: {'properties': {'start_date': {'type': 'string', 'format': 'date-time', 'description': 'Start date for the tap to extract data from.'}, 'api_key': {'type': 'string', 'description': 'API key for the tap to use.'}, 'complex_setting': {'type': 'object', 'description': 'A complex setting, with sub-settings.', 'properties': {'sub_setting': {'type': 'string', 'description': 'A sub-setting.'}}}}, 'required': ['api_key']}

0 comments on commit cc05280

Please sign in to comment.