Skip to content

Commit

Permalink
Ported examples over to new config. documented upgrading
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed May 27, 2010
1 parent 02b916d commit dfecc86
Show file tree
Hide file tree
Showing 17 changed files with 122 additions and 39 deletions.
2 changes: 1 addition & 1 deletion docs/_themes
Submodule _themes updated from f87d00 to 0d8f3d
1 change: 0 additions & 1 deletion docs/becomingbig.rst
Expand Up @@ -27,7 +27,6 @@ endpoints.
Here are some suggestions for how Flask can be modified to better
accommodate large-scale applications:

- implement dotted names for URL endpoints
- get rid of the decorator function registering which causes a lot
of troubles for applications that have circular dependencies. It
also requires that the whole application is imported when the system
Expand Down
4 changes: 4 additions & 0 deletions docs/config.rst
@@ -1,3 +1,5 @@
.. _config:

Configuration Handling
======================

Expand Down Expand Up @@ -47,6 +49,8 @@ Builtin Configuration Values

The following configuration values are used internally by Flask:

.. tabularcolumns:: |p{6.5cm}|p{8.5cm}|

=============================== =========================================
``DEBUG`` enable/disable debug mode
``SECRET_KEY`` the secret key
Expand Down
1 change: 1 addition & 0 deletions docs/contents.rst.inc
Expand Up @@ -41,4 +41,5 @@ Design notes, legal information and changelog are here for the interested.

design
license
upgrading
changelog
5 changes: 0 additions & 5 deletions docs/foreword.rst
Expand Up @@ -84,11 +84,6 @@ widespread usage. Recent versions of Flask scale nicely within reasonable
bounds and if you grow larger, you won't have any troubles adjusting Flask
for your new application size.

Flask serves two purposes: it's an example of how to create a minimal and
opinionated framework on top of Werkzeug to show how this can be done, and
to provide people with a simple tool to prototype larger applications or
to implement small and medium sized applications.

If you suddenly discover that your application grows larger than
originally intended, head over to the :ref:`becomingbig` section to see
some possible solutions for larger applications.
Expand Down
2 changes: 2 additions & 0 deletions docs/patterns/appfactories.rst
@@ -1,3 +1,5 @@
.. _app-factories:

Application Factories
=====================

Expand Down
2 changes: 1 addition & 1 deletion docs/patterns/jquery.rst
Expand Up @@ -77,7 +77,7 @@ inside a `script` block here where different rules apply.
will not be parsed. Everything until ``</script>`` is handled as script.
This also means that there must never be any ``</`` between the script
tags. ``|tojson`` is kindly enough to do the right thing here and
escape slashes for you (``{{ "</script>"|tojson|safe }`` is rendered as
escape slashes for you (``{{ "</script>"|tojson|safe }}`` is rendered as
``"<\/script>"``).


Expand Down
14 changes: 9 additions & 5 deletions docs/testing.rst
Expand Up @@ -94,7 +94,7 @@ this::
class FlaskrTestCase(unittest.TestCase):

def setUp(self):
self.db_fd, flaskr.DATABASE = tempfile.mkstemp()
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
self.app = flaskr.app.test_client()
flaskr.init_db()

Expand Down Expand Up @@ -151,13 +151,13 @@ Now we can easily test if logging in and out works and that it fails with
invalid credentials. Add this new test to the class::

def test_login_logout(self):
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD)
rv = self.login('admin', 'default')
assert 'You were logged in' in rv.data
rv = self.logout()
assert 'You were logged out' in rv.data
rv = self.login(flaskr.USERNAME + 'x', flaskr.PASSWORD)
rv = self.login('adminx', 'default')
assert 'Invalid username' in rv.data
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD + 'x')
rv = self.login('admin', 'defaultx')
assert 'Invalid password' in rv.data

Test Adding Messages
Expand All @@ -167,7 +167,7 @@ Now we can also test that adding messages works. Add a new test method
like this::

