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
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
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
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
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
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)], )))
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
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
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'))