[Sqlalchemy-commits] sqlalchemy: - further fixes to no trans in progress, no trans ev...
Brought to you by:
zzzeek
From: <co...@sq...> - 2010-12-09 15:05:51
|
details: http://hg.sqlalchemy.org/sqlalchemy/sqlalchemy/rev/f16ec288c70b changeset: 7105:f16ec288c70b user: zzzeek date: Thu Dec 09 10:04:23 2010 -0500 description: - further fixes to no trans in progress, no trans ever for TLEngine, [ticket:1998] Subject: sqlalchemy: - further fixes to no trans in progress, no trans ever for TLEngine, [ticket:1998] details: http://hg.sqlalchemy.org/sqlalchemy/sqlalchemy/rev/65a556d23fe9 changeset: 7106:65a556d23fe9 user: zzzeek date: Thu Dec 09 10:04:23 2010 -0500 description: - further fixes to no trans in progress, no trans ever for TLEngine, [ticket:1998] diffstat: README.py3k | 14 +- README.unittests | 78 +- doc/build/core/engines.rst | 19 +- doc/build/core/event.rst | 99 - doc/build/core/events.rst | 27 - doc/build/core/index.rst | 4 +- doc/build/core/interfaces.rst | 17 +- doc/build/core/pooling.rst | 12 +- doc/build/core/schema.rst | 100 +- doc/build/core/tutorial.rst | 4 +- doc/build/dialects/sqlite.rst | 2 - doc/build/intro.rst | 8 +- doc/build/orm/events.rst | 43 - doc/build/orm/extensions/hybrid.rst | 11 - doc/build/orm/extensions/index.rst | 1 - doc/build/orm/index.rst | 3 +- doc/build/orm/interfaces.rst | 92 +- doc/build/orm/tutorial.rst | 32 +- examples/custom_attributes/custom_management.py | 3 +- examples/custom_attributes/listen_for_events.py | 50 +- examples/derived_attributes/__init__.py | 10 + examples/derived_attributes/attributes.py | 168 ++ examples/sharding/attribute_shard.py | 7 +- examples/versioning/test_versioning.py | 2 +- lib/sqlalchemy/__init__.py | 2 +- lib/sqlalchemy/dialects/firebird/base.py | 4 +- lib/sqlalchemy/dialects/maxdb/base.py | 1 - lib/sqlalchemy/dialects/mssql/base.py | 13 +- lib/sqlalchemy/dialects/mysql/base.py | 18 +- lib/sqlalchemy/dialects/postgresql/base.py | 29 +- lib/sqlalchemy/dialects/postgresql/psycopg2.py | 1 - lib/sqlalchemy/dialects/sqlite/base.py | 28 +- lib/sqlalchemy/dialects/sqlite/pysqlite.py | 42 +- lib/sqlalchemy/dialects/sybase/base.py | 2 - lib/sqlalchemy/engine/base.py | 496 ++--- lib/sqlalchemy/engine/ddl.py | 38 +- lib/sqlalchemy/engine/default.py | 358 +-- lib/sqlalchemy/engine/strategies.py | 27 +- lib/sqlalchemy/engine/threadlocal.py | 30 +- lib/sqlalchemy/event.py | 275 --- lib/sqlalchemy/events.py | 319 --- lib/sqlalchemy/ext/declarative.py | 24 +- lib/sqlalchemy/ext/hybrid.py | 123 - lib/sqlalchemy/interfaces.py | 103 +- lib/sqlalchemy/log.py | 205 +- lib/sqlalchemy/orm/__init__.py | 70 +- lib/sqlalchemy/orm/attributes.py | 966 +++++++++-- lib/sqlalchemy/orm/dependency.py | 83 +- lib/sqlalchemy/orm/deprecated_interfaces.py | 573 ------- lib/sqlalchemy/orm/dynamic.py | 25 +- lib/sqlalchemy/orm/events.py | 896 ---------- lib/sqlalchemy/orm/instrumentation.py | 683 -------- lib/sqlalchemy/orm/interfaces.py | 437 +++++- lib/sqlalchemy/orm/mapper.py | 621 +++--- lib/sqlalchemy/orm/properties.py | 228 +- lib/sqlalchemy/orm/query.py | 97 +- lib/sqlalchemy/orm/scoping.py | 86 +- lib/sqlalchemy/orm/session.py | 76 +- lib/sqlalchemy/orm/state.py | 50 +- lib/sqlalchemy/orm/strategies.py | 16 +- lib/sqlalchemy/orm/unitofwork.py | 15 +- lib/sqlalchemy/orm/util.py | 140 +- lib/sqlalchemy/pool.py | 292 ++- lib/sqlalchemy/queue.py | 185 ++ lib/sqlalchemy/schema.py | 342 +-- lib/sqlalchemy/sql/compiler.py | 16 +- lib/sqlalchemy/sql/expression.py | 203 +- lib/sqlalchemy/sql/operators.py | 2 +- lib/sqlalchemy/sql/util.py | 3 +- lib/sqlalchemy/test/__init__.py | 27 + lib/sqlalchemy/test/assertsql.py | 295 +++ lib/sqlalchemy/test/engines.py | 305 +++ lib/sqlalchemy/test/entities.py | 83 + lib/sqlalchemy/test/orm.py | 111 + lib/sqlalchemy/test/pickleable.py | 75 + lib/sqlalchemy/test/profiling.py | 222 ++ lib/sqlalchemy/test/requires.py | 327 ++++ lib/sqlalchemy/test/schema.py | 79 + lib/sqlalchemy/test/testing.py | 797 +++++++++ lib/sqlalchemy/test/util.py | 76 + lib/sqlalchemy/topological.py | 83 + lib/sqlalchemy/types.py | 46 +- lib/sqlalchemy/util.py | 1875 +++++++++++++++++++++++ lib/sqlalchemy/util/__init__.py | 31 - lib/sqlalchemy/util/_collections.py | 885 ---------- lib/sqlalchemy/util/compat.py | 190 -- lib/sqlalchemy/util/deprecations.py | 112 - lib/sqlalchemy/util/langhelpers.py | 691 -------- lib/sqlalchemy/util/queue.py | 185 -- lib/sqlalchemy/util/topological.py | 83 - lib/sqlalchemy_nose/config.py | 173 ++ lib/sqlalchemy_nose/noseplugin.py | 166 ++ setup.cfg | 2 +- setup.py | 13 +- sqla_nose.py | 18 +- test/aaa_profiling/test_compiler.py | 4 +- test/aaa_profiling/test_memusage.py | 10 +- test/aaa_profiling/test_orm.py | 12 +- test/aaa_profiling/test_pool.py | 10 +- test/aaa_profiling/test_resultset.py | 36 +- test/aaa_profiling/test_zoomark.py | 6 +- test/aaa_profiling/test_zoomark_orm.py | 2 +- test/base/test_dependency.py | 16 +- test/base/test_events.py | 264 --- test/base/test_except.py | 2 +- test/base/test_utils.py | 8 +- test/bootstrap/config.py | 173 -- test/bootstrap/noseplugin.py | 174 -- test/dialect/test_access.py | 2 +- test/dialect/test_firebird.py | 4 +- test/dialect/test_informix.py | 2 +- test/dialect/test_maxdb.py | 4 +- test/dialect/test_mssql.py | 48 +- test/dialect/test_mxodbc.py | 4 +- test/dialect/test_mysql.py | 38 +- test/dialect/test_oracle.py | 8 +- test/dialect/test_postgresql.py | 63 +- test/dialect/test_sqlite.py | 17 +- test/dialect/test_sybase.py | 2 +- test/engine/_base.py | 4 +- test/engine/test_bind.py | 8 +- test/engine/test_ddlevents.py | 270 +-- test/engine/test_execute.py | 436 +---- test/engine/test_metadata.py | 420 +++++ test/engine/test_parseconnect.py | 4 +- test/engine/test_pool.py | 368 +--- test/engine/test_reconnect.py | 10 +- test/engine/test_reflection.py | 7 +- test/engine/test_transaction.py | 39 +- test/ex/test_examples.py | 2 +- test/ext/test_associationproxy.py | 6 +- test/ext/test_compiler.py | 2 +- test/ext/test_declarative.py | 226 +- test/ext/test_horizontal_shard.py | 9 +- test/ext/test_hybrid.py | 102 - test/ext/test_orderinglist.py | 4 +- test/ext/test_serializer.py | 16 +- test/ext/test_sqlsoup.py | 2 +- test/lib/__init__.py | 27 - test/lib/assertsql.py | 314 --- test/lib/engines.py | 301 --- test/lib/entities.py | 83 - test/lib/orm.py | 111 - test/lib/pickleable.py | 75 - test/lib/profiling.py | 217 -- test/lib/requires.py | 327 ---- test/lib/schema.py | 79 - test/lib/testing.py | 795 --------- test/lib/util.py | 126 - test/orm/_base.py | 9 +- test/orm/_fixtures.py | 6 +- test/orm/inheritance/test_abc_inheritance.py | 4 +- test/orm/inheritance/test_abc_polymorphic.py | 4 +- test/orm/inheritance/test_basic.py | 158 +- test/orm/inheritance/test_concrete.py | 12 +- test/orm/inheritance/test_magazine.py | 6 +- test/orm/inheritance/test_manytomany.py | 4 +- test/orm/inheritance/test_poly_linked_list.py | 8 +- test/orm/inheritance/test_polymorph.py | 75 +- test/orm/inheritance/test_polymorph2.py | 10 +- test/orm/inheritance/test_productspec.py | 4 +- test/orm/inheritance/test_query.py | 94 +- test/orm/inheritance/test_selects.py | 2 +- test/orm/inheritance/test_single.py | 6 +- test/orm/test_association.py | 6 +- test/orm/test_assorted_eager.py | 82 +- test/orm/test_attributes.py | 308 +-- test/orm/test_backref_mutations.py | 13 +- test/orm/test_bind.py | 8 +- test/orm/test_cascade.py | 1247 +++----------- test/orm/test_collection.py | 35 +- test/orm/test_compile.py | 37 +- test/orm/test_cycles.py | 8 +- test/orm/test_defaults.py | 18 +- test/orm/test_deprecations.py | 6 +- test/orm/test_dynamic.py | 9 +- test/orm/test_eager_relations.py | 78 +- test/orm/test_evaluator.py | 8 +- test/orm/test_expire.py | 10 +- test/orm/test_extendedattr.py | 46 +- test/orm/test_generative.py | 19 +- test/orm/test_immediate_load.py | 4 +- test/orm/test_instrumentation.py | 171 +- test/orm/test_lazy_relations.py | 10 +- test/orm/test_load_on_fks.py | 6 +- test/orm/test_manytomany.py | 10 +- test/orm/test_mapper.py | 451 +--- test/orm/test_merge.py | 12 +- test/orm/test_naturalpks.py | 10 +- test/orm/test_onetoone.py | 4 +- test/orm/test_pickled.py | 10 +- test/orm/test_query.py | 508 +---- test/orm/test_relationships.py | 102 +- test/orm/test_scoping.py | 182 ++- test/orm/test_selectable.py | 35 +- test/orm/test_session.py | 604 ++---- test/orm/test_subquery_relations.py | 10 +- test/orm/test_transaction.py | 6 +- test/orm/test_unitofwork.py | 54 +- test/orm/test_unitofworkv2.py | 8 +- test/orm/test_utils.py | 42 +- test/orm/test_versioning.py | 6 +- test/perf/README | 17 - test/perf/insertspeed.py | 2 +- test/perf/large_flush.py | 2 +- test/perf/masscreate2.py | 2 +- test/perf/masseagerload.py | 2 +- test/perf/massload.py | 2 +- test/perf/masssave.py | 2 +- test/perf/objselectspeed.py | 4 +- test/perf/objupdatespeed.py | 4 +- test/perf/ormsession.py | 4 +- test/perf/poolload.py | 2 +- test/perf/sessions.py | 4 +- test/perf/wsgi.py | 2 +- test/sql/test_case_statement.py | 4 +- test/sql/test_columns.py | 95 + test/sql/test_compiler.py | 39 +- test/sql/test_constraints.py | 10 +- test/sql/test_defaults.py | 8 +- test/sql/test_functions.py | 10 +- test/sql/test_generative.py | 19 +- test/sql/test_labels.py | 4 +- test/sql/test_metadata.py | 573 ------- test/sql/test_query.py | 8 +- test/sql/test_quote.py | 6 +- test/sql/test_returning.py | 6 +- test/sql/test_rowcount.py | 2 +- test/sql/test_selectable.py | 4 +- test/sql/test_types.py | 60 +- test/sql/test_unicode.py | 4 +- test/zblog/tables.py | 2 +- test/zblog/test_zblog.py | 2 +- 233 files changed, 11111 insertions(+), 15677 deletions(-) diffs (truncated from 35797 to 300 lines): diff -r d0efa32bddb8 -r 65a556d23fe9 README.py3k --- a/README.py3k Thu Dec 09 00:21:13 2010 -0500 +++ b/README.py3k Thu Dec 09 10:04:23 2010 -0500 @@ -39,9 +39,17 @@ Running Tests ------------- -To run unit tests in Py3k, Nose 1.0 is required, or a development -version of Nose that supports Python 3. The tests are run -using ./sqla_nose.py as described in README.unittests. +To run the unit tests, ensure Distribute is installed as above, +and also that at least the ./lib/ and ./test/ directories have been converted +to Python 3 using the source tool above. A Python 3 version of Nose +can be acquired from Bitbucket using Mercurial: + + hg clone http://bitbucket.org/jpellerin/nose3/ + cd nose3 + python3 setup.py install + +The tests can then be run using the "nosetests3" script installed by the above, +using the same instructions in README.unittests. Current 3k Issues ----------------- diff -r d0efa32bddb8 -r 65a556d23fe9 README.unittests --- a/README.unittests Thu Dec 09 00:21:13 2010 -0500 +++ b/README.unittests Thu Dec 09 10:04:23 2010 -0500 @@ -5,37 +5,59 @@ SQLAlchemy unit tests by default run using Python's built-in sqlite3 module. If running on Python 2.4, pysqlite must be installed. -Unit tests are run using nose. Nose is available at: +Unit tests are run using nose. Note that in most cases, +nose needs to be installed manually. Documentation and +downloads for nose are available at: - http://pypi.python.org/pypi/nose/ +http://somethingaboutorange.com/mrl/projects/nose/0.11.1/index.html + +Or using setuptools: + + $ easy_install nose SQLAlchemy implements a nose plugin that must be present when tests are run. -This plugin is invoked when the test runner script provided with -SQLAlchemy is used. +This plugin is available when SQLAlchemy is installed via setuptools. -**NOTE:** - the nose plugin is no longer installed by setuptools as of -version 0.7 ! Use "python setup.py test" or "./sqla_nose.py". +INSTANT TEST RUNNER +------------------- -RUNNING TESTS VIA SETUP.PY --------------------------- A plain vanilla run of all tests using sqlite can be run via setup.py: $ python setup.py test + +(NOTE: this command is broken for Python 2.7 with nose 0.11.3, see +Nose issue 340. You will need to use 'nosetests' directly, see below.) + +Setuptools will take care of the rest ! To run nose directly and have +its full set of options available, read on... -The -v flag also works here: +SETUP +----- - $ python setup.py test -v +All that's required is for SQLAlchemy to be installed via setuptools. +For example, to create a local install in a source distribution directory: -RUNNING ALL TESTS ------------------- + $ export PYTHONPATH=. + $ python setup.py develop -d . + +The above will create a setuptools "development" distribution in the local +path, which allows the Nose plugin to be available when nosetests is run. +The plugin is enabled using the "with-sqlalchemy=True" configuration +in setup.cfg. + +RUNNING ALL TESTS +----------------- To run all tests: - $ ./sqla_nose.py + $ nosetests + +(NOTE: if running with Python 2.7 and nose 0.11.3, add "-w test/" to the command. +Again this is a Nose issue, see Nose issue 342.) If you're running the tests on Microsoft Windows, then there is an additional -argument that must be passed to ./sqla_nose.py: +argument that must be passed to nosetests: - > ./sqla_nose.py --first-package-wins=True + > nosetests --first-package-wins=True This is required because noseâs importer will normally evict a package from sys.modules if it sees a package with the same name in a different location. @@ -44,29 +66,39 @@ Assuming all tests pass, this is a very unexciting output. To make it more intersesting: - $ ./sqla_nose.py -v + $ nosetests -v + +ALTERNATE TEST RUNNER +--------------------- + +The script "sqla_nose.py" is a front-end to Nose which manually associates +the SQLAlchemy testing plugin with Nose at runtime. This script can run the +tests without any reliance upon setuptools. In 0.7 we'll be removing the +Nose plugin from setup, so this will be the way going forward to run tests: + + $ python sqla_nose.py -v RUNNING INDIVIDUAL TESTS ------------------------- Any directory of test modules can be run at once by specifying the directory path: - $ ./sqla_nose.py test/dialect + $ nosetest test/dialect Any test module can be run directly by specifying its module name: - $ ./sqla_nose.py test.orm.test_mapper + $ nosetests test.orm.test_mapper To run a specific test within the module, specify it as module:ClassName.methodname: - $ ./sqla_nose.py test.orm.test_mapper:MapperTest.test_utils + $ nosetests test.orm.test_mapper:MapperTest.test_utils COMMAND LINE OPTIONS -------------------- Help is available via --help: - $ ./sqla_nose.py --help + $ nosetests --help The --help screen is a combination of common nose options and options which the SQLAlchemy nose plugin adds. The most commonly SQLAlchemy-specific @@ -154,7 +186,7 @@ If you'll be running the tests frequently, database aliases can save a lot of typing. The --dbs option lists the built-in aliases and their matching URLs: - $ ./sqla_nose.py --dbs + $ nosetests --dbs Available --db options (use --dburi to override) mysql mysql://scott:tiger@127.0.0.1:3306/test oracle oracle://scott:tiger@127.0.0.1:1521 @@ -163,7 +195,7 @@ To run tests against an aliased database: - $ ./sqla_nose.py --db=postgresql + $ nosetests --db=postgresql To customize the URLs with your own users or hostnames, make a simple .ini file called `test.cfg` at the top level of the SQLAlchemy source distribution @@ -181,7 +213,7 @@ Any log target can be directed to the console with command line options, such as: - $ ./sqla_nose.py test.orm.unitofwork --log-info=sqlalchemy.orm.mapper \ + $ nosetests test.orm.unitofwork --log-info=sqlalchemy.orm.mapper \ --log-debug=sqlalchemy.pool --log-info=sqlalchemy.engine This would log mapper configuration, connection pool checkouts, and SQL @@ -193,7 +225,7 @@ Coverage is tracked using Nose's coverage plugin. See the nose documentation for details. Basic usage is: - $ ./sqla_nose.py test.sql.test_query --with-coverage + $ nosetests test.sql.test_query --with-coverage BIG COVERAGE TIP !!! There is an issue where existing .pyc files may store the incorrect filepaths, which will break the coverage system. If diff -r d0efa32bddb8 -r 65a556d23fe9 doc/build/core/engines.rst --- a/doc/build/core/engines.rst Thu Dec 09 00:21:13 2010 -0500 +++ b/doc/build/core/engines.rst Thu Dec 09 10:04:23 2010 -0500 @@ -43,7 +43,7 @@ backends; each is described as its own package in the :ref:`sqlalchemy.dialects_toplevel` package. A SQLAlchemy dialect always requires that an appropriate DBAPI driver is installed. -The table below summarizes the state of DBAPI support in SQLAlchemy 0.7. The values +The table below summarizes the state of DBAPI support in SQLAlchemy 0.6. The values translate as: * yes / Python platform - The SQLAlchemy dialect is mostly or fully operational on the target platform. @@ -209,20 +209,19 @@ sqlite_memory_db = create_engine('sqlite://') -The :class:`.Engine` will ask the connection pool for a +The :class:`~sqlalchemy.engine.base.Engine` will ask the connection pool for a connection when the ``connect()`` or ``execute()`` methods are called. The -default connection pool, :class:`~.QueuePool`, will open connections to the +default connection pool, :class:`~sqlalchemy.pool.QueuePool`, as well as the +default connection pool used with SQLite, +:class:`~sqlalchemy.pool.SingletonThreadPool`, will open connections to the database on an as-needed basis. As concurrent statements are executed, -:class:`.QueuePool` will grow its pool of connections to a +:class:`~sqlalchemy.pool.QueuePool` will grow its pool of connections to a default size of five, and will allow a default "overflow" of ten. Since the -:class:`.Engine` is essentially "home base" for the +:class:`~sqlalchemy.engine.base.Engine` is essentially "home base" for the connection pool, it follows that you should keep a single -:class:`.Engine` per database established within an +:class:`~sqlalchemy.engine.base.Engine` per database established within an application, rather than creating a new one for each connection. -.. note:: :class:`.QueuePool` is not used by default for SQLite engines. See - :ref:`sqlite_toplevel` for details on SQLite connection pool usage. - .. autoclass:: sqlalchemy.engine.url.URL :members: @@ -289,7 +288,7 @@ logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) -By default, the log level is set to ``logging.WARN`` within the entire +By default, the log level is set to ``logging.ERROR`` within the entire ``sqlalchemy`` namespace so that no log operations occur, even within an application that has logging enabled otherwise. diff -r d0efa32bddb8 -r 65a556d23fe9 doc/build/core/event.rst --- a/doc/build/core/event.rst Thu Dec 09 00:21:13 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -.. _event_toplevel: - -Events -====== - -SQLAlchemy includes an event API which publishes a wide variety of hooks into -the internals of both SQLAlchemy Core and ORM. The system is all new -as of version 0.7 and supercedes the previous system of "extension", "proxy", -and "listener" classes. - -Event Registration ------------------- - -Subscribing to an event occurs through a single API point, the :func:`.listen` function. This function -accepts a user-defined listening function, a string identifier which identifies the event to be -intercepted, and a target. Additional positional and keyword arguments may be supported by -specific types of events, which may specify alternate interfaces for the given event function, or provide -instructions regarding secondary event targets based on the given target. - -The name of an event and the argument signature of a corresponding listener function is derived from -a class bound specification method, which exists bound to a marker class that's described in the documentation. -For example, the documentation for :meth:`.PoolEvents.on_connect` indicates that the event name is ``"on_connect"`` -and that a user-defined listener function should receive two positional arguments:: - - from sqlalchemy.event import listen - from sqlalchemy.pool import Pool - - def my_on_connect(dbapi_con, connection_record): - print "New DBAPI connection:", dbapi_con - - listen(Pool, 'on_connect', my_on_connect) - -Targets -------- - -The :func:`.listen` function is very flexible regarding targets. It generally accepts classes, instances of those -classes, and related classes or objects from which the appropriate target can be derived. For example, -the above mentioned ``"on_connect"`` event accepts :class:`.Engine` classes and objects as well as :class:`.Pool` -classes and objects:: - - from sqlalchemy.event import listen - from sqlalchemy.pool import Pool, QueuePool - from sqlalchemy import create_engine - from sqlalchemy.engine import Engine - import psycopg2 - - def connect(): - return psycopg2.connect(username='ed', host='127.0.0.1', dbname='test') - - my_pool = QueuePool(connect) - my_engine = create_engine('postgresql://ed@localhost/test') - - # associate listener with all instances of Pool - listen(Pool, 'on_connect', my_on_connect) - - # associate listener with all instances of Pool - # via the Engine class - listen(Engine, 'on_connect', my_on_connect) - - # associate listener with my_pool - listen(my_pool, 'on_connect', my_on_connect) - - # associate listener with my_engine.pool - listen(my_engine, 'on_connect', my_on_connect) |