From a511b1423334f855e996bb06714b36aa86f861e9 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 5 Jan 2012 02:41:32 -0500 Subject: fix urldispatch matching and generation to cope with various inputs --- docs/narr/urldispatch.rst | 87 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) (limited to 'docs/narr/urldispatch.rst') diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 35613ea1b..7e485f8ae 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -235,7 +235,7 @@ When matching the following URL: .. code-block:: text - foo/La%20Pe%C3%B1a + http://example.com/foo/La%20Pe%C3%B1a The matchdict will look like so (the value is URL-decoded / UTF-8 decoded): @@ -243,6 +243,50 @@ The matchdict will look like so (the value is URL-decoded / UTF-8 decoded): {'bar':u'La Pe\xf1a'} +Literal strings in the path segment should represent the *decoded* value of +the ``PATH_INFO`` provided to Pyramid. You don't want to use a URL-encoded +value or a bytestring representing the literal's UTF-8 in the pattern. For +example, rather than this: + +.. code-block:: text + + /Foo%20Bar/{baz} + +You'll want to use something like this: + +.. code-block:: text + + /Foo Bar/{baz} + +For patterns that contain "high-order" characters in its literals, you'll +want to use a Unicode value as the pattern as opposed to any URL-encoded or +UTF-8-encoded value. For example, you might be tempted to use a bytestring +pattern like this: + +.. code-block:: text + + /La Pe\xc3\xb1a/{x} + +But that probably won't match as you expect it to. You'll want to use a +Unicode value as the pattern instead rather than raw bytestring escapes. You +can use a high-order Unicode value as the pattern by using `Python source +file encoding `_ plus the "real" +character in the Unicode pattern in the source, like so: + +.. code-block:: text + + /La Peña/{x} + +Or you can ignore source file encoding and use equivalent Unicode escape +characters in the pattern. + +.. code-block:: text + + /La Pe\xf1a/{x} + +Dynamic segment names cannot contain high-order characters, so this applies +only to literals in the pattern. + If the pattern has a ``*`` in it, the name which follows it is considered a "remainder match". A remainder match *must* come at the end of the pattern. Unlike segment replacement markers, it does not need to be preceded by a @@ -612,7 +656,6 @@ Use the :meth:`pyramid.request.Request.route_url` method to generate URLs based on route patterns. For example, if you've configured a route with the ``name`` "foo" and the ``pattern`` "{a}/{b}/{c}", you might do this. -.. ignore-next-block .. code-block:: python :linenos: @@ -620,7 +663,45 @@ based on route patterns. For example, if you've configured a route with the This would return something like the string ``http://example.com/1/2/3`` (at least if the current protocol and hostname implied ``http://example.com``). -See the :meth:`~pyramid.request.Request.route_url` API documentation for more + +To get only the *path* of a route, use the +:meth:`pyramid.request.Request.route_path` API instead of +:meth:`~pyramid.request.Request.route_url`. + +.. code-block:: python + + url = request.route_path('foo', a='1', b='2', c='3') + +This will return the string ``/1/2/3`` rather than a full URL. + +Note that URLs and paths generated by ``route_path`` and ``route_url`` are +always URL-quoted string types (which contain no non-ASCII characters). +Therefore, if you've added a route like so: + +.. code-block:: python + + config.add_route('la', u'/La Peña/{city}') + +And you later generate a URL using ``route_path`` or ``route_url`` like so: + +.. code-block:: python + + url = request.route_path('la', city=u'Québec') + +You will wind up with the path encoded to UTF-8 and URL quoted like so: + +.. code-block:: python + + /La%20Pe%C3%B1a/Qu%C3%A9bec + +.. note:: + + Generating URL-quoted URLs and paths is new as of Pyramid 1.3 (and Pyramid + 1.2 after 1.2.6). Previous versions generated unquoted URLs and paths + (which was broken). + +See the :meth:`~pyramid.request.Request.route_url` and +:meth:`~pyramid.request.Request.route_path` API documentation for more information. .. index:: -- cgit v1.2.3 From e3dadfd5865f58a2f816e558e8dbc636dd037197 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 5 Jan 2012 05:55:31 -0500 Subject: bring docs up to date with code --- docs/narr/urldispatch.rst | 59 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 15 deletions(-) (limited to 'docs/narr/urldispatch.rst') diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 7e485f8ae..6d9dfdd92 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -267,11 +267,12 @@ pattern like this: /La Pe\xc3\xb1a/{x} -But that probably won't match as you expect it to. You'll want to use a -Unicode value as the pattern instead rather than raw bytestring escapes. You -can use a high-order Unicode value as the pattern by using `Python source -file encoding `_ plus the "real" -character in the Unicode pattern in the source, like so: +But this will either cause an error at startup time or it won't match +properly. You'll want to use a Unicode value as the pattern instead rather +than raw bytestring escapes. You can use a high-order Unicode value as the +pattern by using `Python source file encoding +`_ plus the "real" character in the +Unicode pattern in the source, like so: .. code-block:: text @@ -664,7 +665,7 @@ based on route patterns. For example, if you've configured a route with the This would return something like the string ``http://example.com/1/2/3`` (at least if the current protocol and hostname implied ``http://example.com``). -To get only the *path* of a route, use the +To generate only the *path* portion of a URL from a route, use the :meth:`pyramid.request.Request.route_path` API instead of :meth:`~pyramid.request.Request.route_url`. @@ -674,8 +675,14 @@ To get only the *path* of a route, use the This will return the string ``/1/2/3`` rather than a full URL. +Replacement values passed to ``route_url`` or ``route_path`` must be Unicode +or bytestrings encoded in UTF-8. One exception to this rule exists: if +you're trying to replace a "remainder" match value (a ``*stararg`` +replacement value), the value may be a tuple containing Unicode strings or +UTF-8 strings. + Note that URLs and paths generated by ``route_path`` and ``route_url`` are -always URL-quoted string types (which contain no non-ASCII characters). +always URL-quoted string types (they contain no non-ASCII characters). Therefore, if you've added a route like so: .. code-block:: python @@ -690,19 +697,41 @@ And you later generate a URL using ``route_path`` or ``route_url`` like so: You will wind up with the path encoded to UTF-8 and URL quoted like so: -.. code-block:: python +.. code-block:: text /La%20Pe%C3%B1a/Qu%C3%A9bec -.. note:: +If you have a ``*stararg`` remainder dynamic part of your route pattern: + +.. code-block:: python + + config.add_route('abc', 'a/b/c/*foo') + +And you later generate a URL using ``route_path`` or ``route_url`` using a +*string* as the replacement value: + +.. code-block:: python + + url = request.route_path('abc', foo=u'Québec/biz') - Generating URL-quoted URLs and paths is new as of Pyramid 1.3 (and Pyramid - 1.2 after 1.2.6). Previous versions generated unquoted URLs and paths - (which was broken). +The value you pass will be URL-quoted except for embedded slashes in the +result: + +.. code-block:: text + + /a/b/c/Qu%C3%A9bec/biz + +You can get a similar result by passing a tuple composed of path elements: + +.. code-block:: python + + url = request.route_path('abc', foo=(u'Québec', u'biz')) + +Each value in the tuple will be url-quoted and joined by slashes in this case: + +.. code-block:: text -See the :meth:`~pyramid.request.Request.route_url` and -:meth:`~pyramid.request.Request.route_path` API documentation for more -information. + /a/b/c/Qu%C3%A9bec/biz .. index:: single: static routes -- cgit v1.2.3