def new(identity, value_info, getter=None, setter=None, meta=None): cls_name = utils.mk_class_name(identity, "Attribute") cls = MetaAttribute(cls_name, (_DynAttribute, ), {"__slots__": ()}) cls.annotate_identity(identity) cls.annotate_value(value_info) cls.apply_class_meta(meta) if getter is not None: Action = action.MetaAction.new("get." + identity, ActionCategories.retrieve, effects=[getter], result_info=value_info, is_idempotent=True) cls.annotate_action(u"get", Action) if setter is not None: def _set_attribute(value, context): d = setter(value, context) # attribute setter return the validate value d.addCallback(defer.override_result, value) return d Action = action.MetaAction.new("set." + identity, ActionCategories.update, effects=[_set_attribute], value_info=value_info, result_info=value_info, is_idempotent=True) cls.annotate_action(u"set", Action) return cls
def new(name, factory, label=None, desc=None): cls_name = utils.mk_class_name(name, "Action") return MetaActionItem(cls_name, (ActionItem, ), {"__slots__": (), "_name": _validate_str(name), "_factory": _validate_action_factory(factory), "_label": _validate_optstr(label), "_desc": _validate_optstr(desc)})
def new(identity, child_names=None, child_source=None, child_view=None, child_model=None, child_label=None, child_desc=None, child_meta=None, meta=None): cls_name = utils.mk_class_name(identity) cls = MetaCollection(cls_name, (_DynCollection, ), {"__slots__": ()}) cls.annotate_identity(identity) cls.annotate_child_label(child_label) cls.annotate_child_desc(child_desc) cls.annotate_child_model(child_model) if child_meta: for meta_item in child_meta: cls.annotate_child_meta(*meta_item) cls.annotate_child_names(child_names) cls.annotate_child_source(child_source) cls.annotate_child_view(child_view) cls.apply_class_meta(meta) return cls
def new(name, source=None, view=None, model=None, enabled=None, browse=None, fetch=None, label=None, desc=None, meta=None): cls_name = utils.mk_class_name(name, "ModelItem") name = _validate_str(name) ref = models_reference.Relative(name) enabled = True if enabled is None else enabled cls = MetaModelItem(cls_name, (ModelItem, ), {"__slots__": (), "_name": name, "_reference": ref, "_source": _validate_effect(source), "_fetch": _validate_effect(fetch), "_browse": _validate_effect(browse), "_factory": _validate_model_factory(model), "_view": _validate_effect(view), "_enabled": _validate_effect(enabled), "_label": _validate_optstr(label), "_desc": _validate_optstr(desc)}) cls.apply_class_meta(meta) return cls
def new(name, category, effects=None, params=None, value_info=None, result_info=None, is_idempotent=True, enabled=True): cls_name = utils.mk_class_name(name, "Action") cls = MetaAction(cls_name, (Action, ), {"__slots__": ()}) cls.annotate_category(category) if value_info is not None: cls.annotate_value(value_info) if result_info is not None: cls.annotate_result(result_info) cls.annotate_is_idempotent(is_idempotent) cls.annotate_enabled(enabled) if params: if isinstance(params, Param): params = [params] for p in params: cls.annotate_param_instance(p) if effects: for e in effects: cls.annotate_effect(e) return cls
def __init__(cls, name, bases, dct): cls._query_target = None cls._query_model = None cls._connection_getter = None cls._static_conditions = None cls._factory = None cls._fetch_documents_set = False cls._fetch_documents = staticmethod(effect.identity) cls._item_field = None # this processes all the annotations super(QueryViewMeta, cls).__init__(name, bases, dct) if cls._factory is None: # The class is not annotated with view_factory() annotations # This is only valid in the base class, althought no actions # should be created. return # validate that the required annotations have been called if cls._query_target is None: raise ValueError("This model needs to be annotated with " "query_target(source|view)") if not callable(cls._connection_getter): raise ValueError("This model needs to be annotated with " "db_connection(effect) annotation") # define the Select and Count actions name = utils.mk_class_name(cls._factory.name, "Query") QueryValue = MetaQueryValue.new(name, cls._factory, cls._allowed_fields, cls._include_value) result_info = value.Model() name = utils.mk_class_name(cls._factory.name, "IncludeValue") IncludeValue = value.MetaCollection.new( name, [value.FixedValues(cls._allowed_fields)]) name = utils.mk_class_name(cls._factory.name, "AggregateValue") AggregateValue = value.MetaCollection.new( name, [value.FixedValues(cls._model_aggregations.keys())]) build_query = parse_incoming_query(cls._factory, cls._static_conditions, cls._include_value, cls._model_aggregations) def render_select_response(value, context, *args, **kwargs): cls = type(context['model']) if not cls._query_set_factory: # query set collection is created only once per class type factory = MetaQueryResult.new(cls) factory.annotate_meta('json', 'render-as-list') cls._query_set_factory = factory if cls._fetch_documents_set: context['result'].update(value) # convert all the aggregate values using their IValueInfo if kwargs.get('aggregate'): raw_values = context['result'].aggregations context['result'].aggregations = dict() for index, name in enumerate(kwargs['aggregate']): value_info = cls._model_aggregations[name][0] v = raw_values[index] try: published = value_info.publish(v) except Exception as e: error.handle_exception( None, e, "Failed publishing the result %r", v) else: context['result'].aggregations[name] = published result = cls._query_set_factory(context['source'], context['result']) return result.initiate(view=context['view'], officer=context.get('officer'), aspect=context.get('aspect')) def store_select_result(value, context, *args, **kwargs): context['result'], context['responses'] = value return value[0] def do_include_value(value, context, *args, **kwargs): # If there was a custom routing for fetching items defined, # we need to call the include_value() explicitely. If # query.select() was used, there is no need for that. cls = context['model'] if context['query'].include_value and cls._fetch_documents_set: return query.include_values(value, context['responses'], context['query']) else: return value SelectAction = action.MetaAction.new( utils.mk_class_name(cls._factory.name, "Select"), ActionCategories.retrieve, is_idempotent=False, result_info=result_info, effects=( build_query, call.model_perform('do_select'), store_select_result, cls._fetch_documents, do_include_value, render_select_response, ), params=[action.Param('query', QueryValue()), action.Param('include_value', IncludeValue(), is_required=False), action.Param('sorting', SortField(cls._allowed_fields), is_required=False), action.Param('skip', value.Integer(0), is_required=False), action.Param('limit', value.Integer(), is_required=False), action.Param('aggregate', AggregateValue(), is_required=False), ]) cls.annotate_action(u"select", SelectAction) # define count action CountAction = action.MetaAction.new( utils.mk_class_name(cls._factory.name, "Count"), ActionCategories.retrieve, effects=[ build_query, call.model_perform('do_count')], result_info=value.Integer(), is_idempotent=False, params=[action.Param('query', QueryValue())]) cls.annotate_action(u"count", CountAction) # define values action (fetch the values for the range) ValuesAction = action.MetaAction.new( utils.mk_class_name(cls._factory.name, "Values"), ActionCategories.retrieve, effects=[ build_query, call.model_perform('fetch_values')], # FIXME: the result is a dictionary of name -> [values], # consider creating the IValidator for this structure result_info=value.Value(), is_idempotent=False, params=[action.Param('query', QueryValue()), action.Param('fields', IncludeValue())]) cls.annotate_action(u"values", ValuesAction) # define how to fetch items if cls._item_field: def fetch_names(value, context): model = context['model'] d = build_query(None, context, query=cls._factory()) d.addCallback(defer.inject_param, 1, query.values, model.connection, cls._item_field) return d cls.annotate_child_names(fetch_names) def fetch_matching(value, context): c = query.Condition( cls._item_field, query.Evaluator.equals, context['key']) q = cls._factory(c) d = build_query(None, context, query=q) d.addCallback(context['model'].do_select, skip=0) # the result on this points (rows, responses) d.addCallback(lambda (r, _): r) d.addCallback(cls._fetch_documents, context) def unpack(result): if result: return result[0] d.addCallback(unpack) return d def fetch_source(value, context): if cls._query_target == 'source': return fetch_matching(value, context) else: return context['model'].source cls.annotate_child_source(fetch_source) def fetch_view(value, context): if cls._query_target == 'view': return fetch_matching(value, context) else: return context['view'] cls.annotate_child_view(fetch_view)
def annotate_view_factory(cls, factory, allowed_fields=[], static_conditions=None, fetch_documents=None): cls._view = IQueryViewFactory(factory) cls._static_conditions = (static_conditions and model._validate_effect(static_conditions)) if not fetch_documents: cls._fetch_documents_set = False fetch_documents = effect.identity else: cls._fetch_documents_set = True fetch_documents = fetch_documents for x in allowed_fields: if not cls._view.has_field(x): raise ValueError("%r doesn't define a field: '%s'" % (cls, x)) cls._allowed_fields = allowed_fields # define query action name = utils.mk_class_name(cls._view.name, "Query") QueryValue = MetaQueryValue.new(name, cls._view, cls._allowed_fields) name = utils.mk_class_name(cls._view.name, "Sorting") SortingValue = MetaSortingValue.new(name, cls._allowed_fields) result_info = value.Model() def get_static_conditions(value, context, *args, **kwargs): def build_query(static_conditions, factory, q): subquery = query.Query(factory, *static_conditions) return query.Query(factory, q, query.Operator.AND, subquery) cls = type(context['model']) if cls._static_conditions: d = cls._static_conditions(None, context) d.addCallback(build_query, cls._view, kwargs['query']) return d return defer.succeed(kwargs['query']) SelectAction = action.MetaAction.new( utils.mk_class_name(cls._view.name, "Select"), ActionCategories.retrieve, is_idempotent=False, result_info=result_info, effects=[ get_static_conditions, call.model_perform('do_select'), fetch_documents, call.model_filter('render_select_response')], params=[action.Param('query', QueryValue()), action.Param('sorting', SortingValue(), is_required=False), action.Param('skip', value.Integer(0), is_required=False), action.Param('limit', value.Integer(), is_required=False)]) cls.annotate_action(u"select", SelectAction) # define count action CountAction = action.MetaAction.new( utils.mk_class_name(cls._view.name, "Count"), ActionCategories.retrieve, effects=[ get_static_conditions, call.model_perform('do_count')], result_info=value.Integer(), is_idempotent=False, params=[action.Param('query', QueryValue())]) cls.annotate_action(u"count", CountAction)