[Python-modules-commits] [flask-sqlalchemy] 01/04: Import flask-sqlalchemy_2.1.orig.tar.gz

Orestis Ioannou oorestisime-guest at moszumanska.debian.org
Tue Feb 23 09:32:34 UTC 2016


This is an automated email from the git hooks/post-receive script.

oorestisime-guest pushed a commit to branch master
in repository flask-sqlalchemy.

commit e9968569ed80011b3477f96fcbced951c1223f3c
Author: Orestis Ioannou <orestis at oioannou.com>
Date:   Thu Feb 18 05:32:35 2016 +0100

    Import flask-sqlalchemy_2.1.orig.tar.gz
---
 CHANGES                                 |  62 +++++--
 Flask_SQLAlchemy.egg-info/PKG-INFO      |  18 +-
 Flask_SQLAlchemy.egg-info/requires.txt  |   3 +-
 LICENSE                                 |   2 +-
 PKG-INFO                                |  18 +-
 README                                  |  48 ++++-
 docs/_static/flask-sqlalchemy-small.png | Bin
 docs/api.rst                            |  13 ++
 docs/binds.rst                          |   3 +-
 docs/conf.py                            |  24 +--
 docs/config.rst                         | 128 ++++++++-----
 docs/contexts.rst                       |  16 +-
 docs/models.rst                         |   4 +-
 docs/quickstart.rst                     |   6 +-
 docs/signals.rst                        |  29 ++-
 flask_sqlalchemy/__init__.py            | 320 ++++++++++++++++++++++----------
 setup.cfg                               |  16 +-
 setup.py                                |  19 +-
 test_sqlalchemy.py                      | 205 +++++++++++++++++++-
 19 files changed, 694 insertions(+), 240 deletions(-)

diff --git a/CHANGES b/CHANGES
index 0723758..8d241b5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,40 +1,74 @@
 Changelog
----------
+=========
 
 Here you can see the full list of changes between each Flask-SQLAlchemy
 release.
 
-Version 0.17
-````````````
+Version 3.0
+-----------
 
-*In development*
+In development, codename Dubnium
+
+Version 2.1
+-----------
+
+Released on October 23rd 2015, codename Caesium
+
+- Table names are automatically generated in more cases, including
+  subclassing mixins and abstract models.
+- Allow using a custom MetaData object.
+- Add support for binds parameter to session.
+
+Version 2.0
+-----------
+
+Released on August 29th 2014, codename Bohrium
+
+- Changed how the builtin signals are subscribed to skip non Flask-SQLAlchemy
+  sessions.  This will also fix the attribute error about model changes
+  not existing.
+- Added a way to control how signals for model modifications are tracked.
+- Made the ``SignallingSession`` a public interface and added a hook
+  for customizing session creation.
+- If the ``bind`` parameter is given to the signalling session it will no
+  longer cause an error that a parameter is given twice.
+- Added working table reflection support.
+- Enabled autoflush by default.
+- Consider ``SQLALCHEMY_COMMIT_ON_TEARDOWN`` harmful and remove from docs.
+
+Version 1.0
+-----------
+
+Released on July 20th 2013, codename Aurum
 
 - Added Python 3.3 support.
 - Dropped 2.5 compatibility.
+- Various bugfixes
+- Changed versioning format to do major releases for each update now.
 
 Version 0.16
-````````````
+------------
 
 - New distribution format (flask_sqlalchemy)
 - Added support for Flask 0.9 specifics.
 
 Version 0.15
-````````````
+------------
 
 - Added session support for multiple databases
 
 Version 0.14
-````````````
+------------
 
 - Make relative sqlite paths relative to the application root.
 
 Version 0.13
-````````````
+------------
 
 - Fixed an issue with Flask-SQLAlchemy not selecting the correct binds.
 
 Version 0.12
-````````````
+------------
 - Added support for multiple databases.
 - Expose Flask-SQLAlchemy's BaseQuery as `db.Query`.
 - Set default query_class for `db.relation`, `db.relationship`, and
@@ -42,12 +76,12 @@ Version 0.12
 - Improved compatibility with Flask 0.7.
 
 Version 0.11
-````````````
+------------
 
 - Fixed a bug introduced in 0.10 with alternative table constructors.
 
 Version 0.10
-````````````
+------------
 
 - Added support for signals.
 - Table names are now automatically set from the class name unless
@@ -61,18 +95,18 @@ Version 0.10
   This makes it possible to omit the metadata.
 
 Version 0.9
