|
1 | | -"""Tiered Debugging module""" |
| 1 | +"""Module for tiered debugging with a global TieredDebug instance. |
| 2 | +
|
| 3 | +This module defines a global `debug` instance of `TieredDebug` and a `begin_end` |
| 4 | +decorator to log function call boundaries at specified debug levels. Copy this |
| 5 | +file into your project to enable project-wide debugging. Import `debug` and `begin_end` |
| 6 | +in any module with `from .debug import debug, begin_end`. |
| 7 | +""" |
2 | 8 |
|
3 | 9 | import typing as t |
4 | 10 | from functools import wraps |
5 | | -from tiered_debug import TieredDebug |
| 11 | +from tiered_debug import TieredDebug, DebugLevel |
| 12 | + |
| 13 | +DEFAULT_BEGIN: DebugLevel = 2 |
| 14 | +"""Default debug level for begin message in begin_end decorator.""" |
| 15 | + |
| 16 | +DEFAULT_END: DebugLevel = 3 |
| 17 | +"""Default debug level for end message in begin_end decorator.""" |
6 | 18 |
|
7 | 19 | debug = TieredDebug() |
| 20 | +"""Global TieredDebug instance for project-wide debugging.""" |
8 | 21 |
|
9 | 22 |
|
10 | | -def begin_end(begin: t.Optional[int] = 2, end: t.Optional[int] = 3) -> t.Callable: |
11 | | - """Decorator to log the beginning and end of a function. |
| 23 | +def begin_end( |
| 24 | + begin: t.Optional[DebugLevel] = DEFAULT_BEGIN, |
| 25 | + end: t.Optional[DebugLevel] = DEFAULT_END, |
| 26 | + debug_obj: t.Optional[TieredDebug] = None, |
| 27 | + stklvl: t.Optional[int] = None, |
| 28 | +) -> t.Callable: |
| 29 | + """Decorator to log the beginning and end of a function call. |
12 | 30 |
|
13 | | - This decorator will log the beginning and end of a function call at the |
14 | | - specified levels, defaulting to 2 for the beginning and 3 for the ending. |
| 31 | + Logs the start and end of a function at the specified debug levels using the |
| 32 | + provided or global `debug` instance. If `begin` or `end` is invalid (not 1-5), |
| 33 | + logs an error and uses default levels (2 for begin, 3 for end). The stack level |
| 34 | + defaults to one level beyond the global `debug.stacklevel` to report the caller's |
| 35 | + context. |
15 | 36 |
|
16 | | - :return: The decorated function. |
| 37 | + :param begin: Debug level (1-5) for the begin message. Defaults to 2. |
| 38 | + :type begin: Optional[DebugLevel] |
| 39 | + :param end: Debug level (1-5) for the end message. Defaults to 3. |
| 40 | + :type end: Optional[DebugLevel] |
| 41 | + :param debug_obj: TieredDebug instance to use for logging. Defaults to global |
| 42 | + `debug`. |
| 43 | + :type debug_obj: Optional[TieredDebug] |
| 44 | + :param stklvl: Stack level for caller reporting. Defaults to debug.stacklevel + 1. |
| 45 | + :type stklvl: Optional[int] |
| 46 | + :return: Decorated function. |
17 | 47 | :rtype: Callable |
18 | 48 | """ |
| 49 | + if debug_obj is None: |
| 50 | + debug_obj = globals()["debug"] |
| 51 | + |
| 52 | + effective_begin = begin |
| 53 | + effective_end = end |
| 54 | + |
| 55 | + if begin not in (1, 2, 3, 4, 5): |
| 56 | + debug_obj.logger.error( |
| 57 | + f"Invalid begin level: {begin}. Using default: {DEFAULT_BEGIN}" |
| 58 | + ) |
| 59 | + effective_begin = DEFAULT_BEGIN |
| 60 | + if end not in (1, 2, 3, 4, 5): |
| 61 | + debug_obj.logger.error( |
| 62 | + f"Invalid end level: {end}. Using default: {DEFAULT_END}" |
| 63 | + ) |
| 64 | + effective_end = DEFAULT_END |
| 65 | + |
19 | 66 | mmap = { |
20 | | - 1: debug.lv1, |
21 | | - 2: debug.lv2, |
22 | | - 3: debug.lv3, |
23 | | - 4: debug.lv4, |
24 | | - 5: debug.lv5, |
| 67 | + 1: debug_obj.lv1, |
| 68 | + 2: debug_obj.lv2, |
| 69 | + 3: debug_obj.lv3, |
| 70 | + 4: debug_obj.lv4, |
| 71 | + 5: debug_obj.lv5, |
25 | 72 | } |
26 | 73 |
|
27 | 74 | def decorator(func: t.Callable) -> t.Callable: |
28 | 75 | @wraps(func) |
29 | 76 | def wrapper(*args, **kwargs): |
30 | 77 | common = f"CALL: {func.__name__}()" |
31 | | - mmap[begin](f"BEGIN {common}", stklvl=debug.stacklevel + 1) |
| 78 | + effective_stklvl = ( |
| 79 | + stklvl if stklvl is not None else debug_obj.stacklevel + 1 |
| 80 | + ) |
| 81 | + mmap[effective_begin](f"BEGIN {common}", stklvl=effective_stklvl) |
32 | 82 | result = func(*args, **kwargs) |
33 | | - mmap[end](f"END {common}", stklvl=debug.stacklevel + 1) |
| 83 | + mmap[effective_end](f"END {common}", stklvl=effective_stklvl) |
34 | 84 | return result |
35 | 85 |
|
36 | 86 | return wrapper |
|
0 commit comments