API Reference
Complete API documentation for Genro-Toolbox.
extract_kwargs
- genro_toolbox.extract_kwargs(_adapter=None, _dictkwargs=None, **extraction_specs)[source]
A decorator that extracts
**kwargsinto sub-families by prefix.This decorator allows methods to accept kwargs with prefixes (e.g., logging_level, cache_ttl) and automatically groups them into separate kwargs dictionaries (e.g., logging_kwargs, cache_kwargs).
- Parameters:
_adapter (
Optional[str]) – Optional name of a method on self that will pre-process kwargs. The adapter method receives kwargs dict and can modify it in-place._dictkwargs (
Optional[dict[str,Any]]) – Optional dict to use instead of**extraction_specs. Useful for dynamic extraction specifications.**extraction_specs (
Any) – Extraction specifications where keys are prefix names. Values can be: - True: Extract and remove (pop=True) - dict: Custom options (slice_prefix, pop)
- Return type:
Callable[[TypeVar(F, bound=Callable[...,Any])],TypeVar(F, bound=Callable[...,Any])]- Returns:
Decorated function that extracts kwargs by prefix.
Example
>>> @extract_kwargs(palette=True, dialog=True, default=True) ... def my_method(self, pane, table=None, ... palette_kwargs=None, dialog_kwargs=None, default_kwargs=None, ... **kwargs): ... pass ... >>> # Call with prefixed parameters >>> obj.my_method(palette_height='200px', palette_width='300px', ... dialog_height='250px') >>> # palette_kwargs={'height': '200px', 'width': '300px'} >>> # dialog_kwargs={'height': '250px'}
Notes
The decorated function MUST have {prefix}_kwargs parameters for each prefix
Reserved keyword ‘class’ is automatically renamed to ‘_class’
Works with both class methods (with self) and standalone functions
Maintains 100% compatibility with original Genropy implementation
Function Signature
def extract_kwargs(
_adapter: Optional[str] = None,
_dictkwargs: Optional[Dict[str, Any]] = None,
**extraction_specs: Any
) -> Callable[[F], F]
Parameters
- _adapter :
Optional[str] Name of a method on
selfthat will be called to pre-processkwargsbefore extraction. The adapter method receives thekwargsdict and can modify it in-place.- _dictkwargs :
Optional[Dict[str, Any]] Optional dictionary of extraction specifications. When provided, this is used instead of
**extraction_specs. Useful for dynamic extraction specifications.- extraction_specs :
Any Keyword arguments where keys are prefix names and values specify extraction behavior:
True: Extract parameters with this prefix and remove them from source (pop=True)dict: Custom extraction options (pop,slice_prefix,is_list)
Returns
- Callable[[F], F]
Decorated function that performs kwargs extraction
Examples
See extract_kwargs Guide for detailed examples.
SmartOptions
- class genro_toolbox.SmartOptions(incoming=None, defaults=None, *, env=None, argv=None, ignore_none=False, ignore_empty=False, filter_fn=None)[source]
Convenience namespace for option management, built on TreeDict.
- Parameters:
incoming (
Union[Mapping[str,Any],str,Path,Callable[...,Any],None]) – Mapping with runtime kwargs, or a file path (str/Path) to load, or a callable to extract defaults and types from its signature.defaults (
Union[Mapping[str,Any],list[str],None]) – Mapping with baseline options, or argv list when incoming is callable.env (
Optional[str]) – Environment variable prefix (e.g., “MYAPP” for MYAPP_HOST). Only used when incoming is a callable (types from signature are used).argv (
Optional[list[str]]) – Command line arguments list. Only used when incoming is a callable.ignore_none (
bool) – Skip incoming entries where the value isNone.ignore_empty (
bool) – Skip empty strings/collections from incoming entries.filter_fn (
Optional[Callable[[str,Any],bool]]) – Optional callable receiving(key, value)and returning True if the pair should be kept.
If incoming is a string or Path and defaults is None, loads config from file. Nested dicts are recursively wrapped in SmartOptions.
- When incoming is a callable with env/argv:
Defaults come from function signature
env values override defaults (with type conversion)
argv values override env (with type conversion)
Priority: defaults < env < argv
- Inherits from TreeDict:
Path notation access: opts[“a.b.c”]
Context managers for thread/async safety
- __init__(incoming=None, defaults=None, *, env=None, argv=None, ignore_none=False, ignore_empty=False, filter_fn=None)[source]
Initialize from dict, JSON string, or None (empty).
Class Signature
class SmartOptions(TreeDict):
def __init__(
self,
incoming: Mapping[str, Any] | str | Path | Callable[..., Any] | None = None,
defaults: Mapping[str, Any] | list[str] | None = None,
*,
env: str | None = None,
argv: list[str] | None = None,
ignore_none: bool = False,
ignore_empty: bool = False,
filter_fn: Callable[[str, Any], bool] | None = None,
)
Parameters
- incoming :
Mapping | str | Path | Callable | None One of:
Mapping with runtime kwargs
str path to config file (YAML, JSON, TOML, INI)
str ‘ENV:PREFIX’ for environment variables
Path object to config file
Callable to extract defaults from signature
- defaults :
Mapping | list[str] | None Mapping with baseline options, or argv list when incoming is callable (legacy).
- env :
str | None Environment variable prefix (e.g., “MYAPP” for MYAPP_HOST). Only used when incoming is callable.
- argv :
list[str] | None Command line arguments list. Only used when incoming is callable.
- ignore_none :
bool When True, skip incoming entries where the value is
None. Default: False.- ignore_empty :
bool When True, skip empty strings/collections from incoming entries. Default: False.
- filter_fn :
Callable[[str, Any], bool] | None Optional custom filter function receiving
(key, value)and returning True if the pair should be kept.
Methods
- as_dict() → dict[str, Any]
Return a copy of current options as a dictionary.
- add(other) → SmartOptions
Merge two SmartOptions (right side wins).
Examples
See SmartOptions Guide for detailed examples.
TreeDict
- class genro_toolbox.TreeDict(data=None)[source]
Hierarchical dictionary with dot-path access, list indexing (#N), and thread/async safety.
- classmethod from_file(path)[source]
Load TreeDict from a config file (JSON/YAML/TOML/INI, auto-detected by extension).
- Return type:
- walk(expand_lists=False, _prefix='')[source]
Iterate over all paths and leaf values.
- Parameters:
expand_lists (
bool) – If True, traverse into lists using #N paths. If False, lists are treated as leaf values.- Yields:
Tuples of (path, value) for each leaf node.
- Return type:
Example
>>> td = TreeDict({"a": 1, "b": {"c": 2}}) >>> list(td.walk()) [('a', 1), ('b.c', 2)]
Class Signature
class TreeDict:
def __init__(
self,
data: dict[str, Any] | str | None = None,
)
Parameters
- data :
dict | str | None Initial data. Can be:
dict: Used directly as underlying data
str: Parsed as JSON
None: Empty TreeDict
Key Features
Path string access:
td["a.b.c"]accesses nested keysAuto-creates intermediate dicts on write
Returns None for missing keys (no KeyError)
List access with #N syntax:
td["items.#0.id"]Thread-safe access via context manager
Async-safe access via async context manager
Methods
- as_dict() → dict[str, Any]
Return underlying data as dict.
- walk(expand_lists: bool = False) → Iterator[tuple[str, Any]]
Iterate all paths and leaf values.
- from_file(path: str | Path) → TreeDict (classmethod)
Load from JSON, YAML, TOML, or INI file.
Examples
td = TreeDict({"user": {"name": "Alice"}})
td["user.name"] # "Alice"
td["missing"] # None
td["settings.theme"] = "dark" # auto-creates intermediate dicts
# List access
td = TreeDict({"items": [{"id": 1}, {"id": 2}]})
td["items.#0.id"] # 1
# Thread-safe
with td:
td["counter"] = td["counter"] + 1
# Async-safe
async with td:
td["counter"] = td["counter"] + 1
See README for more examples.
safe_is_instance
- genro_toolbox.safe_is_instance(obj, class_full_name)[source]
Return True if obj is an instance of class_full_name (checked via MRO, no import).
- Return type:
Function Signature
def safe_is_instance(obj: Any, class_name: str) -> bool
Parameters
- obj :
Any Object to check
- class_name :
str Fully qualified class name (e.g., “builtins.int”, “package.module.ClassName”)
Returns
- bool
True if obj is an instance of the class, False otherwise
Examples
See safe_is_instance Guide for detailed examples.
ASCII Table
render_ascii_table
Function Signature
def render_ascii_table(data: dict, max_width: Optional[int] = None) -> str
Parameters
- data :
dict Table structure containing:
headers: List of column definitions (name, type, format, align, hierarchy)rows: List of row data (list of values)title(optional): Table titlemax_width(optional): Maximum table width in characters
- max_width :
Optional[int] Override max_width from data dict. Default: use data’s max_width or 120
Returns
- str
Formatted ASCII table with borders and alignment
render_markdown_table
Function Signature
def render_markdown_table(data: dict) -> str
Parameters
- data :
dict Table structure (same format as render_ascii_table)
Returns
- str
Markdown-formatted table
Examples
See ASCII Table Guide for detailed examples.
RuleError
Exception raised when a tag expression is invalid.
Inherits from ValueError.
get_uuid
- genro_toolbox.get_uuid()[source]
Generate a 22-char sortable unique ID (Z + 9-char base62 timestamp + 12-char base62 random).
- Return type:
Function Signature
def get_uuid() -> str
Returns
- str
22-character sortable unique identifier.
Format
The ID consists of:
Z: Version marker (distinguishes from legacy UUIDs, sorts after them)9 characters: microseconds since 2025-01-01 UTC (base62 encoded)
12 characters: cryptographically secure random (base62 encoded)
Properties
Lexicographically sortable by creation time (UTC)
URL-safe (alphanumeric only)
22 characters (compatible with legacy Genro ID columns)
Timestamp valid for ~440 years from 2025
Collision probability ~10^-19 for same microsecond
Examples
from genro_toolbox import get_uuid
uid = get_uuid() # e.g., "Z00005KmLxHj7F9aGbCd3e"
len(uid) # 22
uid[0] # 'Z'
uid.isalnum() # True
# IDs are sortable by time
ids = [get_uuid() for _ in range(3)]
sorted(ids) == ids # True
smartasync
- genro_toolbox.smartasync(method)[source]
Decorator that adapts sync/async functions to work in both contexts.
Dispatches based on (async_context, is_coroutine): sync+async→run_until_complete, sync+sync→passthrough, async+async→return coroutine, async+sync→to_thread.
Function Signature
def smartasync(method: Callable) -> Callable
Parameters
- method :
Callable Method or function to decorate (async or sync).
Returns
- Callable
Wrapped function that works in both sync and async contexts.
How It Works
Automatically detects the execution context and adapts:
Context |
Method |
Behavior |
|---|---|---|
Sync |
Async |
|
Sync |
Sync |
Direct call |
Async |
Async |
Return coroutine (for await) |
Async |
Sync |
|
Features
Auto-detection of sync/async context using
asyncio.get_running_loop()Asymmetric caching: caches True (async), always checks False (sync)
Works with both class methods and standalone functions
Compatible with
__slots__classes
Examples
from genro_toolbox import smartasync
class DataManager:
@smartasync
async def fetch_data(self, url: str):
async with httpx.AsyncClient() as client:
return await client.get(url).json()
manager = DataManager()
# Sync context - no await needed
data = manager.fetch_data("https://api.example.com")
# Async context - use await
async def main():
data = await manager.fetch_data("https://api.example.com")
Cache Reset
For testing, you can reset the cache:
manager.fetch_data._smartasync_reset_cache()
Helper Functions
filtered_dict
def filtered_dict(
data: Optional[Mapping[str, Any]],
filter_fn: Optional[Callable[[str, Any], bool]] = None,
) -> Dict[str, Any]
Return a dict filtered through filter_fn.
Parameters:
data: Source mapping (can be None)filter_fn: Optional filter callable(key, value) → bool
Returns: Filtered dictionary
DictObj
- class genro_toolbox.DictObj[source]
Dict with dot-access for attribute-style read/write.
Example:
ctx = DictObj() ctx.db = connection ctx.session = session_obj ctx.db.execute(...) # dot-access "db" in ctx # dict-access
Class Signature
class DictObj(dict):
...
A dict subclass that supports attribute-style access for reading, writing, and deleting.
Examples
from genro_toolbox import DictObj
ctx = DictObj()
ctx.db = connection # same as ctx["db"] = connection
ctx.db.execute(...) # dot-access read
"db" in ctx # True (dict-access)
del ctx.session # same as del ctx["session"]
Raises AttributeError (not KeyError) when accessing a missing attribute.
smartsplit
- genro_toolbox.smartsplit(path, separator)[source]
Split a string by separator, ignoring escaped occurrences.
Function Signature
def smartsplit(path: str, separator: str) -> list[str]
Parameters
- path :
str The string to split.
- separator :
str The separator substring.
Returns
- list[str]
List of substrings with whitespace stripped. Escaped separators (prefixed with
\) are preserved.
Examples
from genro_toolbox import smartsplit
smartsplit("a.b.c", ".") # ['a', 'b', 'c']
smartsplit(r"a\.b.c", ".") # ['a\\.b', 'c']
smartsplit("one , two , three", ",") # ['one', 'two', 'three']
smarttimer
SmartTimer - Async-only non-blocking timers.
Provides setTimeout/setInterval semantics (like JavaScript) for async contexts. Raises RuntimeError if called outside a running event loop.
- API:
set_timeout(delay, callback, *args, **kwargs) -> timer_id set_interval(delay, callback, *args, **kwargs) -> timer_id cancel_timer(timer_id) -> bool
- Callback handling:
Async callback: awaited directly
Sync callback: offloaded to thread via asyncio.to_thread
- genro_toolbox.smarttimer.set_timeout(delay, callback, *args, **kwargs)[source]
Schedule a one-shot callback after delay seconds. Returns timer ID.
Raises RuntimeError if called outside an async context.
- Return type:
- genro_toolbox.smarttimer.set_interval(delay, callback, *args, initial_delay=None, **kwargs)[source]
Schedule a repeating callback every delay seconds. Returns timer ID.
Raises RuntimeError if called outside an async context.
- Return type:
- genro_toolbox.smarttimer.cancel_timer(timer_id)[source]
Cancel a timer by its ID. Returns True if found and cancelled.
- Return type:
set_timeout
def set_timeout(delay: float, callback: Callable, *args, **kwargs) -> str
Schedule a one-shot callback after delay seconds. Returns a timer ID for cancellation.
Parameters:
delay: Seconds to wait before executing callbackcallback: Function to call (sync or async)*args, **kwargs: Arguments forwarded to callback
Returns: str — Timer ID
set_interval
def set_interval(delay: float, callback: Callable, *args,
initial_delay: float | None = None, **kwargs) -> str
Schedule a repeating callback every delay seconds. Returns a timer ID for cancellation.
Parameters:
delay: Seconds between each callback executioncallback: Function to call (sync or async)initial_delay: Delay before first execution (defaults todelay)*args, **kwargs: Arguments forwarded to callback
Returns: str — Timer ID
cancel_timer
def cancel_timer(timer_id: str) -> bool
Cancel a timer by its ID.
Parameters:
timer_id: The ID returned byset_timeoutorset_interval
Returns: True if the timer was found and cancelled, False otherwise
Context Detection
Context |
Callback |
Strategy |
|---|---|---|
Sync |
Sync |
threading.Timer, direct call |
Sync |
Async |
threading.Timer, temp event loop |
Async |
Async |
asyncio task, await |
Async |
Sync |
asyncio task, to_thread |
Examples
from genro_toolbox import set_timeout, set_interval, cancel_timer
# One-shot
tid = set_timeout(2.0, print, "Hello!")
# Repeating
tid = set_interval(1.0, print, "tick")
cancel_timer(tid)
# Async callback
async def notify(msg):
await send_notification(msg)
set_timeout(5.0, notify, "done")
dictExtract
Utility function for extracting dict items by key prefix. Used internally by extract_kwargs.
def dictExtract(
mydict: dict,
prefix: str,
pop: bool = False,
slice_prefix: bool = True,
is_list: bool = False
) -> dict
Returns a dict of items with keys starting with prefix.
Type Definitions
F = TypeVar('F', bound=Callable[..., Any])
Type variable for decorated function preservation.
See Also
User Guide - Complete feature documentation
Examples - Real-world usage examples
Best Practices - Production patterns