Skip to content

Version 2.0.0

Choose a tag to compare

@Technologicat Technologicat released this 16 Mar 10:25
· 96 commits to master since this release

2.0.0 (16 March 2026) — "Six impossible things before breakfast" edition:

IMPORTANT:

  • Python version support: 3.10–3.14 (dropped 3.8, 3.9; added 3.13, 3.14). PyPy 3.11.
    • If you need unpythonic for Python 3.8 or 3.9, use version 1.0.0.
  • Requires mcpyrate >= 4.0.0.
    • mcpyrate 4.0.0 dropped the Str, Num, NameConstant AST compatibility shims and the getconstant helper. Use ast.Constant directly, and .value to get the constant's value.

New:

  • Python 3.13 and 3.14 support.
  • autoreturn macro now handles match/case statements. Each case branch has its own tail position.
  • New scope analyzer tests for match/case patterns and try/except*.
  • New unpythonic.test.runner module: reusable test runner with module discovery, version-suffix gating (e.g. test_foo_3_11.py skipped on Python < 3.11), and integration with the test framework's warning system. Other projects using unpythonic.test.fixtures can import it directly.
  • New emit_warning() function in unpythonic.test.fixtures for signaling test warnings from infrastructure code (outside test[]/warn[] macros). Used by the test runner for version-suffix skips, which show in the warning count for the innermost enclosing testset.
  • Missing optional dependencies (sympy, mpmath) in tests emit warn[] instead of error[], correctly reflecting that these are expected skips, not failures.
  • Runtime type checker (unpythonic.typecheck): new supported typing features — NoReturn, Never (3.11+), Literal, Type, ClassVar, Final, DefaultDict, OrderedDict, Counter, ChainMap, IO/TextIO/BinaryIO (mapped to io module ABCs), Pattern[T]/Match[T] (string type checked when parametric), ContextManager, AsyncContextManager, Awaitable, Coroutine, AsyncIterable, AsyncIterator, Generator, AsyncGenerator.
  • Runtime type checker: TypedDict support — structural checking of required/optional keys and value types.
  • Runtime type checker: Protocol support — @runtime_checkable Protocols work via isinstance; non-runtime-checkable Protocols raise TypeError with an actionable message.
  • Runtime type checker: parametric forms of abstract ABCs — Iterable[T], Collection[T], Reversible[T] perform best-effort element checking (elements checked when value is Sized; ABC-only for opaque iterators). Iterator[T] and Container[T] accept parametric form with type arg silently ignored (iterating an Iterator would consume it; Container only has __contains__, so elements can't be enumerated).

Fixed:

  • Runtime type checker (unpythonic.typecheck): fixed compatibility with Python 3.14, where typing.Union is no longer a _GenericAlias. Now uses typing.get_origin (available since 3.8).
  • Runtime type checker: fixed TypeVar detection to use isinstance(T, typing.TypeVar) instead of a fragile repr-based heuristic.
  • Runtime type checker: typing.Reversible check now uses isinstance instead of a hasattr("__reversed__") workaround from the Python 3.5 era.
  • Runtime type checker: removed redundant safeissubclass fallbacks for generic types — typing.get_origin handles both bare and parameterized generics on 3.10+.
  • Scope analyzer: fixed MatchCapturesCollector bug where class references (e.g. Point in case Point(x, y):) were incorrectly collected as captured variable names.
  • Macro layer: updated all hasattr(tree, "ctx") checks to use getattr with defaults, for correct behavior on Python 3.13+ where AST fields always exist with default values.
    • Important: Since Python 3.13, the default of ctx is Load(), hence no AST node has its ctx in a "not set yet" state anymore. Hence, any macro-created Name nodes that appear in a Store or Del position MUST have their ctx set appropriately by the macro author. Failing to do so will cause mysterious errors during macro expansion.
  • Macro layer: updated arguments() constructor calls to always include posonlyargs=[], avoiding a DeprecationWarning on Python 3.13 (will become an error in 3.15).
  • MS Windows: unpythonic.net.util failed to load, due to missing termios module (which is *nix only) being loaded by unpythonic.net.__init__ when it imports unpythonic.net.ptyproxy.
    • Fixed by catching ModuleNotFoundError, disabling ptyproxy on MS Windows systems. Thus the remote REPL functionality unpythonic.net.client/server is not available on MS Windows, but the rest of unpythonic works fine.

Deprecated:

  • Parenthesis syntax for macro arguments (e.g. let((x, 1), (y, 2))). Use bracket syntax instead: let[[x, 1], [y, 2]]. The parenthesis syntax is kept for backward compatibility for now.
  • Runtime type checker: typing.Text (deprecated since Python 3.11) and typing.ByteString (deprecated since Python 3.12) support is now marked for removal when the floor bumps to Python 3.12.