Skip to main content

Dev Tools is a collection of utility tools for Python developers — logging, decorators, debugging, progress bars, a markdown link checker, and an AST-based code map generator.

Project description

Bosos Dev Tools

Python 3.10+ Platform PyPI Version PyPI status Test Version & Release codecov License

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 with LOGGER_CONF_PATH)
  • Debug mode (DEBUG=True): logging_dev.conf (override with LOGGER_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 with Exit code: 1, matching the non-zero process exit status. The standard Python traceback is still printed to stderr (the hook augments, it does not replace, the default behavior). KeyboardInterrupt is 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bosos_dev_tools-1.2.2.tar.gz (47.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bosos_dev_tools-1.2.2-py3-none-any.whl (54.4 kB view details)

Uploaded Python 3

File details

Details for the file bosos_dev_tools-1.2.2.tar.gz.

File metadata

  • Download URL: bosos_dev_tools-1.2.2.tar.gz
  • Upload date:
  • Size: 47.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for bosos_dev_tools-1.2.2.tar.gz
Algorithm Hash digest
SHA256 13b9e417e0da9caa08c19ac719d80785a7d9067dc9a1538cf15257dbac8c0137
MD5 14a209dedf085b8a75593b3f80bba5da
BLAKE2b-256 6e9de22234d356bf2a6dd7f7efebb4a478e6bb09b08887d083e630ac1b279d4e

See more details on using hashes here.

File details

Details for the file bosos_dev_tools-1.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for bosos_dev_tools-1.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 093cb4f096590bcda2ed7e9140488ca8da77e39bd4a528f928cb056a37f0d0cb
MD5 1bc360f29988234ffe79540cc1387fbd
BLAKE2b-256 fef42a611c28165b6efd1113ec2a0d3884ca942a07590ad8f4c0302c39bc0424

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page