Exemple #1
0
    def _model_tree_iteration(self, model, visited, context):
        model = IModel(model)
        if model in visited:
            self.log('Skiping already validated model: %r', model)
            return
        visited.append(model)
        yield self._validate_model(model, context)

        if IQueryModel.providedBy(model):
            querymodel = yield model.query_items(offset=0, limit=10)
            items = yield querymodel.fetch_items()
        else:
            try:
                items = yield model.fetch_items()
            except NotSupported:
                self.info('Not iteration further down the model %r because '
                          'it doesnt support fetching items', model)
                return
        for item in items:
            try:
                submodel = yield item.fetch()
            except Unauthorized:
                continue
            if IModel.providedBy(submodel):
                subcontext = context.descend(submodel)
                yield self._model_tree_iteration(submodel, visited, subcontext)
Exemple #2
0
    def _model_tree_iteration(self, model, visited, context):
        model = IModel(model)
        if model in visited:
            self.log('Skiping already validated model: %r', model)
            return
        visited.append(model)
        yield self._validate_model(model, context)

        items = yield model.fetch_items()
        for item in items:
            submodel = yield item.fetch()
            if IModel.providedBy(submodel):
                subcontext = context.descend(submodel)
                yield self._model_tree_iteration(submodel, visited, subcontext)
Exemple #3
0
def write_query_result(doc, obj, *args, **kwargs):
    # This type of object is used as a result of 'select' query of dbmodels api
    result = list()

    if IModel.implementedBy(obj._item_model):
        model_factory = obj._item_model
    else:
        model_factory = model.get_factory(obj._item_model)
    if model_factory is None:
        # use the adapter
        model_factory = IModel

    items = obj.get_items()
    for child in items:
        if obj.query_target == 'view':
            instance = model_factory(obj.source)
            d = instance.initiate(view=child)
        else:
            instance = model_factory(child)
            d = instance.initiate(view=obj.view)
        d.addCallback(applicationjson.render_inline_model, *args, **kwargs)
        result.append(d)
    r = applicationjson.AsyncDict()
    d = defer.DeferredList(result)
    d.addCallback(applicationjson.unpack_deferred_list_result)
    d.addCallback(list)
    r.add('rows', d)

    r.add('total_count', items.total_count)
    r.add('aggregations', items.aggregations)

    d = r.wait()
    d.addCallback(applicationjson.render_json, doc)
    d.addCallback(defer.override_result, None)
    return d
Exemple #4
0
 def _format_attribute_item(self, item, context):
     model = yield safe_fetch(item)
     if not IModel.providedBy(model):
         defer.returnValue("")
     result = yield self._format_attribute(model, context.descend(model),
                                           context, html_links(item))
     defer.returnValue(result)
Exemple #5
0
 def _build_tree(self, tree, model, limit, context):
     if not IModel.providedBy(model):
         return
     items = yield model.fetch_items()
     # [dict of attributes added by this level, list of child rows]
     tree.append([dict(), list()])
     for item in items:
         submodel = yield safe_fetch(item)
         if not submodel:
             continue
         if not IAttribute.providedBy(submodel):
             if limit > 0:
                 if IModel.providedBy(submodel):
                     subcontext = context.descend(submodel)
                     yield self._build_tree(tree[-1][1], submodel,
                                            limit - 1, subcontext)
         else:
             column_name = item.label or item.name
             tree[-1][0][(column_name, limit)] = (item, context)
Exemple #6
0
 def _build_tree(self, tree, model, limit, context):
     if not IModel.providedBy(model):
         return
     items = yield model.fetch_items()
     #FIXME: column ordering do not work
     ordered = self._order_items(model, items)
     # [dict of attributes added by this level, list of child rows]
     tree.append([dict(), list()])
     for item in ordered:
         #FIXME: should not need to fetch model for this
         m = yield item.fetch()
         if not IAttribute.providedBy(m):
             if limit > 0:
                 submodel = yield item.fetch()
                 if IModel.providedBy(submodel):
                     subcontext = context.descend(submodel)
                     yield self._build_tree(tree[-1][1], submodel,
                                            limit - 1, subcontext)
         else:
             column_name = item.label or item.name
             tree[-1][0][(column_name, limit)] = (item, context)
