示例#1
0
    def test_reentrant_action_with_deferred_discriminator(self):
        # see https://github.com/Pylons/pyramid/issues/2697
        from pyramid.registry import Deferred

        output = []
        c = self._makeOne()

        def f(*a, **k):
            output.append(('f', a, k))
            c.actions.append((4, g, (4, ), {}, (), None, 2))

        def g(*a, **k):
            output.append(('g', a, k))

        def h(*a, **k):
            output.append(('h', a, k))

        def discrim():
            self.assertEqual(output, [('f', (1, ), {}), ('g', (2, ), {})])
            return 3

        d = Deferred(discrim)
        c.actions = [
            (d, h, (3, ), {}, (), None, 1),  # order 1
            (1, f, (1, )),  # order 0
            (2, g, (2, )),  # order 0
        ]
        c.execute_actions()
        self.assertEqual(
            output,
            [
                ('f', (1, ), {}),
                ('g', (2, ), {}),
                ('h', (3, ), {}),
                ('g', (4, ), {}),
            ],
        )
示例#2
0
文件: views.py 项目: Cykooz/restfw
def _register_resource_view(config: Configurator,
                            view_class: Type[IResourceView],
                            resource_class: Type[IResource],
                            request_type=None,
                            containment=None,
                            name='',
                            **view_options):
    view_class = config.maybe_dotted(view_class)
    resource_class = config.maybe_dotted(resource_class)
    containment = config.maybe_dotted(containment)

    if not view_class:
        raise ConfigurationError('"view_class" was not specified')

    if request_type is not None:
        request_type = config.maybe_dotted(request_type)
        if not IInterface.providedBy(request_type):
            raise ConfigurationError(
                'request_type must be an interface, not %s' % request_type)

    introspectables = []
    ovals = view_options.copy()
    ovals.update(dict(
        containment=containment,
        request_type=request_type,
    ))

    r_resource_class = resource_class
    if r_resource_class is None:
        r_resource_class = Interface
    if not IInterface.providedBy(r_resource_class):
        r_resource_class = implementedBy(r_resource_class)

    def discrim_func():
        # We need to defer the discriminator until we know what the phash
        # is. It can't be computed any sooner because third-party
        # predicates/view derivers may not yet exist when add_view is
        # called.
        predlist = config.get_predlist('view')
        valid_predicates = predlist.names()
        pvals = {}

        for (k, v) in ovals.items():
            if k in valid_predicates:
                pvals[k] = v

        order, preds, phash = predlist.make(config, **pvals)

        view_intr.update({'phash': phash, 'order': order, 'predicates': preds})
        return 'serializer', resource_class, phash

    discriminator = Deferred(discrim_func)

    view_intr = config.introspectable(
        category_name='Resource views',
        discriminator=discriminator,
        title=config.object_description(view_class),
        type_name='resource view',
    )
    view_intr.update(
        dict(
            name=name,
            context=resource_class,
            containment=containment,
            callable=view_class,
        ))
    view_intr.update(view_options)
    introspectables.append(view_intr)

    def register():
        # __discriminator__ is used by super-dynamic systems
        # that require it for introspection after manual view lookup;
        # see also MultiResourceView.__discriminator__
        view_class.__discriminator__ = lambda *arg: discriminator

        # A resource_views is a set of views which are registered for
        # exactly the same resource type/request type/name triad. Each
        # constituent view in a resource_views differs only by the
        # predicates which it possesses.

        # To find a previously registered view for a resource
        # type/request type/name triad, we need to use the
        # ``registered`` method of the adapter registry rather than
        # ``lookup``. ``registered`` ignores interface inheritance
        # for the required and provided arguments, returning only a
        # view registered previously with the *exact* triad we pass
        # in.

        request_iface = IRequest
        registered = config.registry.adapters.registered
        multi_resource_views = registered((request_iface, r_resource_class),
                                          IResourceView, name)

        if not multi_resource_views:
            multi_resource_views = MultiResourceView(name)
            config.registry.registerAdapter(
                multi_resource_views,
                (request_iface, resource_class),
                IResourceView,
                name,
            )

        multi_resource_views.add(
            view_class,
            view_intr['order'],
            view_intr['phash'],
            view_intr['predicates'],
        )

    config.action(discriminator, register, introspectables=introspectables)
