Beispiel #1
0
class Style:
    @dispatch(
        root=EMPTY,
    )
    def __init__(
        self, *bases, base_template=None, content_block=None, assets=None, root=None, internal=False, **kwargs
    ):
        self.name = None
        self.internal = internal

        self.base_template = base_template
        if not self.base_template:
            for base in reversed(bases):
                if base.base_template:
                    self.base_template = base.base_template
                    break

        self.content_block = content_block
        if not self.content_block:
            for base in reversed(bases):
                if base.content_block:
                    self.content_block = base.content_block
                    break

        if assets:
            from iommi.debug import iommi_debug_on

            if iommi_debug_on():
                print(
                    "Warning: The preferred way to add top level assets config to a Style is via the root argument. "
                    "I.e. assets__* becomes root__assets__*"
                )
            setdefaults_path(root, assets=assets)

        self.root = {k: v for k, v in items(Namespace(*(base.root for base in bases), root)) if v is not None}
        self.config = Namespace(*[x.config for x in bases], recursive_namespace(kwargs))

    def component(self, obj, is_root=False):
        """
        Calculate the namespace of additional argument that should be applied
        to the given object. If is_root is set to True, assets might also be
        added to the namespace.
        """
        result = Namespace()

        # TODO: is this wrong? Should it take classes first, then loop through shortcuts?
        for class_name in class_names_for(type(obj)):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result, shortcuts_config.get(shortcut_name, {}))

        if is_root:
            result = Namespace(result, self.root)

        return result
Beispiel #2
0
class Style:
    @dispatch(
        assets=EMPTY, )
    def __init__(self,
                 *bases,
                 base_template=None,
                 content_block=None,
                 assets=None,
                 **kwargs):
        self.name = None

        self.base_template = base_template
        if not self.base_template:
            for base in reversed(bases):
                if base.base_template:
                    self.base_template = base.base_template
                    break

        self.content_block = content_block
        if not self.content_block:
            for base in reversed(bases):
                if base.content_block:
                    self.content_block = base.content_block
                    break

        self.assets = {
            k: v
            for k, v in Namespace(*(base.assets
                                    for base in bases), assets).items()
            if v is not None
        }
        self.config = Namespace(*[x.config for x in bases],
                                recursive_namespace(kwargs))

    def component(self, obj, is_root=False):
        """
        Calculate the namespace of additional argument that should be applied
        to the given object. If is_root is set to True, assets might also be
        added to the namespace.
        """
        result = Namespace()

        if self.assets and is_root:
            result.assets = self.assets

        # TODO: is this wrong? Should it take classes first, then loop through shortcuts?
        for class_name in class_names_for(type(obj)):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(
                        getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result,
                                       shortcuts_config.get(shortcut_name, {}))
        return result
Beispiel #3
0
    def component(self, obj):
        result = Namespace()
        for class_name in class_names_for(obj.__class__):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(
                        getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result,
                                       shortcuts_config.get(shortcut_name, {}))
        return result
Beispiel #4
0
    def component(self, obj):
        result = Namespace()

        # TODO: is this wrong? Should it take classes first, then loop through shortcuts?
        for class_name in class_names_for(type(obj)):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(
                        getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result,
                                       shortcuts_config.get(shortcut_name, {}))
        return result
Beispiel #5
0
class Style:
    def __init__(self, *bases, **kwargs):
        self.name = None
        self.config = Namespace(*[x.config for x in bases],
                                recursive_namespace(kwargs))

    def component(self, obj):
        result = Namespace()
        for class_name in class_names_for(obj.__class__):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(
                        getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result,
                                       shortcuts_config.get(shortcut_name, {}))
        return result
Beispiel #6
0
def all_column_sorts(request):
    selected_shortcuts = ShortcutSelectorForm().bind(
        request=request).fields.shortcut.value or []

    type_specifics = Namespace(
        choice__choices=['Foo', 'Bar', 'Baz'],
        multi_choice__choices=['Foo', 'Bar', 'Baz'],
    )

    return Page(parts=dict(header=Header('All sorts of columns'),
                           form=ShortcutSelectorForm(),
                           table=Table(
                               columns={
                                   f'column_of_type_{t}': dict(
                                       type_specifics.get(t, {}),
                                       call_target__attribute=t,
                                   )
                                   for t in selected_shortcuts
                               },
                               rows=[DummyRow(i) for i in range(10)],
                           )))