-```````````
+-----------
 
 - applied changes to pass the Flask extension approval process.
 
 Version 0.8
-```````````
+-----------
 
 - added a few configuration keys for creating connections.
 - automatically activate connection recycling for MySQL connections.
 - added support for the Flask testing mode.
 
 Version 0.7
-```````````
+-----------
 
 - Initial public release
diff --git a/Flask_SQLAlchemy.egg-info/PKG-INFO b/Flask_SQLAlchemy.egg-info/PKG-INFO
index d1fa2b4..3b587dd 100644
--- a/Flask_SQLAlchemy.egg-info/PKG-INFO
+++ b/Flask_SQLAlchemy.egg-info/PKG-INFO
@@ -1,10 +1,10 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: Flask-SQLAlchemy
-Version: 1.0
+Version: 2.1
 Summary: Adds SQLAlchemy support to your Flask application
 Home-page: http://github.com/mitsuhiko/flask-sqlalchemy
-Author: Armin Ronacher
-Author-email: armin.ronacher at active-4.com
+Author: Phil Howell
+Author-email: phil at quae.co.uk
 License: BSD
 Description: 
         Flask-SQLAlchemy
@@ -15,7 +15,7 @@ Description:
         Links
         `````
         
-        * `documentation <http://packages.python.org/Flask-SQLAlchemy>`_
+        * `documentation <http://flask-sqlalchemy.pocoo.org>`_
         * `development version
           <http://github.com/mitsuhiko/flask-sqlalchemy/zipball/master#egg=Flask-SQLAlchemy-dev>`_
         
@@ -25,6 +25,12 @@ Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
diff --git a/Flask_SQLAlchemy.egg-info/requires.txt b/Flask_SQLAlchemy.egg-info/requires.txt
index d07e166..fd75ba5 100644
--- a/Flask_SQLAlchemy.egg-info/requires.txt
+++ b/Flask_SQLAlchemy.egg-info/requires.txt
@@ -1,3 +1,2 @@
-setuptools
 Flask>=0.10
-SQLAlchemy
\ No newline at end of file
+SQLAlchemy>=0.7
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 562f7eb..49fcac3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010 by Armin Ronacher.
+Copyright (c) 2014 by Armin Ronacher.
 
 Some rights reserved.
 
diff --git a/PKG-INFO b/PKG-INFO
index d1fa2b4..3b587dd 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,10 +1,10 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: Flask-SQLAlchemy
-Version: 1.0
+Version: 2.1
 Summary: Adds SQLAlchemy support to your Flask application
 Home-page: http://github.com/mitsuhiko/flask-sqlalchemy
-Author: Armin Ronacher
-Author-email: armin.ronacher at active-4.com
+Author: Phil Howell
+Author-email: phil at quae.co.uk
 License: BSD
 Description: 
         Flask-SQLAlchemy
@@ -15,7 +15,7 @@ Description:
         Links
         `````
         
-        * `documentation <http://packages.python.org/Flask-SQLAlchemy>`_
+        * `documentation <http://flask-sqlalchemy.pocoo.org>`_
         * `development version
           <http://github.com/mitsuhiko/flask-sqlalchemy/zipball/master#egg=Flask-SQLAlchemy-dev>`_
         
@@ -25,6 +25,12 @@ Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
diff --git a/README b/README
index 5120fe9..0899ec5 100644
--- a/README
+++ b/README
@@ -1,3 +1,47 @@
-Flask-SQLAlchemy
 
-Adds SQLAlchemy support to Flask.  Under development.
+                          // Flask-SQLAlchemy //
+
+
+    ~ What is Flask-SQLAlchemy?
+
+      Flask-SQLAlchemy is a Flask microframework extension which adds
+      support for the SQLAlchemy SQL toolkit/ORM.
+
+    ~ What's the latest version?
+
+      2.0 is the most recent stable version. 2.1 is slated for release in early February. 
+      
+    ~ What do I need?
+
+      SQLAlchemy, and Flask 0.10 or later. `pip` or `easy_install` will
+      install them for you if you do `pip install Flask-SQLAlchemy`.
+      We encourage you to use a virtualenv. Check the docs for complete
+      installation and usage instructions.
+
+    ~ Where are the docs?
+
+      Go to http://flask-sqlalchemy.pocoo.org/ for a prebuilt version
+      of the current documentation.  Otherwise build them yourself
+      from the sphinx sources in the docs folder.
+
+    ~ Where are the tests?
+
+      Good that you're asking. To run the tests use the
+      `test_sqlalchemy.py` file:
+
+        $ python test_sqlalchemy.py
+
+      If you just want one particular testcase to run you can provide
+      it on the command line:
+
+        $ python test_sqlalchemy.py PaginationTestCase
+        
+      In case you have `tox` installed, you can also run that to have
+      virtualenvs created automatically and tests run inside of them
+      at your convenience. Running just `tox` is enough:
+      
+        $ tox
+
+    ~ Where can I get help?
+
+      Join us on the #pocoo IRC channel on irc.freenode.net.
diff --git a/docs/_static/flask-sqlalchemy-small.png b/docs/_static/flask-sqlalchemy-small.png
old mode 100755
new mode 100644
diff --git a/docs/api.rst b/docs/api.rst
index cf1c804..1e6e76b 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -27,6 +27,13 @@ Models
       Optionally declares the bind to use.  `None` refers to the default
       bind.  For more information see :ref:`binds`.
 
