Example #1
0
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        if mcs_args.is_abstract:
            return super().__new__(*mcs_args)

        cls = super().__new__(*mcs_args)
        routes = {}
        include_methods = set(cls.Meta.include_methods)
        exclude_methods = set(cls.Meta.exclude_methods)
        for method_name in ALL_METHODS:
            if (method_name in exclude_methods
                    or method_name not in include_methods):
                continue

            route = getattr(clsdict.get(method_name), FN_ROUTES_ATTR, [None])[0]
            if not route:
                route = Route(None, mcs_args.getattr(method_name))

            if method_name in INDEX_METHODS:
                rule = '/'
            else:
                rule = cls.Meta.member_param
            route.rule = rule
            routes[method_name] = [route]

        setattr(cls, CONTROLLER_ROUTES_ATTR, routes)
        return cls
Example #2
0
    def get_value(self, meta, base_classes_meta, mcs_args: McsArgs):
        value = super().get_value(meta, base_classes_meta, mcs_args)
        if value is not _missing:
            return value

        return controller_name(mcs_args.name,
                               mcs_args.getattr(REMOVE_SUFFIXES_ATTR))
Example #3
0
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        _set_up_class_dependency_injection(mcs_args)
        if mcs_args.is_abstract:
            return super().__new__(*mcs_args)

        meta = mcs_args.getattr('Meta', None)
        model_missing = False
        try:
            if meta.model is None:
                model_missing = True
        except AttributeError:
            model_missing = True

        if model_missing:
            raise AttributeError(f'{name} is missing the ``class Meta`` model attribute')

        model = None
        try:
            model = unchained.sqlalchemy_bundle.models[meta.model.__name__]
        except AttributeError:
            # this happens when attempting to generate documentation and the
            # sqlalchemy bundle hasn't been loaded
            pass
        except KeyError:
            pass

        meta_dict = dict(meta.__dict__)
        meta_dict.pop('model', None)
        clsdict['Meta'] = type('Meta', (_ModelSerializerMeta,), meta_dict)
        clsdict['Meta'].model = model

        return super().__new__(*mcs_args)
Example #4
0
    def get_value(self, meta, base_classes_meta, mcs_args: McsArgs):
        value = super().get_value(meta, base_classes_meta, mcs_args)
        if value is not _missing:
            return value

        ctrl_name = controller_name(mcs_args.name,
                                    mcs_args.getattr(REMOVE_SUFFIXES_ATTR))
        return '/' + pluralize(ctrl_name.replace('_', '-'))
Example #5
0
    def check_value(self, value, mcs_args: McsArgs):
        if not value:
            return

        if isinstance(value, (list, tuple)):
            assert all(callable(x) for x in value), \
                f'The {self.name} meta option requires a list or tuple of callables'
        else:
            for method_name, decorators in value.items():
                assert mcs_args.getattr(method_name), \
                    f'The {method_name} was not found on {mcs_args.name}'
                assert all(callable(x) for x in decorators), \
                    f'Invalid decorator detected in the {self.name} meta option for ' \
                    f'the {method_name} key'
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        _set_up_class_dependency_injection(mcs_args)
        if mcs_args.is_abstract:
            return super().__new__(*mcs_args)

        meta = mcs_args.getattr('Meta', None)
        model_missing = False
        try:
            if meta.model is None:
                model_missing = True
        except AttributeError:
            model_missing = True

        if model_missing:
            raise AttributeError(
                f'{name} is missing the ``class Meta`` model attribute')

        model = meta.model
        try:
            model = unchained.sqlalchemy_bundle.models[meta.model.__name__]
        except AttributeError as e:
            # this happens when attempting to generate documentation and the
            # sqlalchemy bundle hasn't been loaded
            safe_error = "'DeferredBundleFunctions' object has no attribute 'models'"
            if safe_error not in str(e):
                raise e
        except KeyError:
            pass

        meta_dict = dict(meta.__dict__)

        additional_fields = meta_dict.pop('additional', None)
        if additional_fields:
            fields = [
                name for name, field in clsdict.items()
                if isinstance(field, Field)
            ]
            meta_dict['fields'] = fields + list(additional_fields)

        meta_dict.pop('model', None)
        clsdict['Meta'] = type('Meta', (_ModelSerializerMeta, ), meta_dict)
        clsdict['Meta'].model = model

        return super().__new__(*mcs_args)
Example #7
0
def _set_up_class_dependency_injection(mcs_args: McsArgs):
    mcs_args.clsdict[_DI_AUTOMATICALLY_HANDLED] = True

    cls_attrs_to_inject = [
        k for k, v in mcs_args.clsdict.items() if v == injectable
    ]
    try:
        mcs_args.clsdict[_INJECT_CLS_ATTRS] = \
            cls_attrs_to_inject + mcs_args.getattr(_INJECT_CLS_ATTRS, [])
    except TypeError as e:
        if 'can only concatenate list (not "OptionalMetaclass") to list' not in str(
                e):
            raise e
        mcs_args.clsdict[_INJECT_CLS_ATTRS] = cls_attrs_to_inject

    if '__init__' not in mcs_args.clsdict and cls_attrs_to_inject:
        init = _inject_cls_attrs(
            _call_super_for_cls=f'{mcs_args.module}:{mcs_args.name}')
        init.__di_name__ = mcs_args.name
        init.__signature__ = inspect.signature(object)
        mcs_args.clsdict['__init__'] = init
        mcs_args.clsdict['__signature__'] = init.__signature__
    elif '__init__' in mcs_args.clsdict:
        from .unchained import unchained
        init = unchained.inject()(mcs_args.clsdict['__init__'])
        init.__di_name__ = mcs_args.name
        mcs_args.clsdict['__init__'] = (init if not cls_attrs_to_inject else
                                        _inject_cls_attrs(_wrapped_fn=init))
        mcs_args.clsdict['__signature__'] = init.__signature__

    for attr, value in mcs_args.clsdict.items():
        if isinstance(value, FunctionType):
            if not attr.startswith('__') and not hasattr(
                    value, '__signature__'):
                from .unchained import unchained
                mcs_args.clsdict[attr] = unchained.inject()(value)
            value.__di_name__ = (mcs_args.name if value.__name__ == '__init__'
                                 else f'{mcs_args.name}.{value.__name__}')