Metadata-Version: 2.4
Name: ladon-clear-exceptions-n-warnings
Version: 1.0.1
Summary: Drop-in replacement for Python's built-in exceptions and warnings. Structured output, automatic logging, zero boilerplate.
Project-URL: Homepage, https://github.com/soss-community/ladon_clear_exceptions_n_warnings
Project-URL: Repository, https://github.com/soss-community/ladon_clear_exceptions_n_warnings
Project-URL: Bug Tracker, https://github.com/soss-community/ladon_clear_exceptions_n_warnings/issues
Project-URL: Contact, https://github.com/soss-community
Author: sora7672
License: SOSS Module & Package License (SOSS-MPL) v1.0
        ==============================================
        Copyright (c) 2026 sora7672 & SOSS Community
        Website: https://soss.page
        Organization: https://github.com/soss-community
        
        NOTE: This license may be updated over time.
        Always refer to the latest version at: https://github.com/soss-community
        The version included in this repository was current at time of release.
        
        ---
        
        ACCEPTANCE
        
        By incorporating this package or module into your software, code, or project in any form,
        you confirm that you have read and understood the terms of this license.
        Usage constitutes full acceptance of all conditions stated below.
        
        ---
        
        1. PERMITTED USE
        
           This package/module may be used freely by anyone, for private or commercial purposes,
           subject to the conditions of this license.
        
        2. NO MODIFICATION & DISTRIBUTION
        
           Modification of the original source files is not permitted.
           Modified versions of this package/module may not be redistributed in any form.
        
           Exception:
           You may create child classes or wrapper implementations that extend
           the functionality through inheritance or composition. These must be clearly marked
           as separate works and must not replace or repackage the original.
           This exception exists to allow external verification of behavior, if an issue
           arises in a child class, it can be clearly distinguished from the original.
        
        3. CREDITS & ATTRIBUTION
        
           Any software, project, or codebase that uses this package/module must clearly
           credit it in one of the following locations:
           - A credits section in the README
           - An About screen or page within the software
           - Any other clearly visible location within the project documentation
        
           The credit entry must include:
           - A link to the SOSS community page: https://soss.page
           - The name of the module/package (e.g. "taipan-logger")
           - If multiple SOSS packages/modules are used, all must be listed individually.
        
        4. COMMERCIAL USE
        
           Commercial use of this package/module is explicitly permitted.
           In addition to the credit requirement above, commercial users are strongly encouraged
           to open a discussion on the official GitHub repository with the tag:
           "Using this package/module for my software"
           including the name of their software.
           This will be read and closed by the maintainer.
           This does not replace the credit requirement.
        
        5. ISSUE REPORTING
        
           Issues, bugs, and feature requests are managed exclusively via the official
           GitHub repository of the respective package/module.
           Before reporting an issue, you must have read the README and documentation,
           and must understand the intended purpose of the software.
        
        6. SUPPORT
        
           No official support is provided by the developers or maintainers.
           If you or your organization wish to offer support for this package/module,
           including commercial support, you may apply via the SOSS community page:
           https://soss.page
        
           Approved support providers will be listed there publicly.
           No individual or organization may present themselves as an "official" support
           provider without being listed on the SOSS community page.
        
           Listings may be revoked at any time if quality standards are not maintained.
           The affected party will be notified and the listing updated accordingly.
        
        7. NO MONETIZATION
        
           This package/module is not for sale under any circumstances, regardless of the offer.
        
           Any new maintainer who takes over this project must agree to the same conditions.
           Monetization of this package/module by any maintainer is strictly prohibited.
        
           In the event of a violation, third parties are entitled to pursue legal action
           against the maintainer and to seek the appointment of a new maintainer
           who agrees to these conditions.
        
        8. LEGAL & DISPUTE RESOLUTION
        
           In the event of a dispute arising from improper use or violation of this license,
           all legal costs shall be borne by the party found to be in violation.
           This applies internationally to the extent permitted by applicable law.
        
        9. NO WARRANTY & NO LIABILITY
        
           This package/module is provided "as is", without warranty of any kind.
           The maintainers and contributors make no guarantees regarding functionality,
           fitness for a particular purpose, or absence of errors.
        
           We are human, mistakes can happen. We do our best to keep the code clean and reliable,
           but we accept no liability for any damages, data loss, or other consequences
           arising from the use of this software.
        
        ---
        SOSS-MPL is part of the Sora Open Source Software standard.
        All SOSS-licensed projects must include this license file unchanged.
        Website: https://soss.page
        Organization: https://github.com/soss-community