def test_messages(self):
self.login(flaskr.USERNAME, flaskr.PASSWORD)
self.login('admin', 'default')
rv = self.app.post('/add', data=dict(
title='<Hello>',
text='<strong>HTML</strong> allowed here'
Expand Down Expand Up @@ -214,3 +214,7 @@ functions. Here a full example that showcases this::
assert flask.request.args['name'] == 'Peter'

All the other objects that are context bound can be used the same.

If you want to test your application with different configurations and
there does not seem to be a good way to do that, consider switching to
application factories (see :ref:`app-factories`).
23 changes: 19 additions & 4 deletions docs/tutorial/setup.rst
Expand Up @@ -26,12 +26,27 @@ the values from there.
PASSWORD = 'default'

Next we can create our actual application and initialize it with the
config::
config from the same file::

# create our little application :)
app = Flask(__name__)
app.secret_key = SECRET_KEY
app.debug = DEBUG
app.config.from_object(__name__)

:meth:`~flask.Config.from_object` will look at the given object (if it's a
string it will import it) and then look for all uppercase variables
defined there. In our case, the configuration we just wrote a few lines
of code above. You can also move that into a separate file.

It is also a good idea to be able to load a configuration from a
configurable file. This is what :meth:`~flask.Config.from_envvar` can
do::

app.config.from_envvar('FLASKR_SETTINGS', silent=True)

That way someone can set an environment variable called
:envvar:`FLASKR_SETTINGS` to specify a config file to be loaded which will
then override the default values. The silent switch just tells Flask to
not complain if no such environment key is set.

The `secret_key` is needed to keep the client-side sessions secure.
Choose that key wisely and as hard to guess and complex as possible. The
Expand All @@ -46,7 +61,7 @@ Python shell or a script. This will come in handy later
::

def connect_db():
return sqlite3.connect(DATABASE)
return sqlite3.connect(app.config['DATABASE'])

Finally we just add a line to the bottom of the file that fires up the
server if we run that file as standalone application::
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorial/views.rst
Expand Up @@ -63,9 +63,9 @@ notified about that and the user asked again::
def login():
error = None
if request.method == 'POST':
if request.form['username'] != USERNAME:
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != PASSWORD:
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
Expand Down
56 changes: 56 additions & 0 deletions docs/upgrading.rst
@@ -0,0 +1,56 @@
Upgrading to Newer Releases
===========================

Flask itself is changing like any software is changing over time. Most of
the changes are the nice kind, the kind where you don't have th change
anything in your code to profit from a new release.

However every once in a while there are changes that do require some
changes in your code or there are changes that make it possible for you to
improve your own code quality by taking advantage of new features in
Flask.

This section of the documentation enumerates all the changes in Flask from
release to release and how you can change your code to have a painless
updating experience.

Version 0.5
-----------

Flask 0.5 introduces configuration support and logging as well as
categories for flashing messages. All these are features that are 100%
backwards compatible but you might want to take advantage of them.

Configuration Support
`````````````````````

The configuration support makes it easier to write any kind of application
that requires some sort of configuration. (Which most likely is the case
for any application out there).

If you previously had code like this::

app.debug = DEBUG
app.secret_key = SECRET_KEY

You no longer have to do that, instead you can just load a configuration
into the config object. How this works is outlined in :ref:`config`.

Logging Integration
```````````````````

Flask now configures a logger for you with some basic and useful defaults.
If you run your application in production and want to profit from
automatic error logging, you might be interested in attaching a proper log
handler. Also you can start logging warnings and errors into the logger
when appropriately. For more information on that, read
:ref:`application-errors`.

Categories for Flash Messages
`````````````````````````````

Flash messages can now have categories attached. This makes it possible
to render errors, warnings or regular messages differently for example.
This is an opt-in feature because it requires some rethinking in the code.

Read all about that in the :ref:`message-flashing-pattern` pattern.
4 changes: 3 additions & 1 deletion examples/flaskr/README
Expand Up @@ -10,7 +10,9 @@

~ How do I use it?

1. edit the configuration in the flaskr.py file
1. edit the configuration in the flaskr.py file or
export an FLASKR_SETTINGS environment variable
pointing to a configuration file.

2. fire up a python shell and run this:

Expand Down
10 changes: 5 additions & 5 deletions examples/flaskr/flaskr.py
Expand Up @@ -24,13 +24,13 @@

# create our little application :)
app = Flask(__name__)
app.secret_key = SECRET_KEY
app.debug = DEBUG
app.config.from_object(__name__)
app.config.from_envvar('FLASKR_SETTINGS', silent=True)


def connect_db():
"""Returns a new connection to the database."""
return sqlite3.connect(DATABASE)
return sqlite3.connect(app.config['DATABASE'])


def init_db():
Expand Down Expand Up @@ -76,9 +76,9 @@ def add_entry():
def login():
error = None
if request.method == 'POST':
if request.form['username'] != USERNAME:
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != PASSWORD:
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
Expand Down
16 changes: 10 additions & 6 deletions examples/flaskr/flaskr_tests.py
Expand Up @@ -18,14 +18,14 @@ class FlaskrTestCase(unittest.TestCase):

def setUp(self):
"""Before each test, set up a blank database"""
self.db_fd, flaskr.DATABASE = tempfile.mkstemp()
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
self.app = flaskr.app.test_client()
flaskr.init_db()

def tearDown(self):
"""Get rid of the database again after each test."""
os.close(self.db_fd)
os.unlink(flaskr.DATABASE)
os.unlink(flaskr.app.config['DATABASE'])

def login(self, username, password):
return self.app.post('/login', data=dict(
Expand All @@ -45,18 +45,22 @@ def test_empty_db(self):

def test_login_logout(self):
"""Make sure login and logout works"""
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD)
rv = self.login(flaskr.app.config['USERNAME'],
flaskr.app.config['PASSWORD'])
assert 'You were logged in' in rv.data
rv = self.logout()
assert 'You were logged out' in rv.data
rv = self.login(flaskr.USERNAME + 'x', flaskr.PASSWORD)
rv = self.login(flaskr.app.config['USERNAME'] + 'x',
flaskr.app.config['PASSWORD'])
assert 'Invalid username' in rv.data
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD + 'x')
rv = self.login(flaskr.app.config['USERNAME'],
flaskr.app.config['PASSWORD'] + 'x')
assert 'Invalid password' in rv.data

def test_messages(self):
"""Test that messages work"""
self.login(flaskr.USERNAME, flaskr.PASSWORD)
self.login(flaskr.app.config['USERNAME'],
flaskr.app.config['PASSWORD'])
rv = self.app.post('/add', data=dict(
title='<Hello>',
text='<strong>HTML</strong> allowed here'
Expand Down
4 changes: 3 additions & 1 deletion examples/minitwit/README
Expand Up @@ -10,7 +10,9 @@

~ How do I use it?

1. edit the configuration in the minitwit.py file
1. edit the configuration in the minitwit.py file or
export an MINITWIT_SETTINGS environment variable
pointing to a configuration file.

2. fire up a python shell and run this:

Expand Down
9 changes: 4 additions & 5 deletions examples/minitwit/minitwit.py
Expand Up @@ -27,11 +27,13 @@

# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('MINITWIT_SETTINGS', silent=True)


def connect_db():
"""Returns a new connection to the database."""
return sqlite3.connect(DATABASE)
return sqlite3.connect(app.config['DATABASE'])


def init_db():
Expand Down Expand Up @@ -237,12 +239,9 @@ def logout():
return redirect(url_for('public_timeline'))


# add some filters to jinja and set the secret key and debug mode
# from the configuration.
# add some filters to jinja
app.jinja_env.filters['datetimeformat'] = format_datetime
app.jinja_env.filters['gravatar'] = gravatar_url
app.secret_key = SECRET_KEY
app.debug = DEBUG


if __name__ == '__main__':
Expand Down
4 changes: 2 additions & 2 deletions examples/minitwit/minitwit_tests.py
Expand Up @@ -18,14 +18,14 @@ class MiniTwitTestCase(unittest.TestCase):

def setUp(self):
"""Before each test, set up a blank database"""
self.db_fd, minitwit.DATABASE = tempfile.mkstemp()
self.db_fd, minitwit.app.config['DATABASE'] = tempfile.mkstemp()
self.app = minitwit.app.test_client()
minitwit.init_db()

def tearDown(self):
"""Get rid of the database again after each test."""
os.close(self.db_fd)
os.unlink(minitwit.DATABASE)
os.unlink(minitwit.app.config['DATABASE'])

# helper functions

Expand Down

0 comments on commit dfecc86

Please sign in to comment.