Source code for drc_python_template.core

"""Core helpers that demonstrate the template package shape."""

from __future__ import annotations

import re
from dataclasses import dataclass

_DEFAULT_TOOLCHAIN = ("ruff", "mypy", "pytest", "sphinx")
_PACKAGE_TOKEN_RE = re.compile(r"[^a-z0-9]+")


[docs] @dataclass(frozen=True, slots=True) class ProjectBlueprint: """Describe the baseline choices captured by the template. Args: name: The distribution name used for packaging. package_name: The Python import package name. python_version: The minimum supported Python version line. include_docs: Whether the repository ships with docs scaffolding. include_examples: Whether the repository ships with example scripts. toolchain: The default local quality and documentation tools. """ name: str package_name: str python_version: str = "3.12" include_docs: bool = True include_examples: bool = True toolchain: tuple[str, ...] = _DEFAULT_TOOLCHAIN
[docs] def summary_lines(self) -> tuple[str, ...]: """Return a compact, human-readable project summary. Returns: A tuple of display lines that can be printed directly. """ return ( f"Project: {self.name}", f"Import package: {self.package_name}", f"Python: {self.python_version}+", f"Docs included: {'yes' if self.include_docs else 'no'}", f"Examples included: {'yes' if self.include_examples else 'no'}", f"Toolchain: {', '.join(self.toolchain)}", )
[docs] def normalize_package_name(name: str) -> str: """Convert a project name into a valid import package token. Args: name: An arbitrary project or distribution name. Returns: A normalized, underscore-separated package token. Raises: ValueError: Raised when the normalized name would be empty. """ normalized = _PACKAGE_TOKEN_RE.sub("_", name.strip().lower()).strip("_") if not normalized: raise ValueError("Package name cannot be empty after normalization.") return normalized
[docs] def build_default_blueprint( project_name: str, package_name: str | None = None, ) -> ProjectBlueprint: """Build a default project blueprint for the template repository. Args: project_name: The distribution or repository name. package_name: An optional explicit import package name. Returns: A populated project blueprint. """ resolved_package_name = ( normalize_package_name(project_name) if package_name is None else normalize_package_name(package_name) ) return ProjectBlueprint(name=project_name, package_name=resolved_package_name)
[docs] def describe_project(blueprint: ProjectBlueprint) -> str: """Render a blueprint into a printable multi-line description. Args: blueprint: The project blueprint to describe. Returns: A newline-delimited description string. """ return "\n".join(blueprint.summary_lines())