Bengal 0.4.2
Honest internals — failures now surface as build warnings instead of vanishing, file writes are crash-safe, the rebuild-reason vocabulary and parser contract are unified, config_path is honored, and a documentation sweep makes the reference match the code.
Key theme: Honest internals. 0.4.2 is the second patch off 0.4.0 — thirteen backward-compatible fixes from the same repo-wide audit, plus the audit's own expansion pass. Where 0.4.1 stopped shipping wrong output, 0.4.2 stops hiding what goes wrong: failures that used to vanish at debug level now surface as build warnings, file writes can no longer be truncated by a crash, internal contracts and the documentation finally agree with the code, and the release tooling itself got fixed. No new features, no breaking changes.
What's fixed
Failures surface instead of vanishing
- Search-index/JSON drops are now visible. When per-page data accumulation failed, the page was silently dropped from the search index and JSON outputs at debug level. It now surfaces as a build warning (recorded in the build summary) with the full, untruncated error and a suggestion — the page is still skipped gracefully and the build still completes (
#449). - No more silent
exceptswallows. Restoring cached parsed links that fails now logscached_links_restore_failed(full error,reason="fallback_to_empty") before falling back; and the dev server's build-trigger logstemplate_cache_load_failedinstead of silently nulling the cache, so you can tell why an incremental rebuild stopped tracking template changes (#472).
Your files can't be corrupted mid-write
- Crash-safe writes. Three remaining direct writes — the external-reference index cache, the performance
latest.jsonsnapshot, and thebengal.yamlrewrite onbengal versionregistration — now go through the atomic write-temp-then-rename helpers, so a SIGINT/crash/OOM mid-write can no longer leave a truncated file (#471).
Internals that match their contracts
- One rebuild-reason vocabulary. The two diverged
RebuildReasonCode/RebuildReasondefinitions are unified into a single canonical source; both import paths now resolve to the same objects, andfull_rebuild(reason=...)records its reason instead of discarding it (#445). parse_with_toctells the truth. The base contract now documents and returns the 4-tuple(html, toc, excerpt, meta_description)the parsers actually produce;PythonMarkdownParserreturns four values too, so custom parsers and callers unpack uniformly (#443).Site.from_config(config_path=...)is honored. The documentedconfig_pathargument was silently dropped — Bengal always auto-discoveredbengal.toml. The explicit path now loads, falling back to auto-discovery only when omitted (#444).- Dead and test-only code out of production. Removed the never-called, divergent
phase_cache_savefinalization helper (#451) and a productionfrom unittest.mock import Mockimport in the index generator, replaced by a real serializability check (#450).
Documentation matches the code
- No fabricated CLI. The invented
bengal project ...command group is gone from the docs (skeletons apply duringbengal new site; profiles viabengal build --profile),bengal initreferences corrected tobengal config init, and a new doc-lint fails CI if anybengal <subcommand>in the docs doesn't resolve to a registered command (#435). - Real content-types API. The reference now shows
from bengal.content_types import register_strategywith an instance (not the nonexistentContentTypeRegistryclass), and the "Available types" list matches the actual registry keys (#436). - Reality sweep. Config docs use the real
baseurlkey (notbase_url), stale0.1.10version examples updated, error-code docs name Kida (the default engine) instead of Jinja2, and the architecture reference lists the realbengal/core/pagemodules; the CLI-contract doc-lint allowlist was burned down (bengal validate→check,collections/sources→content …) (#474,#470).
Tooling
- Correct release titles.
make gh-release/poe gh-releasebuilt the GitHub release title from a greedygrep '^name ='that captured the towncrier category names — producing titles likebengal Added Changed Deprecated Removed Fixed Security 0.4.1. A newscripts/publish_github_release.pyreads[project].versionviatomlliband rendersvX.Y.Z — <theme>(#480).
Test integrity
- De-vacuumed a
hasattr(site.data, "tracks")assertion (always true on aDotDict) into a real value check, and addedAssetURLValidator/PerformanceValidatorto the health-validator contract suite they were wrongly excluded from (#473).
Changes at a glance
Removed
- Dead
phase_cache_savebuild-finalization helper (#451).
Fixed
- Visible build warnings for JSON/search-index accumulation failures (
#449) and previously silentexceptswallows (#472). - Crash-safe atomic writes for the ref-cache,
latest.json, andbengal.yaml(#471). - Unified
RebuildReason/RebuildReasonCodevocabulary (#445); 4-tupleparse_with_toccontract (#443); honoredSite.from_config(config_path=...)(#444); removed a productionunittest.mockimport (#450). - Documentation-vs-reality fixes: content-types API (
#436), fabricatedbengal projectgroup (#435),baseurl/version/engine/module drift + CLI-lint allowlist (#474,#470). - Correct GitHub release titles via a rewritten
gh-releasemechanism (#480). - Test-integrity: de-vacuumed assertion + restored validator contract coverage (
#473).
Upgrading
pip install --upgrade bengal-ssg
0.4.2 is a drop-in patch: no breaking changes and no config migration. Everything here makes already-documented behavior actually work. If you parse build output, note that page-accumulation failures now appear as build warnings rather than being silently omitted; if you implement a custom parser, parse_with_toc now returns a 4-tuple (html, toc, excerpt, meta_description).