forked from orbit-oss/flask
Added interactive Python docs, fixed part style.
This commit is contained in:
parent
9d98ad5e07
commit
ef0dc1800f
8 changed files with 215 additions and 81 deletions
4
CHANGES
4
CHANGES
|
|
@ -13,6 +13,10 @@ Release date to be announced
|
|||
log request handling exceptions to that logger when not in debug
|
||||
mode. This makes it possible to receive mails on server errors
|
||||
for example.
|
||||
- added support for context binding that does not require the use of
|
||||
the with statement for playing in the console.
|
||||
- the request context is now available within the with statement making
|
||||
it possible to further push the request context or pop it.
|
||||
|
||||
Version 0.2
|
||||
-----------
|
||||
|
|
|
|||
43
docs/contents.rst.inc
Normal file
43
docs/contents.rst.inc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
User's Guide
|
||||
------------
|
||||
|
||||
This part of the documentation is written text and should give you an idea
|
||||
how to work with Flask. It's a series of step-by-step instructions for
|
||||
web development.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
foreword
|
||||
installation
|
||||
quickstart
|
||||
tutorial/index
|
||||
testing
|
||||
errorhandling
|
||||
shell
|
||||
patterns/index
|
||||
deploying/index
|
||||
becomingbig
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
If you are looking for information on a specific function, class or
|
||||
method, this part of the documentation is for you.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
|
||||
Additional Notes
|
||||
----------------
|
||||
|
||||
Design notes, legal information and changelog are here for the interested.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
design
|
||||
license
|
||||
changelog
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
\pagenumbering{arabic}
|
||||
\definecolor{TitleColor}{rgb}{0,0,0}
|
||||
\definecolor{InnerLinkColor}{rgb}{0,0,0}
|
||||
|
||||
|
|
@ -72,9 +71,10 @@
|
|||
|
||||
\renewcommand\thepart{\@Roman\c@part}
|
||||
\renewcommand\part{%
|
||||
\pagestyle{empty}
|
||||
\if@noskipsec \leavevmode \fi
|
||||
\cleardoublepage
|
||||
\vspace*{8cm}%
|
||||
\vspace*{6cm}%
|
||||
\@afterindentfalse
|
||||
\secdef\@part\@spart}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
\else
|
||||
\addcontentsline{toc}{part}{#1}%
|
||||
\fi
|
||||
{\parindent \z@ \center
|
||||
{\parindent \z@ %\center
|
||||
\interlinepenalty \@M
|
||||
\normalfont
|
||||
\ifnum \c@secnumdepth >\m@ne
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
\vskip 8ex
|
||||
\@afterheading}
|
||||
\def\@spart#1{%
|
||||
{\parindent \z@ \center
|
||||
{\parindent \z@ %\center
|
||||
\interlinepenalty \@M
|
||||
\normalfont
|
||||
\huge \bfseries #1\par}%
|
||||
|
|
|
|||
|
|
@ -27,45 +27,4 @@ following links:
|
|||
.. _Jinja2: http://jinja.pocoo.org/2/
|
||||
.. _Werkzeug: http://werkzeug.pocoo.org/
|
||||
|
||||
User's Guide
|
||||
------------
|
||||
|
||||
This part of the documentation is written text and should give you an idea
|
||||
how to work with Flask. It's a series of step-by-step instructions for
|
||||
web development.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
foreword
|
||||
installation
|
||||
quickstart
|
||||
tutorial/index
|
||||
testing
|
||||
errorhandling
|
||||
patterns/index
|
||||
deploying/index
|
||||
becomingbig
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
If you are looking for information on a specific function, class or
|
||||
method, this part of the documentation is for you:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
|
||||
Additional Notes
|
||||
----------------
|
||||
|
||||
Design notes, legal information and changelog are here for the interested:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
design
|
||||
license
|
||||
changelog
|
||||
.. include:: contents.rst.inc
|
||||
|
|
|
|||
|
|
@ -3,36 +3,4 @@
|
|||
Flask Documentation
|
||||
===================
|
||||
|
||||
User's Guide
|
||||
------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
foreword
|
||||
installation
|
||||
quickstart
|
||||
tutorial/index
|
||||
testing
|
||||
errorhandling
|
||||
patterns/index
|
||||
deploying/index
|
||||
becomingbig
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
api
|
||||
|
||||
Additional Notes
|
||||
----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
design
|
||||
license
|
||||
changelog
|
||||
.. include:: contents.rst.inc
|
||||
|
|
|
|||
110
docs/shell.rst
Normal file
110
docs/shell.rst
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
Working with the Shell
|
||||
======================
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
One of the reasons everybody loves Python is the interactive shell. It
|
||||
basically allows you to execute Python commands in real time and
|
||||
immediately get results back. Flask itself does not come with an
|
||||
interactive shell, because it does not require any specific setup upfront,
|
||||
just import your application and start playing around.
|
||||
|
||||
There are however some handy helpers to make playing around in the shell a
|
||||
more pleasant experience. The main issue with interactive console
|
||||
sessions is that you're not triggering a request like a browser does which
|
||||
means that :data:`~flask.g`, :data:`~flask.request` and others are not
|
||||
available. But the code you want to test might depend on them, so what
|
||||
can you do?
|
||||
|
||||
This is where some helper functions come in handy. Keep in mind however
|
||||
that these functions are not only there for interactive shell usage, but
|
||||
also for unittesting and other situations that require a faked request
|
||||
context.
|
||||
|
||||
Diving into Context Locals
|
||||
--------------------------
|
||||
|
||||
Say you have a utility function that returns the URL the user should be
|
||||
redirected to. Imagine it would always redirect to the URL's ``next``
|
||||
parameter or the HTTP referrer or the index page::
|
||||
|
||||
from flask import request, url_for
|
||||
|
||||
def redirect_url():
|
||||
return request.args.get('next') or \
|
||||
request.referrer or \
|
||||
url_for('index')
|
||||
|
||||
As you can see, it accesses the request object. If you try to run this
|
||||
from a plain Python shell, this is the exception you will see:
|
||||
|
||||
>>> redirect_url()
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AttributeError: 'NoneType' object has no attribute 'request'
|
||||
|
||||
That makes a lot of sense because we currently do not have a request we
|
||||
could access. So we have to make a request and bind it to the current
|
||||
context. The :attr:`~flask.Flask.test_request_context` method can create
|
||||
us a request context:
|
||||
|
||||
>>> ctx = app.test_request_context('/?next=http://example.com/')
|
||||
|
||||
This context can be used in two ways. Either with the `with` statement
|
||||
(which unfortunately is not very handy for shell sessions). The
|
||||
alternative way is to call the `push` and `pop` methods:
|
||||
|
||||
>>> ctx.push()
|
||||
|
||||
From that point onwards you can work with the request object:
|
||||
|
||||
>>> redirect_url()
|
||||
u'http://example.com/'
|
||||
|
||||
Until you call `pop`:
|
||||
|
||||
>>> ctx.pop()
|
||||
>>> redirect_url()
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AttributeError: 'NoneType' object has no attribute 'request'
|
||||
|
||||
|
||||
Firing Before/After Request
|
||||
---------------------------
|
||||
|
||||
By just creating a request context, you still don't have run the code that
|
||||
is normally run before a request. This probably results in your database
|
||||
being unavailable, the current user not being stored on the
|
||||
:data:`~flask.g` object etc.
|
||||
|
||||
This however can easily be done yourself. Just call
|
||||
:meth:`~flask.Flask.preprocess_request`:
|
||||
|
||||
>>> ctx = app.test_request_context()
|
||||
>>> ctx.push()
|
||||
>>> app.preprocess_request()
|
||||
|
||||
Keep in mind that the :meth:`~flask.Flask.preprocess_request` function
|
||||
might return a response object, in that case just ignore it.
|
||||
|
||||
To shutdown a request, you need to trick a bit before the after request
|
||||
functions (triggered by :meth:`~flask.Flask.process_response`) operate on
|
||||
a response object:
|
||||
|
||||
>>> app.process_response(app.response_class())
|
||||
<Response 0 bytes [200 OK]>
|
||||
>>> ctx.pop()
|
||||
|
||||
|
||||
Further Improving the Shell Experience
|
||||
--------------------------------------
|
||||
|
||||
If you like the idea of experimenting in a shell, create yourself a module
|
||||
with stuff you want to star import into your interactive session. There
|
||||
you could also define some more helper methods for common things such as
|
||||
initializing the database, dropping tables etc.
|
||||
|
||||
Just put them into a module (like `shelltools` and import from there):
|
||||
|
||||
>>> from shelltools import *
|
||||
37
flask.py
37
flask.py
|
|
@ -147,15 +147,24 @@ class _RequestContext(object):
|
|||
except HTTPException, e:
|
||||
self.request.routing_exception = e
|
||||
|
||||
def __enter__(self):
|
||||
def push(self):
|
||||
"""Binds the request context."""
|
||||
_request_ctx_stack.push(self)
|
||||
|
||||
def pop(self):
|
||||
"""Pops the request context."""
|
||||
_request_ctx_stack.pop()
|
||||
|
||||
def __enter__(self):
|
||||
self.push()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, tb):
|
||||
# do not pop the request stack if we are in debug mode and an
|
||||
# exception happened. This will allow the debugger to still
|
||||
# access the request object in the interactive shell.
|
||||
if tb is None or not self.app.debug:
|
||||
_request_ctx_stack.pop()
|
||||
self.pop()
|
||||
|
||||
|
||||
def url_for(endpoint, **values):
|
||||
|
|
@ -1202,6 +1211,30 @@ class Flask(_PackageBoundObject):
|
|||
with app.request_context(environ):
|
||||
do_something_with(request)
|
||||
|
||||
The object returned can also be used without the `with` statement
|
||||
which is useful for working in the shell. The example above is
|
||||
doing exactly the same as this code::
|
||||
|
||||
ctx = app.request_context(environ)
|
||||
ctx.push()
|
||||
try:
|
||||
do_something_with(request)
|
||||
finally:
|
||||
ctx.pop()
|
||||
|
||||
The big advantage of this approach is that you can use it without
|
||||
the try/finally statement in a shell for interactive testing:
|
||||
|
||||
>>> ctx = app.test_request_context()
|
||||
>>> ctx.bind()
|
||||
>>> request.path
|
||||
u'/'
|
||||
>>> ctx.unbind()
|
||||
|
||||
.. versionchanged:: 0.5
|
||||
Added support for non-with statement usage and `with` statement
|
||||
is now passed the ctx object.
|
||||
|
||||
:param environ: a WSGI environment
|
||||
"""
|
||||
return _RequestContext(self, environ)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,23 @@ class ContextTestCase(unittest.TestCase):
|
|||
with app.test_request_context('/meh'):
|
||||
assert meh() == 'http://localhost/meh'
|
||||
|
||||
def test_manual_context_binding(self):
|
||||
app = flask.Flask(__name__)
|
||||
@app.route('/')
|
||||
def index():
|
||||
return 'Hello %s!' % flask.request.args['name']
|
||||
|
||||
ctx = app.test_request_context('/?name=World')
|
||||
ctx.push()
|
||||
assert index() == 'Hello World!'
|
||||
ctx.pop()
|
||||
try:
|
||||
index()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
assert 0, 'expected runtime error'
|
||||
|
||||
|
||||
class BasicFunctionalityTestCase(unittest.TestCase):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue