[Python-modules-commits] [sqlalchemy] 01/05: Import sqlalchemy_1.1.6+ds1.orig.tar.gz

Piotr Ożarowski piotr at moszumanska.debian.org
Fri Mar 17 18:10:15 UTC 2017


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

piotr pushed a commit to branch master
in repository sqlalchemy.

commit d752d182f1776db526015e59711fd858fbd36088
Author: Piotr Ożarowski <piotr at debian.org>
Date:   Fri Mar 17 00:23:38 2017 +0100

    Import sqlalchemy_1.1.6+ds1.orig.tar.gz
---
 PKG-INFO                                      |    2 +-
 doc/build/changelog/changelog_11.rst          |  125 +-
 doc/build/changelog/migration_11.rst          |    8 +-
 doc/build/conf.py                             |    4 +-
 doc/build/core/defaults.rst                   |   70 +-
 doc/build/core/event.rst                      |    2 +-
 doc/build/core/selectable.rst                 |    1 +
 doc/build/dialects/index.rst                  |    2 +
 lib/sqlalchemy/__init__.py                    |    2 +-
 lib/sqlalchemy/dialects/mssql/base.py         |    4 +
 lib/sqlalchemy/dialects/mysql/base.py         |    3 +
 lib/sqlalchemy/dialects/postgresql/base.py    |    9 +
 lib/sqlalchemy/dialects/postgresql/ext.py     |   58 +-
 lib/sqlalchemy/engine/reflection.py           |   34 +-
 lib/sqlalchemy/events.py                      |   24 +-
 lib/sqlalchemy/ext/automap.py                 |    6 +-
 lib/sqlalchemy/ext/baked.py                   |   36 +-
 lib/sqlalchemy/ext/declarative/base.py        |    8 +-
 lib/sqlalchemy/ext/indexable.py               |    6 +-
 lib/sqlalchemy/orm/events.py                  |    2 +-
 lib/sqlalchemy/orm/interfaces.py              |   17 +-
 lib/sqlalchemy/orm/mapper.py                  |   16 +
 lib/sqlalchemy/orm/path_registry.py           |   34 +-
 lib/sqlalchemy/orm/persistence.py             |   23 +-
 lib/sqlalchemy/orm/query.py                   |   46 +-
 lib/sqlalchemy/orm/strategies.py              |   45 +-
 lib/sqlalchemy/orm/util.py                    |   13 +-
 lib/sqlalchemy/sql/sqltypes.py                |   32 +-
 test/aaa_profiling/test_memusage.py           |    4 +-
 test/aaa_profiling/test_orm.py                |  163 ++-
 test/aaa_profiling/test_zoomark.py            |   13 +-
 test/aaa_profiling/test_zoomark_orm.py        |   52 +-
 test/base/test_dependency.py                  |   28 +-
 test/base/test_events.py                      |    2 +-
 test/base/test_except.py                      |    1 +
 test/base/test_inspect.py                     |    4 +-
 test/base/test_utils.py                       |  212 ++--
 test/conftest.py                              |    1 -
 test/dialect/mssql/test_compiler.py           |    1 +
 test/dialect/mssql/test_engine.py             |   18 +-
 test/dialect/mssql/test_query.py              |    2 +-
 test/dialect/mssql/test_reflection.py         |   64 +-
 test/dialect/mssql/test_types.py              |   20 +-
 test/dialect/mysql/test_compiler.py           |    9 +-
 test/dialect/mysql/test_dialect.py            |   28 +-
 test/dialect/mysql/test_query.py              |   24 +-
 test/dialect/mysql/test_reflection.py         |   15 +-
 test/dialect/mysql/test_types.py              |  212 ++--
 test/dialect/postgresql/test_compiler.py      |   59 +-
 test/dialect/postgresql/test_dialect.py       |   15 +-
 test/dialect/postgresql/test_on_conflict.py   |    1 -
 test/dialect/postgresql/test_reflection.py    |    4 +-
 test/dialect/postgresql/test_types.py         |   32 +-
 test/dialect/test_firebird.py                 |   98 +-
 test/dialect/test_mxodbc.py                   |   30 +-
 test/dialect/test_oracle.py                   |  576 ++++-----
 test/dialect/test_pyodbc.py                   |    3 +-
 test/dialect/test_sqlite.py                   |   19 +-
 test/dialect/test_suite.py                    |    2 -
 test/dialect/test_sybase.py                   |    2 -
 test/engine/test_bind.py                      |   24 +-
 test/engine/test_ddlevents.py                 |   65 +-
 test/engine/test_execute.py                   |   73 +-
 test/engine/test_logging.py                   |    7 +-
 test/engine/test_parseconnect.py              |    5 +-
 test/engine/test_processors.py                |   23 +-
 test/engine/test_reflection.py                |  563 +++++----
 test/engine/test_transaction.py               |  175 ++-
 test/ext/declarative/test_basic.py            |    1 +
 test/ext/declarative/test_inheritance.py      |   43 +-
 test/ext/declarative/test_reflection.py       |    1 +
 test/ext/test_associationproxy.py             |  341 +++--
 test/ext/test_automap.py                      |    3 +-
 test/ext/test_baked.py                        |   84 +-
 test/ext/test_compiler.py                     |   53 +-
 test/ext/test_extendedattr.py                 |   12 +-
 test/ext/test_horizontal_shard.py             |   51 +-
 test/ext/test_hybrid.py                       |   12 +-
 test/ext/test_indexable.py                    |   17 +-
 test/ext/test_mutable.py                      |    4 +-
 test/ext/test_orderinglist.py                 |   63 +-
 test/ext/test_serializer.py                   |   69 +-
 test/orm/_fixtures.py                         |  266 ++--
 test/orm/inheritance/_poly_fixtures.py        |  143 ++-
 test/orm/inheritance/test_abc_inheritance.py  |  119 +-
 test/orm/inheritance/test_abc_polymorphic.py  |   57 +-
 test/orm/inheritance/test_assorted_poly.py    | 1204 +++++++++---------
 test/orm/inheritance/test_basic.py            | 1147 +++++++++--------
 test/orm/inheritance/test_concrete.py         |  373 +++---
 test/orm/inheritance/test_magazine.py         |  267 ++--
 test/orm/inheritance/test_manytomany.py       |  145 ++-
 test/orm/inheritance/test_poly_linked_list.py |  169 ++-
 test/orm/inheritance/test_poly_persistence.py |  241 ++--
 test/orm/inheritance/test_polymorphic_rel.py  |  156 +--
 test/orm/inheritance/test_productspec.py      |  247 ++--
 test/orm/inheritance/test_relationship.py     |  775 ++++++------
 test/orm/inheritance/test_selects.py          |   48 +-
 test/orm/inheritance/test_single.py           |  542 ++++----
 test/orm/inheritance/test_with_poly.py        |   70 +-
 test/orm/test_association.py                  |   98 +-
 test/orm/test_assorted_eager.py               |  477 +++----
 test/orm/test_attributes.py                   |  781 +++++++-----
 test/orm/test_backref_mutations.py            |  159 +--
 test/orm/test_bind.py                         |    2 -
 test/orm/test_bulk.py                         |    3 +-
 test/orm/test_bundle.py                       |   87 +-
 test/orm/test_cascade.py                      | 1208 +++++++++---------
 test/orm/test_collection.py                   |  284 +++--
 test/orm/test_compile.py                      |  145 ++-
 test/orm/test_composites.py                   |  318 ++---
 test/orm/test_cycles.py                       |  618 ++++-----
 test/orm/test_default_strategies.py           |   28 +-
 test/orm/test_defaults.py                     |   53 +-
 test/orm/test_deferred.py                     |  260 ++--
 test/orm/test_deprecations.py                 |   65 +-
 test/orm/test_descriptor.py                   |   15 +-
 test/orm/test_dynamic.py                      |  118 +-
 test/orm/test_eager_relations.py              |   86 +-
 test/orm/test_evaluator.py                    |   13 +-
 test/orm/test_events.py                       |   11 +-
 test/orm/test_expire.py                       |  406 +++---
 test/orm/test_froms.py                        |  253 ++--
 test/orm/test_generative.py                   |   92 +-
 test/orm/test_hasparent.py                    |   25 +-
 test/orm/test_immediate_load.py               |   34 +-
 test/orm/test_inspect.py                      |   32 +-
 test/orm/test_instrumentation.py              |   22 +-
 test/orm/test_joins.py                        | 1663 ++++++++++++++-----------
 test/orm/test_lazy_relations.py               |   26 +-
 test/orm/test_load_on_fks.py                  |   55 +-
 test/orm/test_loading.py                      |   14 +-
 test/orm/test_lockmode.py                     |   67 +-
 test/orm/test_manytomany.py                   |  227 ++--
 test/orm/test_mapper.py                       |  132 +-
 test/orm/test_merge.py                        |  434 ++++---
 test/orm/test_naturalpks.py                   |  111 +-
 test/orm/test_of_type.py                      |  269 ++--
 test/orm/test_onetoone.py                     |   30 +-
 test/orm/test_options.py                      |  217 ++--
 test/orm/test_pickled.py                      |  233 ++--
 test/orm/test_query.py                        |  182 +--
 test/orm/test_rel_fn.py                       |  586 ++++-----
 test/orm/test_relationships.py                |   26 +-
 test/orm/test_scoping.py                      |   19 +-
 test/orm/test_selectable.py                   |   17 +-
 test/orm/test_session.py                      |  141 +--
 test/orm/test_subquery_relations.py           | 1222 ++++++++++--------
 test/orm/test_sync.py                         |   55 +-
 test/orm/test_transaction.py                  |    5 +-
 test/orm/test_unitofwork.py                   |  950 +++++++-------
 test/orm/test_unitofworkv2.py                 |   48 +-
 test/orm/test_utils.py                        |   45 +-
 test/orm/test_validators.py                   |   86 +-
 test/perf/invalidate_stresstest.py            |   12 +-
 test/perf/orm2010.py                          |   36 +-
 test/requirements.py                          |  231 ++--
 test/sql/test_compiler.py                     |    3 +-
 test/sql/test_constraints.py                  |   26 +-
 test/sql/test_cte.py                          |    5 +-
 test/sql/test_defaults.py                     |   38 +-
 test/sql/test_functions.py                    |    8 +-
 test/sql/test_generative.py                   |   62 +-
 test/sql/test_insert.py                       |    5 +-
 test/sql/test_inspect.py                      |    1 -
 test/sql/test_labels.py                       |   22 +-
 test/sql/test_lateral.py                      |    3 -
 test/sql/test_metadata.py                     |    3 +-
 test/sql/test_operators.py                    |   28 +-
 test/sql/test_query.py                        |    7 +-
 test/sql/test_quote.py                        |    4 +-
 test/sql/test_resultset.py                    |   22 +-
 test/sql/test_returning.py                    |    1 -
 test/sql/test_rowcount.py                     |   11 +-
 test/sql/test_selectable.py                   |   61 +-
 test/sql/test_tablesample.py                  |    1 -
 test/sql/test_type_expressions.py             |    9 +-
 test/sql/test_types.py                        |   44 +-
 test/sql/test_update.py                       |   13 +-
 test/sql/test_utils.py                        |    5 +-
 179 files changed, 12711 insertions(+), 10507 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 93cb008..d6362ea 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: SQLAlchemy
