# 10. NEWS

## 10.1. bitmath-2.1.0

Released: May 24, 2026

bitmath 2.1.0 is a focused follow-up to the 2.0.0 modernization. It finishes the last of the Python 2 cleanup, tightens the project’s quality tooling, retires one piece of legacy API surface, and works through OpenSSF’s full menu of supply-chain checks (Scorecard, Best Practices, and the OSPS Baseline) to put a credible security posture on the record. The public API is essentially unchanged from 2.0; the two breaking changes below are narrow ones that affect internal-type inspection and one deprecated helper.

### 10.1.1. Breaking Changes

Internal representation is uniformly floating-point

  Every bitmath instance now stores its size as a 64-bit float, no matter which constructor created it. Previously the `bytes=` and `bits=` keyword constructors, along with the bit-family value constructors such as `Kib(N)`, leaked Python `int` values through the `.bytes` and `.bits` properties. Those properties now always return `float`, matching the long-documented floating-point measurement design described in the Rules for Math appendix. Equality, ordering, `repr()`, and arithmetic results are unchanged; only code that inspected `type(instance.bytes)` or `type(instance.bits)` directly will observe the difference.

listdir() is deprecated

  `bitmath.listdir()` now emits a `DeprecationWarning` on every call and will be removed in a future release. Iterate with `os.walk()` and call `bitmath.getsize()` directly instead. Closes issue #27.

### 10.1.2. Library Improvements

pathlib support

  `bitmath.getsize()` now accepts `pathlib.Path` objects, not just strings, for its `path` argument.

### 10.1.3. Project Infrastructure

Linting moved to pylint

  pylint replaces flake8/pyflakes across the CI workflow and the local toolchain, and the library is held at a 10.00/10 score. pycodestyle is retained for the PEP 8 whitespace checks pylint does not cover.

Security scanning with bandit

  Bandit is a static analyzer from PyCQA that scans Python source for common security smells (hardcoded secrets, `eval`, `subprocess` calls with `shell=True`, insecure `yaml` and `pickle` deserialization, weak crypto primitives). It runs as part of `make ci` and as a dedicated GitHub Actions workflow that fires on every push, every pull request, and on a weekly schedule, scanning both `bitmath/` and `tests/`.

100% test coverage

  The remaining coverage gaps were closed, including the platform-specific `bitmath.query_device_capacity()` branches, bringing the suite to 100% measured coverage on every supported platform.

Property-based testing with Hypothesis

  Four `@given` properties cover `bitmath.parse_string()` roundtrips, lossless unit conversion across every `(src, dst)` pair in `bitmath.ALL_UNIT_TYPES`, and the contract that `bitmath.parse_string()` raises only `ValueError` on bad input. The roundtrip property already turned up a real parser bug around scientific-notation float formatting, which is filed as a follow-up. See PR #144.

SPDX license headers

  Every source and test file now carries `SPDX-License-Identifier` and `SPDX-FileCopyrightText` headers.

Single-sourced version

  The package version is read dynamically from the `VERSION` file by hatchling, so bumping that one file propagates everywhere.

Signed releases (landing with 2.1.0)

  The 2.1.0 release closes out the open OSSF Scorecard Signed-Releases finding (“Determines if the project cryptographically signs release artifacts,” currently flagged at high severity). Scorecard should reflect the improvement on its next weekly run after the release lands.

### 10.1.4. Security and Supply Chain

Most of the work in this release happened here. OpenSSF’s supply-chain story has matured enough to be worth pursuing in earnest even on a small library like bitmath, and the project now carries the badges and the automation to back them up.

OpenSSF Best Practices passing badge

  bitmath earned the OpenSSF Best Practices passing badge. The full self-assessment is on the linked profile; the badge appears on the README and the docsite landing page alongside the OSSF Scorecard and OSPS Baseline badges.