示例#3
0
def add_mgmt_view(config,
                  view=None,
                  name="",
                  permission='sdi.view',
                  request_type=None,
                  request_method=None,
                  request_param=None,
                  containment=None,
                  attr=None,
                  renderer=None,
                  wrapper=None,
                  xhr=None,
                  accept=None,
                  header=None,
                  path_info=None,
                  custom_predicates=(),
                  context=None,
                  decorator=None,
                  mapper=None,
                  http_cache=None,
                  match_param=None,
                  tab_title=None,
                  tab_condition=None,
                  tab_before=None,
                  tab_after=None,
                  tab_near=None,
                  **predicates):

    view = config.maybe_dotted(view)
    context = config.maybe_dotted(context)
    containment = config.maybe_dotted(containment)
    mapper = config.maybe_dotted(mapper)
    decorator = config.maybe_dotted(decorator)

    route_name = MANAGE_ROUTE_NAME

    pvals = predicates.copy()
    pvals.update(
        dict(
            xhr=xhr,
            request_method=request_method,
            path_info=path_info,
            request_param=request_param,
            header=header,
            accept=accept,
            containment=containment,
            request_type=request_type,
            match_param=match_param,
            custom=predvalseq(custom_predicates),
        ))

    predlist = config.get_predlist('view')

    def view_discrim_func():
        # We need to defer the discriminator until we know what the phash
        # is.  It can't be computed any sooner because thirdparty
        # predicates may not yet exist when add_view is called.
        order, preds, phash = predlist.make(config, **pvals)
        return ('view', context, name, route_name, phash)

    def sdi_view_discrim_func():
        order, preds, phash = predlist.make(config, **pvals)
        return ('sdi view', context, name, route_name, phash)

    view_discriminator = Deferred(view_discrim_func)
    discriminator = Deferred(sdi_view_discrim_func)

    if inspect.isclass(view) and attr:
        view_desc = 'method %r of %s' % (attr, config.object_description(view))
    else:
        view_desc = config.object_description(view)

    config.add_view(view=view,
                    name=name,
                    permission=permission,
                    route_name=route_name,
                    request_method=request_method,
                    request_param=request_param,
                    containment=containment,
                    attr=attr,
                    renderer=renderer,
                    wrapper=wrapper,
                    xhr=xhr,
                    accept=accept,
                    header=header,
                    path_info=path_info,
                    custom_predicates=custom_predicates,
                    context=context,
                    decorator=decorator,
                    mapper=mapper,
                    http_cache=http_cache,
                    match_param=match_param,
                    request_type=request_type,
                    **predicates)

    intr = config.introspectable('sdi views', discriminator, view_desc,
                                 'sdi view')

    if tab_near is not None:
        if tab_before or tab_after:
            raise ConfigurationError(
                'You cannot use tab_near and tab_before/tab_after together')
        if tab_near == LEFT:
            tab_after = FIRST
            tab_before = CENTER1
        elif tab_near == MIDDLE:
            tab_after = CENTER1
            tab_before = CENTER2
        elif tab_near == RIGHT:
            tab_after = CENTER2
            tab_before = LAST
        else:
            raise ConfigurationError(
                'tab_near value must be one of LEFT, MIDDLE, RIGHT, or None')

    intr['tab_title'] = tab_title
    intr['tab_condition'] = tab_condition
    intr['tab_before'] = tab_before
    intr['tab_after'] = tab_after
    intr['tab_near'] = tab_near

    intr.relate('views', view_discriminator)
    config.action(discriminator, introspectables=(intr, ))
