Ejemplo n.º 1
0
def _get_remove_suffixes(name, bases, extras):
    existing_suffixes = deep_getattr({}, bases, REMOVE_SUFFIXES_ATTR, [])
    new_suffixes = [name] + extras
    return (
        [suffix
         for suffix in new_suffixes if suffix not in existing_suffixes] +
        existing_suffixes)
Ejemplo n.º 2
0
    def __new__(mcs, name, bases, clsdict):
        if (ABSTRACT_ATTR in clsdict
                or getattr(clsdict.get('Meta', object), 'abstract', False)):
            return super().__new__(mcs, name, bases, clsdict)

        cls = super().__new__(mcs, name, bases, clsdict)
        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, deep_getattr(clsdict, bases, 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
Ejemplo n.º 3
0
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        set_up_class_dependency_injection(mcs_args)
        if clsdict.get('__abstract__',
                       getattr(clsdict.get('Meta'), 'abstract', False)):
            mcs_args.clsdict[REMOVE_SUFFIXES_ATTR] = _get_remove_suffixes(
                name, bases, CONTROLLER_REMOVE_EXTRA_SUFFIXES)
            mcs_args.clsdict[NOT_VIEWS_ATTR] = _get_not_views(clsdict, bases)

        apply_factory_meta_options(
            mcs_args, default_factory_class=ControllerMetaOptionsFactory)

        cls = super().__new__(*mcs_args)
        if mcs_args.Meta.abstract:
            return cls

        controller_routes = getattr(cls, CONTROLLER_ROUTES_ATTR, {}).copy()
        not_views = deep_getattr({}, bases, NOT_VIEWS_ATTR)

        for method_name, method in clsdict.items():
            if (method_name in not_views
                    or not _is_view_func(method_name, method)):
                controller_routes.pop(method_name, None)
                continue

            controller_routes[method_name] = getattr(method, FN_ROUTES_ATTR,
                                                     [Route(None, method)])

        setattr(cls, CONTROLLER_ROUTES_ATTR, controller_routes)
        return cls
Ejemplo n.º 4
0
def _get_not_views(clsdict, bases):
    not_views = deep_getattr({}, bases, NOT_VIEWS_ATTR, [])
    return ({
        name
        for name, method in clsdict.items() if _is_view_func(name, method)
        and not getattr(method, FN_ROUTES_ATTR, None)
    }.union(not_views))
Ejemplo n.º 5
0
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        set_up_class_dependency_injection(mcs_args)
        if ABSTRACT_ATTR in clsdict:
            return super().__new__(mcs, name, bases, clsdict)

        meta = deep_getattr(clsdict, bases, '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 '
                                 f'Meta model attribute')
        else:
            try:
                meta.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

        clsdict['Meta'] = meta
        return super().__new__(mcs, name, bases, clsdict)
Ejemplo n.º 6
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,
            deep_getattr(mcs_args.clsdict, mcs_args.bases,
                         REMOVE_SUFFIXES_ATTR))
Ejemplo n.º 7
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, deep_getattr(mcs_args.clsdict,
                                                                mcs_args.bases,
                                                                REMOVE_SUFFIXES_ATTR))
        return '/' + pluralize(ctrl_name.replace('_', '-'))
Ejemplo n.º 8
0
    def __new__(mcs, name, bases, clsdict):
        mcs_args = McsArgs(mcs, name, bases, clsdict)
        _set_up_class_dependency_injection(mcs_args)
        process_factory_meta_options(
            mcs_args, default_factory_class=_ServiceMetaOptionsFactory)

        # extended concrete services should not inherit their super's di name
        if deep_getattr({}, bases, '__di_name__', None):
            clsdict['__di_name__'] = None

        return super().__new__(*mcs_args)
Ejemplo n.º 9
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 deep_getattr(mcs_args.clsdict, mcs_args.bases, 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'
Ejemplo n.º 10
0
def test_deep_getattr():
    clsdict = {'a': 'clsdict'}

    class First:
        a = 'first'
        b = 'first'

    class Second:
        b = 'second'
        c = 'second'

    bases = (First, Second)

    assert deep_getattr(clsdict, bases, 'a') == 'clsdict'
    assert deep_getattr(clsdict, bases, 'b') == 'first'
    assert deep_getattr(clsdict, bases, 'c') == 'second'
    with pytest.raises(AttributeError):
        deep_getattr(clsdict, bases, 'd')

    assert deep_getattr(clsdict, bases, 'a', 'default') == 'clsdict'
    assert deep_getattr(clsdict, bases, 'b', 'default') == 'first'
    assert deep_getattr(clsdict, bases, 'c', 'default') == 'second'
    assert deep_getattr(clsdict, bases, 'd', 'default') == 'default'