Source code for dsw_document_template_tool.dsw_compat

"""Official DSW compatibility source helpers.

This module intentionally only discovers *candidate* runtime information.
Checked-in CI runtimes still live in ``config/dsw-compat.yml`` and should only
be updated after complete import and render validation.
"""

from __future__ import annotations

import re
import urllib.error
import urllib.request
from dataclasses import dataclass

OFFICIAL_TEMPLATE_METAMODEL_SPEC_URL = (
    "https://guide.ds-wizard.org/en/latest/more/development/document-templates/specification.html"
)
HTTP_USER_AGENT = "dsw-document-template-tool/compat-discovery"


[docs] class DswCompatSourceError(RuntimeError): """Raised when an official DSW compatibility source cannot be used."""
[docs] @dataclass(frozen=True) class DswTemplateMetamodelSupport: """Official minimum DSW version for a document-template metamodel.""" metamodel_version: str minimum_dsw_version: str source_url: str
[docs] def fetch_official_template_metamodel_support( source_url: str = OFFICIAL_TEMPLATE_METAMODEL_SPEC_URL, *, timeout_seconds: int = 20, ) -> dict[str, DswTemplateMetamodelSupport]: """Fetch and parse the official DSW document-template metamodel table.""" try: request = urllib.request.Request( source_url, headers={"User-Agent": HTTP_USER_AGENT}, ) with urllib.request.urlopen(request, timeout=timeout_seconds) as response: text = response.read().decode("utf-8") except OSError as exc: raise DswCompatSourceError( f"Could not load official DSW metamodel source {source_url!r}: {exc}" ) from exc return parse_template_metamodel_support(text, source_url=source_url)
[docs] def parse_template_metamodel_support( text: str, *, source_url: str, ) -> dict[str, DswTemplateMetamodelSupport]: """Parse DSW metamodel support rows from the official specification page.""" rows: dict[str, DswTemplateMetamodelSupport] = {} for match in re.finditer( r"Version\s+" r"(?P<metamodel>[0-9]+(?:\.[0-9]+)*)" r"\s+\(since\s+" r"(?P<dsw>[0-9]+(?:\.[0-9]+){1,2})" r"\)", text, ): metamodel_version = _normalize_version(match.group("metamodel")) rows[metamodel_version] = DswTemplateMetamodelSupport( metamodel_version=metamodel_version, minimum_dsw_version=_normalize_version(match.group("dsw")), source_url=source_url, ) if not rows: raise DswCompatSourceError( f"Could not parse any metamodel support rows from {source_url!r}" ) return rows
[docs] def runtime_candidate_message( metamodel_version: str, support_by_metamodel: dict[str, DswTemplateMetamodelSupport] | None, ) -> str: """Return a maintainer-facing runtime suggestion for one metamodel.""" if support_by_metamodel is None: return "No official runtime suggestion is available." support = support_by_metamodel.get(_normalize_version(metamodel_version)) if support is None: return "No official DSW metamodel mapping was found for this metamodelVersion." return ( f"Official DSW docs say document-template metamodel " f"{support.metamodel_version} is supported since DSW " f"{support.minimum_dsw_version}. Start by validating a " f"wizard-server/document-worker runtime at or above that version with " f"a matching dsw-tdk release, then add the proven runtime to " f"`config/dsw-compat.yml`." )
def _normalize_version(version: str) -> str: return version.strip()