示例#4
0
def add_tile(config,
             view=None,
             name="",
             schema=colander.Schema(),
             permission=None,
             request_type=None,
             request_method=None,
             request_param=None,
             containment=None,
             attr=None,
             renderer=None,
             wrapper=None,
             xhr=None,
             accept=None,
             header=None,
             path_info=None,
             custom_predicates=(),
             context=None,
             decorator=None,
             mapper=None,
             http_cache=None,
             match_param=None,
             tab_title=None,
             tab_condition=None,
             **predicates):

    view = config.maybe_dotted(view)
    context = config.maybe_dotted(context)
    containment = config.maybe_dotted(containment)
    mapper = config.maybe_dotted(mapper)
    decorator = config.maybe_dotted(decorator)

    name = 'tile:' + name
    view = persistent_tile(view)

    pvals = predicates.copy()
    pvals.update(
        dict(
            xhr=xhr,
            request_method=request_method,
            path_info=path_info,
            request_param=request_param,
            header=header,
            accept=accept,
            containment=containment,
            request_type=request_type,
            match_param=match_param,
            custom=predvalseq(custom_predicates),
        ))

    predlist = config.get_predlist('view')

    def view_discrim_func():
        # We need to defer the discriminator until we know what the phash
        # is.  It can't be computed any sooner because thirdparty
        # predicates may not yet exist when add_view is called.
        order, preds, phash = predlist.make(config, **pvals)
        return ('view', context, name, None, phash)

    view_discriminator = Deferred(view_discrim_func)

    if inspect.isclass(view) and attr:
        view_desc = 'method %r of %s' % (attr, config.object_description(view))
    else:
        view_desc = config.object_description(view)

    config.add_view(view=view,
                    name=name,
                    permission=permission,
                    request_method=request_method,
                    request_param=request_param,
                    containment=containment,
                    attr=attr,
                    renderer=renderer,
                    wrapper=wrapper,
                    xhr=xhr,
                    accept=accept,
                    header=header,
                    path_info=path_info,
                    custom_predicates=custom_predicates,
                    context=context,
                    decorator=decorator,
                    mapper=mapper,
                    http_cache=http_cache,
                    match_param=match_param,
                    request_type=request_type,
                    **predicates)

    discriminator = ('tile', name[5:])
    intr = config.introspectable('tiles', discriminator, view_desc, 'tile')
    intr['schema'] = schema
    intr.relate('views', view_discriminator)
    config.action(discriminator, introspectables=(intr, ))
