Chris McDonough
2010-11-18 2c9d148493aaa977c69e77072466685a3367ad0b
- Add a ``pyramid.url.route_path`` API, allowing folks to generate relative
URLs. Calling ``route_path`` is the same as calling
``pyramid.url.route_url`` with the argument ``_app_url`` equal to the empty
string.

- Add a ``pyramid.request.Request.route_path`` API. This is a convenience
method of the request which calls ``pyramid.url.route_url``.
7 files modified
126 ■■■■■ changed files
CHANGES.txt 11 ●●●●● patch | view | raw | blame | history
TODO.txt 5 ●●●●● patch | view | raw | blame | history
docs/api/url.rst 2 ●●●●● patch | view | raw | blame | history
pyramid/request.py 43 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_request.py 17 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_url.py 21 ●●●●● patch | view | raw | blame | history
pyramid/url.py 27 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,6 +1,17 @@
Next release
============
Features
--------
- Add a ``pyramid.url.route_path`` API, allowing folks to generate relative
  URLs.  Calling ``route_path`` is the same as calling
  ``pyramid.url.route_url`` with the argument ``_app_url`` equal to the empty
  string.
- Add a ``pyramid.request.Request.route_path`` API.  This is a convenience
  method of the request which calls ``pyramid.url.route_url``.
Bug Fixes
---------
TODO.txt
@@ -44,8 +44,6 @@
         action = '^foo$'
           mypackage.views.MyView.foo_GET
- Ability to use configurator as a context manager.
- Provide a response_cookies attribute on the request for rendered
  responses that can be used as input to response.set_cookie.
@@ -78,9 +76,6 @@
- RendererHelper -> RendererInfo?
- translationdir ZCML directive use of ``path_spec`` should maybe die.
- Option for route_url to omit the host and port (perhaps a different
  function named ``route_path``).
- SQLAlchemy idiomatics:
docs/api/url.rst
@@ -9,6 +9,8 @@
  .. autofunction:: route_url
  .. autofunction:: route_path
  .. autofunction:: static_url
  .. autofunction:: urlencode
pyramid/request.py
@@ -11,6 +11,7 @@
from pyramid.url import model_url
from pyramid.url import route_url
from pyramid.url import static_url
from pyramid.url import route_path
class TemplateContext(object):
    pass
@@ -246,13 +247,53 @@
        like this::
          from pyramid.url import static_url
          static_url('mypackage:static/foo.css, request)
          static_url('mypackage:static/foo.css', request)
        See :func:`pyramid.url.static_url` for more information
        
        """
        return static_url(path, self, **kw)
    def route_path(self, route_name, *elements, **kw):
        """Generates a path (aka a 'relative URL', a URL minus the host,
        scheme, and port) for a named :app:`Pyramid`
        :term:`route configuration`.
        .. note:: Calling :meth:`pyramid.Request.route_path` can be used to
                  achieve the same result as :func:`pyramid.url.route_path`.
        This is a convenience method.  The result of calling
        :meth:`pyramid.request.Request.route_path` is the same as calling
        :func:`pyramid.url.route_path` with an explicit ``request``
        parameter.
        This method accepts the same arguments as
        :meth:`pyramid.request.Request.route_url` and performs the same duty.
        It just omits the host, port, and scheme information in the return
        value; only the path, query parameters, and anchor data are present
        in the returned string.
        The :meth:`pyramid.request.Request.route_path` method calls the
        :func:`pyramid.url.route_path` function using the Request object as
        the ``request`` argument.  The ``*elements`` and ``*kw`` arguments
        passed to :meth:`pyramid.request.Request.route_path` are passed
        through to :func:`pyramid.url.route_path` unchanged and its result is
        returned.
        This call to :meth:`pyramid.request.Request.route_path`::
          request.route_path('foobar')
        Is completely equivalent to calling :func:`pyramid.url.route_path`
        like this::
          from pyramid.url import route_path
          route_path('foobar', request)
        See :func:`pyramid.url.route_path` for more information
        """
        return route_path(route_name, self, *elements, **kw)
    # override default WebOb "environ['adhoc_attr']" mutation behavior
    __getattr__ = object.__getattribute__
    __setattr__ = object.__setattr__
pyramid/tests/test_request.py
@@ -266,6 +266,23 @@
        self.assertEqual(result,
                         'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo')
    def test_route_path(self):
        environ = {
            'PATH_INFO':'/',
            'SERVER_NAME':'example.com',
            'SERVER_PORT':'5432',
            'QUERY_STRING':'la=La%20Pe%C3%B1a',
            'wsgi.url_scheme':'http',
            }
        from pyramid.interfaces import IRoutesMapper
        inst = self._makeOne(environ)
        mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3'))
        self.config.registry.registerUtility(mapper, IRoutesMapper)
        result = inst.route_path('flub', 'extra1', 'extra2',
                                a=1, b=2, c=3, _query={'a':1},
                                _anchor=u"foo")
        self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo')
    def test_static_url(self):
        from pyramid.interfaces import IStaticURLInfo
        environ = {
pyramid/tests/test_url.py
@@ -209,6 +209,27 @@
        self.assertEqual(result,  'http://example2.com/1/2/3/a')
        self.assertEqual(route.kw, {}) # shouldnt have anchor/query
class TestRoutePath(unittest.TestCase):
    def setUp(self):
        cleanUp()
    def tearDown(self):
        cleanUp()
    def _callFUT(self, *arg, **kw):
        from pyramid.url import route_path
        return route_path(*arg, **kw)
    def test_with_elements(self):
        from pyramid.interfaces import IRoutesMapper
        request = _makeRequest()
        mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3'))
        request.registry.registerUtility(mapper, IRoutesMapper)
        result = self._callFUT('flub', request, 'extra1', 'extra2',
                               a=1, b=2, c=3, _query={'a':1},
                               _anchor=u"foo")
        self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo')
class TestStaticUrl(unittest.TestCase):
    def setUp(self):
        cleanUp()
pyramid/url.py
@@ -153,6 +153,33 @@
    return app_url + path + suffix + qs + anchor
def route_path(route_name, request, *elements, **kw):
    """Generates a path (aka a 'relative URL', a URL minus the host, scheme,
    and port) for a named :app:`Pyramid` :term:`route configuration`.
    .. note:: Calling :meth:`pyramid.Request.route_path` can be used to
              achieve the same result as :func:`pyramid.url.route_path`.
    This function accepts the same argument as :func:`pyramid.url.route_url`
    and performs the same duty.  It just omits the host, port, and scheme
    information in the return value; only the path, query parameters,
    and anchor data are present in the returned string.
    For example, if you've defined a route named 'foobar' with the path
    ``/:foo/:bar``, this call to ``route_path``::
        route_path('foobar', request, foo='1', bar='2')
    Will return the string ``/1/2``.
    .. note:: Calling ``route_path('route', request)`` is the same as calling
       ``route_url('route', request, _app_url='')``.  ``route_path`` is, in
       fact, implemented in terms of ``route_url`` in just this way. As a
       result, passing ``_app_url`` within the ``**kw`` values passed to
       ``route_path`` will result in an exception.
    """
    return route_url(route_name, request, *elements, _app_url='', **kw)
def model_url(model, request, *elements, **kw):
    """
    Generate a string representing the absolute URL of the ``model``