Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7aa02b2
pyproject.toml: fix requires-python typo
twoerner May 22, 2026
a60cd6b
support Python 3.9 through 3.14
twoerner May 22, 2026
40eed8e
pyproject.toml: declare license via PEP-639 SPDX
twoerner May 22, 2026
75961fd
pyproject.toml: add maintainers block
twoerner May 22, 2026
f30a993
pyproject.toml: add Changelog URL
twoerner May 22, 2026
c9f8fc1
bmaptool: move package version to `__version__`
twoerner May 22, 2026
d8e96db
tests: remove backward-compat test of historical BmapCopy modules
twoerner May 22, 2026
b1ee490
pyproject.toml: swap black for ruff in dev extras
twoerner May 22, 2026
46c6f87
reformat: apply ruff format to the entire tree
twoerner May 22, 2026
66e93c1
add .git-blame-ignore-revs
twoerner May 22, 2026
f39438a
ci: bump actions/checkout in lint job to v4
twoerner May 22, 2026
10db4f2
ci: replace psf/black with a ruff format check
twoerner May 22, 2026
15a6a63
ci: disable fail-fast on the test matrix
twoerner May 22, 2026
7068414
ci: pin actions/checkout to a 40-char SHA
twoerner May 22, 2026
bba83df
ci: pin actions/setup-python to a 40-char SHA
twoerner May 22, 2026
5f2e8a1
ci: declare read-only GITHUB_TOKEN permissions
twoerner May 22, 2026
f94122e
tests: pin pbzip2 and pigz to a single worker
twoerner May 22, 2026
9df0e0f
add .github/dependabot.yml
twoerner May 22, 2026
a40c632
ci: add a non-blocking pip-audit step
twoerner May 22, 2026
2526712
CHANGELOG: describe the modernization changes
twoerner May 22, 2026
08e1d02
pyproject.toml: reflect active maintainership; correct authorship
twoerner Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Revisions listed here are skipped by `git blame` when the file is wired in
# via:
#
# git config blame.ignoreRevsFile .git-blame-ignore-revs
#
# Add only commits whose entire diff is mechanical noise (e.g. a tree-wide
# formatter run). Never list a commit that changes behavior - readers will
# stop seeing it as a real revision in `git blame` output.

# reformat: apply ruff format to the entire tree
46c6f8739b92b5e139c998eb84c7419809ff505d
29 changes: 29 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Dependabot configuration for bmaptool.
# Docs: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
# Keep the GitHub Actions used in .github/workflows/ up to date.
# All third-party actions are SHA-pinned with a "# vX.Y.Z" comment;
# dependabot rewrites both the SHA and the comment when a new tag
# ships, so the comment stays accurate.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
github-actions:
patterns:
- "*"

# Keep Python packages used in pyproject.toml up to date. Runtime
# dependencies are empty today; this primarily exercises the
# [project.optional-dependencies].dev group (ruff).
- package-ecosystem: pip
directory: /
schedule:
interval: weekly
groups:
python:
patterns:
- "*"
31 changes: 26 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,33 @@ on:
- push
- pull_request

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
# Testing with native host python is required in order to test the
# GPG code, since it must use the host python3-gpg package
- "native"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- if: matrix.python-version != 'native'
name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}

Expand Down Expand Up @@ -53,6 +60,20 @@ jobs:

