diff --git a/.travis.yml b/.travis.yml
index 86d7cfea..097c9af6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,13 +15,14 @@ matrix:
include:
- env: TOXENV=docs-html
- env: TOXENV=devel,lowest,codecov
- - os: osx
- language: generic
- env: TOXENV=py3,codecov
- cache:
- directories:
- - $HOME/Library/Caches/Homebrew
- - $HOME/Library/Caches/pip
+# disabled because before_install is too slow
+# - os: osx
+# language: generic
+# env: TOXENV=py3,codecov
+# cache:
+# directories:
+# - $HOME/Library/Caches/Homebrew
+# - $HOME/Library/Caches/pip
allow_failures:
- python: nightly
- python: pypy3.5-6.0
diff --git a/MANIFEST.in b/MANIFEST.in
index d8a725b5..4cb69870 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,4 @@
-include Makefile CHANGES.rst LICENSE AUTHORS tox.ini
+include Makefile CHANGES.rst CONTRIBUTING.rst LICENSE AUTHORS tox.ini
graft artwork
graft tests
diff --git a/docs/config.rst b/docs/config.rst
index 2bc42941..03938ef6 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -301,8 +301,8 @@ The following configuration values are used internally by Flask:
Serialize objects to ASCII-encoded JSON. If this is disabled, the JSON
will be returned as a Unicode string, or encoded as ``UTF-8`` by
- ``jsonify``. This has security implications when rendering the JSON in
- to JavaScript in templates, and should typically remain enabled.
+ ``jsonify``. This has security implications when rendering the JSON into
+ JavaScript in templates, and should typically remain enabled.
Default: ``True``
@@ -553,6 +553,44 @@ To enable such a config you just have to call into
app.config.from_object('configmodule.ProductionConfig')
+Note that :meth:`~flask.Config.from_object` does not instantiate the class
+object. If you need to instantiate the class, such as to access a property,
+then you must do so before calling :meth:`~flask.Config.from_object`::
+
+ from configmodule import ProductionConfig
+ app.config.from_object(ProductionConfig())
+
+ # Alternatively, import via string:
+ from werkzeug.utils import import_string
+ cfg = import_string('configmodule.ProductionConfig')()
+ app.config.from_object(cfg)
+
+Instantiating the configutation object allows you to use ``@property`` in
+your configuration classes::
+
+ class Config(object):
+ """Base config, uses staging database server."""
+ DEBUG = False
+ TESTING = False
+ DB_SERVER = '192.168.1.56'
+
+ @property
+ def DATABASE_URI(self): # Note: all caps
+ return 'mysql://user@{}/foo'.format(self.DB_SERVER)
+
+ class ProductionConfig(Config):
+ """Uses production database server."""
+ DB_SERVER = '192.168.19.32'
+
+ class DevelopmentConfig(Config):
+ DB_SERVER = 'localhost'
+ DEBUG = True
+
+ class TestingConfig(Config):
+ DB_SERVER = 'localhost'
+ DEBUG = True
+ DATABASE_URI = 'sqlite:///:memory:'
+
There are many different ways and it's up to you how you want to manage
your configuration files. However here a list of good recommendations:
@@ -636,7 +674,7 @@ root” (the default) to “relative to instance folder” via the
app = Flask(__name__, instance_relative_config=True)
Here is a full example of how to configure Flask to preload the config
-from a module and then override the config from a file in the config
+from a module and then override the config from a file in the instance
folder if it exists::
app = Flask(__name__, instance_relative_config=True)
diff --git a/docs/patterns/index.rst b/docs/patterns/index.rst
index af5d04f9..2a201e76 100644
--- a/docs/patterns/index.rst
+++ b/docs/patterns/index.rst
@@ -34,7 +34,7 @@ Snippet Archives `_.
jquery
errorpages
lazyloading
- mongokit
+ mongoengine
favicon
streaming
deferredcallbacks
diff --git a/docs/patterns/jquery.rst b/docs/patterns/jquery.rst
index 8a1bfc21..0032e44e 100644
--- a/docs/patterns/jquery.rst
+++ b/docs/patterns/jquery.rst
@@ -105,7 +105,7 @@ example that shows how you would use jQuery and Flask nonetheless::
return render_template('index.html')
As you can see I also added an `index` method here that renders a
-template. This template will load jQuery as above and have a little form
+template. This template will load jQuery as above and have a little form where
we can add two numbers and a link to trigger the function on the server
side.
diff --git a/docs/patterns/mongoengine.rst b/docs/patterns/mongoengine.rst
new file mode 100644
index 00000000..015e7b61
--- /dev/null
+++ b/docs/patterns/mongoengine.rst
@@ -0,0 +1,103 @@
+MongoDB with MongoEngine
+========================
+
+Using a document database like MongoDB is a common alternative to
+relational SQL databases. This pattern shows how to use
+`MongoEngine`_, a document mapper library, to integrate with MongoDB.
+
+A running MongoDB server and `Flask-MongoEngine`_ are required. ::
+
+ pip install flask-mongoengine
+
+.. _MongoEngine: http://mongoengine.org
+.. _Flask-MongoEngine: https://flask-mongoengine.readthedocs.io
+
+
+Configuration
+-------------
+
+Basic setup can be done by defining ``MONGODB_SETTINGS`` on
+``app.config`` and creating a ``MongoEngine`` instance. ::
+
+ from flask import Flask
+ from flask_mongoengine import MongoEngine
+
+ app = Flask(__name__)
+ app.config['MONGODB_SETTINGS'] = {
+ "db": "myapp",
+ }
+ db = MongoEngine(app)
+
+
+Mapping Documents
+-----------------
+
+To declare a model that represents a Mongo document, create a class that
+inherits from ``Document`` and declare each of the fields. ::
+
+ import mongoengine as me
+
+ class Movie(me.Document):
+ title = me.StringField(required=True)
+ year = me.IntField()
+ rated = me.StringField()
+ director = me.StringField()
+ actors = me.ListField()
+
+If the document has nested fields, use ``EmbeddedDocument`` to
+defined the fields of the embedded document and
+``EmbeddedDocumentField`` to declare it on the parent document. ::
+
+ class Imdb(me.EmbeddedDocument):
+ imdb_id = me.StringField()
+ rating = me.DecimalField()
+ votes = me.IntField()
+
+ class Movie(me.Document):
+ ...
+ imdb = me.EmbeddedDocumentField(Imdb)
+
+
+Creating Data
+-------------
+
+Instantiate your document class with keyword arguments for the fields.
+You can also assign values to the field attributes after instantiation.
+Then call ``doc.save()``. ::
+
+ bttf = Movie(title="Back To The Future", year=1985)
+ bttf.actors = [
+ "Michael J. Fox",
+ "Christopher Lloyd"
+ ]
+ bttf.imdb = Imdb(imdb_id="tt0088763", rating=8.5)
+ bttf.save()
+
+
+Queries
+-------
+
+Use the class ``objects`` attribute to make queries. A keyword argument
+looks for an equal value on the field. ::
+
+ bttf = Movies.objects(title="Back To The Future").get_or_404()
+
+Query operators may be used by concatenating them with the field name
+using a double-underscore. ``objects``, and queries returned by
+calling it, are iterable. ::
+
+ some_theron_movie = Movie.objects(actors__in=["Charlize Theron"]).first()
+
+ for recents in Movie.objects(year__gte=2017):
+ print(recents.title)
+
+
+Documentation
+-------------
+
+There are many more ways to define and query documents with MongoEngine.
+For more information, check out the `official documentation
+`_.
+
+Flask-MongoEngine adds helpful utilities on top of MongoEngine. Check
+out their `documentation `_ as well.
diff --git a/docs/patterns/mongokit.rst b/docs/patterns/mongokit.rst
index f3957e09..cf072d5d 100644
--- a/docs/patterns/mongokit.rst
+++ b/docs/patterns/mongokit.rst
@@ -1,144 +1,7 @@
-.. mongokit-pattern:
+:orphan:
-MongoKit in Flask
-=================
+MongoDB with MongoKit
+=====================
-Using a document database rather than a full DBMS gets more common these days.
-This pattern shows how to use MongoKit, a document mapper library, to
-integrate with MongoDB.
-
-This pattern requires a running MongoDB server and the MongoKit library
-installed.
-
-There are two very common ways to use MongoKit. I will outline each of them
-here:
-
-
-Declarative
------------
-
-The default behavior of MongoKit is the declarative one that is based on
-common ideas from Django or the SQLAlchemy declarative extension.
-
-Here an example :file:`app.py` module for your application::
-
- from flask import Flask
- from mongokit import Connection, Document
-
- # configuration
- MONGODB_HOST = 'localhost'
- MONGODB_PORT = 27017
-
- # create the little application object
- app = Flask(__name__)
- app.config.from_object(__name__)
-
- # connect to the database
- connection = Connection(app.config['MONGODB_HOST'],
- app.config['MONGODB_PORT'])
-
-
-To define your models, just subclass the `Document` class that is imported
-from MongoKit. If you've seen the SQLAlchemy pattern you may wonder why we do
-not have a session and even do not define a `init_db` function here. On the
-one hand, MongoKit does not have something like a session. This sometimes
-makes it more to type but also makes it blazingly fast. On the other hand,
-MongoDB is schemaless. This means you can modify the data structure from one
-insert query to the next without any problem. MongoKit is just schemaless
-too, but implements some validation to ensure data integrity.
-
-Here is an example document (put this also into :file:`app.py`, e.g.)::
-
- from mongokit import ValidationError
-
- def max_length(length):
- def validate(value):
- if len(value) <= length:
- return True
- # must have %s in error format string to have mongokit place key in there
- raise ValidationError('%s must be at most {} characters long'.format(length))
- return validate
-
- class User(Document):
- structure = {
- 'name': unicode,
- 'email': unicode,
- }
- validators = {
- 'name': max_length(50),
- 'email': max_length(120)
- }
- use_dot_notation = True
- def __repr__(self):
- return '' % (self.name)
-
- # register the User document with our current connection
- connection.register([User])
-
-
-This example shows you how to define your schema (named structure), a
-validator for the maximum character length and uses a special MongoKit feature
-called `use_dot_notation`. Per default MongoKit behaves like a python
-dictionary but with `use_dot_notation` set to ``True`` you can use your
-documents like you use models in nearly any other ORM by using dots to
-separate between attributes.
-
-You can insert entries into the database like this:
-
->>> from yourapplication.database import connection
->>> from yourapplication.models import User
->>> collection = connection['test'].users
->>> user = collection.User()
->>> user['name'] = u'admin'
->>> user['email'] = u'admin@localhost'
->>> user.save()
-
-Note that MongoKit is kinda strict with used column types, you must not use a
-common `str` type for either `name` or `email` but unicode.
-
-Querying is simple as well:
-
->>> list(collection.User.find())
-[]
->>> collection.User.find_one({'name': u'admin'})
-
-
-.. _MongoKit: https://github.com/namlook/mongokit
-
-
-PyMongo Compatibility Layer
----------------------------
-
-If you just want to use PyMongo, you can do that with MongoKit as well. You
-may use this process if you need the best performance to get. Note that this
-example does not show how to couple it with Flask, see the above MongoKit code
-for examples::
-
- from MongoKit import Connection
-
- connection = Connection()
-
-To insert data you can use the `insert` method. We have to get a
-collection first, this is somewhat the same as a table in the SQL world.
-
->>> collection = connection['test'].users
->>> user = {'name': u'admin', 'email': u'admin@localhost'}
->>> collection.insert(user)
-
-MongoKit will automatically commit for us.
-
-To query your database, you use the collection directly:
-
->>> list(collection.find())
-[{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}]
->>> collection.find_one({'name': u'admin'})
-{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}
-
-These results are also dict-like objects:
-
->>> r = collection.find_one({'name': u'admin'})
->>> r['email']
-u'admin@localhost'
-
-For more information about MongoKit, head over to the
-`website `_.
+MongoKit is no longer maintained. See :doc:`/patterns/mongoengine`
+instead.
diff --git a/docs/patterns/packages.rst b/docs/patterns/packages.rst
index 248cff07..e9d14ca5 100644
--- a/docs/patterns/packages.rst
+++ b/docs/patterns/packages.rst
@@ -3,9 +3,7 @@
Larger Applications
===================
-For larger applications it's a good idea to use a package instead of a
-module. That is quite simple. Imagine a small application looks like
-this::
+Imagine a simple flask application structure that looks like this::
/yourapplication
yourapplication.py
@@ -17,8 +15,10 @@ this::
login.html
...
-The :ref:`tutorial ` is structured this way, see the
-:gh:`example code `.
+While this is fine for small applications, for larger applications
+it's a good idea to use a package instead of a module.
+The :ref:`tutorial ` is structured to use the package pattern,
+see the :gh:`example code `.
Simple Packages
---------------
diff --git a/docs/tutorial/factory.rst b/docs/tutorial/factory.rst
index 8aa80e2b..fbe1c8e2 100644
--- a/docs/tutorial/factory.rst
+++ b/docs/tutorial/factory.rst
@@ -127,7 +127,8 @@ Run The Application
Now you can run your application using the ``flask`` command. From the
terminal, tell Flask where to find your application, then run it in
-development mode.
+development mode. Remember, you should still be in the top-level
+``flask-tutorial`` directory, not the ``flaskr`` package.
Development mode shows an interactive debugger whenever a page raises an
exception, and restarts the server whenever you make changes to the
diff --git a/docs/tutorial/install.rst b/docs/tutorial/install.rst
index 9b37b853..c451d8de 100644
--- a/docs/tutorial/install.rst
+++ b/docs/tutorial/install.rst
@@ -108,6 +108,7 @@ You can observe that the project is now installed with ``pip list``.
Nothing changes from how you've been running your project so far.
``FLASK_APP`` is still set to ``flaskr`` and ``flask run`` still runs
-the application.
+the application, but you can call it from anywhere, not just the
+``flask-tutorial`` directory.
Continue to :doc:`tests`.
diff --git a/flask/config.py b/flask/config.py
index d6074baa..a5475ed1 100644
--- a/flask/config.py
+++ b/flask/config.py
@@ -156,6 +156,10 @@ class Config(dict):
from yourapplication import default_config
app.config.from_object(default_config)
+ Nothing is done to the object before loading. If the object is a
+ class and has ``@property`` attributes, it needs to be
+ instantiated before being passed to this method.
+
You should not use this function to load the actual configuration but
rather configuration defaults. The actual config should be loaded
with :meth:`from_pyfile` and ideally from a location not within the