stratified_packager.toolbelt.utils

Miscellaneous utility functions.

DO NOT import from the qgis package in this module outside of TYPE_CHECKING guards.

Functions

coerce_bool(raw, /)

Interpret a raw value as a boolean.

dedupe_names(names, /)

Disambiguate duplicate names by suffixing _2, _3, .

python_executable()

Return the path to the Python interpreter, even when embedded in a host application.

remove_diacritical_marks(txt, /)

Remove diacritical marks from a string (such as accents, tildes and cedillas).

remove_tree(path, /, *[, attempts, delay])

Best-effort recursive directory removal, retrying briefly on undeletable entries.

sanitize_filename(txt, /)

Turn a string into a valid cross-platform filename, preserving Unicode letters.

sanitize_identifier_name(txt, /)

Turn a string into a valid identifier by removing non-alphanumerics and diacritical marks.

Exceptions

OperationAbortedError

Raised when a long-running toolbelt operation is aborted via its abort callback.

exception stratified_packager.toolbelt.utils.OperationAbortedError[source]

Raised when a long-running toolbelt operation is aborted via its abort callback.

stratified_packager.toolbelt.utils.coerce_bool(raw, /)[source]

Interpret a raw value as a boolean.

Native booleans pass through and numbers use their truthiness; strings are matched case-insensitively (after stripping) against the true tokens ("true", "1", "yes", "on", "t", "y") and false tokens ("false", "0", "no", "off", "f", "n", "").

Parameters:

raw (object) – The raw value.

Return type:

bool

Returns:

The boolean value.

Raises:

ValueError – If raw is not a recognizable boolean token.

stratified_packager.toolbelt.utils.dedupe_names(names, /)[source]

Disambiguate duplicate names by suffixing _2, _3, … in encounter order.

The first occurrence keeps its name; later duplicates get the lowest free suffix (collisions with pre-existing suffixed names are themselves disambiguated). Comparison is case-insensitive, matching SQLite/GeoPackage table-name semantics.

Parameters:

names (Iterable[str]) – The candidate names, in order.

Return type:

list[str]

Returns:

A same-length list of unique names.

stratified_packager.toolbelt.utils.python_executable()[source]

Return the path to the Python interpreter, even when embedded in a host application.

When Python is embedded (e.g. in QGIS) sys.executable points at the host binary rather than the interpreter; reconstruct the interpreter path from the installation layout in that case. Useful for tools that must spawn a Python subprocess, like debugpy.

Return type:

Path | None

Returns:

Path to the interpreter, or None if it cannot be located.

stratified_packager.toolbelt.utils.remove_diacritical_marks(txt, /)[source]

Remove diacritical marks from a string (such as accents, tildes and cedillas).

Parameters:

txt (str) – Original string.

Return type:

str

Returns:

A copy of the original string with the diacritical marks removed.

stratified_packager.toolbelt.utils.remove_tree(path, /, *, attempts=3, delay=0.5)[source]

Best-effort recursive directory removal, retrying briefly on undeletable entries.

On Windows a file some handle still holds open (e.g. a lingering GDAL or SQLite handle on a GeoPackage) cannot be deleted; a plain shutil.rmtree() either raises or, with ignore_errors, silently leaves the residue behind. This helper swallows per-entry errors, sleeps delay seconds before each retry (locks are often released moments after their owner is garbage-collected), and reports whether the tree is actually gone. A missing path counts as success.

Parameters:
  • path (Path) – The directory to remove.

  • attempts (int) – Total removal attempts.

  • delay (float) – Seconds slept before each retry.

Return type:

bool

Returns:

Whether path no longer exists afterwards.

stratified_packager.toolbelt.utils.sanitize_filename(txt, /)[source]

Turn a string into a valid cross-platform filename, preserving Unicode letters.

Strips path separators and the characters Windows forbids in filenames (including control characters), collapses whitespace runs into single spaces, trims leading and trailing whitespace and trailing dots, prefixes _ to reserved Windows device names (CON, NUL, COM1, … — matched against the base name before the first dot, case-insensitively), and truncates to the 255-character filesystem component limit. Unlike sanitize_identifier_name(), Unicode letters and diacritics are preserved.

The result is never empty (_ stands in when nothing survives) and the function is idempotent, but distinct inputs MAY collide — callers that require uniqueness must detect collisions themselves (case-insensitively, for Windows).

Parameters:

txt (str) – Original string (e.g. a stratum name).

Return type:

str

Returns:

A copy of the original string safe to use as a single filename component.

stratified_packager.toolbelt.utils.sanitize_identifier_name(txt, /)[source]

Turn a string into a valid identifier by removing non-alphanumerics and diacritical marks.

Parameters:

txt (str) – Original string.

Return type:

str

Returns:

A copy of the original string with the diacritical marks removed and _ in place of runs of non-alphanumeric characters. If the original string starts with a numeric digit, a _ is inserted at the beginning.

stratified_packager.toolbelt.utils._ILLEGAL_FILENAME_CHARS: Final[re.Pattern[str]] = re.compile('[\\x00-\\x1f\\x7f<>:"/\\\\|?*]')

Characters Windows forbids in filenames (a superset of the POSIX restrictions).

stratified_packager.toolbelt.utils._MAX_FILENAME_LENGTH: Final = 255

Per-component filename length limit on the common filesystems (NTFS, ext4, APFS).

stratified_packager.toolbelt.utils._WINDOWS_RESERVED_NAMES: Final[frozenset[str]] = frozenset({'AUX', 'COM0', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'COM²', 'COM³', 'COM¹', 'CON', 'LPT0', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', 'LPT²', 'LPT³', 'LPT¹', 'NUL', 'PRN'})

Reserved device names (base name before the first dot, case-insensitive).