lint:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v3
- uses: psf/black@stable
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
- name: Install ruff
run: python3 -m pip install ruff==0.15.14
- name: ruff format --check
run: ruff format --check .
- name: Install pip-audit
run: python3 -m pip install pip-audit==2.10.0
- name: pip-audit
continue-on-error: true
run: pip-audit .
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### Added
- `.git-blame-ignore-revs` so `git blame` skips the one-time tree-wide reformat.
- `.github/dependabot.yml` opening weekly grouped pull requests for GitHub Actions and pip.
- Non-blocking `pip-audit` step in the CI lint job.
### Changed
- Drop Python 3.8 from the supported set; add 3.13 and 3.14.
- Replace `black` with `ruff` for code formatting; run `ruff format --check` in CI.
- Apply a one-time tree-wide `ruff format` reformat to the entire codebase.
- Pin third-party CI actions by 40-character SHA.
- Declare `permissions: contents: read` on the CI workflow and on each job.
- Disable `fail-fast` on the CI test matrix so a failure on one Python version does not cancel the rest.
- Single-thread `pbzip2` and `pigz` in the api_base test to avoid OOM events on shared CI runners.
- Reduce `maintainers = [...]` to the single active maintainer (Trevor Woerner) and correct `authors = [...]` to list only the project's original author, Artem Bityutskiy.
### Removed
- The historical pre-Python-3 `BmapCopy` modules under `tests/oldcodebase/` and the backward-compat half of `tests/test_compat.py`.
- `six` from `[project.optional-dependencies].dev` (no longer needed without the backward-compat test).

## [3.9.0]

Expand Down
6 changes: 3 additions & 3 deletions make_a_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ printf "%s" "$new_ver" | egrep -q -x '[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+'

# Remind the maintainer about various important things
ask_question "Did you update the man page"
ask_question "Did you update tests: test-data and oldcodebase"
ask_question "Did you update tests: test-data"

# Change the version in the 'bmaptool/CLI.py' file
sed -i -e "s/^VERSION = \"[0-9]\+\.[0-9]\+\.[0-9]\+\"$/VERSION = \"$new_ver\"/" src/bmaptool/CLI.py
# Change the version in the package
sed -i -e "s/^__version__ = \"[0-9]\+\.[0-9]\+\.[0-9]\+\"$/__version__ = \"$new_ver\"/" src/bmaptool/__init__.py
# Sed the version in the RPM spec file
sed -i -e "s/^Version: [0-9]\+\.[0-9]\+\.[0-9]\+$/Version: $new_ver/" packaging/bmaptool.spec
# Remove the "rc_num" macro from the RPM spec file to make sure we do not have
Expand Down
23 changes: 15 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ dependencies = [
# and no longer functions correctly
#"gpg >= 1.10.0",
]
required-python = ">= 3.8"
requires-python = ">= 3.9"
license = "GPL-2.0-only"
license-files = ["LICENSE"]
authors = [
{name = "Joshua Watt", email = "JPEWhacker@gmail.com"},
{name = "Artem Bityutskiy", email = "dedekind1@gmail.com"},
]
maintainers = [
{name = "Trevor Woerner", email = "twoerner@gmail.com"},
{name = "Tim Orling", email = "ticotimo@gmail.com"},

]
readme = "README.md"
classifiers = [
Expand All @@ -23,23 +25,24 @@ classifiers = [
"Topic :: Software Development :: Embedded Systems",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]

[project.optional-dependencies]
dev = [
"black >= 22.3.0",
"six >= 1.16.0",
"ruff >= 0.6.0",
]

[project.urls]
Homepage = "https://github.com/yoctoproject/bmaptool"
Repository = "https://github.com/yoctoproject/bmaptool.git"
Issues = "https://github.com/yoctoproject/bmaptool/issues"
Changelog = "https://github.com/yoctoproject/bmaptool/blob/main/CHANGELOG.md"

[project.scripts]
bmaptool = "bmaptool.CLI:main"
Expand All @@ -49,4 +52,8 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.version]
path = "src/bmaptool/CLI.py"
path = "src/bmaptool/__init__.py"

[tool.ruff]
line-length = 88
target-version = "py39"
11 changes: 6 additions & 5 deletions src/bmaptool/BmapCopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def set_psplash_pipe(self, path):
self._psplash_pipe = path
else:
_log.warning(
"'%s' is not a pipe, so psplash progress will not be " "updated" % path
"'%s' is not a pipe, so psplash progress will not be updated" % path
)

def set_progress_indicator(self, file_obj, format_string):
Expand Down Expand Up @@ -785,7 +785,7 @@ def sync(self):