Exemple #7
0
    def _wrap_source(self, source, view, model_factory):
        if source is None:
            return source

        if IReference.providedBy(source):
            return source

        if IModel.providedBy(source):
            return self._init_model(source, view)

        if not IModelFactory.providedBy(model_factory):
            if callable(model_factory):
                ctx = self.model.make_context(key=self.name, view=view)
                d = model_factory(source, ctx)
                d.addCallback(self._got_model_factory, source, view)
                return d

        return self._got_model_factory(model_factory, source, view)
Exemple #8
0
    def _render_items(self, model, markup, context):
        try:
            items = yield model.fetch_items()
            if not items:
                return
        except NotSupported:
            return

        array_deepness = render_array(model)
        if array_deepness:
            markup.div(_class='array')(
                self._render_array(model, array_deepness, context)).close()
        else:
            ordered = self._order_items(model, items)
            ul = markup.ul(_class="items")
            for item in ordered:
                submodel = yield safe_fetch(item)
                li = markup.li()

                if item.reference:
                    url = item.reference.resolve(context)
                    markup.span(_class='name')(
                        html.tags.a(href=url)(item.label or item.name)).close()
                else:
                    markup.span(_class='name')(item.label or item.name).close()

                if IAttribute.providedBy(submodel):
                    li.append(self._format_attribute_item(item, context))
                else:
                    markup.span(_class="value").close()

                if item.desc:
                    markup.span(_class='desc')(item.desc).close()

                array_deepness = render_array(item)

                if submodel and array_deepness:
                    if IModel.providedBy(submodel):
                        array = self._render_array(
                            submodel, array_deepness, context)
                        markup.div(_class='array')(array).close()
                li.close()
            ul.close()
Exemple #9
0
    def _render_items(self, model, markup, context):
        items = yield model.fetch_items()
        if not items:
            return

        array_deepness = render_array(model)
        if array_deepness:
            markup.div(_class='array')(
                self._render_array(model, array_deepness, context)).close()
        else:
            ordered = self._order_items(model, items)
            ul = markup.ul(_class="items")
            for item in ordered:
                li = markup.li()

                url = item.reference.resolve(context)
                markup.span(_class='name')(
                    html.tags.a(href=url)(item.label or item.name)).close()

                #FIXME: shouldn't need to fetch the model for that
                m = yield item.fetch()
                if IAttribute.providedBy(m):
                    li.append(self._format_attribute_item(item, context))
                else:
                    markup.span(_class="value").close()

                if item.desc:
                    markup.span(_class='desc')(item.desc).close()

                array_deepness = render_array(item)
                if array_deepness:
                        submodel = yield item.fetch()
                        if IModel.providedBy(submodel):
                            array = self._render_array(submodel,
                                                       array_deepness,
                                                       context)
                            markup.div(_class='array')(array).close()
                li.close()
            ul.close()
        markup.hr()
Exemple #10
0
 def __init__(self, model, name=None, models=[], names=[]):
     self.model = IModel(model)
     self._model_history = list(models) + [self.model]
     self._name_history = list(names) + [name]
     self._methods = set([]) # set([http.Methods])
Exemple #11
0
class ModelResource(BaseResource):

    __slots__ = ("model", "_methods", "_model_history", "_name_history")

    implements(webserver.IWebResource)

    action_methods = {u"set": http.Methods.PUT,
                      u"del": http.Methods.DELETE,
                      u"post": http.Methods.POST}
    method_actions = {http.Methods.DELETE: u"del",
                      http.Methods.PUT: u"set",
                      http.Methods.POST: u"post"}

    def __init__(self, model, name=None, models=[], names=[]):
        self.model = IModel(model)
        self._model_history = list(models) + [self.model]
        self._name_history = list(names) + [name]
        self._methods = set([]) # set([http.Methods])

    def __repr__(self):
        return "<%s %s '%s'>" % (type(self).__name__,
                                 self.model.identity,
                                 self.model.name)

    def __str__(self):
        return repr(self)

    def initiate(self):
        """
        Initiate the resource retrieving all the asynchronous
        information needed to support the IWebResource interface.
        """

        def deduce_methods(actions):
            self._methods.add(http.Methods.GET)
            for action in actions:
                method = self.action_methods.get(action.name)
                if method is not None:
                    self._methods.add(method)

        d = self.model.fetch_actions()
        d.addCallback(deduce_methods)
        d.addCallback(defer.override_result, self)
        return d

    def make_context(self, request, remaining=None):
        return Context(scheme=request.scheme,
                       models=self._model_history,
                       names=self._name_history,
                       remaining=remaining,
                       arguments=request.arguments)

    ### webserver.IWebResource ###

    def is_method_allowed(self, request, location, method):
        return method in self._methods

    def get_allowed_methods(self, request, location):
        return list(self._methods)

    def locate_resource(self, request, location, remaining):

        def locate_model(model_name):
            d = defer.succeed(self.model)
            d.addCallback(retrieve_model, model_name)
            d.addCallback(check_model)
            d.addCallback(wrap_model)
            return d

        def locate_action(action_name):
            d = defer.succeed(self.model)
            d.addCallback(retrieve_action, action_name)
            d.addCallback(wrap_action)
            return d

        def locate_default_action(model_name, action_name):
            d = defer.succeed(self.model)
            d.addCallback(retrieve_model, model_name)
            d.addCallback(check_model)
            d.addCallback(retrieve_action, action_name)
            d.addCallback(wrap_action, fallback=True)
            return d

        def retrieve_model(model, model_name):
            d = model.fetch_item(model_name)
            d.addCallback(got_model_item)
            return d

        def got_model_item(item):
            if item is None:
                raise http.NotFoundError()

            rem = remaining[1:]
            if rem and rem != (u"", ):
                return item.browse()

            return item.fetch()

        def check_model(model):
            if model is None:
                raise http.NotFoundError()

            if IReference.providedBy(model):
                return process_reference(model)

            if model.reference is not None:
                return process_reference(model.reference)

            return model

        def process_reference(reference):
            reference = IReference(reference)
            context = self.make_context(request, remaining[1:])
            address = reference.resolve(context)
            raise http.MovedPermanently(location=address)

        def wrap_model(model):
            if model is None:
                raise http.NotFoundError()

            res = ModelResource(model, model.name,
                                self._model_history, self._name_history)
            return res.initiate(), remaining[1:]

        def retrieve_action(model, action_name):
            d = model.fetch_action(action_name)
            d.addCallback(lambda a: (model, a))
            return d

        def wrap_action(model_action, fallback=False):
            model, action = model_action
            if action is None:
                if fallback:
                    return wrap_model(model)
                raise http.NotFoundError()

            context = self.make_context(request)
            return ActionResource(action, context)

        if not remaining or (remaining == (u'', )):
            if self.model.reference is not None:
                return process_reference(self.model.reference)
            return self

        resource_name = remaining[0]

        if len(remaining) == 1:
            if resource_name.startswith('_'):
                return locate_action(resource_name[1:])
            action_name = self.method_actions.get(request.method)
            return locate_default_action(resource_name, action_name)

        return locate_model(resource_name)

    def action_GET(self, request, response, location):
        response.set_header("Cache-Control", "no-cache")
        response.set_header("connection", "close")
        context = self.make_context(request)
        if location[-1] == u"":
            return self.render_action("get", request, response, context)
        return self.render_model(request, response, context)

    def render_action(self, action_name, request, response, context):

        def got_data(data):
            #FIXME: passing query arguments without validation is not safe
            return response.write_object(data, context=context,
                                         **request.arguments)

        def got_action(action):
            if action is None:
                return self.render_model(request, response, context)

            request.log("Performing action %r on %s model %r",
                        action_name, self.model.identity, self.model.name)
            d = action.perform()
            d.addCallback(got_data)
            return d

        d = self.model.fetch_action(action_name)
        d.addCallback(got_action)
        return d

    def render_model(self, request, response, context):
        #FIXME: passing query arguments without validation is not safe
        return response.write_object(self.model, context=context,
                                     **request.arguments)