'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.
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.
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``.
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`.
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::
traversal_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::
traversal_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.
.. versionchanged:: 1.3
Added the ``app_url`` keyword argument.
.. versionchanged:: 1.5
Allow the ``query`` option to be a string to enable alternative
encodings.
The ``anchor`` option will be escaped instead of using
its raw string representation.
Added the ``route_name``, ``route_kw``, and
``route_remainder_name`` keyword arguments.
.. versionchanged:: 1.9
If ``query`` or ``anchor`` are falsey (such as ``None`` or an
empty string) they will not be included in the generated url.'

def resource_url(self, resource, *elements, **kw):

    try:
        reg = self.registry
    except AttributeError:
        reg = get_current_registry()
    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)
    urlkw = {}
    for name in ('app_url', 'scheme', 'host', 'port', 'query', 'anchor'):
        val = kw.get(name, None)
        if (val is not None):
            urlkw[('_' + name)] = val
    if ('route_name' in kw):
        route_name = kw['route_name']
        remainder = getattr(url_adapter, 'virtual_path_tuple', None)
        if (remainder is None):
            remainder = tuple(url_adapter.virtual_path.split('/'))
        remainder_name = kw.get('route_remainder_name', 'traverse')
        urlkw[remainder_name] = remainder
        if ('route_kw' in kw):
            route_kw = kw.get('route_kw')
            if (route_kw is not None):
                urlkw.update(route_kw)
        return self.route_url(route_name, *elements, **urlkw)
    (app_url, qs, anchor) = parse_url_overrides(self, urlkw)
    resource_url = None
    local_url = getattr(resource, '__resource_url__', None)
    if (local_url is not None):
        d = dict(virtual_path=virtual_path, physical_path=url_adapter.physical_path, app_url=app_url)
        resource_url = local_url(self, d)
    if (resource_url is None):
        resource_url = (app_url + virtual_path)
    if elements:
        suffix = _join_elements(elements)
    else:
        suffix = ''
    return (((resource_url + suffix) + qs) + anchor)
