[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