A collection of essential filesystem and logging utilities designed to
eliminate daily friction in Python development. ``fs-helper`` provides
production-grade implementations of fundamental operations that
developers need constantly but often implement inconsistently across
projects.
This library embodies a philosophy of **invisible infrastructure**
becoming so reliable and predictable that you forget you’re using it.
Every function is designed to solve a problem completely on first
invocation, with zero-configuration defaults that work in production
immediately while providing comprehensive control when needed.
**Who benefits from this:** - **DevOps engineers** automating deployment
and monitoring workflows - **Python developers** building command-line
tools and scripts - **Data scientists** managing file-based workflows
and logging - **Anyone** tired of reimplementing the same filesystem and
logging patterns across projects
**How it fits into your toolchain:** ``fs-helper`` serves as
foundational infrastructure that other tools can depend on. It’s
designed to compose naturally with shell scripts, provide REPL-friendly
exploration, and integrate seamlessly into existing Python projects
without imposing architectural constraints.
Install
-------
::
pip install fs-helper
QuickStart
----------
.. code:: python
import fs_helper as fh
# Production-ready logging in one line
logger = fh.get_logger(__name__)
logger.info("Application started")
# Safe path handling that works everywhere
log_dir = fh.abspath("~/logs")
# Convert any text to a safe filename
safe_name = fh.lazy_filename("User Data: Report (2024)")
# Returns: "User-Data--Report-2024"
# Git-aware path resolution
repo_root = fh.repopath() # Returns None if not in a git repo
if repo_root:
print(f"Working in repository: {repo_root}")
# File monitoring for automation workflows
fh.wait_for_write_age("output.log", age=5, verbose=True)
print("Log file has been stable for 5 seconds, proceeding...")
**What you gain:** Immediate access to bulletproof implementations of
common operations with comprehensive error handling, cross-platform
compatibility, and zero configuration overhead. Functions gracefully
handle edge cases (missing directories, permission issues, invalid
paths) so your code can focus on domain logic rather than infrastructure
concerns.
API Overview
------------
Core Path Operations
~~~~~~~~~~~~~~~~~~~~
- **``abspath(filepath)``** - Enhanced path normalization with tilde
expansion
- ``filepath``: Path string to normalize
- Returns: Absolute path as string
- Internal calls: None
- **``strip_extension(filepath)``** - Remove file extension from path
- ``filepath``: Path string
- Returns: Path without extension
- Internal calls: None
- **``get_extension(filepath)``** - Extract file extension from path
- ``filepath``: Path string
- Returns: Extension without leading dot
- Internal calls: None
- **``repopath(filepath='')``** - Find git repository root for given
path
- ``filepath``: Path to check (defaults to current directory)
- Returns: Repository root path or ``None`` if not in a git repo
- Internal calls: ``abspath()``
Production Logging
~~~~~~~~~~~~~~~~~~
- **``get_logger(module_name, logdir=DEFAULT_LOG_DIR, file_format='%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', stream_format='%(asctime)s: %(message)s', file_level=logging.DEBUG, stream_level=logging.INFO)``**
- Create production-ready logger with file and console output
- ``module_name``: Logger identifier (typically ``__name__``)
- ``logdir``: Directory for log files (defaults to ``~/logs``, falls
back to ``/tmp/logs``)
- ``file_format``: Log format for file output (set to empty string
to disable)
- ``stream_format``: Log format for console output (set to empty
string to disable)
- ``file_level``: Logging level for file (accepts strings like
‘info’ or integers)
- ``stream_level``: Logging level for console
- Returns: Configured logger instance with automatic directory
creation and fallback strategies
- Internal calls: ``abspath()``
- **``get_logfile_from_logger(logger)``** - Extract log file path from
logger instance
- ``logger``: Logger object
- Returns: Path to log file or ``None`` if no file handler
- Internal calls: None
- **``get_logger_filenames(logger)``** - Get all log file paths from
logger
- ``logger``: Logger object
- Returns: List of log file paths
- Internal calls: None
File Utilities
~~~~~~~~~~~~~~
- **``lazy_filename(text, ext='')``** - Convert arbitrary text to safe
filenames
- ``text``: Input text to convert (URLs, user input, API responses)
- ``ext``: Optional extension to append
- Returns: Safe filename string with unsafe characters removed
- Internal calls: None
- **``sha256sum(filepath)``** - Calculate SHA256 checksum of file
- ``filepath``: Path to file
- Returns: Hexadecimal SHA256 digest
- Internal calls: ``abspath()``
Package Analysis
~~~~~~~~~~~~~~~~
- **``get_local_package_info(dirpath, exception=True)``** - Extract
packaging information from Python project directory
- ``dirpath``: Path to project directory
- ``exception``: If True, raise exception for non-Python projects
- Returns: Dictionary with keys: ``setup.py_path``,
``setup.py_content``, ``pyproject.toml_path``,
``pyproject.toml_content``
- Internal calls: ``abspath()``
Monitoring and Coordination
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- **``wait_for_write_age(filepath, age=10, sleeptime=1, verbose=False)``**
- Wait until file hasn’t been modified for specified duration
- ``filepath``: File to monitor
- ``age``: Seconds since last write required
- ``sleeptime``: Polling interval in seconds
- ``verbose``: If True, print status messages
- Returns: ``True`` when condition met
- Internal calls: ``abspath()``
- **``wait_for_empty_directory(dirpath, sleeptime=1, verbose=False)``**
- Wait until directory contains no files
- ``dirpath``: Directory to monitor
- ``sleeptime``: Polling interval in seconds
- ``verbose``: If True, print status messages
- Returns: ``True`` when directory is empty
- Internal calls: ``abspath()``
Raw data
{
"_id": null,
"home_page": "https://github.com/kenjyco/fs-helper",
"name": "fs-helper",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "filesystem, logging, files, helper, kenjyco",
"author": "Ken",
"author_email": "kenjyco@gmail.com",
"download_url": "https://github.com/kenjyco/fs-helper/tarball/v0.0.12",
"platform": null,
"description": "A collection of essential filesystem and logging utilities designed to\neliminate daily friction in Python development. ``fs-helper`` provides\nproduction-grade implementations of fundamental operations that\ndevelopers need constantly but often implement inconsistently across\nprojects.\n\nThis library embodies a philosophy of **invisible infrastructure**\nbecoming so reliable and predictable that you forget you\u2019re using it.\nEvery function is designed to solve a problem completely on first\ninvocation, with zero-configuration defaults that work in production\nimmediately while providing comprehensive control when needed.\n\n**Who benefits from this:** - **DevOps engineers** automating deployment\nand monitoring workflows - **Python developers** building command-line\ntools and scripts - **Data scientists** managing file-based workflows\nand logging - **Anyone** tired of reimplementing the same filesystem and\nlogging patterns across projects\n\n**How it fits into your toolchain:** ``fs-helper`` serves as\nfoundational infrastructure that other tools can depend on. It\u2019s\ndesigned to compose naturally with shell scripts, provide REPL-friendly\nexploration, and integrate seamlessly into existing Python projects\nwithout imposing architectural constraints.\n\nInstall\n-------\n\n::\n\n pip install fs-helper\n\nQuickStart\n----------\n\n.. code:: python\n\n import fs_helper as fh\n\n # Production-ready logging in one line\n logger = fh.get_logger(__name__)\n logger.info(\"Application started\")\n\n # Safe path handling that works everywhere\n log_dir = fh.abspath(\"~/logs\")\n\n # Convert any text to a safe filename\n safe_name = fh.lazy_filename(\"User Data: Report (2024)\")\n # Returns: \"User-Data--Report-2024\"\n\n # Git-aware path resolution\n repo_root = fh.repopath() # Returns None if not in a git repo\n if repo_root:\n print(f\"Working in repository: {repo_root}\")\n\n # File monitoring for automation workflows\n fh.wait_for_write_age(\"output.log\", age=5, verbose=True)\n print(\"Log file has been stable for 5 seconds, proceeding...\")\n\n**What you gain:** Immediate access to bulletproof implementations of\ncommon operations with comprehensive error handling, cross-platform\ncompatibility, and zero configuration overhead. Functions gracefully\nhandle edge cases (missing directories, permission issues, invalid\npaths) so your code can focus on domain logic rather than infrastructure\nconcerns.\n\nAPI Overview\n------------\n\nCore Path Operations\n~~~~~~~~~~~~~~~~~~~~\n\n- **``abspath(filepath)``** - Enhanced path normalization with tilde\n expansion\n\n - ``filepath``: Path string to normalize\n - Returns: Absolute path as string\n - Internal calls: None\n\n- **``strip_extension(filepath)``** - Remove file extension from path\n\n - ``filepath``: Path string\n - Returns: Path without extension\n - Internal calls: None\n\n- **``get_extension(filepath)``** - Extract file extension from path\n\n - ``filepath``: Path string\n - Returns: Extension without leading dot\n - Internal calls: None\n\n- **``repopath(filepath='')``** - Find git repository root for given\n path\n\n - ``filepath``: Path to check (defaults to current directory)\n - Returns: Repository root path or ``None`` if not in a git repo\n - Internal calls: ``abspath()``\n\nProduction Logging\n~~~~~~~~~~~~~~~~~~\n\n- **``get_logger(module_name, logdir=DEFAULT_LOG_DIR, file_format='%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', stream_format='%(asctime)s: %(message)s', file_level=logging.DEBUG, stream_level=logging.INFO)``**\n - Create production-ready logger with file and console output\n\n - ``module_name``: Logger identifier (typically ``__name__``)\n - ``logdir``: Directory for log files (defaults to ``~/logs``, falls\n back to ``/tmp/logs``)\n - ``file_format``: Log format for file output (set to empty string\n to disable)\n - ``stream_format``: Log format for console output (set to empty\n string to disable)\n - ``file_level``: Logging level for file (accepts strings like\n \u2018info\u2019 or integers)\n - ``stream_level``: Logging level for console\n - Returns: Configured logger instance with automatic directory\n creation and fallback strategies\n - Internal calls: ``abspath()``\n\n- **``get_logfile_from_logger(logger)``** - Extract log file path from\n logger instance\n\n - ``logger``: Logger object\n - Returns: Path to log file or ``None`` if no file handler\n - Internal calls: None\n\n- **``get_logger_filenames(logger)``** - Get all log file paths from\n logger\n\n - ``logger``: Logger object\n - Returns: List of log file paths\n - Internal calls: None\n\nFile Utilities\n~~~~~~~~~~~~~~\n\n- **``lazy_filename(text, ext='')``** - Convert arbitrary text to safe\n filenames\n\n - ``text``: Input text to convert (URLs, user input, API responses)\n - ``ext``: Optional extension to append\n - Returns: Safe filename string with unsafe characters removed\n - Internal calls: None\n\n- **``sha256sum(filepath)``** - Calculate SHA256 checksum of file\n\n - ``filepath``: Path to file\n - Returns: Hexadecimal SHA256 digest\n - Internal calls: ``abspath()``\n\nPackage Analysis\n~~~~~~~~~~~~~~~~\n\n- **``get_local_package_info(dirpath, exception=True)``** - Extract\n packaging information from Python project directory\n\n - ``dirpath``: Path to project directory\n - ``exception``: If True, raise exception for non-Python projects\n - Returns: Dictionary with keys: ``setup.py_path``,\n ``setup.py_content``, ``pyproject.toml_path``,\n ``pyproject.toml_content``\n - Internal calls: ``abspath()``\n\nMonitoring and Coordination\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- **``wait_for_write_age(filepath, age=10, sleeptime=1, verbose=False)``**\n - Wait until file hasn\u2019t been modified for specified duration\n\n - ``filepath``: File to monitor\n - ``age``: Seconds since last write required\n - ``sleeptime``: Polling interval in seconds\n - ``verbose``: If True, print status messages\n - Returns: ``True`` when condition met\n - Internal calls: ``abspath()``\n\n- **``wait_for_empty_directory(dirpath, sleeptime=1, verbose=False)``**\n - Wait until directory contains no files\n\n - ``dirpath``: Directory to monitor\n - ``sleeptime``: Polling interval in seconds\n - ``verbose``: If True, print status messages\n - Returns: ``True`` when directory is empty\n - Internal calls: ``abspath()``\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "CLI helpers for filesystem and logging tasks",
"version": "0.0.12",
"project_urls": {
"Download": "https://github.com/kenjyco/fs-helper/tarball/v0.0.12",
"Homepage": "https://github.com/kenjyco/fs-helper"
},
"split_keywords": [
"filesystem",
" logging",
" files",
" helper",
" kenjyco"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "098301b5ba560e1af9b5d4a6e73f96d8c1cc7330d73717311a6a909a814206f0",
"md5": "3113b870f3688e9e6535d6b33496ef74",
"sha256": "f71df0eeae293e632bffd013c54d32823ae96e82ab8beaad60a40b44810244b7"
},
"downloads": -1,
"filename": "fs_helper-0.0.12-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3113b870f3688e9e6535d6b33496ef74",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 6796,
"upload_time": "2025-07-23T18:01:04",
"upload_time_iso_8601": "2025-07-23T18:01:04.334737Z",
"url": "https://files.pythonhosted.org/packages/09/83/01b5ba560e1af9b5d4a6e73f96d8c1cc7330d73717311a6a909a814206f0/fs_helper-0.0.12-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-23 18:01:04",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kenjyco",
"github_project": "fs-helper",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "fs-helper"
}