Example #1
0
    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
Example #2
0
File: model.py Project: sylane/feat
 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)})
Example #3
0
File: model.py Project: sylane/feat
 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
Example #4
0
File: model.py Project: sylane/feat
 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
Example #5
0
    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
Example #6
0
File: models.py Project: f3at/feat
    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)
Example #7
0
    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)