NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Friendly misc/utils/convenience library
Last release 5 months ago
05 May 2026
Release timing varies
gaps range from 8 days to 7 months
Most releases are documented
notes for 43 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
8 years old
193 releases · first in 2018
Nothing published for this version
Be stricter about python specs for freethreading by @thatch in https://github.com/codrsquad/runez/pull/53
Full Changelog: https://github.com/codrsquad/runez/compare/v5.8.0...v5.9.0
Breaking changes worth highlighting:
Breaking changes worth highlighting:
ArtifactInfo.from_basename() raises ValueError on unparseable input (was None). Callers that depended on the None branch need to catch ValueError instead.
PythonSpec.version is never None anymore. Code checking spec.version is None should switch to not spec.is_valid (or not spec.version.is_valid).
cached_property.to_dict(cls) no longer returns None for a class — the method now requires an instance. If any caller passed the class as a "no cached values" sentinel, they need to adjust.
PythonSpec.from_object(Version("foo")) used to return a spec with an invalid version; now returns None.
Non-breaking additions:
runez.OptionalColor, Traceable, Version.required_from_object(), PythonSpec.is_valid
abort() overloads — purely a typing improvement, runtime behavior unchanged
More details:
Stronger and more consistent type annotations across the library (pyenv, system, logsetup, colors, render, serialize); modernized to X | None / list[X] style throughout
Added runez.OptionalColor type alias (Callable | str | None) for parameters accepting a color name, color callable, or None
Added Traceable protocol in runez.logsetup for objects exposing a .trace(message) method
abort() now has proper @overload-ed signatures: NoReturn when fatal, otherwise returns return_value with a preserved generic type
Version.required_from_object(): new classmethod that raises ValueError when a version can't be determined (companion to Version.from_object() which returns None)
Version.from_object(), PythonSpec.from_object() and PythonSpec.from_text() now share a consistent contract: a returned object is guaranteed to be valid, otherwise None is returned
PythonSpec.is_valid property added as a shortcut for spec.version.is_valid
PythonSpec.__init__ now accepts Version | str (tighter input typing)
ArtifactInfo.from_basename() return type narrowed to ArtifactInfo (no longer | None)
cached_property.to_dict(): target must now be an instance (not a class, not None); always returns a dict
cached_property.properties() and cached_property._walk_properties(): annotated as Iterator[...] generators
One column per quarter.
Avoid crashing when trying to flush log buffers at the end of test runs
Support py3.10+ only
Simplified TempFolder()
Avoid crashing when trying to flush log buffers at the end of test runs
Stronger typing for all methods in runez.file
parent_folder() now returns a Path
to_path() no longer accepts/returns None
Nothing published for this version
Don't try to model source any longer in (seldom used) ArtifactInfo
Don't try to model source any longer in (seldom used) ArtifactInfo
Accept basic types in schemas again
Accept basic types in schemas again
Corrected log wrapping, accept level as default logger
Corrected log wrapping, accept level as default logger
Support py3.8+ for a while longer
Support py3.8+ for a while longer
Correctly handle main() functions that return a str
Correctly handle main() functions that return a str
ClickRunner.default_main and ClickRunner.context_wrapper replace deprecated cli.default_main and cli.context
which() looks at current venv bin/ folder first
ClickRunner.default_main and ClickRunner.context_wrapper replace deprecated cli.default_main and cli.context
Removed:
assert_printed() from CapturedStream, TrackedOutput, and ClickRunner
runez.SYS_INFO.platform_id.is_windows
runez.inspector.AutoInstall
runez.inspector.ImportTime
Not exposing in top-level runez import (use from runez.<submodule> import ... if needed):
AdaptedProperty, ascii, config , is_subfolder, PsInfo, Slotted
Simplified runez.schema internals
Turned on flake8-simplify and tryceratops, fixed corresponding issues
Added tests
Modernized GH actions and project metadata
ClickRunner.run() now accepts pathlib.Path objects for main/script args
Fixed operator precedence bug in Version.__le__()
Fixed WrappedHandler.clean_accumulated_logs() crash when called before any test runs
stringified() uses errors="replace" when decoding bytes
make_executable() now preserves existing permission bits instead of hardcoding 0o755
Using extractall(filter="data") from stdlib for path traversal protection
Adapted type declarations, pyright now reports 0 errors
Added freethreading support to PythonSpec: new freethreading parameter, abi_suffix property, and "t" suffix parsing in spec strings
Added freethreading support to PythonSpec: new freethreading parameter, abi_suffix property, and "t" suffix parsing in spec strings
Nothing published for this version
Modernized repo setup, use pyproject.toml, test with py3.14
Modernized repo setup, use pyproject.toml, test with py3.14
Dropped support for EOL-ed python versions < 3.10
Dropped support for EOL-ed python versions < 3.10
Removed legacy pypi listing functions from runez.pyenv:
Removed legacy pypi listing functions from runez.pyenv:
default_pypi_client()
latest_pypi_version()
ls_pypi()
pypi_response()
Restore env vars in IsolatedLogSetup context manager
Restore env vars in IsolatedLogSetup context manager
Added OverrideDryrun context manager
Added OverrideDryrun context manager
Find already scanned python installations by path
Find already scanned python installations by path
* Added py.typed to package
Added py.typed to package
Detect buildkit as docker as well
Detect buildkit as docker as well
Don't capture passthrough runs when file handler given
Don't capture passthrough runs when file handler given
Don't fake existence of PythonInstallation in dryrun mode
Don't fake existence of PythonInstallation in dryrun mode
State when a run failed in runez.log.timeit()
State when a run failed in runez.log.timeit()
Show exit code for failed runez.run() even with pass-through
Don't highlight invoker python anymore
Don't highlight invoker python anymore
Consider "preferred" python only for explicit python3 symlinks in locations that otherwise have pythonM.m symlinks
Corrected side-effect determining preferred_python in PythonDepot
Corrected side-effect determining preferred_python in PythonDepot
No preferred python from PATH env var (only from explicitly configured locations)
No preferred python from PATH env var (only from explicitly configured locations)
Automatically determine a preferred_python in PythonDepot
Automatically determine a preferred_python in PythonDepot
More flexible PythonDepot scan for python binaries
Avoid using pkg_resources
* Test against python 3.12
Test against python 3.12
Accept rc versions for in PythonSpec
Accept rc versions for in PythonSpec
* Corrected resolved_path()
Corrected resolved_path()
Corrected bugs in PythonDepot and PythonSpec
Corrected bugs in PythonDepot and PythonSpec
Generalized PythonDepot specification (API change, PythonDepot now takes a locations specification instead of a scanner object)
Generalized PythonDepot specification (API change, PythonDepot now takes a locations specification instead of a scanner object)
Added property Version.pep_440 (canonical PEP-440_ version representation)
Removed Version.from_text, Version is parsed strictly by default
Accept dots in pypi package names
Pass through any http requests exceptions
Pass through any http requests exceptions
Add an option in readlines() to skip call to rstrip().
Add an option in readlines() to skip call to rstrip().
Nothing published for this version
Fully implemented PEP-440_ for Version ordering
Fully implemented PEP-440_ for Version ordering
Corrected a serialization bug, where nested Serialized objects weren't properly serialized
Corrected a serialization bug, where nested Serialized objects weren't properly serialized
Report last_modified date and size in ArtifactInfo when available
Accept up to 5 version components (was up to 4 before)
Accept up to 5 version components (was up to 4 before)
Report on ignored part of a loosely parsed Version
Corrected comparison of Version-s (was not properly sorting .dev versions before)
Corrected comparison of Version-s (was not properly sorting .dev versions before)
Corrected cli test fixture, avoid crashing when test deleted current working directory
Corrected cli test fixture, avoid crashing when test deleted current working directory
Support a simple optional cache for RestClient-s
Support a simple optional cache for RestClient-s
CVE-2007-4559
Avoid creating anything at import time (removed most globals)
Avoid creating anything at import time (removed most globals)
Allow to configure a preferred_python in PythonDepot
Allow to configure a preferred_python in PythonDepot
* Added __repr__ to RunAudit * Corrected docstrings
Added __repr__ to RunAudit
Corrected docstrings
Nothing published for this version
More generic parsing of PythonSpec
More generic parsing of PythonSpec
Respect optional checksum in url, in decompress()
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Restore cwd after a cli test command run
Restore cwd after a cli test command run
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →