Additional APIs#

Representations#

class AmountValidationError(Error):
    __template__ = "Data is invalid: {reason} ({amount}; MAX={_MAX}) at {ts}"
    _MAX: ClassVar[int] = 1000
    amount: int
    reason: str = "amount is too large"
    ts: datetime = factory(datetime.now)


err = AmountValidationError(amount=15000)

print(str(err))
# Data is invalid: amount is too large (15000; MAX=1000) at 2024-01-13 23:33:13.847586

print(repr(err))
# __main__.AmountValidationError(amount=15000, ts=datetime.datetime(2024, 1, 13, 23, 33, 13, 847586), reason='amount is too large')
  • str and repr output differs

  • str is for humans and Python (Python dictates the result to be exactly and only the message)

  • repr allows to reconstruct the same error instance from its output (if data provided into kwargs supports repr the same way)

    note: class name is fully qualified name of class (dot-separated module full path with class name)

    reconstructed = eval(repr(err).replace("__main__.", "", 1))
    
    print(str(reconstructed))
    # Data is invalid: amount is too large (15000; MAX=1000) at 2024-01-13 23:33:13.847586
    
    print(repr(reconstructed))
    # AmountValidationError(amount=15000, ts=datetime.datetime(2024, 1, 13, 23, 33, 13, 847586), reason='amount is too large')
    
  • in addition to str there is another human-readable representations provided by .as_str() method; it prepends message with class name:

    print(err.as_str())
    # AmountValidationError: Data is invalid: amount is too large (15000; MAX=1000) at 2024-01-13 23:33:13.847586
    

Pickling#

izulu-based errors support pickling by default.

Dumping and loading#

Dumping

  • .as_kwargs() dumps shallow copy of original kwargs

err.as_kwargs()
# {'amount': 15000}
  • .as_dict() by default, combines original kwargs and all “instance attribute” values into “full state”

    err.as_dict()
    # {'amount': 15000, 'ts': datetime(2024, 1, 13, 23, 33, 13, 847586), 'reason': 'amount is too large'}
    

    Additionally, there is the wide flag for enriching the result with “class defaults” (note additional _MAX data)

    err.as_dict(True)
    # {'amount': 15000, 'ts': datetime(2024, 1, 13, 23, 33, 13, 847586), 'reason': 'amount is too large', '_MAX': 1000}
    

    Data combination process follows prioritization — if there are multiple values for same name then high priority data will overlap data with lower priority. Here is the prioritized list of data sources:

    1. kwargs (max priority)

    2. “instance attributes”

    3. “class defaults”

Loading

  • .as_kwargs() result can be used to create inaccurate copy of original error, but pay attention to dynamic factories — datetime.now(), uuid() and many others would produce new values for data missing in kwargs (note ts field in the example below)

inaccurate_copy = AmountValidationError(**err.as_kwargs())

print(inaccurate_copy)
# Data is invalid: amount is too large (15000; MAX=1000) at 2024-02-01 21:11:21.681080
print(repr(inaccurate_copy))
# __main__.AmountValidationError(amount=15000, reason='amount is too large', ts=datetime.datetime(2024, 2, 1, 21, 11, 21, 681080))
  • .as_dict() result can be used to create accurate copy of original error; flag wide should be False by default according to FORBID_KWARG_CONSTS restriction (if you disable FORBID_KWARG_CONSTS then you may need to use wide=True depending on your situation)

accurate_copy = AmountValidationError(**err.as_dict())

print(accurate_copy)
# Data is invalid: amount is too large (15000; MAX=1000) at 2024-02-01 21:11:21.681080
print(repr(accurate_copy))
# __main__.AmountValidationError(amount=15000, reason='amount is too large', ts=datetime.datetime(2024, 2, 1, 21, 11, 21, 681080))

(advanced) Wedge#

There is a special method you can override and additionally manage the machinery.

But it should not be need in 99,9% cases. Avoid it, please.

def _override_message(
    self,
    store: _utils.Store,  # noqa: ARG002
    kwargs: t.Dict[str, t.Any],  # noqa: ARG002
    msg: str,
) -> str:
    """Adapter method to wedge user logic into izulu machinery

    This is the place to override message/formatting if regular mechanics
    don't work for you. It has to return original or your flavored message.
    The method is invoked between izulu preparations and original
    `Exception` constructor receiving the result of this hook.

    You can also do any other logic here. You will be provided with
    complete set of prepared data from izulu. But it's recommended
    to use classic OOP inheritance for ordinary behaviour extension.

    Params:
      * store: dataclass containing inner error class specifications
      * kwargs: original kwargs from user
      * msg: formatted message from the error template
    """

    return msg