Skip to content

Commit

Permalink
Proofreading the documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Edgemon committed Apr 20, 2010
1 parent 4ff9493 commit a7ff9db
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 58 deletions.
18 changes: 9 additions & 9 deletions docs/becomingbig.rst
Expand Up @@ -8,24 +8,24 @@ designed for large scale applications and does not attempt to do so, but
that does not mean you picked the wrong tool in the first place.

Flask is powered by Werkzeug and Jinja2, two libraries that are in use at
a number of large websites out there and all Flask does is bringing those
a number of large websites out there and all Flask does is bring those
two together. Being a microframework, Flask is literally a single file.
What that means for large applications is that it's probably a good idea
to take the code from Flask and put it into a new module within the
applications and expanding on that.
applications and expand on that.

What Could Be Improved?
-----------------------

For instance it makes a lot of sense to change the way endpoints (the
names of the functions / URL rules) are handled to also take the module
name into account. Right now the function name is the URL name, but
imagine you have a large applications consisting of multiple components.
imagine you have a large application consisting of multiple components.
In that case, it makes a lot of sense to use dotted names for the URL
endpoints.

Here some suggestions how Flask can be modified to better accomodate large
scale applications:
Here are some suggestions for how Flask can be modified to better
accomodate large-scale applications:

- implement dotted names for URL endpoints
- get rid of the decorator function registering which causes a lot
Expand All @@ -35,7 +35,7 @@ scale applications:
better solution would be to have one module with all URLs in there and
specifing the target functions explicitly or by name and importing
them when needed.
- switch to explicit request object passing. This makes it more to type
- switch to explicit request object passing. This requires more typing
(because you now have something to pass around) but it makes it a
whole lot easier to debug hairy situations and to test the code.
- integrate the `Babel`_ i18n package or `SQLAlchemy`_ directly into the
Expand All @@ -44,14 +44,14 @@ scale applications:
.. _Babel: http://babel.edgewall.org/
.. _SQLAlchemy: http://www.sqlalchemy.org/

Why does not Flask do all that by Default?
Why does Flask not do all that by Default?
------------------------------------------

There is a huge difference between a small application that only has to
handle a couple of requests per second and with an overall code complexity
of less than 4000 lines of code or something of larger scale. At one
of less than 4000 lines of code and something of larger scale. At some
point it becomes important to integrate external systems, different
storage backends and more.

If Flask was designed with all these contingencies in mind, it would be a
much more complex framework and less easy to get started with.
much more complex framework and harder to get started with.
6 changes: 3 additions & 3 deletions docs/deploying/mod_wsgi.rst
Expand Up @@ -11,8 +11,8 @@ Installing `mod_wsgi`
If you don't have `mod_wsgi` installed yet you have to either install it using
a package manager or compile it yourself.

The mod_wsgi `installation instructions`_ cover installation instructions for
source installations on UNIX systems.
The mod_wsgi `installation instructions`_ cover source installations on UNIX
systems.

If you are using ubuntu / debian you can apt-get it and activate it as follows::

Expand Down Expand Up @@ -44,7 +44,7 @@ For most applications the following file should be sufficient::
If you don't have a factory function for application creation but a singleton
instance you can directly import that one as `application`.

