Set up mypy defaults and make sure codebase passes --strict

This commit is contained in:
2026-08-05 00:50:34 +02:00
parent b8a0a94ba9
commit 406ef9fd8d
4 changed files with 33 additions and 12 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ def setup_logging(verbose: bool = False, log_file: str | None = None) -> None:
logger.addHandler(console) logger.addHandler(console)
def main(): def main() -> None:
setup_logging(verbose=True) setup_logging(verbose=True)
site = Site(Path(".")) site = Site(Path("."))
site.build() site.build()
+17 -8
View File
@@ -3,9 +3,9 @@ import re
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from pathlib import Path from pathlib import Path
from datetime import date from datetime import date
import typing from typing import TYPE_CHECKING, Any, cast
if typing.TYPE_CHECKING: if TYPE_CHECKING:
from omicron.ssg.site import Site from omicron.ssg.site import Site
import yaml import yaml
@@ -34,19 +34,26 @@ def _highlight_code(code: str, lang: str, attrs: str) -> str:
return pygments_highlight(code, lexer, HtmlFormatter()) return pygments_highlight(code, lexer, HtmlFormatter())
def read_frontmatter(path) -> dict: def read_frontmatter(path: Path) -> dict[str, Any]:
lines = [] lines = []
with path.open("r", encoding="utf-8") as f: with path.open("r", encoding="utf-8") as f:
if f.readline() != "---\n": if f.readline() != "---\n":
raise ContentError(f"Frontmatter opening delimiter not found for {path}") raise ContentError(f"Frontmatter opening delimiter not found for {path}")
while (line := f.readline()) != "---\n": while (line := f.readline()) != "---\n":
if line == "": if line == "":
raise ContentError(f"Frontmatter closing delimiter not found for {path}") raise ContentError(
f"Frontmatter closing delimiter not found for {path}"
)
lines.append(line) lines.append(line)
return yaml.safe_load("".join(lines)) data = yaml.safe_load("".join(lines))
if not isinstance(data, dict) or not all(isinstance(k, str) for k in data):
raise ContentError(
f"Frontmatter must be a YAML mapping with string keys in {path}"
)
return cast(dict[str, Any], data)
def create_content(path) -> Content: def create_content(path: Path) -> Content:
if path.suffix in FRONTMATTER_CONTENT: if path.suffix in FRONTMATTER_CONTENT:
meta = read_frontmatter(path) meta = read_frontmatter(path)
elif path.suffix == ".yml": elif path.suffix == ".yml":
@@ -93,7 +100,9 @@ class Content(ABC):
f.readline() # opening --- f.readline() # opening ---
while (line := f.readline()) != "---\n": while (line := f.readline()) != "---\n":
if line == "": if line == "":
raise ContentError(f"Frontmatter closing delimiter not found for {self.source}") raise ContentError(
f"Frontmatter closing delimiter not found for {self.source}"
)
return f.read() return f.read()
@abstractmethod @abstractmethod
@@ -102,7 +111,7 @@ class Content(ABC):
class Article(Content): class Article(Content):
def __init__(self, path: Path, meta: dict): def __init__(self, path: Path, meta: dict[str, Any]):
if "tags" not in meta: if "tags" not in meta:
log.warning("no tags for article in '%s'", path) log.warning("no tags for article in '%s'", path)
super().__init__( super().__init__(
+5 -3
View File
@@ -1,5 +1,5 @@
import logging import logging
from typing import Any from typing import Any, cast
from omicron.ssg.content import ( from omicron.ssg.content import (
Content, Content,
@@ -39,11 +39,13 @@ class Site:
log.debug("Reading config file %s", config_path) log.debug("Reading config file %s", config_path)
with open(config_path, "r") as f: with open(config_path, "r") as f:
config = yaml.safe_load(f) config = yaml.safe_load(f)
if not isinstance(config, dict) or not all(isinstance(k, str) for k in config):
raise ConfigError("config file must be a YAML mapping with string keys")
if "name" not in config: if "name" not in config:
raise ConfigError("name value missing from config") raise ConfigError("name value missing from config")
if "template" not in config: if "template" not in config:
raise ConfigError("template value missing from config") raise ConfigError("template value missing from config")
return config return cast(dict[str, Any], config)
@staticmethod @staticmethod
def resolve_template_path(template: str) -> Path: def resolve_template_path(template: str) -> Path:
@@ -84,7 +86,7 @@ class Site:
self.content.append(content) self.content.append(content)
log.info("Discovered %d content items", len(self.content)) log.info("Discovered %d content items", len(self.content))
def build(self): def build(self) -> None:
self.discover() self.discover()
self.output_path.mkdir(parents=True, exist_ok=True) self.output_path.mkdir(parents=True, exist_ok=True)
(self.output_path / "pygments.css").write_text( (self.output_path / "pygments.css").write_text(
+10
View File
@@ -13,9 +13,19 @@ dependencies = [
"PyYAML", "PyYAML",
] ]
[project.optional-dependencies]
dev = [
"mypy",
"types-PyYAML",
"types-Pygments",
]
[project.scripts] [project.scripts]
ossg = "omicron.ssg.cli:main" ossg = "omicron.ssg.cli:main"
[tool.mypy]
strict = true
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
where = ["."] where = ["."]
include = ["omicron.ssg*"] include = ["omicron.ssg*"]