License-File: LICENSE
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# Ladon - clear exceptions 'n warnings

> Drop-in replacement for Python's built-in exceptions and warnings. Structured output, automatic logging, zero boilerplate.

![Python](https://img.shields.io/badge/python-3.12%2B-blue)
![License](https://img.shields.io/badge/license-OSS%20Community-green)
![Version](https://img.shields.io/badge/version-1.0.0-orange)
[![Community](https://img.shields.io/badge/community-soss.page-purple)](https://soss.page)

---

In Greek mythology, Ladon is the eternal guardian of the Golden Apples of the Hesperides. Many-headed, ever-watchful,  
standing at the boundary between the mortal and the divine.  
That boundary is exactly what Python's core exception system is:  
something every developer depends on, something almost nobody touches.

This package watches over it. Better output, more context, no silent failures,  
and the ability to hook into anything the runtime raises before it propagates.

---

## The problem

Python's default exception output looks like this:

```
Traceback (most recent call last):
  File "main.py", line 12, in <module>
    process(user_input)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
```

Everything is red. No structure. No context about what value caused the error or what was expected.  
Warnings are silently swallowed by default. Logging requires manual setup everywhere.

If you have worked on any Python project longer than a weekend, you have probably written your own exception wrappers.  
This package does it once, properly, for everyone.

---

## What this does

**Structured, color-coded output.**  
Exceptions and warnings are visually distinct and readable.  
The final stack frame is highlighted so you see immediately where it broke, not just the traceback wall.  

**Colors and styles are fully customizable per element.**

**Structured error data.**  
Every exception carries a `.data` dict with the values that caused the error,  
an `.error_code` for programmatic handling, and a `.message` for human-readable output.

**Automatic logging.**  
Logging happens inside `__init__`, before the exception propagates.  
Even caught-and-silenced exceptions leave a log trail when auto-logging is enabled.

**`.check()` on supported classes.** Replaces the `if not isinstance(...): raise` pattern with a single inline call.

**Warnings that cannot be dropped.** Every warning is either printed to STDERR or written to a logger.  
Nothing is ever silently swallowed.

**Hook system.** Register your own function to be called before any exception is raised or any warning is shown.  
Useful for health monitoring, alerting, or metrics.

**One-time warnings.** Mark any warning subclass as `_one_time = True` and it will only fire once per runtime.

**No dependencies.** Standard library only.

---
## How it looks 
This is the default config, you can change it as you like!

![example_exceptions_n_warnings.png](examples/example_exceptions_n_warnings.png)

---

## Installation

```bash
pip install ladon_clear_exceptions_n_warnings
```

Or via the community page: [soss.page](https://soss.page)

---

## Usage

> More examples here: 
> [example_usage.py](examples/example_usage.py)
> [example_warn.log](examples/example_warn.log)

Add one line at the top of your entry module, before any other import:

```python
import ladon_clear_exceptions_n_warnings
```

That is it. All overwritten exception and warning classes are registered directly into Python's builtins on import.  
There is no need to import individual classes. Everything you already use continues to work exactly as before.

```python
# All of these work unchanged
raise ValueError("something went wrong")

try:
    do_something()
except TypeError as e:
    handle(e)

class MyError(ValueError):
    pass
```

Two things surface as warnings rather than silently continuing:

`warnings.warn(...)` called with positional string arguments triggers an `OldWarningWarning` pointing to the exact call site.

Raising exceptions with positional arguments, for example `raise TypeError("message")`  
instead of `raise TypeError(message="message")`, triggers an `OldExceptionWarning`  
showing the type and the values that were passed. Execution still continues normally,  
the warning is just a signal that the call site should be updated.

> If you want to suppress these during a migration before fixing all call sites, use `ladon.supress_warning()` temporarily.
---

## Structured exceptions

Any keyword argument passed to an exception constructor is stored in `.data` and available after the fact.

```python
raise TypeError(
    message="Invalid input for user_id",
    expected=int,
    got=type(user_id),
    var="user_id"
)
```

When caught:

```python
except TypeError as e:
    print(e.message)       # "Invalid input for user_id"
    print(e.error_code)    # numeric code, e.g. 412
    print(e.data)          # {"expected": <class 'int'>, "got": <class 'str'>, "var": "user_id"}
```

### Error codes

Every exception class has a numeric error code. When a subclass inherits from another,  
the parent's code is prepended to the child's. This means the code itself carries the inheritance chain:  
you can see at a glance whether two errors are related, without inspecting the class hierarchy.

For `CheckableError` subclasses, the code is additionally prefixed with `4` to mark it as a checkable type.

---

## `.check()` - inline validation

The following classes expose a `.check()` classmethod. It performs the validation and  
raises the exception with full context already populated. No `if/raise` block needed.

```python
# Type check
TypeError.check(x, int)

# None check
NoneValueError.check(user_id, "user_id")

# Zero division guard
ZeroDivisionError.check(divisor)

# Assertion
AssertionError.check((25 >=18), "condition name")
# if you use ifs or other complex things, try to use () around, to make sure it does not break

# Overflow
OverflowError.check(value, max_allowed)

# Value in allowed set
ValueError.check(status, {"active", "inactive"})

# Configuration validity
ConfigurationError.check(("boot" in config_list), "port")
```

Note: `TypeError.check()` skips `None` silently. Use `NoneValueError.check()` when `None` itself is the error.

---

## Built-in extra exception classes

Beyond the standard Python exceptions, the package ships several additional classes that cover common patterns.  
You can use them to save time writing common usage exceptions yourself.

> Feel free to reach out to us for adding nex exceptions and check logics.

`NoneValueError` raises when a value is `None` but `None` is not acceptable.  
It accepts an optional `parameter_name` for a readable message.

`ConfigurationError` raises when a configuration condition is not met. Pass any boolean expression directly:  
`ConfigurationError.check(api_key is not None)`.

`AttributeReadOnlyError` is intended for use inside `__setattr__`  
to protect attributes that must not be changed after assignment.

`StateError` raises when a method is called on an object that is not in a valid state for that operation.  
It accepts `input_object` and `expected_object_state` for context.

---

## Warnings

Warnings are instantiated as objects.  
Instantiating them triggers output immediately.  
`extra_message` is available on all legacy warning classes to append  
additional context to the message, for example when forwarding a message from a legacy warning call.

```python
DeprecationWarning(
    message="use new_method() instead",
    old="old_method",
    replacement="new_method",
    since="v1.4"
)
```

`warnings.warn()` is still accepted but will surface an `OldWarningWarning` pointing to the exact call site.  
The `*args` positional parameter exists on all warning classes for this compatibility reason only.  
Do not pass values through it intentionally, it will trigger that same warning.

### One-time warnings

```python
class MyWarning(UserWarning):
    _one_time = True
```

This warning fires only once per runtime regardless of how many times it is triggered.

### Built-in extra warning classes

`PerformanceWarning` is for operations that are valid but known to be slow or suboptimal,  
such as fallback paths or missing optimizations.

`SecurityWarning` is for non-fatal security-relevant conditions, such as missing encryption or insecure defaults.

`ConfigurationWarning` is for configurations that are accepted but suboptimal, where execution continues  
but a developer should review the value.

`FixedButWrongValueWarning` is for cases where a function received a wrong input but applied a fallback internally.  
It signals to the caller that their value was incorrect even though nothing crashed.

---

## Logging

Set a logger before enabling log output.  
The logger must have a `FileHandler` with UTF-8 encoding and no `StreamHandler`,  
to prevent duplicate or wrong console output.

```python
import logging
import ladon_clear_exceptions_n_warnings as ladon

logger = logging.getLogger("my_app")
handler = logging.FileHandler("app.log", encoding="utf-8")
logger.addHandler(handler)

ladon.configure_log_warning_and_exceptions(
    logger_instance=logger,
    write_log_warning=True,
    auto_log_exceptions=True,
    suppress_warnings=False,
    code_lines_before_warning=3
)
```

Log output is plain text without ANSI codes. Terminal output is color-coded. Both run independently.

The individual setters are also available:

```python
import ladon_clear_exceptions_n_warnings as ladon
ladon.set_logger(logger)
ladon.enable_log_warning()
ladon.enable_auto_log_exceptions()
ladon.supress_warning()
ladon.set_number_of_prior_warning_code_lines(5)
```

---

## Hook system

Register a function that fires before any exception is raised or any warning is shown.  
Useful for monitoring, alerting, or metrics collection.

```python
def on_exception(exc, is_oop_exception):
    # exc is the exception instance
    # is_oop_exception is True for OOPException subclasses, False for non-overwritten builtins
    send_to_monitoring(exc)

def on_warning(warning):
    log_warning_metric(warning)

ladon.set_exceptions_hook_function(on_exception)
ladon.set_warnings_hook_function(on_warning)
```

The exception hook fires on every `OOPException` instantiation, before the exception propagates.  
The warning hook fires on every warning instantiation, before output is written.

---

## Custom exceptions and warnings

Use `OOPException` as the base for simple custom exceptions.  
Use `CheckableError` if you want to add a `.check()` classmethod.  
Since error codes are passed up the inheritance chain and concatenated at the final parent,  
your custom code is automatically embedded in the code structure.

```python
# No import needed, OOPException and CheckableError are in builtins after the package import

class MyAppError(OOPException):
    def __init__(self, *, resource=None, message=None, **kwargs):
        self.message = message or f"Resource failed: {resource}"
        self.error_code = 999
        super().__init__(message=self.message, error_code=self.error_code, resource=resource, **kwargs)


class StrictIntError(CheckableError):
    def __init__(self, *, message=None, **kwargs):
        self.message = message or "Expected a strict integer"
        self.error_code = 77
        super().__init__(message=self.message, error_code=self.error_code, **kwargs)

    @classmethod
    def check(cls, value):
        if not isinstance(value, int) or isinstance(value, bool):
            raise cls(got=type(value))
```

Use `OOPWarning` as the base for custom warnings.

```python
# OOPWarning is also in builtins after the package import

class SlowQueryWarning(OOPWarning):
    _one_time = False

    def __init__(self, *, duration_ms=None, message=None, extra_message=None, **kwargs):
        self.message = message or f"Query took {duration_ms}ms"
        self.message += (f"\n{extra_message}" if extra_message else "")
        super().__init__(message=self.message, **kwargs)


class MigrationWarning(OOPWarning):
    _one_time = True  # only fires once per runtime

    def __init__(self, *, table=None, message=None, extra_message=None, **kwargs):
        self.message = message or f"Pending migration on table '{table}'" if table else "Pending migration"
        self.message += (f"\n{extra_message}" if extra_message else "")
        super().__init__(message=self.message, **kwargs)

```

Trigger a custom warning by instantiating it directly:

```python
SlowQueryWarning(duration_ms=4200)

# or conditionally
MigrationWarning.show(pending_migrations > 0)
```

---

## Customizing output

All visual elements are managed through `FormatElements`. Each element has a name, a foreground color,  
a background color, and one or more text styles.  
You can update any element at runtime before exceptions or warnings fire.

```python
from ladon_clear_exceptions_n_warnings import FormatElements

# Change the color of the file path in exception output
FormatElements.get("file").update_fg("bright_green")

# Change the error type badge to a blue background
FormatElements.get("error_type").update_bg("blue")

# Inspect what is available
print(FormatElements.get_all_elements())
print(FormatElements.get_all_fg())
print(FormatElements.get_all_bg())
print(FormatElements.get_all_styles())
```

Valid styles are `bold`, `dim`, `italic`, `underline`, `blink`, `inverse`, and `strike`.  
Colors follow the standard 16-color ANSI set with bright variants.

`FormatElements` instances can also be created independently for use in your own terminal output,  
building on the same system the package uses internally.

---

## What is NOT replaced

| Class | Reason |
|---|---|
| `BaseException` | Root of the entire exception hierarchy |
| `KeyboardInterrupt` | System-level signal |
| `SystemExit` | Used by `sys.exit()` |
| `GeneratorExit` | Generator and coroutine lifecycle |
| `KeyError` | Used incorrectly in too many builtin import mechanisms |

The following cannot be replaced because they are loaded before this package is imported:

`UnicodeDecodeError`, `UnicodeEncodeError`, `UnicodeTranslateError`, `ImportError`, `ModuleNotFoundError`,  
`SyntaxError`, `IndentationError`, `TabError`, `StopIteration`, `StopAsyncIteration`, `UnicodeError`,  
`RecursionError`, `IndexError`, `NameError`, `OSError` and all its subclasses.

> We will probably look into this later again,
> because to solve this we need to change some core packages from python.

C-level exceptions raised by the Python interpreter itself also remain native.  
This package covers exceptions raised by your own code and any libraries loaded after the import.

---

## Compatibility

Python 3.12 or higher. No dependencies outside the standard library.

---

## License

OSS Community License.  
If you use this package in a project, include a credit in your README, credits section, or anywhere visible,  
with the package name and a link to [soss.page](https://soss.page).

---

## Community and contributing

Hosted and maintained through the OSS Community.  
Visit [github.com/soss-community](https://github.com/soss-community) for contribution guidelines,  
issue tracking, and discussion.