from __future__ import unicode_literals from importlib import import_module import logging from django.apps import apps from django.utils import six from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ logger = logging.getLogger(__name__) __all__ = ('MailerBackend',) class MailerBackendMetaclass(type): _registry = {} def __new__(mcs, name, bases, attrs): new_class = super(MailerBackendMetaclass, mcs).__new__( mcs, name, bases, attrs ) if not new_class.__module__ == 'mayan.apps.mailer.classes': mcs._registry[ '{}.{}'.format(new_class.__module__, name) ] = new_class return new_class class MailerBackendBase(object): """ Base class for the mailing backends. This class is mainly a wrapper for other Django backends that adds a few metadata to specify the fields it needs to be instanciated at runtime. The fields attribute is a list of dictionaries with the format: { 'name': '' # Field internal name 'label': '' # Label to show to users 'class': '' # Field class to use. Field classes are Python dot paths to Django's form fields. 'initial': '' # Field initial value 'default': '' # Default value. } """ class_path = '' # Dot path to the actual class that will handle the mail fields = {} @classmethod def get_class_fields(cls): backend_field_list = getattr(cls, 'fields', {}).keys() return getattr(cls, 'class_fields', backend_field_list) class MailerBackend(six.with_metaclass(MailerBackendMetaclass, MailerBackendBase)): @classmethod def get(cls, name): return cls._registry[name] @classmethod def get_all(cls): return cls._registry @staticmethod def initialize(): for app in apps.get_app_configs(): try: import_module('{}.mailers'.format(app.name)) except ImportError as exception: if force_text(exception) not in ('No module named mailers', 'No module named \'{}.mailers\''.format(app.name)): logger.error( 'Error importing %s mailers.py file; %s', app.name, exception ) class NullBackend(MailerBackend): label = _('Null backend')