os_helper package
Submodules
- os_helper.cli_argparse module
- os_helper.cli_click module
- os_helper.config_utils module
- os_helper.gui module
- os_helper.hash_utils module
- os_helper.logging_utils module
- os_helper.misc_utils module
- os_helper.path_utils module
- os_helper.profile_utils module
- os_helper.string_utils module
- os_helper.system_utils module
- os_helper.temp_utils module
Module contents
OS Helper
A collection of cross-platform utility functions covering: - file and directory handling - system / OS detection and process helpers - string manipulation and ASCII normalization - temporary files and folders (including remote staging) - hashing of strings, files, and folders - configuration loading (JSON / YAML / .env / environment) - URL checks, downloads, zipping - logging and verbosity helpers
Usage Example
>>> import os_helper as osh
>>> osh.verbosity(1)
>>> if osh.unix():
... osh.info("running on a Unix-based OS")
>>> osh.info(osh.now_string("filename"))
>>> h = osh.hash_string("hello", size=8)
The same helpers are also exposed as an argparse CLI (os-helper) and a
click CLI (os-helper-click, install [cli] extra). See the README
and GUI.md for the multi-surface story.
- os_helper.absolute2relative_path(path, base_path=None)[source]
Convert a path to a relative path expressed from
base_path.- Parameters:
- Returns:
The relative path from
base_pathtopath.- Return type:
Example
>>> absolute2relative_path("/home/user/project/file.txt", "/home/user") 'project/file.txt'
- os_helper.asciistring(input_string, replacement_char='-', lower=True, allow_digits=True)[source]
Convert a given string into a “safe” ASCII string by replacing accented and non-ASCII characters.
Non-ASCII characters that cannot be converted will be replaced with a specified character.
- Parameters:
input_string (str) – The input string to be converted.
replacement_char (str, optional) – The character to replace non-ASCII or unwanted characters with. Defaults to ‘-‘.
lower (bool, optional) – Whether to convert the string to lowercase. Defaults to True.
allow_digits (bool, optional) – Whether to allow digits in the resulting string. Defaults to True.
- Returns:
A “safe” ASCII string with unwanted characters replaced and case adjusted.
- Return type:
Examples
>>> asciistring("MyFile@2024.txt") 'myfile-2024-txt'
>>> asciistring("Café-Con-Leche!", replacement_char="_") 'cafe_con_leche'
>>> asciistring("Special#File$2024", lower=False) 'Special-File-2024'
- os_helper.check(condition, msg='Assertion failed')[source]
Assert a condition, logging an error and raising if it fails.
- Parameters:
- Raises:
AssertionError – If
conditionis falsy.- Return type:
None
- os_helper.checkfile(filepath, msg='', check_empty=False)[source]
Assert that a file exists and, optionally, that it is non-empty.
- Parameters:
- Raises:
AssertionError – If the file does not exist (or is empty when
check_emptyis True).- Return type:
None
Example
>>> checkfile("data.csv", msg="Data file missing", check_empty=True)
- os_helper.copyfile(source, destination)[source]
Copy a file from
sourcetodestination, preserving metadata.If
destinationis an existing directory, the source file name is appended to it (mirroringcpsemantics).- Parameters:
- Raises:
AssertionError – If the source file does not exist or is empty, or if source and destination resolve to the same path.
OSError – If the underlying
shutil.copy2call fails (propagated as-is).
- Return type:
None
Example
>>> copyfile("source.txt", "backup/source_backup.txt")
- os_helper.cpu_timer()[source]
Measure CPU time consumed by the current process using
time.process_time()(sums user + system CPU across all threads).Differs from
wall_timer()in two important ways:It excludes time spent blocked on I/O, sleeping, or waiting on the GPU — so it isolates “actual computation done by Python+native code”.
It excludes subprocesses (ffmpeg, etc.). For those, use
wall_timer()oros.times()directly.
On a multi-threaded computation it can report more seconds than wall-clock — that’s intentional: it counts the CPU work, not the elapsed time.
- Yields:
dict –
{"seconds": float, "milliseconds": float}.- Return type:
Examples
>>> with cpu_timer() as t: ... total = sum(i * i for i in range(1_000_000)) >>> assert t["seconds"] > 0
- os_helper.critical(msg, *args, **kwargs)[source]
Log a message at CRITICAL level via the dedicated
os_helperlogger.- Parameters:
msg (str) – The (possibly %-style) message template.
*args (Any) – Positional interpolation arguments forwarded to
logging.critical.**kwargs (Any) – Keyword options forwarded to
logging.critical.
- Return type:
None
- os_helper.debug(msg, *args, **kwargs)[source]
Log a message at DEBUG level via the dedicated
os_helperlogger.- Parameters:
msg (str) – The (possibly %-style) message template.
*args (Any) – Positional interpolation arguments forwarded to
logging.debug.**kwargs (Any) – Keyword options (e.g.
exc_info) forwarded tologging.debug.
- Return type:
None
- os_helper.dir_exists(path, check_empty=False)[source]
Check if a directory exists, with an option to verify it’s not empty.
- Parameters:
- Returns:
True if the directory exists (and is not empty if check_empty is True), False otherwise.
- Return type:
Example
>>> dir_exists("/path/to/folder") True >>> dir_exists("/path/to/empty_folder", check_empty=True) False
- os_helper.download_file(url, file_path='', *, chunk_size=None, progress=True, check_url=True, resume=True, retries=3, sha256=None, overwrite=False)[source]
Download a URL to a local file: streamed, resumable, retried, atomic, verified.
This is the suite-wide download primitive; every helper that fetches bytes from HTTP (model mirrors, media, templates, catalogs) routes through it so the smart behaviour lives in one place:
Streamed block-by-block, so the payload is never held in memory (a multi-GB model downloads with a flat footprint). The block size adapts to the payload via
_adaptive_chunk_size()(~500 progress updates, clamped[64 KiB, 4 MiB]); passchunk_sizeto override.Resumable (
resume=True): bytes land in a<file>.partsidecar, and an interrupted transfer continues with an HTTPRangerequest instead of restarting. If the server ignoresRange(answers200instead of206), the sidecar is restarted from zero automatically.Retried (
retriesattempts) on transient network errors, with exponential backoff, each retry resuming from the current sidecar size.Atomic: the finished sidecar is
os.replace-d ontofile_pathin one step, sofile_pathonly ever exists as a complete download; a crash leaves a.part, never a truncated final file.Verified (optional
sha256): the finished file’s digest is checked and a mismatch raises (the bad sidecar is discarded).Idempotent (
overwrite=False): an existing, completefile_pathis reused without re-downloading (its digest re-checked whensha256is given), so callers can invoke it unconditionally.
A
tqdmprogress bar is shown on an interactive terminal (auto-suppressed off-TTY). Progress and completion are logged viainfo(), retries viawarning(), hard failures viaerror(). Iffile_pathis empty, the name is derived from the URL’s last segment.- Parameters:
url (str) – The URL to download from.
file_path (str, optional) – Destination path. Defaults to the URL’s last path segment.
chunk_size (int or None, optional) – Streaming block size in bytes.
None(default) adapts to the size.progress (bool, optional) – Show a progress bar on an interactive terminal (default
True).check_url (bool, optional) – Pre-validate the URL with a HEAD request (default
True). SetFalsewhen the server rejects HEAD (405/403).resume (bool, optional) – Continue a partial
<file>.partvia HTTPRange(defaultTrue).Falsediscards any sidecar and downloads from scratch.retries (int, optional) – Extra attempts on transient network errors, with exponential backoff (default
3, so up to four tries total).sha256 (str or None, optional) – Expected lowercase hex SHA-256. When given, the finished file is verified and a mismatch raises
ValueError.overwrite (bool, optional) – Re-download even if
file_pathalready exists (defaultFalse: reuse a complete destination, re-checkingsha256when supplied).
- Returns:
{"path": <destination>, "content_type": <server MIME or "">, "bytes": <size on disk>, "sha256": <hex or "">, "resumed": <bool>}.- Return type:
dict of str to object
- Raises:
AssertionError – If the URL fails the
is_working_url()precondition.ValueError – If
sha256is given and the finished file’s digest does not match.requests.RequestException – If every attempt fails or the server returns a non-2xx status.
- os_helper.emptystring(s)[source]
Return True if
sis None, not a string, or only whitespace.Convenient for input validation where
"",Noneand" "should all be treated the same way.- Parameters:
s (Optional[str]) – The value to check.
- Returns:
True when
sis None or contains only whitespace; False otherwise.- Return type:
Examples
>>> emptystring("") True >>> emptystring(" ") True >>> emptystring(None) True >>> emptystring("hello") False
- os_helper.error(msg, *args, **kwargs)[source]
Log a message at ERROR level via the dedicated
os_helperlogger.Note: this is a non-raising logger call. It will not terminate the program. Use
check()(assertion-style) or raise an exception explicitly if you need failure semantics.- Parameters:
msg (str) – The (possibly %-style) message template.
*args (Any) – Positional interpolation arguments forwarded to
logging.error.**kwargs (Any) – Keyword options forwarded to
logging.error.
- Return type:
None
- os_helper.file_exists(file_path, check_empty=False)[source]
Check if a file exists, with an option to verify it’s not empty.
- Parameters:
- Returns:
True if the file exists (and is not empty if check_empty is True), False otherwise.
- Return type:
Example
>>> file_exists("example.txt") True >>> file_exists("empty.txt", check_empty=True) False
- os_helper.folder_description(path, recursive=True, index_html=True, with_size=True, description_json=True)[source]
List a folder’s files (with sizes) and optionally emit an HTML / JSON index.
Walks
path(recursively by default), skips hidden entries (names starting with"."), and returns a mapping from each file’s path relative topathto its size in bytes. Whenindex_htmlis True, a Bootstrap-styledindex.htmlis written intopath; whendescription_jsonis True, adescription.jsoncompanion file is written as well.- Parameters:
path (str) – Path to the folder to describe (must exist).
recursive (bool, optional) – If True, descend into subdirectories. Defaults to True.
index_html (bool, optional) – If True, write
path/index.htmllinking each entry. Defaults to True.with_size (bool, optional) – If True, include a human-readable size column in the HTML index. Defaults to True.
description_json (bool, optional) – If True, write
path/description.jsonwith the raw mapping. Defaults to True.
- Returns:
Mapping of
relative_file_path -> size_in_bytesfor every non-hidden file found.- Return type:
- Raises:
AssertionError – If
pathdoes not exist or is not a directory.
- os_helper.folder_name_ext(path, checkpath=False)[source]
Decompose a file or folder path into (folder, basename, extension).
The split happens at the last dot in the basename, so multi-part suffixes like
.tar.gzare not collapsed into one extension. Use"basename.extension"to recover the original file name.Returns an empty extension for: - directories, - files whose basename contains no dot.
- Parameters:
- Returns:
(folder, basename, extension)whereextensionexcludes the leading dot.- Return type:
Examples
>>> folder_name_ext("/path/to/file.txt") ('/path/to', 'file', 'txt') >>> folder_name_ext("/path/to/archive.tar.gz") ('/path/to', 'archive.tar', 'gz') >>> folder_name_ext("/path/to/folder") # existing directory ('/path/to', 'folder', '')
- os_helper.format_size(size)[source]
Convert a byte count into a short human-readable string.
Picks an appropriate SI-style unit (B, KB, MB, GB, TB) using decimal thresholds (1000-based). Useful for log lines and progress reporting.
- os_helper.get_config(keys, config_type, path=None, env_files=None)[source]
Load configuration settings using a fixed fallback order.
Precedence (first match wins): 1.
pathpointing to a JSON/YAML file (or, if a directory, the first.json,.yamlor.ymlfile in it that contains all keys);one or more
.envfiles merged intoos.environ;the current process environment.
- Parameters:
keys (List[str]) – Keys required to be present in the resolved configuration.
config_type (str) – Human-readable label used only in log messages.
path (Optional[str], optional) – Path to a configuration file or a directory containing one. If None or empty, this step is skipped.
env_files (Optional[List[str]], optional) –
.envfiles to load intoos.environbefore reading variables. Defaults to[".env"].
- Returns:
Mapping with one entry per requested key.
- Return type:
- Raises:
RuntimeError – If none of the sources provide all required keys.
Example
>>> config = get_config(["host", "port"], "database", path="config.yaml") >>> config {'host': 'localhost', 'port': 5432}
- os_helper.get_nb_workers(workers=-1)[source]
Resolve a worker count, following scikit-learn’s
n_jobsconvention.The default pool size is
os.cpu_count()(or 1 if that returns None), overridable via theNB_WORKERSenvironment variable.- Parameters:
workers (int, optional) –
0: use the full pool size.> 0: use exactly that many workers.< 0: usepool_size + workers + 1(e.g.-1→ all CPUs,-2→ all but one), clamped to at least 1.
- Returns:
The resolved worker count (always >= 1).
- Return type:
Example
>>> get_nb_workers() # -1 → all available CPU cores 4
- os_helper.get_user_ip()[source]
Fetch the caller’s public IPv4 and IPv6 addresses via the ipify API.
- Returns:
{"ipv4": <str or None>, "ipv6": <str or None>}. An individual entry is None when its endpoint fails or returns no address.- Return type:
- Raises:
AssertionError – If both endpoints fail and no address could be retrieved.
- os_helper.getpid()[source]
Return the current process ID as a string.
- Returns:
str(os.getpid()).- Return type:
- os_helper.gpu_timer(backend='auto')[source]
Measure GPU execution time, synchronizing before and after the block.
Backends
"cuda"— usestorch.cuda.Event(enable_timing=True)pairs, which give microsecond-level GPU-side timing."mps"— Apple Silicon. PyTorch’s MPS backend does not expose timing events, so this falls back totorch.mps.synchronize()+time.perf_counter()around the block. Accuracy ~1 ms."auto"— pick CUDA if available, else MPS, else raise.
Both paths synchronize before and after the block so the measured duration corresponds to actual GPU work, not just kernel-queue submission. Without synchronization, GPU ops are asynchronous and the timer would understate the cost dramatically.
- param backend:
"auto"(default),"cuda", or"mps".- type backend:
str, optional
- Yields:
dict –
{"seconds": float, "milliseconds": float}.- raises RuntimeError:
If PyTorch is not installed, or if the requested backend is unavailable on this machine.
- raises ValueError:
If
backendis not one of"auto","cuda","mps".
Examples
>>> import torch >>> if torch.cuda.is_available(): ... x = torch.randn(2048, 2048, device="cuda") ... with gpu_timer() as t: ... y = x @ x ... print(t["milliseconds"])
- os_helper.hash_string(s, size=-1)[source]
Generate a hash of a given string and optionally returns a truncated version.
- Parameters:
- Returns:
The hashed string, optionally truncated.
- Return type:
Example
>>> isinstance(hash_string("example"), str) True >>> len(hash_string("example")) 40 >>> len(hash_string("example", size=8)) 8
Note
The exact digest depends on the underlying hash engine (RIPEMD-160 when available, BLAKE2b truncated to 20 bytes otherwise). The output length stays 40 hex characters either way.
- os_helper.hashfile(path, hash_content=True, date=False)[source]
Generate a hash for a file’s content and/or its last modification date.
- Parameters:
- Returns:
The resulting hash of the file as a 40-character hex string.
- Return type:
- os_helper.hashfolder(path, hash_content=True, hash_path=False, date=False)[source]
Generate a hash for the contents of a folder and/or its path.
- Parameters:
path (str) – The path to the folder to hash.
hash_content (bool, optional) – If True, includes the folder’s contents in the hash (default: True).
hash_path (bool, optional) – If True, includes the folder’s path in the hash (default: False).
date (bool, optional) – If True, includes the current date in the hash (default: False).
- Returns:
The resulting hash of the folder and/or its contents as a 40-character hex string.
- Return type:
- os_helper.info(msg, *args, **kwargs)[source]
Log a message at INFO level via the dedicated
os_helperlogger.- Parameters:
msg (str) – The (possibly %-style) message template.
*args (Any) – Positional interpolation arguments forwarded to
logging.info.**kwargs (Any) – Keyword options forwarded to
logging.info.
- Return type:
None
- os_helper.init_logging(*, level=20, stdout=True, log_format='%(asctime)s | %(levelname)s | %(name)s | %(message)s', date_format='%Y-%m-%d %H:%M:%S', filename=None, capture_warnings=True, reset=True, use_colors=True, propagate=False, name=None, live_stream=False)[source]
Initialize application-wide logging.
This function configures the root logger with a console handler and, optionally, a file handler. It is designed for applications, scripts, notebooks, and machine learning experiments where deterministic logging setup is useful.
- Parameters:
level (int, optional) – Logging level applied to the root logger and its handlers. Typical values are
logging.DEBUG,logging.INFO,logging.WARNING,logging.ERROR, andlogging.CRITICAL.stdout (bool, optional) – If True, console logs are sent to
sys.stdout. Otherwise, they are sent tosys.stderr.log_format (str, optional) – Format string used for log records.
date_format (str, optional) – Format string used for timestamps in log records.
filename (str | pathlib.Path | None, optional) – Optional path to a log file. If provided, logs are also written to this file using UTF-8 encoding.
capture_warnings (bool, optional) – If True, warnings emitted through the
warningsmodule are redirected to the logging system.reset (bool, optional) – If True, existing handlers attached to the root logger are removed before adding new ones. This is often desirable in notebooks and interactive sessions to avoid duplicated messages.
use_colors (bool, optional) – If True, colorize console log levels when ANSI colors are supported. File logs are never colorized.
propagate (bool, optional) – Value assigned to the target logger’s propagation flag.
Falseavoids duplicates for the root logger; a named logger (seename) often wantsTrueso its records still reach a host’s / pytest’s root handlers (e.g.caplog).name (str | None, optional) – Configure this named logger instead of the root. When set, the reset step only removes handlers this function installed (so a host’s / pytest’s handlers on that logger survive), and repeated calls are idempotent — a second call does not stack a duplicate console handler. This is the CLI-friendly mode: configure
"mytool"once, keeppropagate=True, and everylogging.getLogger("mytool.*")inherits the handler + level.live_stream (bool, optional) – If True, the console handler re-resolves
sys.stdout/sys.stderron every emit instead of binding the stream once. This keeps output flowing to wherever the stream currently points — surviving pytest’scapsys(which swaps the streams per test) and any post-config redirection. The default keeps the classic bound-stream handler.
- Returns:
The configured logger (the root logger, or the one named by
name).- Return type:
Notes
This function is intended for top-level applications, notebooks, and experimentation code. Reusable libraries should generally avoid configuring global logging and should instead use:
logger = logging.getLogger(__name__)Examples
>>> logger = init_logging(level=logging.DEBUG, filename="experiment.log") >>> logger.info("Logging is configured.")
>>> logger = init_logging(use_colors=True, reset=True) >>> logger.warning("This is a warning.")
- os_helper.is_working_url(url)[source]
Return True if
urlis syntactically valid and answers 200 to a HEAD.
- os_helper.join(*args)[source]
Join multiple path components into a single absolute, normalized path.
This is the canonical path-construction helper exposed by
os_helperand replaces the olderos_path_constructorfunction (removed in v1.1.0). It accepts either positional components or a single iterable.- Parameters:
*args (str) – The path components to join, or a single iterable of path components.
- Returns:
The absolute, normalized path.
- Return type:
Example
>>> join("folder1", "subfolder2", "file.txt") '/home/user/project/folder1/subfolder2/file.txt' >>> join(["folder1", "subfolder2", "file.txt"]) '/home/user/project/folder1/subfolder2/file.txt'
- os_helper.linux()[source]
Determine if the current operating system is Linux.
- Returns:
True if the operating system is Linux, False otherwise.
- Return type:
- os_helper.macos()[source]
Determine if the current operating system is macOS.
- Returns:
True if the operating system is macOS, False otherwise.
- Return type:
- os_helper.make_directory(folder_path, exist_ok=True)[source]
Create a directory (and missing parents), optionally tolerating prior existence.
- Parameters:
- Raises:
OSError – If the directory cannot be created (propagated from
os.makedirs).AssertionError – If
os.makedirsreturned without error but the directory is still not visible on disk afterwards.
- Return type:
None
Example
>>> make_directory("/path/to/new_folder")
- os_helper.make_temporary_directory(prefix='', directory=None)[source]
Create a temporary directory and return its path — caller owns cleanup.
The non-context-manager companion to
temporary_folder(). Use this when the directory must outlive awithblock: a request handler that schedules deletion after streaming a response, a process-lifetime scratch dir cleaned at exit, or any case where the created path is stored and removed later. It is the suite’stempfile.mkdtemp()— the caller is responsible for removing the tree (e.g. viaremove_directory()/shutil.rmtree/atexit).- Parameters:
- Returns:
Absolute path to the freshly created directory.
- Return type:
Example
>>> work = make_temporary_directory(prefix="myjob-") >>> # ... use `work`, then clean up when you are done ... >>> remove_directory(work)
- os_helper.openfile(filename)[source]
Open a file in the platform’s default application.
Uses
os.startfileon Windows,openon macOS, andxdg-openon Linux. Exceptions from the underlying call are propagated as-is so the caller can react to them.
- os_helper.path_without_home(path)[source]
Convert an absolute path to be relative to the user’s home directory by replacing the home path with ‘~’.
- Parameters:
path (str) – The absolute path to convert.
- Returns:
The path with the home directory replaced by ‘~’, if applicable.
- Return type:
Example
>>> path_without_home("/home/user/project/file.txt") '~/project/file.txt'
- os_helper.progress_bar(total=None, *, desc='', disable=None, unit='B')[source]
Create a
tqdmprogress bar configured for file transfers.The suite-wide byte-transfer bar, so every helper that moves bytes (HTTP download, S3 up / download, SFTP put / get) shows the same progress UI: byte-scaled units (KiB / MiB / GiB), a known total when available (for a percentage + ETA), and — crucially — auto-suppression when ``stderr`` is not a TTY, so CI logs and piped output are never flooded with control characters. Each caller simply wraps its transfer library’s progress hook (
requestschunks, boto3Callback, paramikocallback) around one of these bars.- Parameters:
total (int or None, optional) – Total number of bytes when known (enables percentage + ETA);
Noneleaves the bar open-ended.desc (str, optional) – Short label shown at the left of the bar (e.g. the file / key name).
disable (bool or None, optional) – Force the bar on / off.
None(default) auto-disables whenstderris not an interactive terminal.unit (str, optional) – Progress unit (default
"B";unit_scalerenders raw byte counts as KiB / MiB / GiB).
- Returns:
A ready progress bar; call
.update(n)per transferred chunk and.close()when done.- Return type:
tqdm.tqdm
Examples
>>> bar = progress_bar(total=10, desc="demo", disable=True) >>> bar.total 10 >>> bar.disable True >>> bar.close()
- os_helper.recursive_glob(root_dir, pattern)[source]
Recursively search for files matching a glob pattern under
root_dir.Each subdirectory is walked and the pattern applied in turn, so patterns like
"*.txt"match in nested folders as well as at the top level.- Parameters:
- Returns:
File paths matching the pattern, in walk order.
- Return type:
List[str]
Example
>>> recursive_glob("/home/user", "*.txt") ['/home/user/file1.txt', '/home/user/docs/file2.txt']
- os_helper.relative2absolute_path(path, checkpath=False)[source]
Convert a relative path to an absolute path.
- Parameters:
- Returns:
The absolute path.
- Return type:
- Raises:
FileNotFoundError – If checkpath is True and the path does not exist.
Example
>>> relative2absolute_path("docs/readme.md") '/home/user/project/docs/readme.md'
- os_helper.remove_directory(folder_path)[source]
Remove a directory and all its contents.
A missing directory is treated as a no-op (logged at INFO); any other failure from
shutil.rmtreeis propagated to the caller.- Parameters:
folder_path (str) – The path to the directory to remove.
- Raises:
OSError – If the directory exists but cannot be removed (propagated from
shutil.rmtree).- Return type:
None
Example
>>> remove_directory("/path/to/temp_folder")
- os_helper.remove_files(files_list)[source]
Remove a list of files on a best-effort basis.
Missing entries are skipped and individual removal failures are logged at ERROR level without aborting the rest of the batch. This function does not raise — if you need hard-fail-on-first semantics, call
pathlib.Path(p).unlink()yourself.- Parameters:
files_list (List[str]) – A list of file paths to remove.
- Return type:
None
Example
>>> remove_files(["temp1.txt", "temp2.log"])
- os_helper.size_file(filepath)[source]
Get the size of a file in bytes.
- Parameters:
filepath (str) – The path to the file.
- Returns:
The size of the file in bytes, or -1 if the file does not exist.
- Return type:
Example
>>> size_file("example.txt") 1024
- os_helper.str2time(input_string)[source]
Parse a time string into seconds.
- Parameters:
input_string (str) – A string representing time.
- Returns:
Number of seconds parsed from the string.
- Return type:
Examples
>>> str2time("1:30:00") 5400.0 >>> str2time("1 hr 30 min") 5400.0 >>> str2time("120 s") 120.0 >>> str2time("1.5 hours") 5400.0 >>> str2time("1.5 days") 129600.0
- os_helper.system(cmd, expected_output='', check_exitcode=True, check_empty=False)[source]
Run a shell-style command via
subprocessand capture its output.The command string is parsed with
shlex.split()and executed without spawning an actual shell (shell=False), which avoids shell-injection pitfalls while still accepting a familiar command string.- Parameters:
cmd (str) – Command line to execute (e.g.,
"ffmpeg -i in.mp4 out.mp3").expected_output (str, optional) – If non-empty, a file or directory path expected to be present once the command completes successfully.
check_exitcode (bool, optional) – If True, assert that the process exit code is 0.
check_empty (bool, optional) – If True, also assert that
expected_outputis non-empty (file size > 0 / directory not empty).
- Returns:
{"out": <stdout as str>, "err": <stderr as str>}.- Return type:
- Raises:
AssertionError – If the exit code check or the expected-output check fails.
- os_helper.temporary_filename(suffix='', mode='wt', prefix='', delete=True, directory=None)[source]
Create a temporary file with a unique name that persists even after closing.
This context manager generates a temporary file with a unique name, which is optionally removed after use. It ensures that temporary files are managed safely and are cleaned up to prevent clutter or security issues.
- Parameters:
suffix (str, optional) – File suffix (e.g., “.txt”). Defaults to “”.
mode (str, optional) – Mode in which the file is opened (e.g., “wt” for writing text). Defaults to “wt”.
prefix (str, optional) – Prefix for the file name. Defaults to “”.
delete (bool, optional) – Whether to delete the file after exiting the context. Defaults to True.
directory (str or None, optional) – Parent directory to create the file in (default: the system temp dir). Use this when the temp file must sit next to other inputs — e.g. so a tool that resolves paths relative to the file still finds its siblings.
- Yields:
str – The name of the temporary file.
- Return type:
Example
>>> with temporary_filename(suffix=".txt") as temp_file: ... with open(temp_file, "wt") as fout: ... fout.write("Temporary content") ... # temp_file is automatically deleted after the block
- os_helper.temporary_folder(prefix='', delete=True)[source]
Create a temporary directory with a unique name that persists during the context.
This context manager generates a temporary directory with a unique name, which is optionally removed after use. It ensures that temporary directories are managed safely and are cleaned up to prevent clutter or security issues.
- Parameters:
- Yields:
str – The name of the temporary directory.
- Return type:
Example
>>> with temporary_folder(prefix="tempdir") as temp_dir: ... # Use the temporary directory ... with open(os.path.join(temp_dir, "file.txt"), "w") as f: ... f.write("Temporary content") ... # temp_dir and its contents are automatically deleted after the block
- os_helper.temporary_remote_file(upload_function, delete_function, *, prefix='', suffix='', from_local_file=None, checkfile_function=None, mode='wb', initial_content=None)[source]
Context manager that uploads a file to a remote location and guarantees deletion of the remote artifact when the context exits.
Two modes:
If
from_local_fileis given, that existing local file is uploaded as-is and left untouched on cleanup; only the remote copy is deleted.Otherwise, a uniquely named local temp file is created (optionally pre-populated with
initial_content), uploaded, and removed locally when the context manager exits.
Useful for staging files to S3/GCS/SFTP/anywhere when you only need them briefly: pass in the upload + delete callables for your storage backend and the helper handles the lifecycle.
- Parameters:
upload_function (Callable[[str], str]) – Called with a local file path; must return the remote path/URI.
delete_function (Callable[[str], None]) – Called with the remote path/URI to remove the remote artifact.
prefix (str, optional) – Prefix for the temporary file name (ignored when
from_local_fileis provided).suffix (str, optional) – File extension for the temporary file (with or without leading “.”).
from_local_file (str, optional) – Path to an existing local file to upload instead of creating one.
checkfile_function (Callable[[str], bool], optional) – Optional post-upload sanity check; must return True for success.
mode (str, optional) – Open mode used when writing
initial_contentto the temp file. Defaults to"wb".initial_content (bytes | str, optional) – Optional content written into the new temp file before upload. Type must match
mode(bytes for"wb", str for"wt").
- Yields:
str – The remote file path/URI returned by
upload_function.- Raises:
TypeError – If any supplied callable is not actually callable.
FileNotFoundError – If
from_local_fileis given but the path does not exist.RuntimeError – If
checkfile_functionis provided and returns False after upload.
- Return type:
Examples
>>> storage = {} >>> def upload(p): ... with open(p, "rb") as f: storage[p] = f.read() ... return p >>> def delete(r): ... storage.pop(r, None) >>> with temporary_remote_file(upload, delete, suffix=".bin", ... initial_content=b"hello") as remote: ... assert storage[remote] == b"hello" >>> # remote artifact is gone after the block
- os_helper.tic()[source]
Start (or restart) the implicit global stopwatch.
Returns the start timestamp so callers can pin a handle for nested or interleaved measurements:
>>> t_outer = tic() >>> # ... work ... >>> t_inner = tic() # implicit global now points at t_inner >>> # ... more work ... >>> toc(t_inner) # explicit handle works regardless of which tic() was last >>> toc(t_outer)
- os_helper.time2str(seconds, no_space=False)[source]
Convert a float number of seconds to a readable string, e.g. “1 hr 2 min 5 sec”.
- Parameters:
- Returns:
A human-readable time string.
- Return type:
Examples
>>> time2str(5400.0) "1 hr 30 min" >>> time2str(120.0) "2 min" >>> time2str(3661.0) "1 hr 1 min 1 sec"
- os_helper.toc(handle=None, *, log=False)[source]
Return seconds elapsed since the matching
tic()call.- Parameters:
- Returns:
Seconds elapsed (does not reset the timer — call
tic()again to restart).- Return type:
- Raises:
RuntimeError – If called with no handle and no prior
tic().
Examples
>>> tic() >>> # ... work ... >>> elapsed = toc()
- os_helper.unix()[source]
Determine if the current operating system is Unix-based (Linux or macOS).
- Returns:
True if the operating system is Unix-based (Linux or macOS), False otherwise.
- Return type:
- os_helper.verbosity(level=None)[source]
Get or set the current root logger verbosity.
Called with no argument, returns the current verbosity as an integer. Called with an integer, updates the root logger (and its existing handlers) accordingly and returns the new effective verbosity.
Mapping (higher = more verbose):
>= 2→ DEBUG1→ INFO0→ WARNING-1→ ERROR<= -2→ CRITICAL
Values outside
[-2, 2]are clamped (e.g.verbosity(3)is treated as DEBUG, matching the convenience usage shown in the README).- Parameters:
level (int | None, optional) – New verbosity level to apply, or None to just read the current value.
- Returns:
Current (post-update, when setting) verbosity as an integer in the range
[-2, 2].- Return type:
Examples
>>> verbosity(2) # turn on DEBUG-level logging 2 >>> verbosity() # read current level 2
- os_helper.wall_timer()[source]
Measure real elapsed wall-clock time using
time.perf_counter().Use this when you want to know “how long did this take to run from the user’s perspective” — it includes I/O, sleeps, GPU waits, and subprocess time.
- Yields:
dict –
{"seconds": float, "milliseconds": float}, both fields populated when thewithblock exits.- Return type:
Examples
>>> with wall_timer() as t: ... time.sleep(0.05) >>> assert t["seconds"] >= 0.05
- os_helper.warning(msg, *args, **kwargs)[source]
Log a message at WARNING level via the dedicated
os_helperlogger.- Parameters:
msg (str) – The (possibly %-style) message template.
*args (Any) – Positional interpolation arguments forwarded to
logging.warning.**kwargs (Any) – Keyword options forwarded to
logging.warning.
- Return type:
None
- os_helper.windows()[source]
Determine if the current operating system is Windows.
- Returns:
True if the operating system is Windows, False otherwise.
- Return type:
- os_helper.zip_folder(folder_path, zip_file_path='')[source]
Create a deflated
.ziparchive of a folder’s contents.Hidden files (names beginning with
.) are skipped. Paths inside the archive are stored relative tofolder_path.- Parameters:
- Raises:
AssertionError – If
folder_pathdoes not exist.- Return type:
None