示例#5
0
def add_coroutine_view(config,
                       view=None,
                       name="",
                       for_=None,
                       permission=None,
                       request_type=None,
                       route_name=None,
                       request_method=None,
                       request_param=None,
                       containment=None,
                       attr=None,
                       renderer=None,
                       wrapper=None,
                       xhr=None,
                       accept=None,
                       header=None,
                       path_info=None,
                       custom_predicates=(),
                       context=None,
                       decorator=None,
                       mapper=None,
                       http_cache=None,
                       match_param=None,
                       check_csrf=None,
                       **predicates):
    """ patched version of pyramid add_view that use asyncio coroutine """
    self = config
    if custom_predicates:
        warnings.warn(
            ('The "custom_predicates" argument to Configurator.add_view '
             'is deprecated as of Pyramid 1.5.  Use '
             '"config.add_view_predicate" and use the registered '
             'view predicate as a predicate argument to add_view instead. '
             'See "Adding A Third Party View, Route, or Subscriber '
             'Predicate" in the "Hooks" chapter of the documentation '
             'for more information.'),
            DeprecationWarning,
            stacklevel=4)

    view = self.maybe_dotted(view)
    # transform the view to a coroutine only in case it's really a coroutine
    if not asyncio.iscoroutinefunction(view) and is_generator(view):
        view = asyncio.coroutine(view)

    context = self.maybe_dotted(context)
    for_ = self.maybe_dotted(for_)
    containment = self.maybe_dotted(containment)
    mapper = self.maybe_dotted(mapper)

    def combine(*decorators):
        def decorated(view_callable):
            # reversed() is allows a more natural ordering in the api
            for decorator in reversed(decorators):
                view_callable = decorator(view_callable)
            return view_callable

        return decorated

    if is_nonstr_iter(decorator):
        decorator = combine(*map(self.maybe_dotted, decorator))
    else:
        decorator = self.maybe_dotted(decorator)

    if not view:
        if renderer:

            def view(context, request):
                return {}
        else:
            raise ConfigurationError('"view" was not specified and '
                                     'no "renderer" specified')

    if request_type is not None:
        request_type = self.maybe_dotted(request_type)
        if not IInterface.providedBy(request_type):
            raise ConfigurationError(
                'request_type must be an interface, not %s' % request_type)

    if context is None:
        context = for_

    r_context = context
    if r_context is None:
        r_context = Interface
    if not IInterface.providedBy(r_context):
        r_context = implementedBy(r_context)

    if isinstance(renderer, string_types):
        renderer = renderers.RendererHelper(name=renderer,
                                            package=self.package,
                                            registry=self.registry)

    if accept is not None:
        accept = accept.lower()

    introspectables = []
    pvals = predicates.copy()
    pvals.update(
        dict(
            xhr=xhr,
            request_method=request_method,
            path_info=path_info,
            request_param=request_param,
            header=header,
            accept=accept,
            containment=containment,
            request_type=request_type,
            match_param=match_param,
            check_csrf=check_csrf,
            custom=predvalseq(custom_predicates),
        ))

    def discrim_func():
        # We need to defer the discriminator until we know what the phash
        # is.  It can't be computed any sooner because thirdparty
        # predicates may not yet exist when add_view is called.
        order, preds, phash = predlist.make(self, **pvals)
        view_intr.update({'phash': phash, 'order': order, 'predicates': preds})
        return ('view', context, name, route_name, phash)

    discriminator = Deferred(discrim_func)

    if inspect.isclass(view) and attr:
        view_desc = 'method %r of %s' % (attr, self.object_description(view))
    else:
        view_desc = self.object_description(view)

    tmpl_intr = None

    view_intr = self.introspectable('views', discriminator, view_desc, 'view')
    view_intr.update(
        dict(
            name=name,
            context=context,
            containment=containment,
            request_param=request_param,
            request_methods=request_method,
            route_name=route_name,
            attr=attr,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            match_param=match_param,
            check_csrf=check_csrf,
            callable=view,
            mapper=mapper,
            decorator=decorator,
        ))
    view_intr.update(**predicates)
    introspectables.append(view_intr)
    predlist = self.get_predlist('view')

    def register(permission=permission, renderer=renderer):
        # the discrim_func above is guaranteed to have been called already
        order = view_intr['order']
        preds = view_intr['predicates']
        phash = view_intr['phash']
        request_iface = IRequest
        if route_name is not None:
            request_iface = self.registry.queryUtility(IRouteRequest,
                                                       name=route_name)
            if request_iface is None:
                # route configuration should have already happened in
                # phase 2
                raise ConfigurationError(
                    'No route named %s found for view registration' %
                    route_name)

        if renderer is None:
            # use default renderer if one exists (reg'd in phase 1)
            if self.registry.queryUtility(IRendererFactory) is not None:
                renderer = renderers.RendererHelper(name=None,
                                                    package=self.package,
                                                    registry=self.registry)

        if permission is None:
            # intent: will be None if no default permission is registered
            # (reg'd in phase 1)
            permission = self.registry.queryUtility(IDefaultPermission)

        # added by discrim_func above during conflict resolving
        preds = view_intr['predicates']
        order = view_intr['order']
        phash = view_intr['phash']

        # __no_permission_required__ handled by _secure_view
        deriver = ViewDeriver(
            registry=self.registry,
            permission=permission,
            predicates=preds,
            attr=attr,
            renderer=renderer,
            wrapper_viewname=wrapper,
            viewname=name,
            accept=accept,
            order=order,
            phash=phash,
            package=self.package,
            mapper=mapper,
            decorator=decorator,
            http_cache=http_cache,
        )
        derived_view = deriver(view)
        derived_view.__discriminator__ = lambda *arg: discriminator
        # __discriminator__ is used by superdynamic systems
        # that require it for introspection after manual view lookup;
        # see also MultiView.__discriminator__
        view_intr['derived_callable'] = derived_view

        registered = self.registry.adapters.registered

        # A multiviews is a set of views which are registered for
        # exactly the same context type/request type/name triad.  Each
        # consituent view in a multiview differs only by the
        # predicates which it possesses.

        # To find a previously registered view for a context
        # type/request type/name triad, we need to use the
        # ``registered`` method of the adapter registry rather than
        # ``lookup``.  ``registered`` ignores interface inheritance
        # for the required and provided arguments, returning only a
        # view registered previously with the *exact* triad we pass
        # in.

        # We need to do this three times, because we use three
        # different interfaces as the ``provided`` interface while
        # doing registrations, and ``registered`` performs exact
        # matches on all the arguments it receives.

        old_view = None

        for view_type in (IView, ISecuredView, IMultiView):
            old_view = registered((IViewClassifier, request_iface, r_context),
                                  view_type, name)
            if old_view is not None:
                break

        isexc = isexception(context)

        def regclosure():
            if hasattr(derived_view, '__call_permissive__'):
                view_iface = ISecuredView
            else:
                view_iface = IView
            self.registry.registerAdapter(
                derived_view, (IViewClassifier, request_iface, context),
                view_iface, name)
            if isexc:
                self.registry.registerAdapter(
                    derived_view,
                    (IExceptionViewClassifier, request_iface, context),
                    view_iface, name)

        is_multiview = IMultiView.providedBy(old_view)
        old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)

        if old_view is None:
            # - No component was yet registered for any of our I*View
            #   interfaces exactly; this is the first view for this
            #   triad.
            regclosure()

        elif (not is_multiview) and (old_phash == phash):
            # - A single view component was previously registered with
            #   the same predicate hash as this view; this registration
            #   is therefore an override.
            regclosure()

        else:
            # - A view or multiview was already registered for this
            #   triad, and the new view is not an override.

            # XXX we could try to be more efficient here and register
            # a non-secured view for a multiview if none of the
            # multiview's consituent views have a permission
            # associated with them, but this code is getting pretty
            # rough already
            if is_multiview:
                multiview = old_view
            else:
                multiview = MultiView(name)
                old_accept = getattr(old_view, '__accept__', None)
                old_order = getattr(old_view, '__order__', MAX_ORDER)
                multiview.add(old_view, old_order, old_accept, old_phash)
            multiview.add(derived_view, order, accept, phash)
            for view_type in (IView, ISecuredView):
                # unregister any existing views
                self.registry.adapters.unregister(
                    (IViewClassifier, request_iface, r_context),
                    view_type,
                    name=name)
                if isexc:
                    self.registry.adapters.unregister(
                        (IExceptionViewClassifier, request_iface, r_context),
                        view_type,
                        name=name)
            self.registry.registerAdapter(
                multiview, (IViewClassifier, request_iface, context),
                IMultiView,
                name=name)
            if isexc:
                self.registry.registerAdapter(
                    multiview,
                    (IExceptionViewClassifier, request_iface, context),
                    IMultiView,
                    name=name)
        renderer_type = getattr(renderer, 'type', None)  # gard against None
        intrspc = self.introspector
        if (renderer_type is not None and tmpl_intr is not None
                and intrspc is not None and intrspc.get(
                    'renderer factories', renderer_type) is not None):
            # allow failure of registered template factories to be deferred
            # until view execution, like other bad renderer factories; if
            # we tried to relate this to an existing renderer factory
            # without checking if it the factory actually existed, we'd end
            # up with a KeyError at startup time, which is inconsistent
            # with how other bad renderer registrations behave (they throw
            # a ValueError at view execution time)
            tmpl_intr.relate('renderer factories', renderer.type)

    if mapper:
        mapper_intr = self.introspectable('view mappers', discriminator,
                                          'view mapper for %s' % view_desc,
                                          'view mapper')
        mapper_intr['mapper'] = mapper
        mapper_intr.relate('views', discriminator)
        introspectables.append(mapper_intr)
    if route_name:
        view_intr.relate('routes', route_name)  # see add_route
    if renderer is not None and renderer.name and '.' in renderer.name:
        # the renderer is a template
        tmpl_intr = self.introspectable('templates', discriminator,
                                        renderer.name, 'template')
        tmpl_intr.relate('views', discriminator)
        tmpl_intr['name'] = renderer.name
        tmpl_intr['type'] = renderer.type
        tmpl_intr['renderer'] = renderer
        introspectables.append(tmpl_intr)
    if permission is not None:
        # if a permission exists, register a permission introspectable
        perm_intr = self.introspectable('permissions', permission, permission,
                                        'permission')
        perm_intr['value'] = permission
        perm_intr.relate('views', discriminator)
        introspectables.append(perm_intr)
    self.action(discriminator, register, introspectables=introspectables)