Search code examples
pythondjangodjango-logging

Django: Class to log a mail error


I'm trying to follow the code for Django Unleashed and occasionally (by which I mean often) I have problems to understand the code in full. Here is an exaple of a function that is suppose to log errors when a certain mail does not sent. It is part of a login system.

    def log_mail_error(self, **kwargs):
    msg_list = [
        'Activation email did not send.\n',
        'from_email: {from_email}\n'
        'subject: {subject}\n'
        'message: {message}\n',
    ]
    recipient_list = kwargs.get(
        'recipient_list', [])
    for recipient in recipient_list:
        msg_list.insert(
            1, 'recipient: {r}\n'.format(
                r=recipient))
    if 'error' in kwargs:
        level = ERROR
        error_msg = (
            'error: {0.__class__.__name__}\n'
            'args: {0.args}\n')
        error_info = error_msg.format(
            kwargs['error'])
        msg_list.insert(1, error_info)
    else:
        level = CRITICAL
    msg = ''.join(msg_list).format(**kwargs)
    logger.log(level, msg)

I have a very hard time with one part:

error_msg = (
            'error: {0.__class__.__name__}\n'
            'args: {0.args}\n')
        error_info = error_msg.format(
            kwargs['error'])

I simply don't see where this 0.class.name comes from. What is the zero suppose to mean? There is no object or class called zero in the project. Also I dont really understand the formatting of the error_msg. Potentially I have two fields with {} {} where I could fit "kwargs['error']" but I only have one value to fit into two places for string formatting. But then agian, why the pain with {0.__class [...]} if its just meant to be a placeholder? There is something going on that I dont quite understand. Can someone help?


Solution

  • If you read the format mini language spec you'll notice that formatting a string can allow for passing the order of the received parameters. For example

    '{0} and {1}'.format('foo', 'bar') # outputs foo and bar 
    '{1} and {0}'.format('foo', 'bar') # outputs bar and foo 
    

    This simply means that the code is specifying that the parameter used to expand the format expression should be the first one passed

    Since the actual error object is not defined in your code, i can only assume it's of a type that has a args property attached to it. In other words, the string outputs the type of the error and any parameters it was built with