Package: xcept
xceptxceptis a Python package for the convenience of creating exceptions.Installationpip install xceptUsageBuilt-inExceptionUsually exceptions are created like this:classError(Exception):# Base error class of your application or librarypassclassFooError(Error):# Concrete error classpassclassBarError(Error):# Concrete error classpassIt looks pretty simple.
Let's try to create exceptions with arguments:classError(Exception):def__init__(self,message:str):self.message=messagedef__str__(self):returnself.messageclassFooError(Error):def__init__(self,message:str,a:str):super().__init__(message=message)self.a=aclassBarError(Error):def__init__(self,message:str,b:str,c:int):super().__init__(message=message)self.b=bself.c=cIn the simplest case we have to usesupereach time to initialize a new exception. And we also pass an already prepared message.This does not allow us from getting a modified message when the attributes change:>>>a="value">>>error=FooError(f"Error (a='{a}')!",a)>>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.FooError:Error(a='value')!>>>>>>error.a="new_value">>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.FooError:Error(a='value')!xceptException_The idea ofxceptis based on use ofdataclasses:fromdataclassesimportdataclassfromxceptimportException_@dataclassclassError(Exception_):pass@dataclassclassFooError(Error):a:str@dataclassclassBarError(Error):b:strc:intThe first argument is always a message template with replacement fields:>>>error=FooError("Error ({a=})!",a="value")>>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.FooError:Error(a='value')!>>>>>>error.a="new_value">>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.FooError:Error(a='new_value')!Format syntax is presented here:https://docs.python.org/3.7/library/string.html#format-string-syntaxNote:Only keyword replacement fields are supported.Note:Additionally, there is an expression with the=. It allows you to set a value along with a name:>>>error=FooError("{a}",a="a_value")>>>print(error)a_value>>>>>>error=FooError("{a=}",a="a_value")>>>print(error)a='a_value'If a message template does not contain all replacement fields and all replacement fields is required, theMissingFieldWarningoccurs:>>>error=FooError("Error!",a="value")<input>:1:MissingFieldWarning:Nothereplacementfield'a'inthetemplate'Error!'(FooError)!>>>>>>error=BarError("Error ({b=})!",b="value",c="value")<input>:1:MissingFieldWarning:Nothereplacementfield'c'inthetemplate'Error ({b=})!'(BarError)!>>>>>>error=BarError("Error!",b="value",c="value")<input>:1:MissingFieldWarning:Nothereplacementfields'b','c'inthetemplate'Error!'(BarError)!If for some reason you don't need to include all attributes in a message, defineALL_REPLACEMENT_FIELDS_IS_REQUIRED = False(defaultTrue) to disable checks and warnings:>>>@dataclass...classSomeError(Exception_):...ALL_REPLACEMENT_FIELDS_IS_REQUIRED=False...a:str...b:str...>>>error=SomeError("Error ({a=})!",a="a_value",b="b_value")>>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.SomeError:Error(a='a_value')!If a message template contains unknown replacement fields, theUnknownFieldWarningoccurs and the value is set to<UNKNOWN>:>>>error=FooError("Error ({a=}, {b=}, {c=})!",a="a_value")<input>:1:UnknownFieldWarning:Unknownthereplacementfields'b','c'inthetemplate'Error ({a=}, {b=}, {c=})!'(FooError)!>>>raiseerrorTraceback(mostrecentcalllast):File"<input>",line1__main__.FooError:Error(a='a_value',b=<UNKNOWN>,c=<UNKNOWN>)!If there is no a message template and all replacement fields is required, theMissingTemplateWarningoccurs:>>>@dataclass...classSomeError(Exception_):...pass...>>>error=SomeError(None)# Message template is None<input>:1:MissingTemplateWarning:Noatemplate(SomeError)!You can set a default message template:>>>@dataclass...classSomeError(Exception_):...DEFAULT_TEMPLATE="Default message template ({a=})!"...a:str...>>>raiseSomeError(None,a="a_value")# Message template is NoneTraceback(mostrecentcalllast):File"<input>",line1__main__.SomeError:Defaultmessagetemplate(a='a_value')!