Skip to content

Commit 7620e8f

Browse files
committed
Reflow web example for two-stage routing, document upstr
1 parent a8b13ab commit 7620e8f

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

docs/multidict.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,45 @@ CIMultiDictProxy
335335
Raises :exc:`TypeError` is *multidict* is not :class:`CIMultiDict` instance.
336336

337337
The class is inherited from :class:`MultiDict`.
338+
339+
340+
upstr
341+
-----
342+
343+
:class:`CIMultiDict` accepts :class:`str` as *key* argument for dict
344+
lookups but converts it to upper case internally.
345+
346+
For more effective processing it shoult to know if *key* is already upper cased.
347+
348+
To skip :meth:`~str.upper()` call you may create upper cased string by
349+
hands, e.g::
350+
351+
>>> key = upstr('Key')
352+
>>> key
353+
'KEY'
354+
>>> mdict = CIMultiDict(key='value')
355+
>>> key in mdict
356+
True
357+
>>> mdict[key]
358+
'value'
359+
360+
For performance you should create :class:`upstr` strings once and
361+
store it globally, like :mod:`aiohttp.hdrs` does.
362+
363+
.. class:: upstr(object='')
364+
upstr(bytes_or_buffer[, encoding[, errors]])
365+
366+
Create a new **upper cased** string object from the given
367+
*object*. If *encoding* or *errors* is specified, then the
368+
object must expose a data buffer that will be decoded using the
369+
given encoding and error handler.
370+
371+
Otherwise, returns the result of ``object.__str__()`` (if defined)
372+
or ``repr(object)``.
373+
374+
*encoding* defaults to ``sys.getdefaultencoding()``.
375+
376+
*errors* defaults to ``'strict'``.
377+
378+
The class is inherited from :class:`str` and has all regular
379+
string methods.

docs/web.rst

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,22 @@ While :class:`UrlDispatcher` doesn't accept extra criterias there is
137137
easy way to do the task by implementing the second routing layer by
138138
hands.
139139

140-
The example shows custom processing based on *HTTP Accept* header::
140+
The example shows custom processing based on *HTTP Accept* header:
141141

142-
class Handler:
142+
.. code-block:: python
143+
144+
class AcceptChooser:
143145
144146
def __init__(self):
145147
self._accepts = {}
146148
147149
@asyncio.coroutine
148150
def do_route(self, request):
149-
acceptor = self._accepts.get(request.headers.get('ACCEPT'))
150-
if acceptor is None:
151-
raise HTTPNotAcceptable()
152-
return (yield from acceptor(request))
151+
for accept in request.headers.getall('ACCEPT', []):
152+
acceptor = self._accepts.get(accept):
153+
if acceptor is not None:
154+
return (yield from acceptor(request))
155+
raise HTTPNotAcceptable()
153156
154157
def reg_acceptor(self, accept, handler):
155158
self._accepts[accept] = handler
@@ -163,10 +166,11 @@ The example shows custom processing based on *HTTP Accept* header::
163166
def handle_xml(request):
164167
# do xml handling
165168
166-
handler = Handler()
167-
app.router.add_route('GET', '/', handler.do_route)
168-
handler.reg_acceptor('application/json', handle_json)
169-
handler.reg_acceptor('application/xml', handle_xml)
169+
chooser = AcceptChooser()
170+
app.router.add_route('GET', '/', chooser.do_route)
171+
172+
chooser.reg_acceptor('application/json', handle_json)
173+
chooser.reg_acceptor('application/xml', handle_xml)
170174
171175
172176

0 commit comments

Comments
 (0)