7.7. Exception Define

7.7.1. Define Custom Exceptions

  • Class which inherits from Exception

  • Exceptions should have Error at the end of their names

>>> class MyError(Exception):
...     pass
>>>
>>>
>>> raise MyError
Traceback (most recent call last):
MyError
>>>
>>> raise MyError('More verbose description')
Traceback (most recent call last):
MyError: More verbose description

7.7.2. Example

>>> class AstronautsOnlyError(Exception):
...     pass
>>>
>>>
>>> profession = 'pilot'
>>>
>>> if profession != 'astronaut':
...     raise AstronautsOnlyError
Traceback (most recent call last):
AstronautsOnlyError

7.7.3. Use Case - 0x01

Django Framework Use-case of Custom Exceptions:

>>> 
... from django.contrib.auth.models import User
>>>
>>>
>>> def login(request):
...     username = request.POST.get('username')
...     password = request.POST.get('password')
...
...     try:
...         user = User.objects.get(username, password)
...     except User.DoesNotExist:
...         print('Sorry, no such user in database')

7.7.4. Use Case - 0x02

  • Dragon

>>> class Dragon:
...     def take_damage(self, damage):
...         raise self.IsDead
...
...     class IsDead(Exception):
...         pass
>>>
>>>
>>> wawelski = Dragon()
>>>
>>> try:
...     wawelski.take_damage(10)
... except Dragon.IsDead:
...     print('Dragon is dead')
Dragon is dead

7.7.5. Use Case - 0x03

>>> from datetime import datetime
>>> from uuid import uuid1
>>> import logging
>>>
>>>
>>> logging.basicConfig(
...     level='WARNING',
...     datefmt='%Y-%m-%d %H:%M:%S',
...     format='[{levelname}] {message}',
...     style='{'
... )
>>>
>>>
>>> class MyError(Exception):
...     def __init__(self, *args, **kwargs):
...         self.name = self.__class__.__name__
...         self.reason = self.args[0]
...
...         # make a UUID based on the host ID and current time
...         self.uuid = str(uuid1())
...
...         # save when exception occurred
...         self.when = datetime.now()
...
...         # run normal processing of the exception
...         super().__init__(*args, **kwargs)
>>>
>>>
>>> def run():
...     raise MyError('Error, because it is not working')
>>>
>>>
>>> try:
...     run()
... except Exception as error:
...     name = self.name
...     reason = self.reason
...     when = error.when.strftime('%Y-%m-%d %H:%M:%S')
...     identifier = error.uuid
...
...     # you can write this error to the database
...     # or print it on the stderr
...     logging.error(f'Error happened: {name=}, {reason=}, {when=}, {identifier=}')  
[ERROR] Error happened: name='MyError', reason='Error, because it is not working', when='1969-07-21 02:56:15', identifier='886a59c4-8431-11ec-95bc-acde48001122'

7.7.6. Assignments

Code 7.8. Solution
"""
* Assignment: Exception Custom Exception
* Required: no
* Complexity: easy
* Lines of code: 4 lines
* Time: 5 min

English:
    1. Define custom exception `NegativeKelvinError`
    2. Check value passed to a `result` function
    3. If value is lower than 0, raise `NegativeKelvinError`
    4. Non-functional requirements:
        a. Write solution inside `result` function
        b. Mind the indentation level
    5. Run doctests - all must succeed

Polish:
    1. Zdefiniuj własny wyjątek `NegativeKelvinError`
    2. Sprawdź wartośc przekazaną do funckji jako `float`
    3. Jeżeli wartość jest mniejsza niż 0, podnieś `NegativeKelvinError`
    4. Wymagania niefunkcjonalne:
        a. Rozwiązanie zapisz wewnątrz funkcji `result`
        b. Zwróć uwagę na poziom wcięć
    5. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `class`
    * `pass`
    * `raise`
    * `if`

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> isclass(NegativeKelvinError)
    True
    >>> issubclass(NegativeKelvinError, Exception)
    True
    >>> result(1)
    >>> result(0)
    >>> result(-1)
    Traceback (most recent call last):
    exception_custom_a.NegativeKelvinError
"""


def result(value):
    ...