Bosos Dev Tools
Bosos Dev Tools is a collection of utility tools for Python developers, designed to simplify debugging, logging, and monitoring tasks. This package includes decorators for measuring execution time, a progress bar utility, structured file logging, a markdown link checker, and an AST-based code map generator.
Features
- Custom Logging Handlers: Log messages to various destinations with customizable formats.
- Timing Decorators: Easily measure the execution time of your functions with minimal code changes.
- Progress Bar Utility: Visualize the progress of long-running operations in the console.
- Debug Tools: Check if debug or timing modes are enabled via environment variables.
- Markdown Link Checker: Scan markdown files for broken internal links — available as a library and a CLI tool.
- Code Map Generator: Generate AST-based documentation artifacts (symbol index, dependency graph, entry points, call graph) for any Python package.
Installation
You can install the package via pip:
pip install bosos-dev-tools
Usage
Timing Decorator
Use the timing_decorator to measure the execution time of functions.
from dev_tools.custom_decorators import timing_decorator
@timing_decorator
def example_function():
for i in range(1000000):
pass
example_function()
Progress Bar
Visualize the progress of long-running iterations in the console.
from dev_tools.progress_bar import progress_bar
for item in progress_bar(range(10)):
pass
Debug Tools
Check if debug or timing modes are enabled via environment variables.
Use the logger_setup to set up your logging settings at the beginning of the script.
from dev_tools.debug_tools import is_debug_on, is_timing_on
print('Is debug on:', is_debug_on())
print('Is timing on:', is_timing_on())
from dev_tools.logger_settings import logger_setup
def main():
logger_setup()
if __name__ == '__main__':
main()
Log files are written to a structured folder hierarchy:
logs/
2026/
03/
02/
2026-03-02T062351.log
The folder path is controlled by environment variables:
| Variable | Default | Description |
|---|---|---|
LOGGER_PATH |
./logs |
Base log directory |
LOGGER_DAY_SPECIFIC |
False |
Add a day subfolder (zero-padded) |
LOGGER_SCRIPT_FOLDERS |
False |
Add a script-name subfolder before the year |
LOGGER_APPEND_SAME_DAY |
False |
Reuse one stable log file per folder instead of creating a new file each run |
SCRIPT_NAME |
current working directory name | Identifier used for script-specific folders and stable same-day basenames |
Logging Configuration File
logger_setup() looks for an INI-style logging config file in the current working directory:
- Normal mode:
logging.conf(override withLOGGER_CONF_PATH) - Debug mode (
DEBUG=True):logging_dev.conf(override withLOGGER_CONF_DEV_PATH)
If the config file is not found, a sensible built-in default is used automatically — no .conf file is required. The default configuration writes to both a file handler (all messages) and a console handler (warnings only; or all messages in debug mode).
If LOGGER_APPEND_SAME_DAY=True, logger_setup() uses a stable basename such as my_script.log inside the resolved log folder so repeated runs append to the same file for that folder. This works best with the built-in timed rotation or the included logging.conf files.
If you pass script_name directly to logger_setup(script_name="my_etl_script"), that value takes precedence for that call only. It does not overwrite the process SCRIPT_NAME environment variable for later logging setup calls.
Configuring via arguments instead of env vars
Every behavioral option also has a keyword argument, so you can configure logging in code without setting environment variables. Arguments take precedence; when an argument is left as None the matching environment variable is used (preserving 12-factor / deployment overrides):
| Argument | Env var | Description |
|---|---|---|
logger_path |
LOGGER_PATH |
Base log directory |
script_folders |
LOGGER_SCRIPT_FOLDERS |
Add a script-name subfolder |
day_specific |
LOGGER_DAY_SPECIFIC |
Add a day subfolder |
append_same_day |
LOGGER_APPEND_SAME_DAY |
Reuse one stable log file per folder |
Switching from a file-per-run to a single log per day
By default each run creates its own timestamped file (multi-log), e.g. logs/2026/03/02/2026-03-02T062351.log. To keep one rolling log per day instead, enable same-day append:
from dev_tools.logger_settings import logger_setup
# In code (no env vars needed):
logger_setup(script_name="my_etl", append_same_day=True)
…or via environment variables:
SCRIPT_NAME=my_etl
LOGGER_APPEND_SAME_DAY=True
Same-day runs then append to a stable file such as logs/2026/03/my_etl.log. With the built-in TimedRotatingFileHandler (or the bundled logging.conf), that file rotates at midnight — giving you exactly one file per day.
Exit Code and Unhandled Exceptions
logger_setup() installs a sys.excepthook and an atexit handler so the final log line reflects the real outcome of the run:
- On a clean run, the log ends with
Exit code: 0. - If the script terminates with an unhandled exception, the full traceback is logged (level
CRITICAL) and the log ends withExit code: 1, matching the non-zero process exit status. The standard Python traceback is still printed tostderr(the hook augments, it does not replace, the default behavior).KeyboardInterruptis recorded as a non-zero exit without logging a traceback.
This means a failed run can be identified directly from the log file instead of relying on an external scheduler to report the exit status.
| Variable | Default | Description |
|---|---|---|
LOGGER_CONF_PATH |
logging.conf |
Path to the logging config file |
LOGGER_CONF_DEV_PATH |
logging_dev.conf |
Path to the debug logging config file |
DEBUG |
False |
Enable debug mode (verbose console output) |
Markdown Link Checker
Scan markdown files for broken internal links. Available as a library or a CLI tool.
As a library:
from dev_tools.md_link_checker import scan_all
from pathlib import Path
result = scan_all(Path("."))
for r in result.results:
if r.status == "broken":
print(f"{r.source_file}:{r.line_number} -> {r.target} ({r.reason})")
As a CLI:
# Installed console script
md-link-checker --verbose
# Or run as a module
python -m dev_tools.md_link_checker --no-anchors --json
Code Map Generator
Generate AST-based documentation for a Python package — symbol index, dependency graph, entry points, and call graph.
As a library:
from pathlib import Path
from dev_tools.codemap_generator import CodeMapGenerator
gen = CodeMapGenerator(src_root=Path("src"), package_name="my_package")
gen.analyze()
gen.write_outputs(output_dir=Path("docs"))
As a CLI:
# Installed console script
codemap-generator --package my_package
# Or run as a module
python -m dev_tools.codemap_generator --package my_package --output-dir docs
Releasing
Releases are automated and triggered only by merging a pull request into main. The version bump follows Semantic Versioning and is chosen by PR label:
| PR label | Bump | Example |
|---|---|---|
| (none) | patch (default) | 1.2.3 → 1.2.4 |
release:minor |
minor | 1.2.3 → 1.3.0 |
release:major |
major | 1.2.3 → 2.0.0 |
On merge, the Version & Release workflow bumps the version in pyproject.toml, moves the [Unreleased] changelog entries under the new version heading, publishes to PyPI, and creates a matching GitHub Release. To release a minor or major version, add the corresponding label to the PR before merging.
License
This project is licensed under the MIT License. See the LICENSE file for more details.
Links
- Source Code: GitHub Repository
- Issue Tracker: GitHub Issues
- Changelog: CHANGELOG.md
Metadata
Release files for bosos-dev-tools 1.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bosos_dev_tools-1.2.2.tar.gz | 47.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bosos_dev_tools-1.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 102.0 kB
Release files / bosos_dev_tools-1.2.2.tar.gz
| Download URL | bosos_dev_tools-1.2.2.tar.gz |
|---|---|
| Size | 47.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
13b9e417e0da9caa08c19ac719d80785a7d9067dc9a1538cf15257dbac8c0137
|
|
BLAKE2b-256 checksum How to use checksums |
6e9de22234d356bf2a6dd7f7efebb4a478e6bb09b08887d083e630ac1b279d4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / bosos_dev_tools-1.2.2-py3-none-any.whl
| Download URL | bosos_dev_tools-1.2.2-py3-none-any.whl |
|---|---|
| Size | 54.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
093cb4f096590bcda2ed7e9140488ca8da77e39bd4a528f928cb056a37f0d0cb
|
|
BLAKE2b-256 checksum How to use checksums |
fef42a611c28165b6efd1113ec2a0d3884ca942a07590ad8f4c0302c39bc0424
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|