diff --git a/docs/nix/render_options/__init__.py b/docs/nix/render_options/__init__.py index eb4cd0e53..c49097599 100644 --- a/docs/nix/render_options/__init__.py +++ b/docs/nix/render_options/__init__.py @@ -32,7 +32,7 @@ from typing import Any from clan_lib.errors import ClanError from clan_lib.services.modules import ( CategoryInfo, - Frontmatter, + ModuleFrontmatter, ) # Get environment variables @@ -176,9 +176,8 @@ def print_options( return res -def module_header(module_name: str, has_inventory_feature: bool = False) -> str: - indicator = " 🔹" if has_inventory_feature else "" - return f"# {module_name}{indicator}\n\n" +def module_header(module_name: str) -> str: + return f"# {module_name}\n\n" clan_core_descr = """ @@ -385,7 +384,7 @@ Learn how to use `clanServices` in practice in the [Using clanServices guide](.. # output += f"`clan.modules.{module_name}`\n" output += f"*{module_info['manifest']['description']}*\n" - fm = Frontmatter("") + fm = ModuleFrontmatter("") # output += "## Categories\n\n" output += render_categories( module_info["manifest"]["categories"], fm.categories_info @@ -417,7 +416,7 @@ Learn how to use `clanServices` in practice in the [Using clanServices guide](.. of.write(output) -def build_option_card(module_name: str, frontmatter: Frontmatter) -> str: +def build_option_card(module_name: str, frontmatter: ModuleFrontmatter) -> str: """ Build the overview index card for each reference target option. """ @@ -431,7 +430,7 @@ def build_option_card(module_name: str, frontmatter: Frontmatter) -> str: indented_text = indent + ("\n" + indent).join(lines) return indented_text - def to_md_li(module_name: str, frontmatter: Frontmatter) -> str: + def to_md_li(module_name: str, frontmatter: ModuleFrontmatter) -> str: md_li = ( f"""- **[{module_name}](./{"-".join(module_name.split(" "))}.md)**\n\n""" ) diff --git a/pkgs/clan-cli/clan_lib/services/modules.py b/pkgs/clan-cli/clan_lib/services/modules.py index 7955fc1df..c2e3587a5 100644 --- a/pkgs/clan-cli/clan_lib/services/modules.py +++ b/pkgs/clan-cli/clan_lib/services/modules.py @@ -2,7 +2,7 @@ import re import tomllib from dataclasses import dataclass, field from pathlib import Path -from typing import Any, TypedDict +from typing import Any, TypedDict, TypeVar from clan_lib.api import API from clan_lib.errors import ClanError @@ -22,7 +22,7 @@ class CategoryInfo(TypedDict): @dataclass -class Frontmatter: +class ModuleFrontmatter: description: str categories: list[str] = field(default_factory=lambda: ["Uncategorized"]) features: list[str] = field(default_factory=list) @@ -87,14 +87,19 @@ def parse_frontmatter(readme_content: str) -> tuple[dict[str, Any] | None, str]: raise ClanError( msg, description="Invalid TOML frontmatter", - location="extract_frontmatter", + location="parse_frontmatter", ) from e return frontmatter_parsed, remaining_content return None, readme_content -def extract_frontmatter(readme_content: str, err_scope: str) -> tuple[Frontmatter, str]: +T = TypeVar("T") + + +def extract_frontmatter[T]( + readme_content: str, err_scope: str, fm_class: type[T] +) -> tuple[T, str]: """ Extracts TOML frontmatter from a README file content. @@ -111,13 +116,13 @@ def extract_frontmatter(readme_content: str, err_scope: str) -> tuple[Frontmatte frontmatter_raw, remaining_content = parse_frontmatter(readme_content) if frontmatter_raw: - return Frontmatter(**frontmatter_raw), remaining_content + return fm_class(**frontmatter_raw), remaining_content # If no frontmatter is found, raise an error msg = "Invalid README: Frontmatter not found." raise ClanError( msg, - location="extract_frontmatter", + location="extract_module_frontmatter", description=f"{err_scope} does not contain valid frontmatter.", ) @@ -128,7 +133,9 @@ def has_inventory_feature(module_path: Path) -> bool: return False with readme_file.open() as f: readme = f.read() - frontmatter, _ = extract_frontmatter(readme, f"{module_path}") + frontmatter, _ = extract_frontmatter( + readme, f"{module_path}", fm_class=ModuleFrontmatter + ) return "inventory" in frontmatter.features @@ -338,7 +345,7 @@ def get_module_info( with module_readme.open() as f: readme = f.read() frontmatter, readme_content = extract_frontmatter( - readme, f"{module_path}/README.md" + readme, f"{module_path}/README.md", fm_class=ModuleFrontmatter ) return LegacyModuleInfo( diff --git a/pkgs/clan-cli/clan_lib/templates/disk.py b/pkgs/clan-cli/clan_lib/templates/disk.py index 49a897bc0..95346c004 100644 --- a/pkgs/clan-cli/clan_lib/templates/disk.py +++ b/pkgs/clan-cli/clan_lib/templates/disk.py @@ -11,7 +11,7 @@ from clan_lib.errors import ClanError from clan_lib.git import commit_file from clan_lib.machines.hardware import HardwareConfig, get_machine_hardware_config from clan_lib.machines.machines import Machine -from clan_lib.services.modules import Frontmatter, extract_frontmatter +from clan_lib.services.modules import ModuleFrontmatter, extract_frontmatter log = logging.getLogger(__name__) @@ -57,7 +57,7 @@ class Placeholder: class DiskSchema: name: str readme: str - frontmatter: Frontmatter + frontmatter: ModuleFrontmatter placeholders: dict[str, Placeholder] @@ -128,7 +128,7 @@ def get_machine_disk_schemas( raw_readme = (disk_template / "README.md").read_text() frontmatter, readme = extract_frontmatter( - raw_readme, f"{disk_template}/README.md" + raw_readme, f"{disk_template}/README.md", fm_class=ModuleFrontmatter ) disk_schemas[schema_name] = DiskSchema(