Store that file somewhere where you will find it again (eg:
Store that file somewhere that you will find it again (e.g.:
`/var/www/yourapplication`) and make sure that `yourapplication` and all
the libraries that are in use are on the python load path. If you don't
want to install it system wide consider using a `virtual python`_ instance.
Expand Down
22 changes: 11 additions & 11 deletions docs/design.rst
Expand Up @@ -2,7 +2,7 @@ Design Decisions in Flask
=========================

If you are curious why Flask does certain things the way it does and not
different, this section is for you. This should give you an idea about
differently, this section is for you. This should give you an idea about
some of the design decisions that may appear arbitrary and surprising at
first, especially in direct comparison with other frameworks.

Expand Down Expand Up @@ -44,10 +44,10 @@ something it can be very helpful to create a minimal application to test
specific behavior. When the application object is deleted everything it
allocated will be freed again.

Another thing that becomes possible with having an explicit object laying
Another thing that becomes possible when you have an explicit object laying
around in your code is that you can subclass the base class
(:class:`~flask.Flask`) to alter specific behaviour. This would not be
possible without hacks if the object was created ahead of time for you
possible without hacks if the object were created ahead of time for you
based on a class that is not exposed to you.

But there is another very important reason why Flask depends on an
Expand Down Expand Up @@ -83,23 +83,23 @@ that limitation that Jinja2 is *always* configured will probably go away,
the decision to bundle one template engine and use that will not.

Template engines are like programming languages and each of those engines
has a certain understandment about how things work. On the surface they
has a certain understanding about how things work. On the surface they
all work the same: you tell the engine to evaluate a template with a set
of variables and take the return value as string.

But that's about where similarities end. Jinja2 for example has an
extensive filter system, a certain way to do template inheritance, support
for reusable blocks (macros) that can be used from inside templates and
also from Python code, is using unicode for all operations, supports
also from Python code, uses unicode for all operations, supports
iterative template rendering, configurable syntax and more. On the other
hand an engine like Genshi is based on XML stream evaluation, template
inheritance by taking the availability of XPath into account and more.
Mako on the other hand treats templates similar to Python modules.

When it comes to bridge a template engine with an application or framework
there is more than just rendering templates. Flask uses Jinja2's
extensive autoescaping support for instance. Also it provides ways to
access macros from Jinja2 templates.
When it comes to connecting a template engine with an application or
framework there is more than just rendering templates. For instance,
Flask uses Jinja2's extensive autoescaping support. Also it provides
ways to access macros from Jinja2 templates.

A template abstraction layer that would not take the unique features of
the template engines away is a science on its own and a too large
Expand All @@ -115,9 +115,9 @@ over to the Ruby side of web development there we have a protocol very
similar to WSGI. Just that it's called Rack there, but besides that it
looks very much like a WSGI rendition for Ruby. But nearly all
applications in Ruby land do not work with Rack directly, but on top of a
lirbary with the same name. This Rack library has two equivalents in
library with the same name. This Rack library has two equivalents in
Python: WebOb (formerly Paste) and Werkzeug. Paste is still around but
from my understanding it's sortof deprecated in favour of WebOb. The
from my understanding it's sort of deprecated in favour of WebOb. The
development of WebOb and Werkzeug started side by side with similar ideas
in mind: be a good implementation of WSGI for other applications to take
advantage.
Expand Down
18 changes: 9 additions & 9 deletions docs/installation.rst
Expand Up @@ -9,10 +9,10 @@ way and why there are multiple ways.

Flask depends on two external libraries: `Werkzeug
<http://werkzeug.pocoo.org/>`_ and `Jinja2 <http://jinja.pocoo.org/2/>`_.
The first on is responsible for interfacing WSGI the latter to render
The first one is responsible for interfacing WSGI the latter for rendering
templates. Now you are maybe asking, what is WSGI? WSGI is a standard
in Python that is basically responsible for ensuring that your application
is behaving in a specific way that you can run it on different
is behaving in a specific way so that you can run it on different
environments (for example on a local development server, on an Apache2, on
lighttpd, on Google's App Engine or whatever you have in mind).

Expand All @@ -26,10 +26,10 @@ Virtualenv is what you want to use during development and in production if
you have shell access. So first: what does virtualenv do? If you are
like me and you like Python, chances are you want to use it for another
project as well. Now the more projects you have, the more likely it is
that you will be working with different versions of Python itself or a
library involved. Because let's face it: quite often libraries break
backwards compatibility and it's unlikely that your application will
not have any dependencies, that just won't happen. So virtualenv for the
that you will be working with different versions of Python itself or at
least an individual library. Because let's face it: quite often libraries
break backwards compatibility and it's unlikely that your application will
not have any dependencies, that just won't happen. So virtualenv to the
rescue!

It basically makes it possible to have multiple side-by-side
Expand All @@ -47,7 +47,7 @@ or even better::

$ sudo pip install virtualenv

Changes are you have virtualenv installed on your system then. Maybe it's
Chances are you have virtualenv installed on your system then. Maybe it's
even in your package manager (on ubuntu try ``sudo apt-get install
python-virtualenv``).

Expand Down Expand Up @@ -152,7 +152,7 @@ Once you have done that it's important to add the `easy_install` command
and other Python scripts to the path. To do that you have to add the
Python installation's Script folder to the `PATH` variable.

To do that, click right on your "Computer" desktop icon and click
To do that, right-click on your "Computer" desktop icon and click
"Properties". On Windows Vista and Windows 7 then click on "Advanced System
settings", on Windows XP click on the "Advanced" tab instead. Then click
on the "Environment variables" button and double click on the "Path"
Expand All @@ -165,7 +165,7 @@ the following value::

;C:\Python26\Scripts

Then you are done. To check if it worked, open the cmd and execute
Then you are done. To check that it worked, open the cmd and execute
"easy_install". If you have UAC enabled it should prompt you for admin
privileges.

Expand Down
6 changes: 3 additions & 3 deletions docs/patterns/packages.rst
Expand Up @@ -48,12 +48,12 @@ What did we gain from this? Now we can restructure the application a bit
into multiple modules. The only thing you have to remember is the
following quick checklist:

1. the `Flask` application object creation have to be in the
1. the `Flask` application object creation has to be in the
`__init__.py` file. That way each module can import it safely and the
`__name__` variable will resole to the correct package.
`__name__` variable will resolve to the correct package.
2. all the view functions (the ones with a :meth:`~flask.Flask.route`
decorator on top) have to be imported when in the `__init__.py` file.
Not the objects itself, but the module it is in. Do the importing at
Not the object itself, but the module it is in. Do the importing at
the *bottom* of the file.

Here an example `__init__.py`::
Expand Down
18 changes: 9 additions & 9 deletions docs/patterns/sqlalchemy.rst
Expand Up @@ -6,7 +6,7 @@ SQLAlchemy in Flask
Many people prefer `SQLAlchemy`_ for database access. In this case it's
encouraged to use a package instead of a module for your flask application
and drop the models into a separate module (:ref:`larger-applications`).
Although that is not necessary but makes a lot of sense.
While that is not necessary, it makes a lot of sense.

There are three very common ways to use SQLAlchemy. I will outline each
of them here:
Expand Down Expand Up @@ -52,7 +52,7 @@ automatically remove database sessions at the end of the request for you::
db_session.remove()
return response

Here an example model (put that into `models.py` for instance)::
Here is an example model (put this into `models.py`, e.g.)::

from sqlalchemy import Column, Integer, String
from yourapplication.database import Base
Expand All @@ -70,7 +70,7 @@ Here an example model (put that into `models.py` for instance)::
def __repr__(self):
return '<User %r>' % (self.name, self.email)

You can insert entries into the database like this then:
You can insert entries into the database like this:

>>> from yourapplication.database import db_session
>>> from yourapplication.models import User
Expand All @@ -95,11 +95,11 @@ Manual Object Relational Mapping
Manual object relational mapping has a few upsides and a few downsides
versus the declarative approach from above. The main difference is that
you define tables and classes separately and map them together. It's more
flexible but a little more to type. In general it works similar to the
flexible but a little more to type. In general it works like the
declarative approach, so make sure to also split up your application into
multiple modules in a package.

Here the example `database.py` module for your application::
Here is an example `database.py` module for your application::

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker
Expand All @@ -112,7 +112,7 @@ Here the example `database.py` module for your application::
def init_db():
metadata.create_all(bind=engine)

As for the declarative approach you need to close down the session after
As for the declarative approach you need to close the session after
each request. Put this into your application module::

from yourapplication.database import db_session
Expand All @@ -122,7 +122,7 @@ each request. Put this into your application module::
db_session.remove()
return response

Here an example table and model (put that into `models.py` for instance)::
Here is an example table and model (put this into `models.py`)::

from sqlalchemy import Table, Column, Integer, String
from sqlalchemy.orm import mapper
Expand Down Expand Up @@ -172,7 +172,7 @@ connection first so that we can use a transaction:

SQLAlchemy will automatically commit for us.

To query your database, yu use the engine directly or use a connection:
To query your database, you use the engine directly or use a connection:

>>> users.select(users.c.id == 1).execute().first()
(1, u'admin', u'admin@localhost')
Expand All @@ -183,7 +183,7 @@ These results are also dict-like tuples:
>>> r['name']
u'admin'

You can also pass string of SQL statements to the
You can also pass strings of SQL statements to the
:meth:`~sqlalchemy.engine.base.Connection.execute` method:

>>> engine.execute('select * from users where id = :1', [1]).first()
Expand Down
6 changes: 3 additions & 3 deletions docs/patterns/sqlite3.rst
Expand Up @@ -3,12 +3,12 @@
Using SQLite 3 with Flask
=========================

In Flask you can implement opening of dabase connections at the beginning
In Flask you can implement opening of database connections at the beginning
of the request and closing at the end with the
:meth:`~flask.Flask.before_request` and :meth:`~flask.Flask.after_request`
decorators in combination with the special :class:`~flask.g` object.

So here a simple example how you can use SQLite 3 with Flask::
So here a simple example of how you can use SQLite 3 with Flask::

import sqlite3
from flask import g
Expand Down Expand Up @@ -70,7 +70,7 @@ Initial Schemas

Relational databases need schemas, so applications often ship a
`schema.sql` file that creates the database. It's a good idea to provide
a function that creates the database bases on that schema. This function
a function that creates the database based on that schema. This function
can do that for you::

from contextlib import closing
Expand Down
22 changes: 11 additions & 11 deletions docs/testing.rst
Expand Up @@ -8,14 +8,14 @@ Testing Flask Applications
Not sure where that is coming from, and it's not entirely correct, but
also not that far from the truth. Untested applications make it hard to
improve existing code and developers of untested applications tend to
become pretty paranoid. If an application however has automated tests you
can savely change things and you will instantly know if your change broke
become pretty paranoid. If an application however has automated tests, you
can safely change things and you will instantly know if your change broke
something.

Flask gives you a couple of ways to test applications. It mainly does
that by exposing the Werkzeug test :class:`~werkzeug.Client` class to your
code and handling the context locals for you. You can then use that with
your favourite testing solution. In this documentation we will us the
your favourite testing solution. In this documentation we will use the
:mod:`unittest` package that comes preinstalled with each Python
installation.

Expand Down Expand Up @@ -50,13 +50,13 @@ In order to test that, we add a second module (
if __name__ == '__main__':
unittest.main()

The code in the `setUp` function creates a new test client and initialize
The code in the `setUp` function creates a new test client and initializes
a new database. That function is called before each individual test function.
What the test client does for us is giving us a simple interface to the
What the test client does is give us a simple interface to the
application. We can trigger test requests to the application and the
client will also keep track of cookies for us.

Because SQLite3 is filesystem based we can easily use the tempfile module
Because SQLite3 is filesystem-based we can easily use the tempfile module
to create a temporary database and initialize it. Just make sure that you
keep a reference to the :class:`~tempfile.NamedTemporaryFile` around (we
store it as `self.db` because of that) so that the garbage collector does
Expand Down Expand Up @@ -112,20 +112,20 @@ Run it again and you should see one passing test::

OK

Of course you can submit forms with the test client as well which we will
Of course you can submit forms with the test client as well, which we will
use now to log our user in.

Logging In and Out
------------------

The majority of the functionality of our application is only available for
the administration user. So we need a way to log our test client into the
the administration user. So we need a way to log our test client in to the
application and out of it again. For that we fire some requests to the
login and logout pages with the required form data (username and
password). Because the login and logout pages redirect, we tell the
client to `follow_redirects`.

Add the following two methods do your `FlaskrTestCase` class::
Add the following two methods to your `FlaskrTestCase` class::

def login(self, username, password):
return self.app.post('/login', data=dict(
Expand All @@ -137,7 +137,7 @@ Add the following two methods do your `FlaskrTestCase` class::
return self.app.get('/logout', follow_redirects=True)

Now we can easily test if logging in and out works and that it fails with
invalid credentials. Add this as new test to the class::
invalid credentials. Add this new test to the class::

def test_login_logout(self):
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD)
Expand Down Expand Up @@ -165,7 +165,7 @@ like this::
assert '&lt;Hello&gt' in rv.data
assert '<strong>HTML</strong> allowed here' in rv.data

Here we also check that HTML is allowed in the text but not in the title
Here we check that HTML is allowed in the text but not in the title,
which is the intended behavior.

Running that should now give us three passing tests::
Expand Down

1 comment on commit a7ff9db

@mitsuhiko
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for that.

Please sign in to comment.