Beispiel #7
0
class Style:
    def __init__(self,
                 *bases,
                 base_template=None,
                 content_block=None,
                 **kwargs):
        self.name = None

        self.base_template = base_template
        if not self.base_template:
            for base in reversed(bases):
                if base.base_template:
                    self.base_template = base.base_template
                    break

        self.content_block = content_block
        if not self.content_block:
            for base in reversed(bases):
                if base.content_block:
                    self.content_block = base.content_block
                    break

        self.config = Namespace(*[x.config for x in bases],
                                recursive_namespace(kwargs))

    def component(self, obj):
        result = Namespace()

        # TODO: is this wrong? Should it take classes first, then loop through shortcuts?
        for class_name in class_names_for(type(obj)):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(
                        getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result,
                                       shortcuts_config.get(shortcut_name, {}))
        return result
Beispiel #8
0
    def component(self, obj, is_root=False):
        """
        Calculate the namespace of additional argument that should be applied
        to the given object. If is_root is set to True, assets might also be
        added to the namespace.
        """
        result = Namespace()

        # TODO: is this wrong? Should it take classes first, then loop through shortcuts?
        for class_name in class_names_for(type(obj)):
            if class_name in self.config:
                config = Namespace(self.config.get(class_name, {}))
                shortcuts_config = Namespace(config.pop('shortcuts', {}))
                result.update(config)

                for shortcut_name in reversed(getattr(obj, '__tri_declarative_shortcut_stack', [])):
                    result = Namespace(result, shortcuts_config.get(shortcut_name, {}))

        if is_root:
            result = Namespace(result, self.root)

        return result
Beispiel #9
0
    def __init__(self,
                 *,
                 model=None,
                 rows=None,
                 filters=None,
                 _filters_dict=None,
                 auto=None,
                 **kwargs):
        assert isinstance(filters, dict)

        if auto:
            auto = QueryAutoConfig(**auto)
            auto_model, auto_rows, filters = self._from_model(
                model=auto.model,
                rows=auto.rows,
                filters=filters,
                include=auto.include,
                exclude=auto.exclude,
            )

            assert model is None, "You can't use the auto feature and explicitly pass model. " \
                                  "Either pass auto__model, or we will set the model for you from auto__rows"
            model = auto_model

            if rows is None:
                rows = auto_rows

        model, rows = model_and_rows(model, rows)

        setdefaults_path(
            kwargs,
            form__call_target=self.get_meta().form_class,
        )

        self.query_advanced_value = None
        self.query_error = None

        # Here we need to remove the freetext config from kwargs because we want to
        # handle it differently from the other fields.
        # BUT It's not safe to modify kwargs deeply! Because reinvoke() is evil:
        # It will call init again with the same kwargs + whatever additional kwargs
        # might have come from a parent or styling info.
        freetext_config = kwargs.get('form', {}).get('fields',
                                                     {}).get('freetext', {})
        if 'form' in kwargs and 'fields' in kwargs[
                'form'] and 'freetext' in kwargs['form']['fields']:
            # copy (just) the namespace so we can safely remove freetext from it
            kwargs = Namespace(flatten(Namespace(kwargs)))
            freetext_config = kwargs.get('form',
                                         {}).get('fields',
                                                 {}).pop('freetext', {})

        super(Query, self).__init__(model=model, rows=rows, **kwargs)

        collect_members(self,
                        name='filters',
                        items=filters,
                        items_dict=_filters_dict,
                        cls=self.get_meta().member_class)

        field_class = self.get_meta().form_class.get_meta().member_class

        declared_fields = Struct()
        declared_fields[FREETEXT_SEARCH_NAME] = field_class(
            _name=FREETEXT_SEARCH_NAME,
            display_name=gettext('Search'),
            required=False,
            include=False,
            help__include=False,
            **freetext_config)

        for name, filter in items(declared_members(self).filters):
            field = setdefaults_path(
                Namespace(),
                filter.field,
                _name=name,
                model_field=filter.model_field,
                attr=name if filter.attr is MISSING else filter.attr,
                call_target__cls=field_class,
                help__include=False,
            )
            declared_fields[name] = field()

        # noinspection PyCallingNonCallable
        self.form: Form = self.form(
            _name='form',
            _fields_dict=declared_fields,
            attrs__method='get',
            actions__submit=dict(
                attrs={'data-iommi-filter-button': ''},
                display_name=gettext('Filter'),
            ),
        )
        declared_members(self).form = self.form

        self.advanced = declared_members(self).advanced = self.advanced(
            _name='advanced')

        self.form_container = self.form_container(_name='form_container')

        # Filters need to be at the end to not steal the short names
        set_declared_member(self, 'filters',
                            declared_members(self).pop('filters'))