OSPS Baseline Levels 1 and 2 (Level 3 mostly)

  OSPS Baseline Level 1: 23 Met, 2 Not Applicable, 0 Unmet. Level 2: 19 Met, 0 Unmet. Level 3: 18 Met, 2 Not Applicable, 1 Unmet. The single Unmet at Level 3 is OSPS-QA-07.01 (non-author code review), which is structurally blocked by this being a single-maintainer project. Closing it would require either onboarding a second maintainer or changing the project governance model, neither of which is happening in 2.1.0. The control responses backing each Met assessment live in the docsite under Project Architecture and the policy documents listed below.

OSSF Scorecard

  `.github/workflows/scorecard.yml` runs on every push to `master`, on branch-protection-rule changes, and on a weekly cron. Current score and history are published at https://securityscorecards.dev/viewer/?uri=github.com/timlnx/bitmath.

GitHub Actions pinned to commit SHAs

  Every GitHub Actions reference in `.github/workflows/` is now pinned to a full-length commit SHA with the version as a trailing `# vX.Y.Z` comment. Floating tags (the old `@v4`) and floating branch refs (the now-removed `MishaKav/pytest-coverage-comment@main` third-party step) are gone. Dependabot keeps the SHAs fresh.

Dependabot

  `.github/dependabot.yml` watches the `github-actions` and `pip` ecosystems on a weekly cadence. Minor and patch bumps are grouped per ecosystem to keep PR noise bounded; major bumps land as standalone PRs so breaking-change review stays honest.

Hardened workflow token permissions

  Every workflow declares an explicit `permissions: read-all` at the top level, with `write` scopes applied only to the jobs that need them (`security-events: write` for SARIF upload, `id-token: write` for PyPI OIDC Trusted Publishing, and so on). The default-write `GITHUB_TOKEN` posture is no longer inherited anywhere.

SCA via pip-audit

  `.github/workflows/sca.yml` runs pip-audit on every push, every pull request, and on a weekly cron. bitmath has no runtime dependencies, so this scans the test-only deps in `requirements.txt`. Findings are resolved on the release-blocking timetable specified in `SECURITY_POLICIES.md`.

CycloneDX SBOM attached to every release

  The publish workflow now installs the built wheel into an isolated venv, snapshots it with cyclonedx-py, and attaches the resulting `bitmath-<version>.cdx.json` to the GitHub release alongside the wheel and sdist. Downstream consumers who SBOM-scan everything they ingest can now pull bitmath’s SBOM from the release page directly instead of generating their own.

### 10.1.5. Project Documentation and Governance

The documentation set picked up five new top-level files this release. These exist to answer standing security, governance, and verification questions for downstream consumers without requiring a real-time email exchange, and several of them are direct deliverables for OSPS Baseline controls.