+   .. attribute:: __tablename__
+
+      The name of the table in the database.  This is required by SQLAlchemy;
+      however, Flask-SQLAlchemy will set it automatically if a model has a
+      primary key defined.  If the ``__table__`` or ``__tablename__`` is set
+      explicitly, that will be used instead.
+
 .. autoclass:: BaseQuery
    :members: get, get_or_404, paginate, first_or_404
 
@@ -55,6 +62,12 @@ Models
       doesn’t contain any rows.  This results in an execution of the
       underlying query.
 
+Sessions
+````````
+
+.. autoclass:: SignallingSession
+   :members:
+
 Utilities
 `````````
 
diff --git a/docs/binds.rst b/docs/binds.rst
index 154e546..3c57a1b 100644
--- a/docs/binds.rst
+++ b/docs/binds.rst
@@ -69,4 +69,5 @@ a table object directly you will have to put it in there::
     )
 
 If you specified the `__bind_key__` on your models you can use them exactly the
-you are used to.  The model connects to the specified database connection itself.
+way you are used to.  The model connects to the specified database connection 
+itself.
diff --git a/docs/conf.py b/docs/conf.py
index d99a841..a45e1f5 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -42,7 +42,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'Flask-SQLAlchemy'
-copyright = u'2010-2011, Armin Ronacher'
+copyright = u'2010-2014, Armin Ronacher'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -51,10 +51,10 @@ import pkg_resources
 try:
     release = pkg_resources.get_distribution('Flask-SQLAlchemy').version
 except pkg_resources.DistributionNotFound:
-    print 'To build the documentation, The distribution information of'
-    print 'Flask-SQLAlchemy has to be available.  Either install the package'
-    print 'into your development environment or run "setup.py develop"'
-    print 'to setup the metadata.  A virtualenv is recommended!'
+    print('To build the documentation, The distribution information of')
+    print('Flask-SQLAlchemy has to be available.  Either install the package')
+    print('into your development environment or run "setup.py develop"')
+    print('to setup the metadata.  A virtualenv is recommended!')
     sys.exit(1)
 del pkg_resources
 
@@ -232,13 +232,13 @@ pygments_style = 'flask_theme_support.FlaskyStyle'
 # fall back if theme is not there
 try:
     __import__('flask_theme_support')
-except ImportError, e:
-    print '-' * 74
-    print 'Warning: Flask themes unavailable.  Building with default theme'
-    print 'If you want the Flask themes, run this command and build again:'
-    print
-    print '  git submodule update --init'
-    print '-' * 74
+except ImportError as e:
+    print('-' * 74)
+    print('Warning: Flask themes unavailable.  Building with default theme')
+    print('If you want the Flask themes, run this command and build again:')
+    print()
+    print('  git submodule update --init')
+    print('-' * 74)
 
     pygments_style = 'tango'
     html_theme = 'default'
diff --git a/docs/config.rst b/docs/config.rst
index 446efff..6ac5bf8 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -14,48 +14,53 @@ A list of configuration keys currently understood by the extension:
 
 .. tabularcolumns:: |p{6.5cm}|p{8.5cm}|
 
-================================= =========================================
-``SQLALCHEMY_DATABASE_URI``       The database URI that should be used for
-                                  the connection.  Examples:
-
-                                  - ``sqlite:////tmp/test.db``
-                                  - ``mysql://username:password@server/db``
-``SQLALCHEMY_BINDS``              A dictionary that maps bind keys to
-                                  SQLAlchemy connection URIs.  For more
-                                  information about binds see :ref:`binds`.
-``SQLALCHEMY_ECHO``               If set to `True` SQLAlchemy will log all
-                                  the statements issued to stderr which can
-                                  be useful for debugging.
-``SQLALCHEMY_RECORD_QUERIES``     Can be used to explicitly disable or
-                                  enable query recording.  Query recording
-                                  automatically happens in debug or testing
-                                  mode.  See :func:`get_debug_queries` for
-                                  more information.
-``SQLALCHEMY_NATIVE_UNICODE``     Can be used to explicitly disable native
-                                  unicode support.  This is required for
-                                  some database adapters (like PostgreSQL
-                                  on some Ubuntu versions) when used with
-                                  inproper database defaults that specify
-                                  encoding-less databases.
-``SQLALCHEMY_POOL_SIZE``          The size of the database pool.  Defaults
-                                  to the engine's default (usually 5)
-``SQLALCHEMY_POOL_TIMEOUT``       Specifies the connection timeout for the
-                                  pool.  Defaults to 10.
-``SQLALCHEMY_POOL_RECYCLE``       Number of seconds after which a
-                                  connection is automatically recycled.
-                                  This is required for MySQL, which removes
-                                  connections after 8 hours idle by
-                                  default.  Note that Flask-SQLAlchemy
-                                  automatically sets this to 2 hours if
-                                  MySQL is used.
-``SQLALCHEMY_MAX_OVERFLOW``       Controls the number of connections that
-                                  can be created after the pool reached
-                                  its maximum size.  When those additional
-                                  connections are returned to the pool,
-                                  they are disconnected and discarded.
-``SQLALCHEMY_COMMIT_ON_TEARDOWN`` Commit session when the app context is
-                                  torn down, unless there was an exception.
-================================= =========================================
+================================== =========================================
+``SQLALCHEMY_DATABASE_URI``        The database URI that should be used for
+                                   the connection.  Examples:
+
+                                   - ``sqlite:////tmp/test.db``
+                                   - ``mysql://username:password@server/db``
+``SQLALCHEMY_BINDS``               A dictionary that maps bind keys to
+                                   SQLAlchemy connection URIs.  For more
+                                   information about binds see :ref:`binds`.
+``SQLALCHEMY_ECHO``                If set to `True` SQLAlchemy will log all
+                                   the statements issued to stderr which can
+                                   be useful for debugging.
+``SQLALCHEMY_RECORD_QUERIES``      Can be used to explicitly disable or
+                                   enable query recording.  Query recording
+                                   automatically happens in debug or testing
+                                   mode.  See :func:`get_debug_queries` for
+                                   more information.
+``SQLALCHEMY_NATIVE_UNICODE``      Can be used to explicitly disable native
+                                   unicode support.  This is required for
+                                   some database adapters (like PostgreSQL
+                                   on some Ubuntu versions) when used with
+                                   improper database defaults that specify
+                                   encoding-less databases.
+``SQLALCHEMY_POOL_SIZE``           The size of the database pool.  Defaults
+                                   to the engine's default (usually 5)
+``SQLALCHEMY_POOL_TIMEOUT``        Specifies the connection timeout for the
+                                   pool.  Defaults to 10.
+``SQLALCHEMY_POOL_RECYCLE``        Number of seconds after which a
+                                   connection is automatically recycled.
+                                   This is required for MySQL, which removes
+                                   connections after 8 hours idle by
+                                   default.  Note that Flask-SQLAlchemy
+                                   automatically sets this to 2 hours if
+                                   MySQL is used.
+``SQLALCHEMY_MAX_OVERFLOW``        Controls the number of connections that
+                                   can be created after the pool reached
+                                   its maximum size.  When those additional
+                                   connections are returned to the pool,
+                                   they are disconnected and discarded.
+``SQLALCHEMY_TRACK_MODIFICATIONS`` If set to ``True``, Flask-SQLAlchemy will
+                                   track modifications of objects and emit
+                                   signals.  The default is ``None``, which
+                                   enables tracking but issues a warning
+                                   that it will be disabled by default in
+                                   the future.  This requires extra memory
+                                   and should be disabled if not needed.
+================================== =========================================
 
 .. versionadded:: 0.8
    The ``SQLALCHEMY_NATIVE_UNICODE``, ``SQLALCHEMY_POOL_SIZE``,
@@ -68,6 +73,11 @@ A list of configuration keys currently understood by the extension:
 .. versionadded:: 0.17
    The ``SQLALCHEMY_MAX_OVERFLOW`` configuration key was added.
 
+.. versionadded:: 2.0
+   The ``SQLALCHEMY_TRACK_MODIFICATIONS`` configuration key was added.
+.. versionchanged:: 2.1
+   ``SQLALCHEMY_TRACK_MODIFICATIONS`` will warn if unset.
+
 Connection URI Format
 ---------------------
 
@@ -101,3 +111,37 @@ Oracle::
 SQLite (note the four leading slashes)::
 
     sqlite:////absolute/path/to/foo.db
+
+Using custom MetaData and naming conventions
+--------------------------------------------
+
+You can optionally construct the :class:`SQLAlchemy` object with a custom
+:class:`~sqlalchemy.schema.MetaData` object.
+This allows you to, among other things,
+specify a `custom constraint naming convention
+<http://docs.sqlalchemy.org/en/latest/core/constraints.html#constraint-naming-conventions>`_.
+Doing so is important for dealing with database migrations (for instance using
+`alembic <https://alembic.readthedocs.org>`_ as stated
+`here <http://alembic.readthedocs.org/en/latest/naming.html>`_. Since SQL
+defines no standard naming conventions, there is no guaranteed nor effective
+compatibility by default among database implementations. You can define a
+custom naming convention like this as suggested by the SQLAlchemy docs::
+
+    from sqlalchemy import MetaData
+    from flask import Flask
+    from flask.ext.sqlalchemy import SQLAlchemy
+
+    convention = {
+        "ix": 'ix_%(column_0_label)s',
+        "uq": "uq_%(table_name)s_%(column_0_name)s",
+        "ck": "ck_%(table_name)s_%(constraint_name)s",
+        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
+        "pk": "pk_%(table_name)s"
+    }
+
+    metadata = MetaData(naming_convention=convention)
+    db = SQLAlchemy(app, metadata=metadata)
+
+For more info about :class:`~sqlalchemy.schema.MetaData`,
+`check out the official docs on it
+<http://docs.sqlalchemy.org/en/latest/core/metadata.html>`_.
diff --git a/docs/contexts.rst b/docs/contexts.rst
index 1318a61..edf12bb 100644
--- a/docs/contexts.rst
+++ b/docs/contexts.rst
@@ -16,7 +16,7 @@ object globally, how does the latter learn about the former?  The answer
 is the :meth:`~SQLAlchemy.init_app` function::
 
     from flask import Flask
-    from flask.ext.sqlalchemy import SQLAlchemy
+    from flask_sqlalchemy import SQLAlchemy
 
     db = SQLAlchemy()
 
@@ -26,28 +26,28 @@ is the :meth:`~SQLAlchemy.init_app` function::
         return app
 
 
-What it does it preparing the application to work with
+What it does is prepare the application to work with
 :class:`SQLAlchemy`.  However that does not now bind the
 :class:`SQLAlchemy` object to your application.  Why doesn't it do that?
 Because there might be more than one application created.
 
 So how does :class:`SQLAlchemy` now really know about your application?
-You will have to setup a request context.  If you are working inside a
-Flask view function, that automatically happens.  However if you are
+You will have to setup an application context.  If you are working inside
+a Flask view function, that automatically happens.  However if you are
 working inside the interactive shell, you will have to do that yourself
-(see `Creating a Request Context
-<http://flask.pocoo.org/docs/shell/#creating-a-request-context>`_).
+(see `Creating an Application Context
+<http://flask.pocoo.org/docs/appcontext/#creating-an-application-context>`_).
 
 In a nutshell, do something like this:
 
 >>> from yourapp import create_app
 >>> app = create_app()
->>> app.test_request_context().push()
+>>> app.app_context().push()
 
 Inside scripts it makes also sense to use the with-statement::
 
     def my_function():
-        with app():
+        with app.app_context():
             user = db.User(...)
             db.session.add(user)
             db.session.commit()
diff --git a/docs/models.rst b/docs/models.rst
index fa6eea4..fc11130 100644
--- a/docs/models.rst
+++ b/docs/models.rst
@@ -103,9 +103,9 @@ when SQLAlchemy will load the data from the database:
     query as the parent using a `JOIN` statement.
 -   ``'subquery'`` works like ``'joined'`` but instead SQLAlchemy will
     use a subquery.
--   ``'dynamic'`` is special and useful if you have may items.  Instead of
+-   ``'dynamic'`` is special and useful if you have many items.  Instead of
     loading the items SQLAlchemy will return another query object which
-    you can further refine before loading them items.  This is usually
+    you can further refine before loading the items.  This is usually
     what you want if you expect more than a handful of items for this
     relationship.
 
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index e32a58a..a1726f4 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -6,7 +6,7 @@ Quickstart
 .. currentmodule:: flask.ext.sqlalchemy
 
 Flask-SQLAlchemy is fun to use, incredibly easy for basic applications, and
-readily extends for larger applications.  For the complete guide, checkout out
+readily extends for larger applications.  For the complete guide, checkout
 the API documentation on the :class:`SQLAlchemy` class.
 
 A Minimal Application
@@ -22,7 +22,7 @@ provides a class called `Model` that is a declarative base which can be
 used to declare models::
 
     from flask import Flask
-    from flask.ext.sqlalchemy import SQLAlchemy
+    from flask_sqlalchemy import SQLAlchemy
 
     app = Flask(__name__)
     app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
@@ -41,7 +41,7 @@ used to declare models::
         def __repr__(self):
             return '<User %r>' % self.username
 
-To create the initial database, just import the `db` object from a
+To create the initial database, just import the `db` object from an
 interactive Python shell and run the
 :meth:`SQLAlchemy.create_all` method to create the
 tables and database:
diff --git a/docs/signals.rst b/docs/signals.rst
index 04e95f6..6a577b3 100644
--- a/docs/signals.rst
+++ b/docs/signals.rst
@@ -1,27 +1,24 @@
 Signalling Support
 ==================
 
-.. versionadded:: 0.10
-
-Starting with Flask-SQLAlchemy 0.10 you can now connect to signals to get
-notifications when certain things happen.
+Connect to the following signals to get notified before and after changes are committed to the database.
+These changes are only tracked if ``SQLALCHEMY_TRACK_MODIFICATIONS`` is enabled in the config.
 
-The following two signals exist:
+.. versionadded:: 0.10
+.. versionchanged:: 2.1
+   ``before_models_committed`` is triggered correctly.
+.. deprecated:: 2.1
+   This will be disabled by default in a future version.
 
 .. data:: models_committed
 
-   This signal is sent when changed models where committed to the
-   database.  The sender is the application that emitted the changes
-   and the models and an operation identifier are passed as list of tuples
-   in the form ``(model, operation)`` to the receiver in the `changes`
-   parameter.
+   This signal is sent when changed models were committed to the database.
+
+   The sender is the application that emitted the changes.
+   The receiver is passed the ``changes`` parameter with a list of tuples in the form ``(model instance, operation)``.
 
-   The model is the instance of the model that was sent to the database
-   and the operation is ``'insert'`` when a model was inserted,
-   ``'delete'`` when the model was deleted and ``'update'`` if any
-   of the columns where updated.
+   The operation is one of ``'insert'``, ``'update'``, and ``'delete'``.
 
 .. data:: before_models_committed
 
-   Works exactly the same as :data:`models_committed` but is emitted
-   right before the committing takes place.
+   This signal works exactly like :data:`models_committed` but is emitted before the commit takes place.
diff --git a/flask_sqlalchemy/__init__.py b/flask_sqlalchemy/__init__.py
index 9309244..a6b67eb 100644
--- a/flask_sqlalchemy/__init__.py
+++ b/flask_sqlalchemy/__init__.py
@@ -5,7 +5,7 @@
 
     Adds basic SQLAlchemy support to your application.
 
-    :copyright: (c) 2012 by Armin Ronacher, Daniel Neuhäuser.
+    :copyright: (c) 2014 by Armin Ronacher, Daniel Neuhäuser.
     :license: BSD, see LICENSE for more details.
 """
 from __future__ import with_statement, absolute_import
@@ -14,20 +14,20 @@ import re
 import sys
 import time
 import functools
+import warnings
 import sqlalchemy
 from math import ceil
 from functools import partial
-from flask import _request_ctx_stack, abort
+from flask import _request_ctx_stack, abort, has_request_context, request
 from flask.signals import Namespace
 from operator import itemgetter
 from threading import Lock
-from sqlalchemy import orm, event
+from sqlalchemy import orm, event, inspect
 from sqlalchemy.orm.exc import UnmappedClassError
-from sqlalchemy.orm.session import Session
-from sqlalchemy.event import listen
+from sqlalchemy.orm.session import Session as SessionBase
 from sqlalchemy.engine.url import make_url
 from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
-from flask.ext.sqlalchemy._compat import iteritems, itervalues, xrange, \
+from flask_sqlalchemy._compat import iteritems, itervalues, xrange, \
      string_types
 
 # the best timer function for the platform
@@ -42,6 +42,9 @@ except ImportError:
     _app_ctx_stack = None
 
 
+__version__ = '2.1'
+
+
 # Which stack should we use?  _app_ctx_stack is new in 0.9
 connection_stack = _app_ctx_stack or _request_ctx_stack
 
@@ -130,16 +133,37 @@ def _calling_context(app_path):
     return '<unknown>'
 
 
-class _SignallingSession(Session):
+class SignallingSession(SessionBase):
+    """The signalling session is the default session that Flask-SQLAlchemy
+    uses.  It extends the default session system with bind selection and
+    modification tracking.
+
+    If you want to use a different session you can override the
+    :meth:`SQLAlchemy.create_session` function.
 
-    def __init__(self, db, autocommit=False, autoflush=False, **options):
-        self.app = db.get_app()
-        self._model_changes = {}
-        Session.__init__(self, autocommit=autocommit, autoflush=autoflush,
-                         bind=db.engine,
-                         binds=db.get_binds(self.app), **options)
+    .. versionadded:: 2.0
+
+    .. versionadded:: 2.1
+        The `binds` option was added, which allows a session to be joined
+        to an external transaction.
+    """
+
+    def __init__(self, db, autocommit=False, autoflush=True, app=None, **options):
+        #: The application that this session belongs to.
+        self.app = app = db.get_app()
+        track_modifications = app.config['SQLALCHEMY_TRACK_MODIFICATIONS']
+        bind = options.pop('bind', None) or db.engine
+        binds = options.pop('binds', None) or db.get_binds(app)
+
+        if track_modifications is None or track_modifications:
+            _SessionSignalEvents.register(self)
+
+        SessionBase.__init__(
+            self, autocommit=autocommit, autoflush=autoflush,
+            bind=bind, binds=binds, **options
+        )
 
-    def get_bind(self, mapper, clause=None):
+    def get_bind(self, mapper=None, clause=None):
         # mapper is None if someone tries to just get a connection
         if mapper is not None:
             info = getattr(mapper.mapped_table, 'info', {})
@@ -147,60 +171,74 @@ class _SignallingSession(Session):
             if bind_key is not None:
                 state = get_state(self.app)
                 return state.db.get_engine(self.app, bind=bind_key)
-        return Session.get_bind(self, mapper, clause)
+        return SessionBase.get_bind(self, mapper, clause)
 
 
 class _SessionSignalEvents(object):
-
-    def register(self):
-        listen(Session, 'before_commit', self.session_signal_before_commit)
-        listen(Session, 'after_commit', self.session_signal_after_commit)
-        listen(Session, 'after_rollback', self.session_signal_after_rollback)
+    @classmethod
+    def register(cls, session):
+        if not hasattr(session, '_model_changes'):
+            session._model_changes = {}
+
+        event.listen(session, 'before_flush', cls.record_ops)
+        event.listen(session, 'before_commit', cls.record_ops)
+        event.listen(session, 'before_commit', cls.before_commit)
+        event.listen(session, 'after_commit', cls.after_commit)
+        event.listen(session, 'after_rollback', cls.after_rollback)
+
+    @classmethod
+    def unregister(cls, session):
+        if hasattr(session, '_model_changes'):
+            del session._model_changes
+
+        event.remove(session, 'before_flush', cls.record_ops)
+        event.remove(session, 'before_commit', cls.record_ops)
+        event.remove(session, 'before_commit', cls.before_commit)
+        event.remove(session, 'after_commit', cls.after_commit)
+        event.remove(session, 'after_rollback', cls.after_rollback)
 
     @staticmethod
-    def session_signal_before_commit(session):
-        d = session._model_changes
-        if d:
-            before_models_committed.send(session.app, changes=d.values())
+    def record_ops(session, flush_context=None, instances=None):
+        try:
+            d = session._model_changes
+        except AttributeError:
+            return
 
-    @staticmethod
-    def session_signal_after_commit(session):
-        d = session._model_changes
-        if d:
-            models_committed.send(session.app, changes=d.values())
-            d.clear()
+        for targets, operation in ((session.new, 'insert'), (session.dirty, 'update'), (session.deleted, 'delete')):
+            for target in targets:
+                state = inspect(target)
+                key = state.identity_key if state.has_identity else id(target)
+                d[key] = (target, operation)
 
     @staticmethod
-    def session_signal_after_rollback(session):
-        session._model_changes.clear()
-
-
-class _MapperSignalEvents(object):
-
-    def __init__(self, mapper):
-        self.mapper = mapper
-
-    def register(self):
-        listen(self.mapper, 'after_delete', self.mapper_signal_after_delete)
-        listen(self.mapper, 'after_insert', self.mapper_signal_after_insert)
-        listen(self.mapper, 'after_update', self.mapper_signal_after_update)
+    def before_commit(session):
+        try:
+            d = session._model_changes
+        except AttributeError:
+            return
 
-    def mapper_signal_after_delete(self, mapper, connection, target):
-        self._record(mapper, target, 'delete')
+        if d:
+            before_models_committed.send(session.app, changes=list(d.values()))
 
-    def mapper_signal_after_insert(self, mapper, connection, target):
-        self._record(mapper, target, 'insert')
+    @staticmethod
+    def after_commit(session):
+        try:
+            d = session._model_changes
+        except AttributeError:
+            return
 
-    def mapper_signal_after_update(self, mapper, connection, target):
-        self._record(mapper, target, 'update')
+        if d:
+            models_committed.send(session.app, changes=list(d.values()))
+            d.clear()
 
     @staticmethod
-    def _record(mapper, target, operation):
-        s = orm.object_session(target)
-        if isinstance(s, _SignallingSession):
-            pk = tuple(mapper.primary_key_from_instance(target))
-            s._model_changes[pk] = (target, operation)
+    def after_rollback(session):
+        try:
+            d = session._model_changes
+        except AttributeError:
+            return
 
+        d.clear()
 
 
 class _EngineDebuggingSignalEvents(object):
@@ -211,8 +249,8 @@ class _EngineDebuggingSignalEvents(object):
         self.app_package = import_name
 
     def register(self):
-        listen(self.engine, 'before_cursor_execute', self.before_cursor_execute)
-        listen(self.engine, 'after_cursor_execute', self.after_cursor_execute)
+        event.listen(self.engine, 'before_cursor_execute', self.before_cursor_execute)
+        event.listen(self.engine, 'after_cursor_execute', self.after_cursor_execute)
 
     def before_cursor_execute(self, conn, cursor, statement,
                               parameters, context, executemany):
@@ -227,9 +265,9 @@ class _EngineDebuggingSignalEvents(object):
             if queries is None:
                 queries = []
                 setattr(ctx, 'sqlalchemy_queries', queries)
-            queries.append( _DebugQueryTuple( (
+            queries.append(_DebugQueryTuple((
                 statement, parameters, context._query_start_time, _timer(),
-                _calling_context(self.app_package) ) ) )
+                _calling_context(self.app_package))))
 
 
 def get_debug_queries():
@@ -393,16 +431,50 @@ class BaseQuery(orm.Query):
             abort(404)
         return rv
 
-    def paginate(self, page, per_page=20, error_out=True):
+    def paginate(self, page=None, per_page=None, error_out=True):
         """Returns `per_page` items from page `page`.  By default it will
         abort with 404 if no items were found and the page was larger than
         1.  This behavor can be disabled by setting `error_out` to `False`.
 
+        If page or per_page are None, they will be retrieved from the
+        request query.  If the values are not ints and ``error_out`` is
+        true, it will abort with 404.  If there is no request or they
+        aren't in the query, they default to page 1 and 20
+        respectively.
+
         Returns an :class:`Pagination` object.
         """
+
+        if has_request_context():
+            if page is None:
+                try:
+                    page = int(request.args.get('page', 1))
+                except (TypeError, ValueError):
+                    if error_out:
+                        abort(404)
+
+                    page = 1
+
+            if per_page is None:
+                try:
+                    per_page = int(request.args.get('per_page', 20))
+                except (TypeError, ValueError):
+                    if error_out:
+                        abort(404)
+
+                    per_page = 20
+        else:
+            if page is None:
+                page = 1
+
+            if per_page is None:
+                per_page = 20
+
         if error_out and page < 1:
             abort(404)
+
         items = self.limit(per_page).offset((page - 1) * per_page).all()
+
         if not items and page != 1 and error_out:
             abort(404)
 
@@ -478,24 +550,51 @@ class _EngineConnector(object):
             return rv
 
 
-def _defines_primary_key(d):
-    """Figures out if the given dictonary defines a primary key column."""
-    return any(v.primary_key for k, v in iteritems(d)
-               if isinstance(v, sqlalchemy.Column))
+def _should_set_tablename(bases, d):
+    """Check what values are set by a class and its bases to determine if a
+    tablename should be automatically generated.
+
+    The class and its bases are checked in order of precedence: the class
+    itself then each base in the order they were given at class definition.
+
+    Abstract classes do not generate a tablename, although they may have set
+    or inherited a tablename elsewhere.
+
+    If a class defines a tablename or table, a new one will not be generated.
... 564 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/flask-sqlalchemy.git



More information about the Python-modules-commits mailing list