Collection of convenience functions used in Python packages and scripts. These are written and maintained for my own personal use. Comprehensive tests are included but I make no guarantees about the quality or correctness of the code.
- Filesystem Utilities: Common filesystem operations
- Logging: A wrapper around the Loguru logger with configurable log levels and custom styles.
- Network: Helper functions for working with network connections.
- Pretty Printing: Rich text formatting for console output with customizable styles
- Pytest Fixtures: Convenience functions and fixtures for testing.
- Questions: Short-cut functions for asking questions and getting user input using the questionary library.
- Shell Commands: Safe execution of shell commands with proper error handling
- Strings: Convenience functions for working with strings.
- Text Processing: Convenience functions for working with text files.
- Other miscellaneous utilities.
- Python 3.10 or higher
- Dependencies are managed with uv
nclutils has a few dependencies that are included in the project.
- questionary - For asking questions
- rich - For pretty printing
- sh - For running shell commands
- Loguru - For logging
# With uv
uv add nclutils
# With pip
pip install nclutils-
backup_path(path: Path, raise_on_missing: bool = False, with_progress: bool = False, transient: bool = True) -> Path | NoneCreate a backup of a file or directory. Silently returns
Noneif the source path does not exist by default. -
clean_directory(directory: Path) -> NoneRecursively cleans up the contents of a directory, deleting all files and subdirectories without deleting the directory itself.
-
copy_directory(src: Path, dst: Path, with_progress: bool = False, transient: bool = True, keep_backup: bool = True) -> PathCopy a directory with an optional progress bar for each file. If the destination directory already exists, it will be backed up with a timestamped suffix.
-
copy_file(src: Path, dst: Path, with_progress: bool = False, transient: bool = True, keep_backup: bool = True) -> PathCopy a file with a progress bar. If the destination file already exists, it will be backed up with a timestamped suffix.
Raises
FileNotFoundErrorif the source file does not exist or is not a file. -
directory_tree(directory: Path, show_hidden: bool = False) -> TreeBuild a rich.tree representation of a directory's contents.
-
find_files(path: Path, globs: list[str] | None = None, ignore_dotfiles: bool = False) -> list[Path]Search for files within a directory optionally matching specific glob patterns.
-
find_subdirectories(directory: Path, depth: int = 1, filter_regex: str = "", ignore_dotfiles: bool = False, leaf_dirs_only: bool = False) -> list[Path]Find and filter subdirectories with granular control:
from pathlib import Path from nclutils import find_subdirectories root_directory = Path(".") # Find subdirectories with specific criteria subdirs = find_subdirectories( root_directory, depth=2, # How deep to search filter_regex=r"^a", # Only dirs starting with 'a' leaf_dirs_only=True, # Furthest down directories only ignore_dotfiles=True # Skip hidden directories )
-
find_user_home_dir(username: str | None = None) -> Path | NoneFind the home directory for a requested user or the current user if no user is requested. When running under sudo, the home directory for the sudo user is returned.
-
loggerA wrapper around the Loguru logger with configurable log levels and custom styles. See the logging docs for more information.
-
network_available(address: str = "8.8.4.4", port: int = 53, timeout: int = 5) -> boolCheck if a network connection is available.
The pretty printing module provides styled console output with configurable log levels and custom styles. See the pretty_print docs for more information.
-
consoleA rich console object for styled console output.
-
err_consoleA rich console object for styled console output to stderr.
-
PrettyPrinter(Class)Styled console output with configurable levels and custom styles.
-
print_debug(envar_prefix: str = None, custom: list[dict] = None, packages: list[str] = None, all_packages: bool = False) -> NonePrint debug information about the current environment.
The nclutils.pytest_fixtures module contains convenience functions and fixtures that are useful for testing. See the pytest_fixtures docs for more information.
clean_stdoutClean the stdout of the console output by creating a wrapper aroundcapsysto capture console stdout output.clean_stderrClean the stderr of the console output by creating a wrapper aroundcapsysto capture console stderr output.clean_stderroutClean the stdout and stderr of the console output by creating a wrapper aroundcapsysto capture both stdout and stderr output.debugPrints debug information to the console. Useful for writing and debugging tests.pytest_assertrepr_comparePatches the default pytest behavior of hiding whitespace differences in assertion failure messages. Replaces spaces and tabs with[space]and[tab]markers.
Convenience functions for working with the questionary library.
See the questions docs for more information.
-
choose_one_from_list(choices: list[T] | list[tuple[str, T]] | list[dict[str, T]], message: str) -> T | NonePresents a list of options to the user and returns a single selected option.
-
choose_multiple_from_list(choices: list[T] | list[tuple[str, T]] | list[dict[str, T]], message: str) -> list[T] | NonePresents a list of options to the user and returns a list of selected options.
Convenience functions built on top of the sh module. See the shell_commands docs for more information.
-
run_command(cmd: str, args: list[str] = [], quiet: bool = False, pushd: str | Path | None = None, okay_codes: list[int] | None = None, exclude_regex: str | None = None, sudo: bool = False, fg: bool = False) -> strExecute shell commands with proper error handling and output control.
-
which(cmd: str) -> str | NoneCheck if a command exists in the PATH. Returns the absolute path to the command if found, otherwise
None.
-
camel_case(text: str) -> strConvert a string to camel case. (
hello world -> helloWorld) -
deburr(text: str) -> strDeburr a string. (
crème brûlée -> creme brulee) -
kebab_case(text: str) -> strConvert a string to kebab case. (
hello world -> hello-world) -
int_to_emoji(num: int, markdown: bool = False, images: bool = False) -> strTransform integers between 0-10 into their corresponding emoji codes or image representations. For numbers outside this range, return the number as a string with optional markdown formatting.
-
list_words(text: str, pattern: str = "", strip_apostrophes: bool = False) -> list[str]Extract words from text by splitting on word boundaries and handling contractions. Optionally use a custom regex pattern for more control over word splitting. Handles apostrophes, underscores, and mixed case text intelligently.
from nclutils import list_words print(list_words("Jim's horse is fast")) # ["Jim's", 'horse', 'is', 'fast'] print(list_words("Jim's horse is fast", strip_apostrophes=True)) # ['Jims', 'horse', 'is', 'fast'] print(list_words("fred, barney, & pebbles", "[^, ]+")) # ['fred', 'barney', '&', 'pebbles']
-
random_string(length: int) -> strGenerate a random string of ASCII letters with the specified length.
-
pad(text: str, length: int, chars: str = " ") -> strPad a string with a character.
-
pad_end(text: str, length: int, chars: str = " ") -> strPad a string on the right side.
-
pad_start(text: str, length: int, chars: str = " ") -> strPad a string on the left side.
-
pascal_case(text: str) -> strConvert a string to pascal case. (
Hello World -> HelloWorld) -
separator_case(text: str, separator: str = "-") -> strConvert a string to separator case. (
hello world -> hello-world) -
snake_case(text: str) -> strConvert a string to snake case. (
hello world -> hello_world) -
strip_ansi(text: str) -> strStrip ANSI escape sequences from a string. (
\x1b[31mHello, World!\x1b[0m -> Hello, World!) -
split_camel_case(string_list: list[str], match_case_list: tuple[str, ...] = ()) -> list[str]Split camel case strings into into separate words returning a list of words. Optionally, provide a list of strings that should not be split.
-
replace_in_file(path: str | Path, replacements: dict[str, str], *, use_regex: bool = False) -> boolReplace text in a file with a dictionary of replacements.
from nclutils import replace_in_file replacements = {"old": "new"} replace_in_file(path="test.txt", replacements=replacements) # Or use regex replacements = {"^old": "new"} replace_in_file(path="test.txt", replacements=replacements, use_regex=True)
-
ensure_lines_in_file(path: str | Path, lines: list[str], *, at_top: bool = False) -> boolEnsure lines are in a file. If the lines are not present, they will be added to the file.
-
check_python_version(major: int, minor: int) -> boolCheck if the current Python version meets minimum requirements.
-
format_iso_timestamp(datetime_obj: datetime, microseconds: bool = True) -> strFormats a given datetime object as an ISO 8601 timestamp, ensuring UTC formatting with a trailing Z.
-
iso_timestamp(microseconds: bool = False) -> strReturns an ISO 8601 timestamp in UTC for the current time. (
2024-03-15T12:34:56Z) -
new_timestamp_uid(bits: int = 32) -> strGenerate a unique ID with a UTC timestamp prefix. (
0240315T123456-kgk5mzn) -
new_uid(bits: int = 64) -> strGenerate a unique ID with the specified number of bits. (
kgk5mzn) -
unique_id(prefix: str = "") -> strGenerate consecutive unique IDs with an optional prefix.
from nclutils import unique_id print(unique_id()) # 1 print(unique_id("id_")) # id_2 print(unique_id()) # 3
See CONTRIBUTING.md for more information.