-Version: 1.1.5
+Version: 1.1.6
 Summary: Database Abstraction Library
 Home-page: http://www.sqlalchemy.org
 Author: Mike Bayer
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst
index c44e781..4083dbb 100644
--- a/doc/build/changelog/changelog_11.rst
+++ b/doc/build/changelog/changelog_11.rst
@@ -19,6 +19,129 @@
         :start-line: 5
 
 .. changelog::
+    :version: 1.1.6
+    :released: February 28, 2017
+
+    .. change::
+        :tags: bug, mysql
+
+        Added new MySQL 8.0 reserved words to the MySQL dialect for proper
+        quoting.  Pull request courtesy Hanno Schlichting.
+
+    .. change:: 3915
+        :tags: bug, orm
+        :tickets: 3915
+
+        Addressed some long unattended performance concerns within the joined
+        eager loader query construction system that have accumulated since
+        earlier versions as a result of increased abstraction. The use of ad-
+        hoc :class:`.AliasedClass` objects per query, which produces lots of
+        column lookup overhead each time, has been replaced with a cached
+        approach that makes use of a small pool of :class:`.AliasedClass`
+        objects that are reused between invocations of joined eager loading.
+        Some mechanics involving eager join path construction have also been
+        optimized.   Callcounts for an end-to-end query construction + single
+        row fetch test with a worst-case joined loader scenario have been
+        reduced by about 60% vs. 1.1.5 and 42% vs. that of 0.8.6.
+
+    .. change:: 3804
+        :tags: bug, postgresql
+        :tickets: 3804
+
+        Added regular expressions for the "IMPORT FOREIGN SCHEMA",
+        "REFRESH MATERIALIZED VIEW" Postgresql statements so that they
+        autocommit when invoked via a connection or engine without
+        an explicit transaction.  Pull requests courtesy Frazer McLean
+        and Paweł Stiasny.
+
+    .. change:: 3909
+        :tags: bug, orm
+        :tickets: 3909
+
+        Fixed a major inefficiency in the "eager_defaults" feature whereby
+        an unnecessary SELECT would be emitted for column values where the
+        ORM had explicitly inserted NULL, corresponding to attributes that
+        were unset on the object but did not have any server default
+        specified, as well as expired attributes on update that nevertheless
+        had no server onupdate set up.   As these columns are not part of the
+        RETURNING that eager_defaults tries to use, they should not be
+        post-SELECTed either.
+
+    .. change:: 3908
+        :tags: bug, orm
+        :tickets: 3908
+
+        Fixed two closely related bugs involving the mapper eager_defaults
+        flag in conjunction with single-table inheritance; one where the
+        eager defaults logic would inadvertently try to access a column
+        that's part of the mapper's "exclude_properties" list (used by
+        Declarative with single table inheritance) during the eager defaults
+        fetch, and the other where the full load of the row in order to
+        fetch the defaults would fail to use the correct inheriting mapper.
+
+
+    .. change:: 3905
+        :tags: bug, sql
+        :tickets: 3905
+
+        Fixed bug whereby the :meth:`.DDLEvents.column_reflect` event would not
+        allow a non-textual expression to be passed as the value of the
+        "default" for the new column, such as a :class:`.FetchedValue`
+        object to indicate a generic triggered default or a
+        :func:`.sql.expression.text` construct.  Clarified the documentation
+        in this regard as well.
+
+    .. change:: 3901
+        :tags: bug, ext
+        :tickets: 3901
+
+        Fixed bug in new :mod:`sqlalchemy.ext.indexable` extension
+        where setting of a property that itself refers to another property
+        would fail.
+
+    .. change:: 3900
+        :tags: bug, postgresql
+        :tickets: 3900
+
+        Fixed bug in Postgresql :class:`.ExcludeConstraint` where the
+        "whereclause" and "using" parameters would not be copied during an
+        operation like :meth:`.Table.tometadata`.
+
+    .. change:: 3898
+        :tags: bug, mssql
+        :tickets: 3898
+
+        Added a version check to the "get_isolation_level" feature, which is
+        invoked upon first connect, so that it skips for SQL Server version
+        2000, as the necessary system view is not available prior to SQL Server
+        2005.
+
+    .. change:: 3897
+        :tags: feature, ext
+        :tickets: 3896
+
+        Added :meth:`.baked.Result.scalar` and :meth:`.baked.Result.count`
+        to the "baked" query system.
+
+    .. change:: 3895
+        :tags: bug, orm, declarative
+        :tickets: 3895
+
+        Fixed bug where the "automatic exclude" feature of declarative that
+        ensures a column local to a single table inheritance subclass does
+        not appear as an attribute on other derivations of the base would
+        not take effect for multiple levels of subclassing from the base.
+
+    .. change:: 3893
+        :tags: bug, orm
+        :tickets: 3893
+
+        Fixed bug first introduced in 0.9.7 as a result of :ticket:`3106`
+        which would cause an incorrect query in some forms of multi-level
+        subqueryload against aliased entities, with an unnecessary extra
+        FROM entity in the innermost subquery.
+
+.. changelog::
     :version: 1.1.5
     :released: January 17, 2017
 
