Source code for ripozo.viewsets.constructor
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from ripozo.decorators import _apiclassmethod
from ripozo.exceptions import BaseRestEndpointAlreadyExists
import logging
import inspect
import six
logger = logging.getLogger(__name__)
[docs]class ResourceMetaClass(type):
"""
A metaclass that is used for registering ResourceBase
and its subclasses
:param dict registered_resource_classes: A dictionary mapping
the classes instantiated by this meta class to their
base_urls
:param dict registered_names_map: A dictionary mapping the names
of the classes to the actual instances of this meta class
"""
registered_resource_classes = {}
registered_names_map = {}
def __new__(mcs, name, bases, attrs):
"""
The instantiator for the metaclass. This
is responsible for creating the actual class
itself.
:return: The class
:rtype: type
"""
logger.debug('ResourceMetaClass "{0}" class being created'.format(name))
klass = super(ResourceMetaClass, mcs).__new__(mcs, name, bases, attrs)
if attrs.get('__abstract__', False) is True: # Don't register endpoints of abstract classes
logger.debug('ResourceMetaClass "{0}" is abstract. Not being registered'.format(name))
return klass
mcs._register_class(klass)
logger.debug('ResourceMetaClass "{0}" successfully registered'.format(name))
return klass
@classmethod
def _register_class(mcs, klass):
"""
Checks if the class is in the registry
and adds it to the registry if the classes base_url
is not in it. Otherwise it raises a BaseRestEndpointAlreadyExists
exception so as not to offer multiple endpoints for the same base_url
:param klass: The class to register
:raises: BaseRestEndpointAlreadyExists
"""
if klass.base_url in six.itervalues(mcs.registered_resource_classes):
raise BaseRestEndpointAlreadyExists
mcs.registered_resource_classes[klass] = klass.base_url
mcs.registered_names_map[klass.__name__] = klass
# TODO test and doc this
for name, method in inspect.getmembers(klass):
if getattr(method, '__manager_field_validators__', False) is True \
or getattr(method, 'manager_field_validators', False) is True:
if not hasattr(method, 'cls'):
setattr(method, 'cls', klass)
method = classmethod(method)
setattr(klass, name, method)