Example #1
0
    def register():
        log.info('===>>> Mapping {} to resource {}'.format(entity, resource))
        registry.cms_entity_resources[entity] = resource

        if add_url_adapter:
            config.add_resource_url_adapter(
                lambda resource2, request:
                ResourceURL(resource(request, resource2), request),
                entity)
Example #2
0
    def resource_url(self, resource, *elements, **kw):
        """

        Generate a string representing the absolute URL of the
        :term:`resource` object based on the ``wsgi.url_scheme``,
        ``HTTP_HOST`` or ``SERVER_NAME`` in the request, plus any
        ``SCRIPT_NAME``.  The overall result of this method is always a
        UTF-8 encoded string.

        Examples::

            request.resource_url(resource) =>

                                       http://example.com/

            request.resource_url(resource, 'a.html') =>

                                       http://example.com/a.html

            request.resource_url(resource, 'a.html', query={'q':'1'}) =>

                                       http://example.com/a.html?q=1

            request.resource_url(resource, 'a.html', anchor='abc') =>

                                       http://example.com/a.html#abc

            request.resource_url(resource, app_url='') =>

                                       /

        Any positional arguments passed in as ``elements`` must be strings
        Unicode objects, or integer objects.  These will be joined by slashes
        and appended to the generated resource URL.  Each of the elements
        passed in is URL-quoted before being appended; if any element is
        Unicode, it will converted to a UTF-8 bytestring before being
        URL-quoted. If any element is an integer, it will be converted to its
        string representation before being URL-quoted.

        .. warning:: if no ``elements`` arguments are specified, the resource
                     URL will end with a trailing slash.  If any
                     ``elements`` are used, the generated URL will *not*
                     end in a trailing slash.

        If a keyword argument ``query`` is present, it will be used to compose
        a query string that will be tacked on to the end of the URL.  The value
        of ``query`` may be a sequence of two-tuples *or* a data structure with
        an ``.items()`` method that returns a sequence of two-tuples
        (presumably a dictionary).  This data structure will be turned into a
        query string per the documentation of :func:``pyramid.url.urlencode``
        function.  This will produce a query string in the
        ``x-www-form-urlencoded`` encoding.  A non-``x-www-form-urlencoded``
        query string may be used by passing a *string* value as ``query`` in
        which case it will be URL-quoted (e.g. query="foo bar" will become
        "foo%20bar").  However, the result will not need to be in ``k=v`` form
        as required by ``x-www-form-urlencoded``.  After the query data is
        turned into a query string, a leading ``?`` is prepended, and the
        resulting string is appended to the generated URL.

        .. note::

           Python data structures that are passed as ``query`` which are
           sequences or dictionaries are turned into a string under the same
           rules as when run through :func:`urllib.urlencode` with the ``doseq``
           argument equal to ``True``.  This means that sequences can be passed
           as values, and a k=v pair will be placed into the query string for
           each value.

        .. versionchanged:: 1.5
           Allow the ``query`` option to be a string to enable alternative
           encodings.

        If a keyword argument ``anchor`` is present, its string
        representation will be used as a named anchor in the generated URL
        (e.g. if ``anchor`` is passed as ``foo`` and the resource URL is
        ``http://example.com/resource/url``, the resulting generated URL will
        be ``http://example.com/resource/url#foo``).

        .. note::

           If ``anchor`` is passed as a string, it should be UTF-8 encoded. If
           ``anchor`` is passed as a Unicode object, it will be converted to
           UTF-8 before being appended to the URL.

        .. versionchanged:: 1.5
           The ``anchor`` option will be escaped instead of using
           its raw string representation.

        If both ``anchor`` and ``query`` are specified, the anchor element
        will always follow the query element,
        e.g. ``http://example.com?foo=1#bar``.

        If any of the keyword arguments ``scheme``, ``host``, or ``port`` is
        passed and is non-``None``, the provided value will replace the named
        portion in the generated URL.  For example, if you pass
        ``host='foo.com'``, and the URL that would have been generated
        without the host replacement is ``http://example.com/a``, the result
        will be ``http://foo.com/a``.
        
        If ``scheme`` is passed as ``https``, and an explicit ``port`` is not
        passed, the ``port`` value is assumed to have been passed as ``443``.
        Likewise, if ``scheme`` is passed as ``http`` and ``port`` is not
        passed, the ``port`` value is assumed to have been passed as
        ``80``. To avoid this behavior, always explicitly pass ``port``
        whenever you pass ``scheme``.

        If a keyword argument ``app_url`` is passed and is not ``None``, it
        should be a string that will be used as the port/hostname/initial
        path portion of the generated URL instead of the default request
        application URL.  For example, if ``app_url='http://foo'``, then the
        resulting url of a resource that has a path of ``/baz/bar`` will be
        ``http://foo/baz/bar``.  If you want to generate completely relative
        URLs with no leading scheme, host, port, or initial path, you can
        pass ``app_url=''``.  Passing ``app_url=''`` when the resource path is
        ``/baz/bar`` will return ``/baz/bar``.

        .. versionadded:: 1.3
           ``app_url``

        If ``app_url`` is passed and any of ``scheme``, ``port``, or ``host``
        are also passed, ``app_url`` will take precedence and the values
        passed for ``scheme``, ``host``, and/or ``port`` will be ignored.

        If the ``resource`` passed in has a ``__resource_url__`` method, it
        will be used to generate the URL (scheme, host, port, path) for the
        base resource which is operated upon by this function.
        
        .. seealso::

            See also :ref:`overriding_resource_url_generation`.

        .. versionadded:: 1.5
           ``route_name``, ``route_kw``, and ``route_remainder_name``
           
        If ``route_name`` is passed, this function will delegate its URL
        production to the ``route_url`` function.  Calling
        ``resource_url(someresource, 'element1', 'element2', query={'a':1},
        route_name='blogentry')`` is roughly equivalent to doing::

           remainder_path = request.resource_path(someobject)
           url = request.route_url(
                     'blogentry',
                     'element1',
                     'element2',
                     _query={'a':'1'},
                     traverse=traversal_path,
                     )

        It is only sensible to pass ``route_name`` if the route being named has
        a ``*remainder`` stararg value such as ``*traverse``.  The remainder
        value will be ignored in the output otherwise.

        By default, the resource path value will be passed as the name
        ``traverse`` when ``route_url`` is called.  You can influence this by
        passing a different ``route_remainder_name`` value if the route has a
        different ``*stararg`` value at its end.  For example if the route
        pattern you want to replace has a ``*subpath`` stararg ala
        ``/foo*subpath``::

           request.resource_url(
                          resource,
                          route_name='myroute',
                          route_remainder_name='subpath'
                          )

        If ``route_name`` is passed, it is also permissible to pass
        ``route_kw``, which will passed as additional keyword arguments to
        ``route_url``.  Saying ``resource_url(someresource, 'element1',
        'element2', route_name='blogentry', route_kw={'id':'4'},
        _query={'a':'1'})`` is roughly equivalent to::

           remainder_path = request.resource_path_tuple(someobject)
           kw = {'id':'4', '_query':{'a':'1'}, 'traverse':traversal_path}
           url = request.route_url(
                     'blogentry',
                     'element1',
                     'element2',
                     **kw,
                     )

        If ``route_kw`` or ``route_remainder_name`` is passed, but
        ``route_name`` is not passed, both ``route_kw`` and
        ``route_remainder_name`` will be ignored.  If ``route_name``
        is passed, the ``__resource_url__`` method of the resource passed is
        ignored unconditionally.  This feature is incompatible with
        resources which generate their own URLs.
        
        .. note::

           If the :term:`resource` used is the result of a :term:`traversal`, it
           must be :term:`location`-aware.  The resource can also be the context
           of a :term:`URL dispatch`; contexts found this way do not need to be
           location-aware.

        .. note::

           If a 'virtual root path' is present in the request environment (the
           value of the WSGI environ key ``HTTP_X_VHM_ROOT``), and the resource
           was obtained via :term:`traversal`, the URL path will not include the
           virtual root prefix (it will be stripped off the left hand side of
           the generated URL).

        .. note::

           For backwards compatibility purposes, this method is also
           aliased as the ``model_url`` method of request.
        """
        try:
            reg = self.registry
        except AttributeError:
            reg = get_current_registry()  # b/c

        url_adapter = reg.queryMultiAdapter((resource, self), IResourceURL)
        if url_adapter is None:
            url_adapter = ResourceURL(resource, self)

        virtual_path = getattr(url_adapter, 'virtual_path', None)

        if virtual_path is None:
            # old-style IContextURL adapter (Pyramid 1.2 and previous)
            warnings.warn(
                'Pyramid is using an IContextURL adapter to generate a '
                'resource URL; any "app_url", "host", "port", or "scheme" '
                'arguments passed to resource_url are being ignored.  To '
                'avoid this behavior, as of Pyramid 1.3, register an '
                'IResourceURL adapter instead of an IContextURL '
                'adapter for the resource type(s).  IContextURL adapters '
                'will be ignored in a later major release of Pyramid.',
                DeprecationWarning, 2)

            resource_url = url_adapter()

        else:
            # IResourceURL adapter (Pyramid 1.3 and after)
            app_url = None
            scheme = None
            host = None
            port = None

            if 'route_name' in kw:
                newkw = {}
                route_name = kw['route_name']
                remainder = getattr(url_adapter, 'virtual_path_tuple', None)
                if remainder is None:
                    # older user-supplied IResourceURL adapter without 1.5
                    # virtual_path_tuple
                    remainder = tuple(url_adapter.virtual_path.split('/'))
                remainder_name = kw.get('route_remainder_name', 'traverse')
                newkw[remainder_name] = remainder

                for name in ('app_url', 'scheme', 'host', 'port', 'query',
                             'anchor'):
                    val = kw.get(name, None)
                    if val is not None:
                        newkw['_' + name] = val

                if 'route_kw' in kw:
                    route_kw = kw.get('route_kw')
                    if route_kw is not None:
                        newkw.update(route_kw)

                return self.route_url(route_name, *elements, **newkw)

            if 'app_url' in kw:
                app_url = kw['app_url']

            if 'scheme' in kw:
                scheme = kw['scheme']

            if 'host' in kw:
                host = kw['host']

            if 'port' in kw:
                port = kw['port']

            if app_url is None:
                if scheme or host or port:
                    app_url = self._partial_application_url(scheme, host, port)
                else:
                    app_url = self.application_url

            resource_url = None
            local_url = getattr(resource, '__resource_url__', None)

            if local_url is not None:
                # the resource handles its own url generation
                d = dict(
                    virtual_path=virtual_path,
                    physical_path=url_adapter.physical_path,
                    app_url=app_url,
                )
                # allow __resource_url__ to punt by returning None
                resource_url = local_url(self, d)

            if resource_url is None:
                # the resource did not handle its own url generation or the
                # __resource_url__ function returned None
                resource_url = app_url + virtual_path

        qs = ''
        anchor = ''

        if 'query' in kw:
            query = kw['query']
            if isinstance(query, string_types):
                qs = '?' + url_quote(query, QUERY_SAFE)
            elif query:
                qs = '?' + urlencode(query, doseq=True)

        if 'anchor' in kw:
            anchor = kw['anchor']
            anchor = url_quote(anchor, ANCHOR_SAFE)
            anchor = '#' + anchor

        if elements:
            suffix = _join_elements(elements)
        else:
            suffix = ''

        return resource_url + suffix + qs + anchor