@@ -748,7 +871,7 @@
 
         Made a slight behavioral change in the ``sqlalchemy.ext.compiler``
         extension, whereby the existing compilation schemes for an established
-        construct would be removed if that construct was itself didn't already
+        construct would be removed if that construct itself didn't already
         have its own dedicated ``__visit_name__``.  This was a
         rare occurrence in 1.0, however in 1.1 :class:`.postgresql.ARRAY`
         subclasses :class:`.sqltypes.ARRAY` and has this behavior.
diff --git a/doc/build/changelog/migration_11.rst b/doc/build/changelog/migration_11.rst
index 04bdd72..58ca270 100644
--- a/doc/build/changelog/migration_11.rst
+++ b/doc/build/changelog/migration_11.rst
@@ -1505,16 +1505,16 @@ Support for Python's native ``enum`` type and compatible forms
 The :class:`.Enum` type can now be constructed using any
 PEP-435 compliant enumerated type.   When using this mode, input values
 and return values are the actual enumerated objects, not the
-string values::
+string/integer/etc values::
 
     import enum
     from sqlalchemy import Table, MetaData, Column, Enum, create_engine
 
 
     class MyEnum(enum.Enum):
-        one = "one"
-        two = "two"
-        three = "three"
+        one = 1
+        two = 2
+        three = 3
 
 
     t = Table(
diff --git a/doc/build/conf.py b/doc/build/conf.py
index e4477e4..bf2f725 100644
--- a/doc/build/conf.py
+++ b/doc/build/conf.py
@@ -107,9 +107,9 @@ copyright = u'2007-2017, the SQLAlchemy authors and contributors'
 # The short X.Y version.
 version = "1.1"
 # The full version, including alpha/beta/rc tags.
-release = "1.1.5"
+release = "1.1.6"
 
-release_date = "January 17, 2017"
+release_date = "Feburary 28, 2017"
 
 site_base = os.environ.get("RTD_SITE_BASE", "http://www.sqlalchemy.org")
 site_adapter_template = "docs_adapter.mako"
diff --git a/doc/build/core/defaults.rst b/doc/build/core/defaults.rst
index 9fe0a92..140e40d 100644
--- a/doc/build/core/defaults.rst
+++ b/doc/build/core/defaults.rst
@@ -334,7 +334,7 @@ the SQL commandline, we can use the :paramref:`.Column.server_default`
 parameter in conjunction with the value-generation function of the
 sequence, available from the :meth:`.Sequence.next_value` method::
 
-    cart_id_seq = Sequence('cart_id_seq')
+    cart_id_seq = Sequence('cart_id_seq', metadata=meta)
     table = Table("cartitems", meta,
         Column(
             "cart_id", Integer, cart_id_seq,
@@ -343,7 +343,32 @@ sequence, available from the :meth:`.Sequence.next_value` method::
         Column("createdate", DateTime())
     )
 
-The above metadata will generate a CREATE TABLE statement on PostgreSQL as::
+or with the ORM::
+
+    class CartItem(Base):
+        __tablename__ = 'cartitems'
+
+        cart_id_seq = Sequence('cart_id_seq', metadata=Base.metadata)
+        cart_id = Column(
+            Integer, cart_id_seq,
+            server_default=cart_id_seq.next_value(), primary_key=True)
+        description = Column(String(40))
+        createdate = Column(DateTime)
+
+In the above two examples, we set the :paramref:`.Sequence.metadata` parameter
+of the :class:`.Sequence` object to refer to the same :class:`.MetaData` object
+as that of the :class:`.Table`. The purpose of this is so that when we invoke
+:meth:`.MetaData.create_all`, the "CREATE SEQUENCE" statement will be emitted
+for the :class:`.Sequence`::
+
+    CREATE SEQUENCE cart_id_seq
+
+Alternatively, we can emit the "CREATE SEQUENCE" using the :class:`.Sequence`
+object itself as in ``cart_id_seq.create(engine)``, in the same way as
+:meth:`.Table.create`.
+
+When the "CREATE TABLE" statement is emitted, on PostgreSQL it would be
+emitted as::
 
     CREATE TABLE cartitems (
         cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
@@ -352,15 +377,38 @@ The above metadata will generate a CREATE TABLE statement on PostgreSQL as::
         PRIMARY KEY (cart_id)
     )
 
-We place the :class:`.Sequence` also as a Python-side default above, that
-is, it is mentioned twice in the :class:`.Column` definition.   Depending
-on the backend in use, this may not be strictly necessary, for example
-on the PostgreSQL backend the Core will use ``RETURNING`` to access the
-newly generated primary key value in any case.   However, for the best
-compatibility, :class:`.Sequence` was originally intended to be a Python-side
-directive first and foremost so it's probably a good idea to specify it
-in this way as well.
-
+In the definition for the :class:`.Column`, the above examples
+illustrate placement of the :class:`.Sequence` twice in the definition
+in two different contexts;
+as both a client side default generator object as well as a server
+side default::
+
+    Column(
+        "cart_id", Integer, cart_id_seq,
+        server_default=cart_id_seq.next_value(),
+        primary_key=True)
+
+Placing the :class:`.Sequence` as the "client side" default means that when the
+Core or ORM runs a :class:`.Insert` construct, it will either pre-invoke the
+:class:`.Sequence` and use the new value in the subsequent INSERT statement, or
+more commonly will render an invocation of the sequence explicitly within the
+INSERT statement itself, in conjunction with the use of RETURNING to get the
+newly generated value from the statement, assuming that this column is part of
+the table's primary key.   Assuming that RETURNING is available and enabled, it
+doesn't matter whether the :class:`.Sequence` is specified as a "client side"
+default in addition to :paramref:`.Column.server_default`, or only as
+:paramref:`.Column.server_default`.  RETURNING is normally used on the
+PostgreSQL and Oracle backends for single-row INSERT statements in order to
+retrieve newly created primary key values, so in most cases the "client side"
+setting isn't needed, however including :class:`.Sequence` as an explicit
+default generation object will allow the best compatibility, as
+:class:`.Sequence` was originally designed to be used in this way.
+
+.. seealso::
+
+    :ref:`postgresql_sequences` - in the Postgresql dialect documentation
+
+    :ref:`oracle_returning` - in the Oracle dialect documentation
 
 Default Objects API
 -------------------
diff --git a/doc/build/core/event.rst b/doc/build/core/event.rst
index 1a81dba..edc16e6 100644
--- a/doc/build/core/event.rst
+++ b/doc/build/core/event.rst
@@ -129,7 +129,7 @@ this value can be supported::
     def validate_phone(target, value, oldvalue, initiator):
         """Strip non-numeric characters from a phone number"""
 
-        return re.sub(r'(?![0-9])', '', value)
+        return re.sub(r'\D', '', value)
 
     # setup listener on UserContact.phone attribute, instructing
     # it to use the return value
diff --git a/doc/build/core/selectable.rst b/doc/build/core/selectable.rst
index f486016..57e3897 100644
--- a/doc/build/core/selectable.rst
+++ b/doc/build/core/selectable.rst
@@ -90,6 +90,7 @@ elements are themselves :class:`.ColumnElement` subclasses).
 
 .. autoclass:: SelectBase
    :members:
+   :inherited-members:
 
 .. autoclass:: TableClause
    :members:
diff --git a/doc/build/dialects/index.rst b/doc/build/dialects/index.rst
index cb96706..c5d239b 100644
--- a/doc/build/dialects/index.rst
+++ b/doc/build/dialects/index.rst
@@ -55,6 +55,8 @@ Production Ready
   Anywhere, developed by SAP.
 * `sqlalchemy-monetdb <https://github.com/gijzelaerr/sqlalchemy-monetdb>`_ - driver for MonetDB.
 * `snowflake-sqlalchemy <https://github.com/snowflakedb/snowflake-sqlalchemy>`_ - driver for `Snowflake <https://www.snowflake.net/>`_.
+* `sqlalchemy-tds <https://github.com/m32/sqlalchemy-tds>`_ - driver for MS-SQL,
+  on top of `pythone-tds <https://github.com/denisenkom/pytds>`_.
 
 Experimental / Incomplete
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py
index 78d53f4..5786cd0 100644
--- a/lib/sqlalchemy/__init__.py
+++ b/lib/sqlalchemy/__init__.py
@@ -128,7 +128,7 @@ from .schema import (
 from .inspection import inspect
 from .engine import create_engine, engine_from_config
 
-__version__ = '1.1.5'
+__version__ = '1.1.6'
 
 
 def __go(lcls):
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index 3e16e6e..6975754 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -1685,6 +1685,10 @@ class MSDialect(default.DefaultDialect):
         cursor.close()
 
     def get_isolation_level(self, connection):
+        if self.server_version_info < MS_2005_VERSION:
+            raise NotImplementedError(
+                "Can't fetch isolation level prior to SQL Server 2005")
+
         cursor = connection.cursor()
         cursor.execute("""
           SELECT CASE transaction_isolation_level
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 8b0d00a..822e932 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -676,6 +676,9 @@ RESERVED_WORDS = set(
 
      'generated', 'optimizer_costs', 'stored', 'virtual',  # 5.7
 
+     'admin', 'except', 'grouping', 'of', 'persist', 'recursive',
+        'role',  # 8.0
+
      ])
 
 AUTOCOMMIT_RE = re.compile(
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index 44e12f1..aaaa64c 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -9,6 +9,7 @@ r"""
 .. dialect:: postgresql
     :name: PostgreSQL
 
+.. _postgresql_sequences:
 
 Sequences/SERIAL
 ----------------
@@ -877,6 +878,11 @@ from sqlalchemy.types import INTEGER, BIGINT, SMALLINT, VARCHAR, \
     CHAR, TEXT, FLOAT, NUMERIC, \
     DATE, BOOLEAN, REAL
 
+AUTOCOMMIT_REGEXP = re.compile(
+    r'\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER|'
+    'IMPORT FOREIGN SCHEMA|REFRESH MATERIALIZED VIEW)',
+    re.I | re.UNICODE)
+
 RESERVED_WORDS = set(
     ["all", "analyse", "analyze", "and", "any", "array", "as", "asc",
      "asymmetric", "both", "case", "cast", "check", "collate", "column",
@@ -1997,6 +2003,9 @@ class PGExecutionContext(default.DefaultExecutionContext):
 
         return super(PGExecutionContext, self).get_insert_default(column)
 
+    def should_autocommit_text(self, statement):
+        return AUTOCOMMIT_REGEXP.match(statement)
+
 
 class PGDialect(default.DefaultDialect):
     name = 'postgresql'
diff --git a/lib/sqlalchemy/dialects/postgresql/ext.py b/lib/sqlalchemy/dialects/postgresql/ext.py
index ec95f37..55eded9 100644
--- a/lib/sqlalchemy/dialects/postgresql/ext.py
+++ b/lib/sqlalchemy/dialects/postgresql/ext.py
@@ -82,10 +82,51 @@ static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
 
     def __init__(self, *elements, **kw):
         r"""
+        Create an :class:`.ExcludeConstraint` object.
+
+        E.g.::
+
+            const = ExcludeConstraint(
+                (Column('period'), '&&'),
+                (Column('group'), '='),
+                where=(Column('group') != 'some group')
+            )
+
+        The constraint is normally embedded into the :class:`.Table` construct
+        directly, or added later using :meth:`.append_constraint`::
+
+            some_table = Table(
+                'some_table', metadata,
+                Column('id', Integer, primary_key=True),
+                Column('period', TSRANGE()),
+                Column('group', String)
+            )
+
+            some_table.append_constraint(
+                ExcludeConstraint(
+                    (some_table.c.period, '&&'),
+                    (some_table.c.group, '='),
+                    where=some_table.c.group != 'some group',
+                    name='some_table_excl_const'
+                )
+            )
+
         :param \*elements:
           A sequence of two tuples of the form ``(column, operator)`` where
-          column must be a column name or Column object and operator must
-          be a string containing the operator to use.
+          "column" is a SQL expression element or a raw SQL string, most
+          typically a :class:`.Column` object,
+          and "operator" is a string containing the operator to use.
+
+          .. note::
+
+                A plain string passed for the value of "column" is interpreted
+                as an arbitrary SQL  expression; when passing a plain string,
+                any necessary quoting and escaping syntaxes must be applied
+                manually. In order to specify a column name when a
+                :class:`.Column` object is not available, while ensuring that
+                any necessary quoting rules take effect, an ad-hoc
+                :class:`.Column` or :func:`.sql.expression.column` object may
+                be used.
 
         :param name:
           Optional, the in-database name of this constraint.
@@ -103,9 +144,16 @@ static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
           for this constraint. Defaults to 'gist'.
 
         :param where:
-          Optional string.  If set, emit WHERE <predicate> when issuing DDL
+          Optional SQL expression construct or literal SQL string.
+          If set, emit WHERE <predicate> when issuing DDL
           for this constraint.
 
+          .. note::
+
+                A plain string passed here is interpreted as an arbitrary SQL
+                expression; when passing a plain string, any necessary quoting
+                and escaping syntaxes must be applied manually.
+
         """
         columns = []
         render_exprs = []
@@ -151,7 +199,9 @@ static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
         c = self.__class__(*elements,
                            name=self.name,
                            deferrable=self.deferrable,
-                           initially=self.initially)
+                           initially=self.initially,
+                           where=self.where,
+                           using=self.using)
         c.dispatch._update(self.dispatch)
         return c
 
diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py
index bd25013..dfa81f4 100644
--- a/lib/sqlalchemy/engine/reflection.py
+++ b/lib/sqlalchemy/engine/reflection.py
@@ -340,20 +340,17 @@ class Inspector(object):
         Given a string `table_name` and an optional string `schema`, return
         column information as a list of dicts with these keys:
 
-        name
-          the column's name
+        * ``name`` - the column's name
 
-        type
+        * ``type`` - the type of this column; an instance of
           :class:`~sqlalchemy.types.TypeEngine`
 
-        nullable
-          boolean
+        * ``nullable`` - boolean flag if the column is NULL or NOT NULL
 
-        default
-          the column's default value
+        * ``default`` - the column's server default value - this is returned
+          as a string SQL expression.
 
-        attrs
-          dict containing optional column attributes
+        * ``attrs``  - dict containing optional column attributes
 
         :param table_name: string name of the table.  For special quoting,
          use :class:`.quoted_name`.
@@ -362,6 +359,9 @@ class Inspector(object):
          of the database connection.  For special quoting,
          use :class:`.quoted_name`.
 
+        :return: list of dictionaries, each representing the definition of
+         a database column.
+
         """
 
         col_defs = self.dialect.get_columns(self.bind, table_name, schema,
@@ -649,14 +649,14 @@ class Inspector(object):
 
         colargs = []
         if col_d.get('default') is not None:
-            # the "default" value is assumed to be a literal SQL
-            # expression, so is wrapped in text() so that no quoting
-            # occurs on re-issuance.
-            colargs.append(
-                sa_schema.DefaultClause(
-                    sql.text(col_d['default']), _reflected=True
-                )
-            )
+            default = col_d['default']
+            if isinstance(default, sql.elements.TextClause):
+                default = sa_schema.DefaultClause(default, _reflected=True)
+            elif not isinstance(default, sa_schema.FetchedValue):
+                default = sa_schema.DefaultClause(
+                    sql.text(col_d['default']), _reflected=True)
+
+            colargs.append(default)
 
         if 'sequence' in col_d:
             self._reflect_col_sequence(col_d, colargs)
diff --git a/lib/sqlalchemy/events.py b/lib/sqlalchemy/events.py
index 2ed44f5..7aa3001 100644
--- a/lib/sqlalchemy/events.py
+++ b/lib/sqlalchemy/events.py
@@ -178,7 +178,29 @@ class DDLEvents(event.Events):
         The dictionary of column information as returned by the
         dialect is passed, and can be modified.  The dictionary
         is that returned in each element of the list returned
-        by :meth:`.reflection.Inspector.get_columns`.
+        by :meth:`.reflection.Inspector.get_columns`:
+
+            * ``name`` - the column's name
+
+            * ``type`` - the type of this column, which should be an instance
+              of :class:`~sqlalchemy.types.TypeEngine`
+
+            * ``nullable`` - boolean flag if the column is NULL or NOT NULL
+
+            * ``default`` - the column's server default value.  This is
+              normally specified as a plain string SQL expression, however the
+              event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`,
+              or :func:`.sql.expression.text` object as well.
+
+              .. versionchanged:: 1.1.6
+
+                    The :meth:`.DDLEvents.column_reflect` event allows a non
+                    string :class:`.FetchedValue`,
+                    :func:`.sql.expression.text`, or derived object to be
+                    specified as the value of ``default`` in the column
+                    dictionary.
+
+            * ``attrs``  - dict containing optional column attributes
 
         The event is called before any action is taken against
         this dictionary, and the contents can be modified.
diff --git a/lib/sqlalchemy/ext/automap.py b/lib/sqlalchemy/ext/automap.py
index 5c1fec2..219bfe1 100644
--- a/lib/sqlalchemy/ext/automap.py
+++ b/lib/sqlalchemy/ext/automap.py
@@ -633,9 +633,9 @@ def generate_relationship(
      that user-defined implementations correctly differentiate between the two
      functions, if a custom relationship function is being used.
 
-    :attrname: the attribute name to which this relationship is being assigned.
-     If the value of :paramref:`.generate_relationship.return_fn` is the
-     :func:`.backref` function, then this name is the name that is being
+    :param attrname: the attribute name to which this relationship is being
+     assigned. If the value of :paramref:`.generate_relationship.return_fn` is
+     the :func:`.backref` function, then this name is the name that is being
      assigned to the backref.
 
     :param local_cls: the "local" class to which this relationship or backref
diff --git a/lib/sqlalchemy/ext/baked.py b/lib/sqlalchemy/ext/baked.py
index c329eb4..0904666 100644
--- a/lib/sqlalchemy/ext/baked.py
+++ b/lib/sqlalchemy/ext/baked.py
@@ -17,7 +17,7 @@ from ..orm.query import Query
 from ..orm import strategies, attributes, properties, \
     strategy_options, util as orm_util, interfaces
 from .. import log as sqla_log
-from ..sql import util as sql_util
+from ..sql import util as sql_util, func, literal_column
 from ..orm import exc as orm_exc
 from .. import exc as sa_exc
 from .. import util
@@ -254,6 +254,40 @@ class Result(object):
         return context.query.params(self._params).\
             with_session(self.session)._execute_and_instances(context)
 
+    def count(self):
+        """return the 'count'.
+
+        Equivalent to :meth:`.Query.count`.
+
+        Note this uses a subquery to ensure an accurate count regardless
+        of the structure of the original statement.
+
+        .. versionadded:: 1.1.6
+
+        """
+
+        col = func.count(literal_column('*'))
+        bq = self.bq.with_criteria(lambda q: q.from_self(col))
+        return bq.for_session(self.session).scalar()
+
+    def scalar(self):
+        """Return the first element of the first result or None
+        if no rows present.  If multiple rows are returned,
+        raises MultipleResultsFound.
+
+        Equivalent to :meth:`.Query.scalar`.
+
+        .. versionadded:: 1.1.6
+
+        """
+        try:
+            ret = self.one()
+            if not isinstance(ret, tuple):
+                return ret
+            return ret[0]
+        except orm_exc.NoResultFound:
+            return None
+
     def first(self):
         """Return the first row.
 
diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py
index 16cb05e..3beee31 100644
--- a/lib/sqlalchemy/ext/declarative/base.py
+++ b/lib/sqlalchemy/ext/declarative/base.py
@@ -492,8 +492,12 @@ class _MapperConfig(object):
 
             if 'exclude_properties' not in mapper_args:
                 mapper_args['exclude_properties'] = exclude_properties = \
-                    set([c.key for c in inherited_table.c
-                         if c not in inherited_mapper._columntoproperty])
+                    set(
+                        [c.key for c in inherited_table.c
+                         if c not in inherited_mapper._columntoproperty]
+                ).union(
+                    inherited_mapper.exclude_properties or ()
+                )
                 exclude_properties.difference_update(
                     [c.key for c in self.declared_columns])
 
diff --git a/lib/sqlalchemy/ext/indexable.py b/lib/sqlalchemy/ext/indexable.py
index 8298a65..b1ce129 100644
--- a/lib/sqlalchemy/ext/indexable.py
+++ b/lib/sqlalchemy/ext/indexable.py
@@ -227,6 +227,7 @@ The above query will render::
 """
 from __future__ import absolute_import
 
+from sqlalchemy import inspect
 from ..orm.attributes import flag_modified
 from ..ext.hybrid import hybrid_property
 
@@ -318,13 +319,14 @@ class index_property(hybrid_property):  # noqa
 
     def fset(self, instance, value):
         attr_name = self.attr_name
-        column_value = getattr(instance, attr_name)
+        column_value = getattr(instance, attr_name, None)
         if column_value is None:
             column_value = self.datatype()
             setattr(instance, attr_name, column_value)
         column_value[self.index] = value
         setattr(instance, attr_name, column_value)
-        flag_modified(instance, attr_name)
+        if attr_name in inspect(instance).mapper.attrs:
+            flag_modified(instance, attr_name)
 
     def fdel(self, instance):
         attr_name = self.attr_name
diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py
index 653f66d..d2ccec4 100644
--- a/lib/sqlalchemy/orm/events.py
+++ b/lib/sqlalchemy/orm/events.py
@@ -1812,7 +1812,7 @@ class AttributeEvents(event.Events):
         def validate_phone(target, value, oldvalue, initiator):
             "Strip non-numeric characters from a phone number"
 
-            return re.sub(r'(?![0-9])', '', value)
+            return re.sub(r'\D', '', value)
 
         # setup listener on UserContact.phone attribute, instructing
         # it to use the return value
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 3fad83e..fbe8f50 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -28,6 +28,7 @@ from .base import (InspectionAttr, InspectionAttr,
     InspectionAttrInfo, _MappedAttribute)
 import collections
 from .. import inspect
+from . import path_registry
 
 # imported later
 MapperExtension = SessionExtension = AttributeExtension = None
@@ -459,10 +460,24 @@ class StrategizedProperty(MapperProperty):
 
     """
 
-    __slots__ = '_strategies', 'strategy'
+    __slots__ = (
+        '_strategies', 'strategy',
+        '_wildcard_token', '_default_path_loader_key'
+    )
 
     strategy_wildcard_key = None
 
+    def _memoized_attr__wildcard_token(self):
+        return ("%s:%s" % (
+            self.strategy_wildcard_key, path_registry._WILDCARD_TOKEN), )
+
+    def _memoized_attr__default_path_loader_key(self):
+        return (
+            "loader",
+            ("%s:%s" % (
+                self.strategy_wildcard_key, path_registry._DEFAULT_TOKEN), )
+        )
+
     def _get_context_loader(self, context, path):
         load = None
 
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index f45b56a..962486d 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -2042,6 +2042,22 @@ class Mapper(InspectionAttr):
         )
 
     @_memoized_configured_property
+    def _server_default_plus_onupdate_propkeys(self):
+        result = set()
+
+        for table, columns in self._cols_by_table.items():
+            for col in columns:
+                if (
+                        (
+                            col.server_default is not None or
+                            col.server_onupdate is not None
+                        ) and col in self._columntoproperty
+                ):
+                    result.add(self._columntoproperty[col].key)
+
+        return result
+
+    @_memoized_configured_property
     def _server_onupdate_default_cols(self):
         return dict(
             (
diff --git a/lib/sqlalchemy/orm/path_registry.py b/lib/sqlalchemy/orm/path_registry.py
index 0377f96..580995a 100644
--- a/lib/sqlalchemy/orm/path_registry.py
+++ b/lib/sqlalchemy/orm/path_registry.py
@@ -203,6 +203,13 @@ class PropRegistry(PathRegistry):
         self.parent = parent
         self.path = parent.path + (prop,)
 
+        self._wildcard_path_loader_key = (
+            "loader",
+            self.parent.path + self.prop._wildcard_token
+        )
+        self._default_path_loader_key = self.prop._default_path_loader_key
+        self._loader_key = ("loader", self.path)
+
     def __str__(self):
         return " -> ".join(
             str(elem) for elem in self.path
@@ -216,33 +223,6 @@ class PropRegistry(PathRegistry):
     def entity(self):
         return self.prop.mapper
 
-    @util.memoized_property
-    def _wildcard_path_loader_key(self):
-        """Given a path (mapper A, prop X), replace the prop with the wildcard,
... 47733 lines suppressed ...

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



More information about the Python-modules-commits mailing list