if self._dest_supports_fsync:
try:
os.fsync(self._f_dest.fileno()),
(os.fsync(self._f_dest.fileno()),)
except OSError as err:
raise Error(
"cannot synchronize '%s': %s " % (self._dest_path, err.strerror)
Expand Down Expand Up @@ -878,9 +878,10 @@ def copy(self, sync=True, verify=True):
# This was observed e.g. in Fedora 17.
# The old settings are saved and restored by the context managers.

with SysfsChange(self._sysfs_max_ratio_path, "1") as max_ratio_chg, SysfsChange(
self._sysfs_scheduler_path, "none"
) as scheduler_chg:
with (
SysfsChange(self._sysfs_max_ratio_path, "1") as max_ratio_chg,
SysfsChange(self._sysfs_scheduler_path, "none") as scheduler_chg,
):
if max_ratio_chg.error:
_log.warning(
"failed to disable excessive buffering, expect "
Expand Down
11 changes: 4 additions & 7 deletions src/bmaptool/CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from typing import NamedTuple
from . import BmapCreate, BmapCopy, BmapHelpers, TransRead

VERSION = "3.9.0"
from . import __version__ as VERSION

log = logging.getLogger() # pylint: disable=C0103

Expand Down Expand Up @@ -615,9 +615,7 @@ def copy_command(args):
)

if args.bmap_sig and not bmap_obj:
error_out(
"the bmap signature file was specified, but bmap file was " "not found"
)
error_out("the bmap signature file was specified, but bmap file was not found")

f_obj = verify_bmap_signature(args, bmap_obj, bmap_path, image_obj.is_url)
if f_obj:
Expand Down Expand Up @@ -653,8 +651,7 @@ def copy_command(args):
log.info("no bmap given, copy entire image to '%s'" % args.dest)
else:
error_out(
"bmap file not found, please, use --nobmap option to "
"flash without bmap"
"bmap file not found, please, use --nobmap option to flash without bmap"
)
else:
log.info("block map format version %s" % writer.bmap_version)
Expand Down Expand Up @@ -767,7 +764,7 @@ def create_command(args):
"all %s are mapped, no holes in '%s'"
% (creator.image_size_human, args.image)
)
log.warning("was the image handled incorrectly and holes " "were expanded?")
log.warning("was the image handled incorrectly and holes were expanded?")


def parse_arguments():
Expand Down
7 changes: 3 additions & 4 deletions src/bmaptool/Filemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def __init__(self, image):
raise Error("cannot flush image file '%s': %s" % (self._image_path, err))

try:
os.fsync(self._f_image.fileno()),
(os.fsync(self._f_image.fileno()),)
except OSError as err:
raise Error(
"cannot synchronize image file '%s': %s "
Expand Down Expand Up @@ -192,8 +192,7 @@ def _lseek(file_obj, offset, whence):
return -1
elif err.errno == errno.EINVAL:
raise ErrorNotSupp(
"the kernel or file-system does not support "
'"SEEK_HOLE" and "SEEK_DATA"'
'the kernel or file-system does not support "SEEK_HOLE" and "SEEK_DATA"'
)
else:
raise
Expand Down Expand Up @@ -422,7 +421,7 @@ def _invoke_fiemap(self, block, count):
raise ErrorNotSupp(errstr)
if err.errno == errno.ENOTTY:
errstr = (
"FilemapFiemap: the FIEMAP ioctl is not supported " "by the kernel"
"FilemapFiemap: the FIEMAP ioctl is not supported by the kernel"
)
_log.debug(errstr)
raise ErrorNotSupp(errstr)
Expand Down
3 changes: 1 addition & 2 deletions src/bmaptool/TransRead.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ def _decode_sshpass_exit_code(code):
result = "invalid/incorrect password"
elif code == 6:
result = (
"host public key is unknown. sshpass exits without "
"confirming the new key"
"host public key is unknown. sshpass exits without confirming the new key"
)
elif code == 255:
# SSH result =s 255 on any error
Expand Down
1 change: 1 addition & 0 deletions src/bmaptool/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "3.9.0"
Loading