Changelog

All notable changes to switchlang are documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

0.1.3 - 2026-06-11

Fixed

  • An exception raised inside the with block now always aborts the switch, even when the exception object is falsy. __exit__ guarded its re-raise with if exc_val:, a truthiness test that invokes the exception’s __bool__/__len__. An exception whose __bool__ returned False slipped past the guard, so the matched case action ran before the exception propagated. The guard now tests exc_val is not None, restoring the documented “no case actions run on exception” guarantee for every exception type. (#15)

0.1.2 - 2026-06-11

This release brings switchlang’s whole public-facing surface up to date — a documentation site, a shipped type-hint contract, refreshed docs — and fixes two correctness bugs in the public API (#13, #14).

Added

  • Type information now ships with the package. A py.typed marker makes the hints public API, so switchlang’s signatures type-check and autocomplete in IDEs and type checkers. Every public signature is annotated — case() -> bool, __enter__() -> switch, __exit__(...), result -> Any, and closed_range(...) -> range — using modern, Python 3.9-safe syntax (from __future__ import annotations). (#13)
  • Documentation site at mkennedy.codes/docs/python-switch, built with Great Docs (Quarto): a landing page plus an API reference for switch and closed_range. Includes scripts/build_docs.py and scripts/serve_docs.py. (#13)
  • closed_range() now validates its step. A step less than 1 raises a clear ValueError instead of surfacing a raw range error (for step=0) or silently producing an empty range (for a negative step). (#14)
  • uv add switchlang installation instructions alongside pip. (#13)

Changed

  • Packaging modernized to pyproject.toml + hatchling: the version is read from package metadata, a [dev] extra is provided, Python 3.9–3.15 classifiers and a Typing :: Typed classifier are declared, and full project URLs (docs, repository, issues, PyPI, funding) are published. (#13)
  • case() now always returns bool. It previously returned None on a scalar no-match but False on a list no-match; the return value is now a consistent bool. (#13)
  • Tooling: ruff pinned to target-version = "py39" to match requires-python = ">=3.9". (#13)

Fixed

  • closed_range(start, stop, step) no longer overshoots stop when step > 1. The inclusive bound was built as range(start, stop + step, step), which added a full extra step — e.g. closed_range(1, 6, 2) yielded [1, 3, 5, 7], letting 7 (a value outside the stated range) silently match the case. The bound is now computed as stop + 1, so values never pass stop while stop is still included when a step lands on it exactly (closed_range(1, 7, 2) -> 1, 3, 5, 7). (#14)
  • .result no longer breaks for matched cases that return an always-equal object. The “no result” sentinel was compared with ==, so a returned object with a permissive __eq__ (a NumPy array is the real-world case) made .result raise “No result has been computed” even though a result existed. The sentinel is now compared by identity (is). (#14)

Documentation

  • README refreshed: version and docs badges, a prominent link to the documentation site, an honest feature list (“Validates that case actions are callable”, replacing an inaccurate signature-verification claim), a new s.result bullet, a new “Fall-through and results” section, a new “Why not just match?” section, a closed_range usage example, and f-strings throughout. (#13)
  • Docstrings rewritten to render as the API reference: switch is described as a context manager; default() documents that ordering is not enforced (register it last); case() documents its return contract, the ValueErrors it raises, and the internal no-match sentinel; result documents that the last function executed wins under fall-through; and closed_range is documented as returning a range object (not a “generator”) with its step semantics and ValueError. (#13)

0.1.1 - 2025-09-11

Changed

  • Standardized string literals on double quotes across the codebase and added an initial round of type annotations, including a fix for a potential type warning on s.result.

0.1.0 - 2020-12-10

Added

  • Initial public release of switchlang on PyPI: an explicit switch block for Python built on the with statement, with default cases, duplicate-case detection, list/range cases, opt-in fall-through, and the closed_range helper.