Example #3
0
    def resource_url(self, resource, *elements, **kw):
        """

        Generate a string representing the absolute URL of the
        :term:`resource` object based on the ``wsgi.url_scheme``,
        ``HTTP_HOST`` or ``SERVER_NAME`` in the request, plus any
        ``SCRIPT_NAME``.  The overall result of this method is always a
        UTF-8 encoded string.

        Examples::

            request.resource_url(resource) =>

                                       http://example.com/

            request.resource_url(resource, 'a.html') =>

                                       http://example.com/a.html

            request.resource_url(resource, 'a.html', query={'q':'1'}) =>

                                       http://example.com/a.html?q=1

            request.resource_url(resource, 'a.html', anchor='abc') =>

                                       http://example.com/a.html#abc

            request.resource_url(resource, app_url='') =>

                                       /

        Any positional arguments passed in as ``elements`` must be strings
        Unicode objects, or integer objects.  These will be joined by slashes
        and appended to the generated resource URL.  Each of the elements
        passed in is URL-quoted before being appended; if any element is
        Unicode, it will converted to a UTF-8 bytestring before being
        URL-quoted. If any element is an integer, it will be converted to its
        string representation before being URL-quoted.

        .. warning:: if no ``elements`` arguments are specified, the resource
                     URL will end with a trailing slash.  If any
                     ``elements`` are used, the generated URL will *not*
                     end in trailing a slash.

        If a keyword argument ``query`` is present, it will be used to
        compose a query string that will be tacked on to the end of the URL.
        The value of ``query`` must be a sequence of two-tuples *or* a data
        structure with an ``.items()`` method that returns a sequence of
        two-tuples (presumably a dictionary).  This data structure will be
        turned into a query string per the documentation of
        ``pyramid.url.urlencode`` function.  After the query data is turned
        into a query string, a leading ``?`` is prepended, and the resulting
        string is appended to the generated URL.

        .. note::

           Python data structures that are passed as ``query`` which are
           sequences or dictionaries are turned into a string under the same
           rules as when run through :func:`urllib.urlencode` with the ``doseq``
           argument equal to ``True``.  This means that sequences can be passed
           as values, and a k=v pair will be placed into the query string for
           each value.

        If a keyword argument ``anchor`` is present, its string
        representation will be used as a named anchor in the generated URL
        (e.g. if ``anchor`` is passed as ``foo`` and the resource URL is
        ``http://example.com/resource/url``, the resulting generated URL will
        be ``http://example.com/resource/url#foo``).

        .. note::

           If ``anchor`` is passed as a string, it should be UTF-8 encoded. If
           ``anchor`` is passed as a Unicode object, it will be converted to
           UTF-8 before being appended to the URL.  The anchor value is not
           quoted in any way before being appended to the generated URL.

        If both ``anchor`` and ``query`` are specified, the anchor element
        will always follow the query element,
        e.g. ``http://example.com?foo=1#bar``.

        If any of the keyword arguments ``scheme``, ``host``, or ``port`` is
        passed and is non-``None``, the provided value will replace the named
        portion in the generated URL.  For example, if you pass
        ``host='foo.com'``, and the URL that would have been generated
        without the host replacement is ``http://example.com/a``, the result
        will be ``https://foo.com/a``.
        
        If ``scheme`` is passed as ``https``, and an explicit ``port`` is not
        passed, the ``port`` value is assumed to have been passed as ``443``.
        Likewise, if ``scheme`` is passed as ``http`` and ``port`` is not
        passed, the ``port`` value is assumed to have been passed as
        ``80``. To avoid this behavior, always explicitly pass ``port``
        whenever you pass ``scheme``.

        If a keyword argument ``app_url`` is passed and is not ``None``, it
        should be a string that will be used as the port/hostname/initial
        path portion of the generated URL instead of the default request
        application URL.  For example, if ``app_url='http://foo'``, then the
        resulting url of a resource that has a path of ``/baz/bar`` will be
        ``http://foo/baz/bar``.  If you want to generate completely relative
        URLs with no leading scheme, host, port, or initial path, you can
        pass ``app_url=''`.  Passing ``app_url=''` when the resource path is
        ``/baz/bar`` will return ``/baz/bar``.

        .. note::

           ``app_url`` is new as of Pyramid 1.3.

        If ``app_url`` is passed and any of ``scheme``, ``port``, or ``host``
        are also passed, ``app_url`` will take precedence and the values
        passed for ``scheme``, ``host``, and/or ``port`` will be ignored.

        If the ``resource`` passed in has a ``__resource_url__`` method, it
        will be used to generate the URL (scheme, host, port, path) that for
        the base resource which is operated upon by this function.  See also
        :ref:`overriding_resource_url_generation`.

        .. note::

           If the :term:`resource` used is the result of a :term:`traversal`, it
           must be :term:`location`-aware.  The resource can also be the context
           of a :term:`URL dispatch`; contexts found this way do not need to be
           location-aware.

        .. note::

           If a 'virtual root path' is present in the request environment (the
           value of the WSGI environ key ``HTTP_X_VHM_ROOT``), and the resource
           was obtained via :term:`traversal`, the URL path will not include the
           virtual root prefix (it will be stripped off the left hand side of
           the generated URL).

        .. note::

           For backwards compatibility purposes, this method is also
           aliased as the ``model_url`` method of request.
        """
        try:
            reg = self.registry
        except AttributeError:
            reg = get_current_registry() # b/c

        url_adapter = reg.queryMultiAdapter((resource, self), IResourceURL)
        if url_adapter is None:
            url_adapter = ResourceURL(resource, self)

        virtual_path = getattr(url_adapter, 'virtual_path', None)

        if virtual_path is None:
            # old-style IContextURL adapter (Pyramid 1.2 and previous)
            warnings.warn(
                'Pyramid is using an IContextURL adapter to generate a '
                'resource URL; any "app_url", "host", "port", or "scheme" '
                'arguments passed to resource_url are being ignored.  To '
                'avoid this behavior, as of Pyramid 1.3, register an '
                'IResourceURL adapter instead of an IContextURL '
                'adapter for the resource type(s).  IContextURL adapters '
                'will be ignored in a later major release of Pyramid.',
                DeprecationWarning,
                2)

            resource_url = url_adapter()

        else:
            # newer-style IResourceURL adapter (Pyramid 1.3 and after)
            app_url = None
            scheme = None
            host = None
            port = None

            if 'app_url' in kw:
                app_url = kw['app_url']

            if 'scheme' in kw:
                scheme = kw['scheme']

            if 'host' in kw:
                host = kw['host']

            if 'port' in kw:
                port = kw['port']

            if app_url is None:
                if scheme or host or port:
                    app_url = self._partial_application_url(scheme, host, port)
                else:
                    app_url = self.application_url

            resource_url = None
            local_url = getattr(resource, '__resource_url__', None)

            if local_url is not None:
                # the resource handles its own url generation
                d = dict(
                    virtual_path = virtual_path,
                    physical_path = url_adapter.physical_path,
                    app_url = app_url,
                    )
                # allow __resource_url__ to punt by returning None
                resource_url = local_url(self, d)

            if resource_url is None:
                # the resource did not handle its own url generation or the
                # __resource_url__ function returned None
                resource_url = app_url + virtual_path

        qs = ''
        anchor = ''

        if 'query' in kw:
            query = kw['query']
            if query:
                qs = '?' + urlencode(query, doseq=True)

        if 'anchor' in kw:
            anchor = kw['anchor']
            if isinstance(anchor, text_type):
                anchor = native_(anchor, 'utf-8')
            anchor = '#' + anchor

        if elements:
            suffix = _join_elements(elements)
        else:
            suffix = ''

        return resource_url + suffix + qs + anchor