diff options
| author | Bert JW Regeer <bertjw@regeer.org> | 2017-11-20 13:55:50 -0700 |
|---|---|---|
| committer | Bert JW Regeer <bertjw@regeer.org> | 2017-11-20 13:55:50 -0700 |
| commit | a750188f3fb985188ecce5e1a694a2f2f7704ae1 (patch) | |
| tree | 4efc107fe00b28257388b5d42ea0ee6975ddd750 /docs/reference.txt | |
| parent | 9273bbcd7511d36dc2526d3b47cab0d982158b75 (diff) | |
| download | webob-a750188f3fb985188ecce5e1a694a2f2f7704ae1.tar.gz | |
Code in references.txt is now Python 3
And it passes doctest again
Diffstat (limited to 'docs/reference.txt')
| -rw-r--r-- | docs/reference.txt | 193 |
1 files changed, 84 insertions, 109 deletions
diff --git a/docs/reference.txt b/docs/reference.txt index b88e908..c16126e 100644 --- a/docs/reference.txt +++ b/docs/reference.txt @@ -3,10 +3,6 @@ WebOb Reference .. contents:: -.. comment: - - >>> from doctest import ELLIPSIS - Introduction ============ @@ -62,7 +58,7 @@ constructor that will fill in a minimal environment: >>> req = Request.blank('/article?id=1') >>> from pprint import pprint - >>> pprint(req.environ) + >>> pprint(req.environ) # doctest: +ELLIPSIS {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/article', 'QUERY_STRING': 'id=1', @@ -71,14 +67,15 @@ constructor that will fill in a minimal environment: 'SERVER_NAME': 'localhost', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': 'HTTP/1.0', - 'wsgi.errors': <open file '<stderr>', mode 'w' at ...>, - 'wsgi.input': <...IO... object at ...>, + 'wsgi.errors': <...TextIOWrapper ...'<stderr>' ...>, + 'wsgi.input': <...IO object at 0x...>, 'wsgi.multiprocess': False, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0)} + Request Body ------------ @@ -93,13 +90,13 @@ turned into a file-like object. You can read the entire body with >>> hasattr(req.body_file, 'read') True >>> req.body - '' + b'' >>> req.method = 'PUT' - >>> req.body = 'test' + >>> req.body = b'test' >>> hasattr(req.body_file, 'read') True >>> req.body - 'test' + b'test' Method & URL ------------ @@ -115,14 +112,14 @@ request object: 'http' >>> req.script_name # The base of the URL '' - >>> req.script_name = '/blog' # make it more interesting - >>> req.path_info # The yet-to-be-consumed part of the URL + >>> req.script_name = '/blog' # make it more interesting + >>> req.path_info # The yet-to-be-consumed part of the URL '/article' - >>> req.content_type # Content-Type of the request body + >>> req.content_type # Content-Type of the request body '' - >>> print req.remote_user # The authenticated user (there is none set) + >>> print(req.remote_user) # The authenticated user (there is none set) None - >>> print req.remote_addr # The remote IP + >>> print(req.remote_addr) # The remote IP None >>> req.host 'localhost:80' @@ -200,13 +197,13 @@ Some examples: >>> req = Request.blank('/test?check=a&check=b&name=Bob') >>> req.GET - MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')]) + GET([('check', 'a'), ('check', 'b'), ('name', 'Bob')]) >>> req.GET['check'] - u'b' + 'b' >>> req.GET.getall('check') - [u'a', u'b'] - >>> req.GET.items() - [(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')] + ['a', 'b'] + >>> list(req.GET.items()) + [('check', 'a'), ('check', 'b'), ('name', 'Bob')] We'll have to create a request body and change the method to get ``POST``. Until we do that, the variables are boring: @@ -215,14 +212,14 @@ Until we do that, the variables are boring: >>> req.POST <NoVars: Not a form request> - >>> req.POST.items() # NoVars can be read like a dict, but not written + >>> list(req.POST.items()) # NoVars can be read like a dict, but not written [] >>> req.method = 'POST' - >>> req.body = 'name=Joe&email=joe@example.com' + >>> req.body = b'name=Joe&email=joe@example.com' >>> req.POST - MultiDict([(u'name', u'Joe'), (u'email', u'joe@example.com')]) + MultiDict([('name', 'Joe'), ('email', 'joe@example.com')]) >>> req.POST['name'] - u'Joe' + 'Joe' Often you won't care where the variables come from. (Even if you care about the method, the location of the variables might not be important.) There is a @@ -232,18 +229,18 @@ contains variables from both sources: .. code-block:: python >>> req.params - NestedMultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob'), (u'name', u'Joe'), (u'email', u'joe@example.com')]) + NestedMultiDict([('check', 'a'), ('check', 'b'), ('name', 'Bob'), ('name', 'Joe'), ('email', 'joe@example.com')]) >>> req.params['name'] - u'Bob' + 'Bob' >>> req.params.getall('name') - [u'Bob', u'Joe'] + ['Bob', 'Joe'] >>> for name, value in req.params.items(): - ... print '%s: %r' % (name, value) - check: u'a' - check: u'b' - name: u'Bob' - name: u'Joe' - email: u'joe@example.com' + ... print('%s: %r' % (name, value)) + check: 'a' + check: 'b' + name: 'Bob' + name: 'Joe' + email: 'joe@example.com' The ``POST`` and ``GET`` nomenclature is historical -- :py:meth:`req.GET <webob.request.BaseRequest.GET>` can be used for non-GET requests to access @@ -252,29 +249,30 @@ also be used for PUT requests with the appropriate Content-Type. >>> req = Request.blank('/test?check=a&check=b&name=Bob') >>> req.method = 'PUT' - >>> req.body = body = 'var1=value1&var2=value2&rep=1&rep=2' + >>> req.body = b'var1=value1&var2=value2&rep=1&rep=2' >>> req.environ['CONTENT_LENGTH'] = str(len(req.body)) >>> req.environ['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' >>> req.GET - MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')]) + GET([('check', 'a'), ('check', 'b'), ('name', 'Bob')]) >>> req.POST - MultiDict([(u'var1', u'value1'), (u'var2', u'value2'), (u'rep', u'1'), (u'rep', u'2')]) + MultiDict([('var1', 'value1'), ('var2', 'value2'), ('rep', '1'), ('rep', '2')]) Unicode Variables ~~~~~~~~~~~~~~~~~ -Submissions are non-unicode (``str``) strings, unless some character set is -indicated. A client can indicate the character set with ``Content-Type: -application/x-www-form-urlencoded; charset=utf8``, but very few clients -actually do this (sometimes XMLHttpRequest requests will do this, as JSON is -always UTF8 even when a page is served with a different character set). You can -force a charset, which will affect all the variables: +Submissions are by default UTF-8, you can force a different character set by +setting the charset on the ``Request`` object explicitly. A client can indicate +the character set with ``Content-Type: application/x-www-form-urlencoded; +charset=utf8``, but very few clients actually do this (sometimes XMLHttpRequest +requests will do this, as JSON is always UTF8 even when a page is served with a +different character set). You can force a charset, which will affect all the +variables: .. code-block:: python >>> req.charset = 'utf8' >>> req.GET - MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')]) + GET([('check', 'a'), ('check', 'b'), ('name', 'Bob')]) Cookies ------- @@ -286,7 +284,7 @@ they will be decoded into Unicode strings if you set the charset. >>> req.headers['Cookie'] = 'test=value' >>> req.cookies - MultiDict([(u'test', u'value')]) + <RequestCookies (dict-like) with values {'test': 'value'}> Modifying the request --------------------- @@ -339,7 +337,7 @@ example means that ``text/html`` is okay, but >>> req.accept = 'text/html;q=0.5, application/xhtml+xml;q=1' >>> req.accept - <MIMEAccept('text/html;q=0.5, application/xhtml+xml')> + <AcceptValidHeader ('text/html;q=0.5, application/xhtml+xml')> >>> 'text/html' in req.accept True @@ -431,29 +429,18 @@ range) should be returned: .. code-block:: python >>> req.if_range - <Empty If-Range> - >>> req.if_range.match(etag='some-etag', last_modified=datetime(2005, 1, 1, 12, 0)) - True + IfRange(<ETag *>) >>> req.if_range = 'opaque-etag' - >>> req.if_range.match(etag='other-etag') - False - >>> req.if_range.match(etag='opaque-etag') - True - -You can also pass in a response object with: - -.. code-block:: python - >>> from webob import Response >>> res = Response(etag='opaque-etag') - >>> req.if_range.match_response(res) + >>> res in req.if_range True To get the range information: >>> req.range = 'bytes=0-100' >>> req.range - <Range ranges=(0, 101)> + <Range bytes 0-101> >>> cr = req.range.content_range(length=1000) >>> cr.start, cr.stop, cr.length (0, 101, 1000) @@ -516,7 +503,7 @@ A handier response can be had with: .. code-block:: python >>> res = req.get_response(wsgi_app) - >>> res + >>> res # doctest: +ELLIPSIS <Response ... 200 OK> >>> res.status '200 OK' @@ -571,7 +558,7 @@ The core attributes are unsurprising: >>> res.headerlist [('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0')] >>> res.body - '' + b'' You can set any of these attributes, e.g.: @@ -582,24 +569,19 @@ You can set any of these attributes, e.g.: '404 Not Found' >>> res.status_code 404 - >>> res.headerlist = [('Content-type', 'text/html')] - >>> res.body = 'test' - >>> print res + >>> res.headerlist = [('Content-Type', 'text/html')] + >>> res.body = b'test' + >>> print(res) 404 Not Found - Content-type: text/html + Content-Type: text/html Content-Length: 4 <BLANKLINE> test - >>> res.body = u"test" - Traceback (most recent call last): - ... - TypeError: You cannot set Response.body to a unicode object (use Response.text) - >>> res.text = u"test" + >>> res.body = "test" # doctest: +ELLIPSIS Traceback (most recent call last): ... - AttributeError: You cannot access Response.text unless charset is set - >>> res.charset = 'utf8' - >>> res.text = u"test" + TypeError: You cannot set Response.body to a text object (use Response.text) + >>> res.text = "test" >>> res.body b'test' @@ -615,7 +597,7 @@ the list in ``res.headers``: .. code-block:: python >>> res.headers - ResponseHeaders([('Content-Type', 'text/html; charset=utf8'), ('Content-Length', '4')]) + ResponseHeaders([('Content-Type', 'text/html'), ('Content-Length', '4')]) This is case-insensitive. It can support multiple values for a key, though only if you use ``res.headers.add(key, value)`` or read them @@ -645,20 +627,19 @@ app_iter in-place (turning the app_iter into a list if necessary): >>> res = Response(content_type='text/plain', charset=None) >>> f = res.body_file - >>> f.write('hey') - >>> f.write(u'test') + >>> f.write('hey') # doctest: +ELLIPSIS Traceback (most recent call last): - . . . - TypeError: You can only write unicode to Response if charset has been set + ... + TypeError: You can only write text to Response if charset has been set >>> f.encoding - >>> res.charset = 'utf8' + >>> res.charset = 'UTF-8' >>> f.encoding - 'utf8' - >>> f.write(u'test') + 'UTF-8' + >>> f.write('test') >>> res.app_iter - ['', 'hey', 'test'] + [b'', b'test'] >>> res.body - 'heytest' + b'test' Header Getters -------------- @@ -680,10 +661,10 @@ handled through two separate properties: 'text/html; charset=utf8' >>> res.content_type = 'application/atom+xml' >>> res.content_type_params - {'charset': 'utf8'} - >>> res.content_type_params = {'type': 'entry', 'charset': 'utf8'} + {'charset': 'UTF-8'} + >>> res.content_type_params = {'type': 'entry', 'charset': 'UTF-8'} >>> res.headers['content-type'] - 'application/atom+xml; charset=utf8; type=entry' + 'application/atom+xml; charset=UTF-8; type=entry' Other headers: @@ -772,9 +753,9 @@ After setting all these headers, here's the result: .. code-block:: python - >>> for name, value in res.headerlist: - ... print '%s: %s' % (name, value) - Content-Type: application/atom+xml; charset=utf8; type=entry + >>> for name, value in res.headerlist: # doctest: +ELLIPSIS + ... print('%s: %s' % (name, value)) # doctest: +ELLIPSIS + Content-Type: application/atom+xml; charset=UTF-8; type=entry Location: http://localhost/foo Accept-Ranges: bytes Age: 120 @@ -807,7 +788,7 @@ You can also set Cache-Control related attributes with >>> res.cache_expires(0) >>> res.headers['Cache-Control'] 'max-age=0, must-revalidate, no-cache, no-store' - >>> res.headers['Expires'] + >>> res.headers['Expires'] # doctest: +ELLIPSIS '... GMT' You can also use the :py:class:`~datetime.timedelta` @@ -831,11 +812,11 @@ methods. Most importantly: >>> res.set_cookie('key', 'value', max_age=360, path='/', ... domain='example.org', secure=True) - >>> res.headers['Set-Cookie'] + >>> res.headers['Set-Cookie'] # doctest: +ELLIPSIS 'key=value; Domain=example.org; Max-Age=360; Path=/; expires=... GMT; secure' >>> # To delete a cookie previously set in the client: >>> res.delete_cookie('bad_cookie') - >>> res.headers['Set-Cookie'] + >>> res.headers['Set-Cookie'] # doctest: +ELLIPSIS 'bad_cookie=; Max-Age=0; Path=/; expires=... GMT' The only other real method of note (note that this does *not* delete @@ -845,7 +826,7 @@ the cookie from clients, only from the response object): >>> res.unset_cookie('key') >>> res.unset_cookie('bad_cookie') - >>> print res.headers.get('Set-Cookie') + >>> print(res.headers.get('Set-Cookie')) None Binding a Request @@ -873,15 +854,16 @@ A possible pattern for your application might be: >>> def my_app(environ, start_response): ... req = Request(environ) ... res = Response() + ... res.charset = 'UTF-8' ... res.content_type = 'text/plain' ... parts = [] ... for name, value in sorted(req.environ.items()): ... parts.append('%s: %r' % (name, value)) - ... res.body = '\n'.join(parts) + ... res.text = '\n'.join(parts) ... return res(environ, start_response) >>> req = Request.blank('/') >>> res = req.get_response(my_app) - >>> print res + >>> print(res) # doctest: +ELLIPSIS 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: ... @@ -894,7 +876,7 @@ A possible pattern for your application might be: SERVER_NAME: 'localhost' SERVER_PORT: '80' SERVER_PROTOCOL: 'HTTP/1.0' - wsgi.errors: <open file '<stderr>', mode 'w' at ...> + wsgi.errors: <...> wsgi.input: <...IO... object at ...> wsgi.multiprocess: False wsgi.multithread: False @@ -916,12 +898,12 @@ simple body is provided. >>> from webob.exc import * >>> exc = HTTPTemporaryRedirect(location='foo') >>> req = Request.blank('/path/to/something') - >>> print str(req.get_response(exc)).strip() + >>> print(str(req.get_response(exc)).strip()) 307 Temporary Redirect Location: http://localhost/path/to/foo Content-Length: 126 Content-Type: text/plain; charset=UTF-8 - <BLANKLINE> + \r 307 Temporary Redirect <BLANKLINE> The resource has been moved to http://localhost/path/to/foo; you should be redirected automatically. @@ -932,7 +914,7 @@ request will an HTML response be given: .. code-block:: python >>> req.accept += 'text/html' - >>> print str(req.get_response(exc)).strip() + >>> print(str(req.get_response(exc)).strip()) 307 Temporary Redirect Location: http://localhost/path/to/foo Content-Length: 270 @@ -951,13 +933,6 @@ request will an HTML response be given: </body> </html> - -This is taken from `paste.httpexceptions -<https://bitbucket.org/ianb/paste/src/0e5a48796ab969d874c6b772c5c33561ac2d1b0d/paste/httpexceptions.py?at=default&fileviewer=file-view-default#httpexceptions.py-8>`_, -and if you have Paste installed then these exceptions will be subclasses of -the Paste exceptions. - - Conditional WSGI Application ---------------------------- @@ -976,12 +951,12 @@ To enable this you must create the response like ... last_modified=datetime(2005, 1, 1, 12, 0, tzinfo=UTC)) >>> req = Request.blank('/') >>> req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC) - >>> req.get_response(res) + >>> req.get_response(res) # doctest: +ELLIPSIS <Response ... 304 Not Modified> >>> del req.if_modified_since >>> res.etag = 'opaque-tag' >>> req.if_none_match = 'opaque-tag' - >>> req.get_response(res) + >>> req.get_response(res) # doctest: +ELLIPSIS <Response ... 304 Not Modified> >>> req.if_none_match = '*' @@ -1009,4 +984,4 @@ To enable this you must create the response like >>> result.headers['content-range'] 'bytes 1-4/10' >>> result.body - '1234' + b'1234' |