MAINTAINERS.md

  New top-level file naming the sole current maintainer, the sensitive-resource access that comes with the role (PyPI account, GitHub admin, GPG key, ReadTheDocs admin), maintainer responsibilities, and a standing open call for a Debian/Ubuntu co-maintainer (see issue #117 if you’re interested).

ARCHITECTURE.md

  New top-level design document covering runtime architecture, the build and release pipeline (including the Packit downstream RPM flow into Fedora and EPEL), CI gates, trust boundaries, and the documentation pipeline. Lives at the repo root so the OpenSSF scanner finds it by filename, and so anyone exploring the repo for the first time can get the design picture before reading code.

SECURITY_ASSESSMENT.md

  Standing threat model describing the attack surfaces (supply chain, PyPI account, source repository, build chain, distribution chain), the mitigations in place for each, and the automated security tooling stack with what each tool catches.

SECURITY_POLICIES.md

  The SAST and SCA remediation thresholds and release-blocking criteria in one place. Bandit and pip-audit findings, severity ladder, the rule for what blocks a release versus what gets a follow-up, and the timetable for acting on each.

VERIFICATION.md

  Downstream-consumer guide for verifying a bitmath release end to end: integrity via the SHA-256 sums published alongside the GitHub release, authenticity via PEP 740 attestations and pypi-attestations, and provenance via the CycloneDX SBOM. If your organization’s policy requires verifying every dependency before installation, this is the playbook.

SECURITY.md tightened up

  Coordinated Vulnerability Disclosure now states explicit response timeframes (72 hours to acknowledge a report, 7 days to triage), and the document picked up new Scope of Support, Duration of Support, and Secrets and Credentials Policy sections.

HTTPS for all project doc URLs

  Every `http://` reference to project-owned documentation (`bitmath.readthedocs.io`, the docsite, README badge targets, NEWS historical links, CONTRIBUTING) has been switched to `https://` to clear the bestpractices.dev `sites_https` check. ReadTheDocs was already serving TLS; only the scheme needed flipping. See PR #146.

## 10.2. bitmath-2.0.0

Released: April 25, 2026

Nearly eight years after 1.3.3 shipped in 2018, bitmath is back with a major release. Version 2.0.0 is a thorough modernization: the Python 2 era is officially over, the library picks up several long-requested features, and the entire project infrastructure has been rebuilt from scratch. If you’ve been running bitmath on Python 3.9 or later and quietly wishing it felt more modern — this release is for you.

Check over on my blog for a personal recap of this release, how much it means to me, and what it took to get here.

### 10.2.1. Breaking Changes

Python support

  Python 3.9+ only. Python 2 and Python < 3.9 are no longer supported or tested.

parse_string() default system

  The default unit system when `strict=False` is now NIST (base-2). Previously it defaulted to SI (base-10). Code that relied on the old default for ambiguous strings such as `"1g"` could get a different result. See parse_string with strict=False for full details. All bitmath now consistently defaults to the NIST system.

parse_string_unsafe() deprecated

  Use `bitmath.parse_string()` with `strict=False` instead. The old name still works but emits a `DeprecationWarning`.

bitmath.integrations removed

  The `argparse`, `click`, and `progressbar` integrations have been removed from the package. Copy-paste replacements are provided in the new Integration Examples documentation chapter. No changes to calling code are required — just a local copy of the relevant snippet.

Byte and Bit display names

  `Byte` and `Bit` now display as `B` and `b` respectively, matching the abbreviated style of every other unit. Code that compares formatted strings (e.g. `"{unit}"` in a format template or the output of `str()` / `repr()`) against the literal words `"Byte"` or `"Bit"` will need to be updated. The class names themselves are unchanged.

query_device_capacity() on macOS

  `bitmath.query_device_capacity()` now raises `NotImplementedError` on macOS. System Integrity Protection (SIP) blocks raw block device access even for root, making the previous ioctl path unreliable. Use `bitmath.query_capacity()` instead.

Build and install

  `setup.py` and `setup.py.in` are gone. Installation is `pip install bitmath`. Source builds use `python -m build`.

### 10.2.2. Library Improvements

The core API is unchanged — every bitmath object you created before still works exactly the same way. What 2.0.0 adds on top of that:

Full NIST unit coverage

  The four largest NIST prefix units — `ZiB`, `YiB`, `Zib`, and `Yib` — are now first-class bitmath types. All constants (NIST_PREFIXES, NIST_STEPS, ALL_UNIT_TYPES) reflect reality.

f-string and format() support

  bitmath objects now implement the Python format protocol (`__format__`, PEP 3101). They can be used directly in f-strings with format specs — `f"{some_size:.2f}"` just works. See Python Format Protocol (f-strings and format()) for the full reference. Credit to Jonathan Eunice for the original concept in PR #76.

bitmath.sum() and built-in sum()

  A new `bitmath.sum()` function returns a unit-normalized result when summing mixed-type iterables. For uniform collections, the built-in `sum()` now works directly on bitmath sequences without a `start=` argument.

Thread-safe context manager

  The `bitmath.format()` context manager previously mutated module-level globals, making it unsafe under concurrent access. It now uses `threading.local` with proper save/restore semantics, including correct nesting behavior. Closes issue #83.

best_prefix() bit-family fix

  `bitmath.best_prefix()` incorrectly converted bit-family units (e.g. `Kib`) into byte-family units (e.g. `KiB`). The unit family is now preserved. Closes issue #95.

query_capacity() — recommended volume size API

  New `bitmath.query_capacity()` returns a `bitmath.Capacity` NamedTuple of `(total, used, free)` `bitmath.Bitmath` instances for any path or mount point. Works cross-platform without elevated privileges. This is the recommended API for “how big is this volume?” queries. Accepts `bestprefix=True` (default) to get already human-readable units (e.g. `GiB`) and `system=bitmath.SI` to opt into decimal prefixes instead of the default NIST binary prefixes. Set `bestprefix=False` to receive raw `bitmath.Byte` instances.

Windows device capacity

  `bitmath.query_device_capacity()` now works on Windows via `DeviceIoControl`. Open the device as `open(r'\\.\PhysicalDrive0', 'rb')` (administrator privileges required). Unsupported platforms raise `NotImplementedError`. The new `bitmath.SUPPORTED_PLATFORMS` constant lists all platforms where the function is available. Closes issue #52.

query_device_capacity() Linux buffer fix

  `bitmath.query_device_capacity()` on Linux was passing an integer where an ioctl buffer was required, causing `OSError: [Errno 14] Bad address`. The call now correctly allocates a zero-filled buffer of the proper size via `b'\\x00' * struct.calcsize(fmt)`.

Flexible string parsing

  `bitmath.parse_string()` with `strict=False` accepts ambiguous input such as `"1g"` or `"1GB"` and resolves it to the most likely unit. When the system cannot be reliably determined, NIST is the tiebreaker. Closes issue #54.

Floor division, modulo, and divmod for capacity math

  bitmath objects now implement `__floordiv__` (`//`), `__mod__` (`%`), and `__divmod__` — useful for chunk-and-remainder capacity planning (“how many N-sized chunks fit into this device, and how much is left over?”). `bm1 // bm2` returns an `int` (count of whole divisions), mirroring how `bm1 / bm2` returns a unitless ratio. `bm1 % bm2` and `divmod(bm1, bm2)` return remainders as bitmath objects of the left-hand operand’s type, consistent with every other bitmath arithmetic operator. The identity `(a // b) * b + (a % b) == a` holds. See Capacity Math: Floor Division and Modulo for worked examples including `best_prefix()` coercion and `bitmath.format` context-manager integration.

### 10.2.3. Project Infrastructure

The project infrastructure has been rebuilt to reflect how Python projects are actually maintained in 2026:

Project Security

  GitHub now has branch protection enabled. Releases are signed with the maintainers GPG key.

Packaging

  `pyproject.toml` with a hatchling backend replaces the old `setup.py`/`setup.py.in` template system. The package is PEP 517/PEP 518 compliant. `MANIFEST.in` is gone; sdist content is declared explicitly in `pyproject.toml`.

GitHub Actions

  CI now runs against Python 3.9 through 3.13 on Ubuntu, macOS, and Windows, with actions pinned to current versions (`checkout@v6`, `setup-python@v5`). Tests run on every pull request, not just pushes.

Security scanning

  CodeQL analysis runs on every push to master, every pull request, and on a weekly schedule.

ReadTheDocs

  `.readthedocs.yaml` is now present and explicit. The RTD build uses Python 3.11 and installs `sphinx_rtd_theme` directly.

Development workflow

  `make ci` is the single command for a full local build: unique test name check, pycodestyle, flake8, and pytest with coverage. `make build`, `make pypitest`, and `make pypi` replace the old `make sdist upload` pattern.

Fedora/EPEL

  Expect to see fresh builds in Fedora/EPEL over the coming weeks. Hopefully I can sneak this into EPEL 10, EPEL 9 might be picky since this is a major version change.

### 10.2.4. Closing Thoughts

bitmath started as a small passion project of mine. A utility for thinking about and clearly expressing file sizes, and that’s still exactly what it is. This 2.0.0 release doesn’t change what the library does. What I’ve done is change the very foundation that it’s built on. The test suite measures in at 311 tests now, basically 100% coverage when you add all the platform-specific checks together. The documentation has been comprehensively reviewed and updated. The packaging is modernized.

It really is a remarkable milestone in project history. I have to give the warmest thanks to all of the users and fans who have written bug reports and submitted pull requests. Especially in the least active years of the project. Most of those PRs and Issues have been integrated into this massive 2.0.0 release.

Thanks for your patience and your participation.

If you’ve been holding off on adopting bitmath because the last release predated your Python version — yeah I totally get it. This place was a dumpster for the last 8 years.

Go on, give it a shot. It really is better than ever.

## 10.3. bitmath-1.4.0-1

bitmath-1.4.0 was published on 2026-04-16.

### 10.3.1. Project

Version 1.4.0 is a maintenance release — the final release to support Python 2 era packaging infrastructure. It addresses two long-standing issues and makes no breaking changes.

### 10.3.2. Changes

Bug Fixes

- Fixed packaging: `bitmath.integrations` subpackage was missing from the `packages` list in `setup.py.in`, causing the argparse, click, and progressbar integrations to be absent from installed distributions. Reported in PR #107.

- Modernized mock imports in the test suite: `tests/test_progressbar.py` and `tests/test_query_device_capacity.py` now prefer `unittest.mock` (stdlib, Python 3.3+) and fall back to the third-party `mock` package. Based on PR #105.

## 10.4. bitmath-1.3.3-1

bitmath-1.3.3-1 was published on 2018-08-23.

### 10.4.1. Project

Version 1.3.3 is a minor update primarily released to synchronize versions across platforms. Additionally there are small packaging updates to keep up with changing standards.

Minor bug fixes and documentation tweaks are included as well.

The project now has an official Code of Conduct, as well as issue and pull request templates.

What happened to bitmath 1.3.2? It only ever existed as an idea in source control.

### 10.4.2. Changes

Bug Fixes

Alexander Kapshuna has submitted several fixes since the last release. Thanks!

- Packaging requirements fixes

- Python 3 compatibility

- Subclassing and Type checking fixes/improvements

Marcus Kazmierczak submitted a fix for some broken documentation links.

And Dawid Gosławski make sure our documentation is accurate.

Thanks to all the bitmath contributors over the years!

## 10.5. bitmath-1.3.1-1

bitmath-1.3.1-1 was published on 2016-07-17.

### 10.5.1. Changes

Added Functionality

- New function: `bitmath.parse_string_unsafe()`, a less strict version of `bitmath.parse_string()`. Accepts inputs using non-standard prefix units (such as single-letter, or mis-capitalized units).

- Inspired by @darkblaze69’s request in #60 “Problems in parse_string”.

### 10.5.2. Project

Ubuntu

- Bitmath is now available for installation via Ubuntu Xenial, Wily, Vivid, Trusty, and Precise PPAs.

- Ubuntu builds inspired by @hkraal reporting an installation issue on Ubuntu systems.

Documentation

- Cleaned up a lot of broken or re-directing links using output from the Sphinx `make linkcheck` command.

## 10.6. bitmath-1.3.0-1

bitmath-1.3.0-1 was published on 2016-01-08.

### 10.6.1. Changes

Bug Fixes

- Closed GitHub Issue #55 “best_prefix for negative values”. Now `bitmath.best_prefix()` returns correct prefix units for negative values. Thanks mbdm!

## 10.7. bitmath-1.2.4-1

bitmath-1.2.4-1 was published on 2015-11-30.

### 10.7.1. Changes

Added Functionality

- New bitmath module function: `bitmath.query_device_capacity()`. Create `bitmath.Byte` instances representing the capacity of a block device. Support is presently limited to Linux and Mac.

- The `bitmath.parse_string()` function now can parse ‘octet’ based units. Enhancement requested in #53 parse french unit names by walidsa3d.

Bug Fixes

- #49 - Fix handling unicode input in the bitmath.parse_string function. Thanks drewbrew!

- #50 - Update the `setup.py` script to be python3.x compat. Thanks ssut!

### 10.7.2. Documentation

- The project documentation is now installed along with the bitmath library in RPM packages.

### 10.7.3. Project

Fedora/EPEL

Look for separate python3.x and python2.x packages coming soon to Fedora and EPEL. This is happening because of the initiative to update the base Python implementation on Fedora to Python 3.x

- BZ1282560

## 10.8. bitmath-1.2.3-1

bitmath-1.2.3-1 was published on 2015-01-03.

### 10.8.1. Changes

Added Functionality

- New utility: `progressbar` integration: bitmath.integrations.BitmathFileTransferSpeed. A more functional file transfer speed widget.

### 10.8.2. Documentation

- The command-line `bitmath` tool now has online documentation

- A full demo of the `argparse` and `progressbar` integrations has been written. Additionally, it includes a comprehensive demonstration of the full capabilities of the bitmath library. View it in the Real Life Demos Creating Download Progress Bars example.

### 10.8.3. Project

Tests

- Travis-CI had some issues with installing dependencies for the 3.x build unittests. These were fixed and the build status has returned back to normal.

## 10.9. bitmath-1.2.0-1

bitmath-1.2.0-1 was published on 2014-12-29.

### 10.9.1. Changes

Added Functionality

- New utility: `argparse` integration: bitmath.BitmathType. Allows you to specify arguments as bitmath types.

### 10.9.2. Documentation

- The command-line `bitmath` tool now has a proper manpage

### 10.9.3. Project

Tests

- The command-line `bitmath` tool is now properly unittested. Code coverage back to ~100%.

## 10.10. bitmath-1.1.0-1

bitmath-1.1.0-1 was published on 2014-12-20.

- GitHub Milestone Tracker for 1.1.0

### 10.10.1. Changes

Added Functionality

- New `bitmath` command-line tool added. Provides CLI access to basic unit conversion functions

- New utility function bitmath.parse_string for parsing a human-readable string into a bitmath object. Patch submitted by new contributor tonycpsu.

## 10.11. bitmath-1.0.5-1 through 1.0.8-1

bitmath-1.0.8-1 was published on 2014-08-14.

- GitHub Milestone Tracker for 1.0.8

### 10.11.1. Major Updates

- bitmath has a proper documentation website up now on Read the Docs, check it out: bitmath.readthedocs.io

- bitmath is now Python 3.x compatible

- bitmath is now included in the Extra Packages for Enterprise Linux EPEL6 and EPEL7 repositories (pkg info)

- merged 6 pull requests from 3 contributors

### 10.11.2. Bug Fixes

- fixed some math implementation bugs

  - commutative multiplication

  - true division

### 10.11.3. Changes

Added Functionality

- best-prefix guessing: automatic best human-readable unit selection

- support for bitwise operations

- formatting customization methods (including plural/singular selection)

- exposed many more instance attributes (all instance attributes are usable in custom formatting)

- a context manager for applying formatting to an entire block of code

- utility functions for sizing files and directories

- add instance properties equivalent to `instance.to_THING()` methods

### 10.11.4. Project

Tests

- Test suite is now implemented using Python virtualenv’s for consistency across across platforms

- Test suite now contains 150 unit tests. This is 110 more tests than the previous major release (1.0.4-1)

- Test suite now runs on EPEL6 and EPEL7

- Code coverage is stable around 95-100%

## 10.12. bitmath-1.0.4-1

This is the first release of bitmath. bitmath-1.0.4-1 was published on 2014-03-20.

### 10.12.1. Project

Available via:

- PyPi

- Fedora 19

- Fedora 20

bitmath had been under development for 12 days when the 1.0.4-1 release was made available.

### 10.12.2. Debut Functionality

- Converting between SI and NIST prefix units (`GiB` to `kB`)

- Converting between units of the same type (SI to SI, or NIST to NIST)

- Basic arithmetic operations (subtracting 42KiB from 50GiB)

- Rich comparison operations (`1024 Bytes == 1KiB`)

- Sorting

- Useful console and print representations