Metadata-Version: 2.4
Name: genro-toolbox
Version: 0.2.0
Summary: Essential utilities for Genro Kyō
Project-URL: Repository, https://github.com/genropy/genro-toolbox
Project-URL: Documentation, https://genro-toolbox.readthedocs.io/en/latest/
Author: Genropy Team
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: decorators,dict-utils,genro,toolbox,utilities
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: myst-parser>=2.0.0; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints>=2.0.0; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == 'docs'
Requires-Dist: sphinx>=8.0.0; extra == 'docs'
Requires-Dist: sphinxcontrib-mermaid>=0.9.0; extra == 'docs'
Provides-Extra: test
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Description-Content-Type: text/markdown

<p align="center">
  <img src="docs/assets/logo.png" alt="Genro-Toolbox Logo" width="200">
</p>

<p align="center">
  <a href="https://badge.fury.io/py/genro-toolbox"><img src="https://badge.fury.io/py/genro-toolbox.svg" alt="PyPI version"></a>
  <a href="https://pypi.org/project/genro-toolbox/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
  <a href="https://github.com/genropy/genro-toolbox/actions/workflows/test.yml"><img src="https://github.com/genropy/genro-toolbox/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
  <a href="https://codecov.io/gh/genropy/genro-toolbox"><img src="https://codecov.io/gh/genropy/genro-toolbox/graph/badge.svg" alt="codecov"></a>
  <a href="https://genro-toolbox.readthedocs.io/"><img src="https://readthedocs.org/projects/genro-toolbox/badge/?version=latest" alt="Documentation"></a>
  <a href="llm-docs/"><img src="https://img.shields.io/badge/LLM%20Docs-available-brightgreen" alt="LLM Docs"></a>
</p>

# Genro-Toolbox

> Essential utilities for the Genro ecosystem

Part of [Genro Kyō](https://github.com/genropy) ecosystem.

A lightweight, zero-dependency Python library providing core utilities that can be used across all Genro projects.

📚 **[Full Documentation](https://genro-toolbox.readthedocs.io/)**

## Installation

```bash
pip install genro-toolbox
```

## Features

- **SmartOptions** - Merge runtime kwargs with defaults
- **MultiDefault** - Load config from multiple sources (files, env vars, dicts)
- **extract_kwargs** - Decorator to group kwargs by prefix
- **safe_is_instance** - isinstance() without importing the class
- **render_ascii_table** - ASCII table rendering with formatting
- **render_markdown_table** - Markdown table rendering

## Examples

### SmartOptions

```python
from genro_toolbox import SmartOptions

opts = SmartOptions(
    {"timeout": 30},                    # runtime values
    {"timeout": 10, "retries": 3},      # defaults
    ignore_none=True,
    ignore_empty=True,
)

opts.timeout   # 30 (runtime wins)
opts.retries   # 3 (from defaults)
opts.as_dict() # {"timeout": 30, "retries": 3}
```

### MultiDefault

```python
from genro_toolbox import MultiDefault, SmartOptions

# Load config from multiple sources (later sources override earlier)
defaults = MultiDefault(
    {'host': 'localhost', 'port': 8000},  # base defaults
    'config.ini',                          # file config
    'ENV:MYAPP',                           # environment variables
    skip_missing=True,                     # ignore missing files
    types={'port': int, 'debug': bool},    # explicit type conversion
)

# Use with SmartOptions
opts = SmartOptions(
    incoming={'port': 9000},  # runtime override
    defaults=defaults,
)

opts.host  # 'localhost' (from dict or file)
opts.port  # 9000 (from incoming, converted to int)
```

### extract_kwargs Decorator

```python
from genro_toolbox import extract_kwargs

@extract_kwargs(logging=True, cache=True)
def my_function(name, logging_kwargs=None, cache_kwargs=None, **kwargs):
    print(f"logging: {logging_kwargs}")
    print(f"cache: {cache_kwargs}")

my_function(
    "test",
    logging_level="INFO",
    logging_format="json",
    cache_ttl=300,
)
# logging: {'level': 'INFO', 'format': 'json'}
# cache: {'ttl': 300}
```

### safe_is_instance

```python
from genro_toolbox import safe_is_instance

# Check type without importing
safe_is_instance(42, "builtins.int")              # True
safe_is_instance(my_obj, "mypackage.BaseClass")   # True (includes subclasses)
```

### ASCII & Markdown Tables

```python
from genro_toolbox import render_ascii_table, render_markdown_table

data = {
    "headers": [
        {"name": "Name", "type": "str"},
        {"name": "Active", "type": "bool"},
    ],
    "rows": [
        ["Alice", "yes"],
        ["Bob", "no"],
    ],
}

print(render_ascii_table(data))
# +-------+--------+
# |Name   |Active  |
# +-------+--------+
# |Alice  |true    |
# +-------+--------+
# |Bob    |false   |
# +-------+--------+
```

## Philosophy

> If you write a generic helper that could be useful elsewhere, put it in genro-toolbox.

This library serves as the foundation for utilities shared across:
- genro-asgi
- genro-routes
- genro-api
- Other Genro Kyō projects

## License

Apache License 2.0 - See [LICENSE](LICENSE) for details.

Copyright 2025 Softwell S.r.l.
