stratified_packager.toolbelt.zipping
Plugin-agnostic zip assembly, atomic publishing and archive-path validation helpers.
DO NOT import from the qgis package in this module (it must stay usable from worker
threads and scripts/); standard library only.
Archive paths handled here are relative, slash-separated paths inside a zip (or below an output directory). Validation is strict and never sanitizes: callers that build paths from user expressions are expected to surface the reported violation instead of silently rewriting the path.
Module Attributes
Suffix of in-progress zip files; consumers only ever see fully published zips. |
Functions
|
Assemble a zip from |
|
Group distinct paths that collide case-insensitively (the Windows filesystem rule). |
|
Check one path component against the strict filename rules. |
|
Yield |
|
Publish built at final via |
|
Remove leftover |
|
Write a |
|
Validate a relative archive path and split it into its components. |
- stratified_packager.toolbelt.zipping._check_abort(abort, token)[source]
Raise when the abort callback signals cancellation.
- stratified_packager.toolbelt.zipping._copy_stream(src, dst, abort, token)[source]
Copy src into dst in chunks, polling abort between chunks.
- Parameters:
- Raises:
OperationAbortedError – If abort returned
True.- Return type:
- stratified_packager.toolbelt.zipping._raise_path_error(path, reason)[source]
Raise the
ValueErrorfor an invalid archive path.
- stratified_packager.toolbelt.zipping._write_members(archive, members, compression, compression_level, abort)[source]
Stream every member into the open archive.
- Parameters:
archive (
ZipFile) – Archive open for writing.members (
Iterable[tuple[Path,str]]) –(source file, arcname)pairs.compression (
int) – The archive-level compression constant.compression_level (
int) – The Deflate level (0when stored).abort (
Callable[[],bool] |None) – Optional abort callback polled per member and per chunk.
- Raises:
OperationAbortedError – If abort returned
True.- Return type:
- stratified_packager.toolbelt.zipping.build_zip(zip_path, members, *, compression_level, abort=None)[source]
Assemble a zip from
(source file, arcname)members.Compression is Deflate at compression_level, except level
0which stores entries uncompressed (ZIP_STORED). Zip64 extensions are enabled, so archives and members beyond 4 GiB are supported. Sources are streamed in chunks, so large members do not load into memory.- Parameters:
zip_path (
Path) – Destination zip file path (parent directory must exist; an existing file is overwritten).members (
Iterable[tuple[Path,str]]) –(source file, arcname)pairs; arcnames use/separators.compression_level (
int) –0to9;0selectsZIP_STORED.abort (
Callable[[],bool] |None) – Optional callback polled before every member and between copy chunks; returningTrueaborts the build.
- Return type:
- Returns:
zip_path.
- Raises:
OperationAbortedError – If abort returned
True; the partial file is removed before raising.
- stratified_packager.toolbelt.zipping.case_insensitive_collisions(paths, /)[source]
Group distinct paths that collide case-insensitively (the Windows filesystem rule).
- stratified_packager.toolbelt.zipping.filename_component_error(component, /)[source]
Check one path component against the strict filename rules.
The rules mirror
utils.sanitize_filename()(illegal characters, reserved Windows device names, trailing dots/spaces, length) but validate instead of fixing — a violation is reported, never repaired.
- stratified_packager.toolbelt.zipping.iter_file_members(root, arc_prefix='', /)[source]
Yield
(source file, arcname)pairs for every file below root, recursively.Directory entries themselves are not yielded (zip directories materialize from member paths). Arcnames are slash-separated and prefixed with arc_prefix.
- stratified_packager.toolbelt.zipping.publish_atomic(built, final, *, abort=None)[source]
Publish built at final via
<final>.partand an atomic rename.The source is copied (chunked, abortable) to
<final>.partin the destination directory, then renamed withos.replace()semantics — consumers of the destination directory only ever observe complete files. When built already lives on the destination filesystem the copy is still performed (simple and correct); callers building directly in the output directory pass a.partpath as built instead and usepathlib.Path.replace()themselves.- Parameters:
- Return type:
- Returns:
final.
- Raises:
OperationAbortedError – If abort returned
True; the.partfile is removed before raising.
- stratified_packager.toolbelt.zipping.remove_stale_parts(directory, zip_names, /)[source]
Remove leftover
<name>.partfiles for this run’s target zip names.Only the given names are touched — foreign
.partfiles (other tools, other runs with different targets) are left alone.
- stratified_packager.toolbelt.zipping.sha256_sidecar(path, /)[source]
Write a
<name>.sha256checksum file next to path.The content follows the
sha256sumconvention:<hex digest> <filename>with a trailing newline, so standard tools can verify it. Written UTF-8: the filename may carry non-ASCII characters (e.g. an accented stratum name), whichsha256sumreads back in the locale byte encoding.
- stratified_packager.toolbelt.zipping.split_archive_path(path, /)[source]
Validate a relative archive path and split it into its components.
Accepts
/and\as separators. Rejects absolute paths (POSIX or Windows, including drive-letter and UNC forms),./..components, and any component violatingfilename_component_error().- Parameters:
path (
str) – The relative path to validate (e.g. an evaluated gpkg or zip path).- Return type:
- Returns:
The validated components, in order.
- Raises:
ValueError – If the path is empty, absolute, escapes the root, or contains an invalid component; the message names the violation.
- stratified_packager.toolbelt.zipping.PART_SUFFIX: Final = '.part'
Suffix of in-progress zip files; consumers only ever see fully published zips.
- stratified_packager.toolbelt.zipping._COPY_CHUNK_SIZE: Final = 4194304
Chunk size (4 MiB) for abortable file copies.
- stratified_packager.toolbelt.zipping._DRIVE_PREFIX: Final[re.Pattern[str]] = re.compile('^[A-Za-z]:')
Windows drive-letter prefix marking an absolute (or drive-relative) path.