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

Piotr Ożarowski piotr at moszumanska.debian.org
Sun Jul 31 19:26:13 UTC 2016


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

piotr pushed a commit to branch master
in repository sqlalchemy.

commit 796dc5659d53dd9ffcd94d6b0b5089a52c97b516
Author: Piotr Ożarowski <piotr at debian.org>
Date:   Sun Jul 31 11:00:31 2016 +0200

    Import sqlalchemy_1.0.14+ds1.orig.tar.gz
---
 PKG-INFO                                      |   2 +-
 doc/build/changelog/changelog_05.rst          |   2 +-
 doc/build/changelog/changelog_08.rst          |   2 +-
 doc/build/changelog/changelog_10.rst          |  93 +++++++++
 doc/build/changelog/migration_08.rst          |   2 +-
 doc/build/changelog/migration_09.rst          |   2 +-
 doc/build/conf.py                             |  37 +---
 doc/build/core/constraints.rst                |   2 +-
 doc/build/core/metadata.rst                   |  19 +-
 doc/build/faq/ormconfiguration.rst            |   2 +-
 doc/build/orm/session_basics.rst              |   2 +-
 examples/dogpile_caching/__init__.py          |   2 +-
 examples/vertical/dictlike-polymorphic.py     |   2 +-
 lib/sqlalchemy/__init__.py                    |   3 +-
 lib/sqlalchemy/connectors/mxodbc.py           |   2 +-
 lib/sqlalchemy/dialects/oracle/base.py        |  25 ++-
 lib/sqlalchemy/dialects/postgresql/base.py    |   3 +
 lib/sqlalchemy/engine/base.py                 |   2 +-
 lib/sqlalchemy/engine/reflection.py           |   1 +
 lib/sqlalchemy/engine/result.py               |   2 +-
 lib/sqlalchemy/ext/automap.py                 |   2 +-
 lib/sqlalchemy/ext/mutable.py                 |   2 +-
 lib/sqlalchemy/orm/strategies.py              |   2 +-
 lib/sqlalchemy/schema.py                      |   1 +
 lib/sqlalchemy/sql/default_comparator.py      |   2 +-
 lib/sqlalchemy/sql/schema.py                  |  60 +++++-
 lib/sqlalchemy/sql/selectable.py              |  50 +++--
 lib/sqlalchemy/sql/type_api.py                |   2 +-
 lib/sqlalchemy/testing/plugin/plugin_base.py  |   3 +
 lib/sqlalchemy/testing/plugin/pytestplugin.py |  10 +-
 lib/sqlalchemy/testing/provision.py           |  10 +-
 lib/sqlalchemy/util/_collections.py           |   4 +-
 test/base/test_utils.py                       |  35 ++++
 test/dialect/postgresql/test_dialect.py       |  21 +-
 test/dialect/postgresql/test_reflection.py    |  23 +++
 test/dialect/test_oracle.py                   |  73 +++++++
 test/engine/test_pool.py                      | 284 ++++++++++++++------------
 test/engine/test_reflection.py                |  27 ++-
 test/sql/test_defaults.py                     |   3 +-
 test/sql/test_generative.py                   |  17 ++
 test/sql/test_metadata.py                     |  44 ++--
 test/sql/test_operators.py                    |   6 +
 test/sql/test_types.py                        |   4 +-
 43 files changed, 663 insertions(+), 229 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 6705ec2..2ba9b83 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: SQLAlchemy
-Version: 1.0.13
+Version: 1.0.14
 Summary: Database Abstraction Library
 Home-page: http://www.sqlalchemy.org
 Author: Mike Bayer
diff --git a/doc/build/changelog/changelog_05.rst b/doc/build/changelog/changelog_05.rst
index 04ab11d..f612cee 100644
--- a/doc/build/changelog/changelog_05.rst
+++ b/doc/build/changelog/changelog_05.rst
@@ -3461,7 +3461,7 @@
         :tickets: 
 
       Fixed query.join() when used in conjunction with a
-      columns-only clause and an SQL-expression ON clause in the
+      columns-only clause and a SQL-expression ON clause in the
       join.
 
     .. change::
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 5d74af7..ddf6be5 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -2440,7 +2440,7 @@
         :tickets: 2589
 
       The Beaker caching example has been converted
-      to use `dogpile.cache <http://dogpilecache.readthedocs.org/>`_.
+      to use `dogpile.cache <https://dogpilecache.readthedocs.io/>`_.
       This is a new caching library written by the same
       creator of Beaker's caching internals, and represents a
       vastly improved, simplified, and modernized system of caching.
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index 39670b0..1b27a1d 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -16,6 +16,99 @@
         :start-line: 5
 
 .. changelog::
+    :version: 1.0.14
+    :released: July 6, 2016
+
+    .. change::
+        :tags: bug, postgresql
+        :tickets: 3739
+        :versions: 1.1.0b3
+
+        Fixed bug whereby :class:`.TypeDecorator` and :class:`.Variant`
+        types were not deeply inspected enough by the Postgresql dialect
+        to determine if SMALLSERIAL or BIGSERIAL needed to be rendered
+        rather than SERIAL.
+
+    .. change::
+        :tags: bug, oracle
+        :tickets: 3741
+        :versions: 1.1.0b3
+
+        Fixed bug in :paramref:`.Select.with_for_update.of`, where the Oracle
+        "rownum" approach to LIMIT/OFFSET would fail to accomodate for the
+        expressions inside the "OF" clause, which must be stated at the topmost
+        level referring to expression within the subquery.  The expressions are
+        now added to the subquery if needed.
+
+    .. change::
+        :tags: bug, sql
+        :tickets: 3735
+        :versions: 1.1.0b2
+
+        Fixed issue in SQL math negation operator where the type of the
+        expression would no longer be the numeric type of the original.
+        This would cause issues where the type determined result set
+        behaviors.
+
+    .. change::
+        :tags: bug, sql
+        :tickets: 3728
+        :versions: 1.1.0b2
+
+        Fixed bug whereby the ``__getstate__`` / ``__setstate__``
+        methods for sqlalchemy.util.Properties were
+        non-working due to the transition in the 1.0 series to ``__slots__``.
+        The issue potentially impacted some third-party applications.
+        Pull request courtesy Pieter Mulder.
+
+    .. change::
+        :tags: bug, sql
+        :tickets: 3724
+
+        :meth:`.FromClause.count` is pending deprecation for 1.1.  This function
+        makes use of an arbitrary column in the table and is not reliable;
+        for Core use, ``func.count()`` should be preferred.
+
+    .. change::
+        :tags: bug, sql
+        :tickets: 3722
+
+        Fixed bug in :class:`.CTE` structure which would cause it to not
+        clone properly when a union was used, as is common in a recursive
+        CTE.  The improper cloning would cause errors when the CTE is used
+        in various ORM contexts such as that of a :func:`.column_property`.
+
+    .. change::
+        :tags: bug, sql
+        :tickets: 3721
+
+        Fixed bug whereby :meth:`.Table.tometadata` would make a duplicate
+        :class:`.UniqueConstraint` for each :class:`.Column` object that
+        featured the ``unique=True`` parameter.
+
+    .. change::
+        :tags: bug, engine, postgresql
+        :tickets: 3716
+
+        Fixed bug in cross-schema foreign key reflection in conjunction
+        with the :paramref:`.MetaData.schema` argument, where a referenced
+        table that is present in the "default" schema would fail since there
+        would be no way to indicate a :class:`.Table` that has "blank" for
+        a schema.  The special symbol :attr:`.schema.BLANK_SCHEMA` has been
+        added as an available value for :paramref:`.Table.schema` and
+        :paramref:`.Sequence.schema`, indicating that the schema name
+        should be forced to be ``None`` even if :paramref:`.MetaData.schema`
+        is specified.
+
+    .. change::
+        :tags: bug, examples
+        :tickets: 3704
+
+        Fixed a regression that occurred in the
+        examples/vertical/dictlike-polymorphic.py example which prevented it
+        from running.
+
+.. changelog::
     :version: 1.0.13
     :released: May 16, 2016
 
diff --git a/doc/build/changelog/migration_08.rst b/doc/build/changelog/migration_08.rst
index 9e94de5..3dfd9a1 100644
--- a/doc/build/changelog/migration_08.rst
+++ b/doc/build/changelog/migration_08.rst
@@ -578,7 +578,7 @@ that were not flushed in the current transaction.
 Caching Example now uses dogpile.cache
 ---------------------------------------
 
-The caching example now uses `dogpile.cache <http://dogpilecache.readthedocs.org/>`_.
+The caching example now uses `dogpile.cache <https://dogpilecache.readthedocs.io/>`_.
 Dogpile.cache is a rewrite of the caching portion
 of Beaker, featuring vastly simpler and faster operation,
 as well as support for distributed locking.
diff --git a/doc/build/changelog/migration_09.rst b/doc/build/changelog/migration_09.rst
index e8dcb9f..fef0306 100644
--- a/doc/build/changelog/migration_09.rst
+++ b/doc/build/changelog/migration_09.rst
@@ -1095,7 +1095,7 @@ can be dropped in using callable functions.
 
 It is hoped that the :class:`.AutomapBase` system provides a quick
 and modernized solution to the problem that the very famous
-`SQLSoup <https://sqlsoup.readthedocs.org/en/latest/>`_
+`SQLSoup <https://sqlsoup.readthedocs.io/en/latest/>`_
 also tries to solve, that of generating a quick and rudimentary object
 model from an existing database on the fly.  By addressing the issue strictly
 at the mapper configuration level, and integrating fully with existing
diff --git a/doc/build/conf.py b/doc/build/conf.py
index 46f3b0a..7653827 100644
--- a/doc/build/conf.py
+++ b/doc/build/conf.py
@@ -13,25 +13,6 @@
 
 import sys
 import os
-import traceback
-
-def force_install_reqs():
-    import logging
-
-    log = logging.getLogger("pip")
-    handler = logging.StreamHandler(sys.stderr)
-    handler.setFormatter(logging.Formatter("[pip] %(message)s"))
-    log.addHandler(handler)
-    log.setLevel(logging.INFO)
-
-    log.info("READTHEDOCS is set, force-installing requirements.txt")
-
-    from pip.commands import install
-    req = os.path.join(os.path.dirname(__file__), "requirements.txt")
-    cmd = install.InstallCommand()
-    options, args = cmd.parse_args(["-v", "-U", "-r", req])
-    cmd.run(options, args)
-
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -42,18 +23,6 @@ sys.path.insert(0, os.path.abspath('.'))
 
 import sqlalchemy
 
-# attempt to force pip to definitely get the latest
-# versions of libraries, see
-# https://github.com/rtfd/readthedocs.org/issues/1293
-rtd = os.environ.get('READTHEDOCS', None) == 'True'
-if rtd:
-    try:
-        force_install_reqs()
-    except:
-        traceback.print_exc()
-
-
-
 
 # -- General configuration -----------------------------------------------------
 
@@ -138,9 +107,9 @@ copyright = u'2007-2016, the SQLAlchemy authors and contributors'
 # The short X.Y version.
 version = "1.0"
 # The full version, including alpha/beta/rc tags.
-release = "1.0.13"
+release = "1.0.14"
 
-release_date = "May 16, 2016"
+release_date = "July 6, 2016"
 
 site_base = os.environ.get("RTD_SITE_BASE", "http://www.sqlalchemy.org")
 site_adapter_template = "docs_adapter.mako"
@@ -373,7 +342,7 @@ epub_copyright = u'2007-2015, SQLAlchemy authors'
 #epub_tocdup = True
 
 intersphinx_mapping = {
-    'alembic': ('http://alembic.readthedocs.org/en/latest/', None),
+    'alembic': ('http://alembic.zzzcomputing.com/en/latest/', None),
     'psycopg2': ('http://pythonhosted.org/psycopg2', None),
 }
 
diff --git a/doc/build/core/constraints.rst b/doc/build/core/constraints.rst
index 197eeb8..bf47a5b 100644
--- a/doc/build/core/constraints.rst
+++ b/doc/build/core/constraints.rst
@@ -426,7 +426,7 @@ parameters which create :class:`.UniqueConstraint` and :class:`.Index` objects
 without an explicit name being specified.
 
 The use case of alteration of existing tables and constraints can be handled
-by schema migration tools such as `Alembic <http://http://alembic.readthedocs.org/>`_.
+by schema migration tools such as `Alembic <http://alembic.zzzcomputing.com/>`_.
 However, neither Alembic nor SQLAlchemy currently create names for constraint
 objects where the name is otherwise unspecified, leading to the case where
 being able to alter existing constraints means that one must reverse-engineer
diff --git a/doc/build/core/metadata.rst b/doc/build/core/metadata.rst
index 5052e0e..1e762b1 100644
--- a/doc/build/core/metadata.rst
+++ b/doc/build/core/metadata.rst
@@ -243,7 +243,7 @@ database schemas in relation to application code using schema migration tools.
 
 There are two major migration tools available for SQLAlchemy:
 
-* `Alembic <http://alembic.readthedocs.org>`_ - Written by the author of SQLAlchemy,
+* `Alembic <http://alembic.zzzcomputing.com>`_ - Written by the author of SQLAlchemy,
   Alembic features a highly customizable environment and a minimalistic usage pattern,
   supporting such features as transactional DDL, automatic generation of "candidate"
   migrations, an "offline" mode which generates SQL scripts, and support for branch
@@ -303,6 +303,23 @@ described in the individual documentation sections for each dialect.
 Column, Table, MetaData API
 ---------------------------
 
+.. attribute:: sqlalchemy.schema.BLANK_SCHEMA
+
+    Symbol indicating that a :class:`.Table` or :class:`.Sequence`
+    should have 'None' for its schema, even if the parent
+    :class:`.MetaData` has specified a schema.
+
+    .. seealso::
+
+        :paramref:`.MetaData.schema`
+
+        :paramref:`.Table.schema`
+
+        :paramref:`.Sequence.schema`
+
+    .. versionadded:: 1.0.14
+
+
 .. autoclass:: Column
     :members:
     :inherited-members:
diff --git a/doc/build/faq/ormconfiguration.rst b/doc/build/faq/ormconfiguration.rst
index faaee44..24eacb7 100644
--- a/doc/build/faq/ormconfiguration.rst
+++ b/doc/build/faq/ormconfiguration.rst
@@ -294,7 +294,7 @@ the two queries may not see the same results:
     ORDER BY anon_1.users_id
 
 Depending on database specifics, there is
-a chance we may get the a result like the following for the two queries::
+a chance we may get a result like the following for the two queries::
 
     -- query #1
     +--------+
diff --git a/doc/build/orm/session_basics.rst b/doc/build/orm/session_basics.rst
index 0f96ba5..198603b 100644
--- a/doc/build/orm/session_basics.rst
+++ b/doc/build/orm/session_basics.rst
@@ -410,7 +410,7 @@ by default. This also defeats the purpose of using the Session as a cache.
 The :class:`.Session` is not designed to be a
 global object from which everyone consults as a "registry" of objects.
 That's more the job of a **second level cache**.   SQLAlchemy provides
-a pattern for implementing second level caching using `dogpile.cache <http://dogpilecache.readthedocs.org/>`_,
+a pattern for implementing second level caching using `dogpile.cache <https://dogpilecache.readthedocs.io/>`_,
 via the :ref:`examples_caching` example.
 
 How can I get the :class:`~sqlalchemy.orm.session.Session` for a certain object?
diff --git a/examples/dogpile_caching/__init__.py b/examples/dogpile_caching/__init__.py
index bf67eeb..0f19854 100644
--- a/examples/dogpile_caching/__init__.py
+++ b/examples/dogpile_caching/__init__.py
@@ -1,5 +1,5 @@
 """
-Illustrates how to embed `dogpile.cache <http://dogpilecache.readthedocs.org/>`_
+Illustrates how to embed `dogpile.cache <https://dogpilecache.readthedocs.io/>`_
 functionality within
 the :class:`.Query` object, allowing full cache control as well as the
 ability to pull "lazy loaded" attributes from long term cache
diff --git a/examples/vertical/dictlike-polymorphic.py b/examples/vertical/dictlike-polymorphic.py
index e3d5ba5..7147ac4 100644
--- a/examples/vertical/dictlike-polymorphic.py
+++ b/examples/vertical/dictlike-polymorphic.py
@@ -134,7 +134,7 @@ if __name__ == '__main__':
         char_value = Column(UnicodeText, info={'type': (str, 'string')})
         boolean_value = Column(Boolean, info={'type': (bool, 'boolean')})
 
-    class Animal(ProxiedDictMixin._base_class(Base)):
+    class Animal(ProxiedDictMixin, Base):
         """an Animal"""
 
         __tablename__ = 'animal'
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py
index 89033a3..06ceb49 100644
--- a/lib/sqlalchemy/__init__.py
+++ b/lib/sqlalchemy/__init__.py
@@ -114,13 +114,14 @@ from .schema import (
     ThreadLocalMetaData,
     UniqueConstraint,
     DDL,
+    BLANK_SCHEMA
 )
 
 
 from .inspection import inspect
 from .engine import create_engine, engine_from_config
 
-__version__ = '1.0.13'
+__version__ = '1.0.14'
 
 
 def __go(lcls):
diff --git a/lib/sqlalchemy/connectors/mxodbc.py b/lib/sqlalchemy/connectors/mxodbc.py
index 9fc0ce6..d49ca4b 100644
--- a/lib/sqlalchemy/connectors/mxodbc.py
+++ b/lib/sqlalchemy/connectors/mxodbc.py
@@ -6,7 +6,7 @@
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
 """
-Provide an SQLALchemy connector for the eGenix mxODBC commercial
+Provide a SQLALchemy connector for the eGenix mxODBC commercial
 Python adapter for ODBC. This is not a free product, but eGenix
 provides SQLAlchemy with a license for use in continuous integration
 testing.
diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py
index eb63983..dd44a49 100644
--- a/lib/sqlalchemy/dialects/oracle/base.py
+++ b/lib/sqlalchemy/dialects/oracle/base.py
@@ -285,7 +285,7 @@ import re
 
 from sqlalchemy import util, sql
 from sqlalchemy.engine import default, reflection
-from sqlalchemy.sql import compiler, visitors, expression
+from sqlalchemy.sql import compiler, visitors, expression, util as sql_util
 from sqlalchemy.sql import operators as sql_operators
 from sqlalchemy.sql.elements import quoted_name
 from sqlalchemy import types as sqltypes, schema as sa_schema
@@ -754,6 +754,20 @@ class OracleCompiler(compiler.SQLCompiler):
                 limitselect._oracle_visit = True
                 limitselect._is_wrapper = True
 
+                # add expressions to accomodate FOR UPDATE OF
+                for_update = select._for_update_arg
+                if for_update is not None and for_update.of:
+                    for_update = for_update._clone()
+                    for_update._copy_internals()
+
+                    for elem in for_update.of:
+                        select.append_column(elem)
+
+                    adapter = sql_util.ClauseAdapter(select)
+                    for_update.of = [
+                        adapter.traverse(elem)
+                        for elem in for_update.of]
+
                 # If needed, add the limiting clause
                 if limit_clause is not None:
                     if not self.dialect.use_binds_for_limits:
@@ -773,7 +787,7 @@ class OracleCompiler(compiler.SQLCompiler):
 
                 # If needed, add the ora_rn, and wrap again with offset.
                 if offset_clause is None:
-                    limitselect._for_update_arg = select._for_update_arg
+                    limitselect._for_update_arg = for_update
                     select = limitselect
                 else:
                     limitselect = limitselect.column(
@@ -786,13 +800,18 @@ class OracleCompiler(compiler.SQLCompiler):
                     offsetselect._oracle_visit = True
                     offsetselect._is_wrapper = True
 
+                    if for_update is not None and for_update.of:
+                        for elem in for_update.of:
+                            if limitselect.corresponding_column(elem) is None:
+                                limitselect.append_column(elem)
+
                     if not self.dialect.use_binds_for_limits:
                         offset_clause = sql.literal_column(
                             "%d" % select._offset)
                     offsetselect.append_whereclause(
                         sql.literal_column("ora_rn") > offset_clause)
 
-                    offsetselect._for_update_arg = select._for_update_arg
+                    offsetselect._for_update_arg = for_update
                     select = offsetselect
 
         return compiler.SQLCompiler.visit_select(self, select, **kwargs)
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index 8c676a3..766847c 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1578,6 +1578,9 @@ class PGDDLCompiler(compiler.DDLCompiler):
 
         colspec = self.preparer.format_column(column)
         impl_type = column.type.dialect_impl(self.dialect)
+        if isinstance(impl_type, sqltypes.TypeDecorator):
+            impl_type = impl_type.impl
+
         if column.primary_key and \
             column is column.table._autoincrement_column and \
             (
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 80edd95..40c80ec 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -844,7 +844,7 @@ class Connection(Connectable):
         return self.execute(object, *multiparams, **params).scalar()
 
     def execute(self, object, *multiparams, **params):
-        """Executes the a SQL statement construct and returns a
+        """Executes a SQL statement construct and returns a
         :class:`.ResultProxy`.
 
         :param object: The statement to be executed.  May be
diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py
index 98fcfa0..52aa69c 100644
--- a/lib/sqlalchemy/engine/reflection.py
+++ b/lib/sqlalchemy/engine/reflection.py
@@ -692,6 +692,7 @@ class Inspector(object):
             else:
                 sa_schema.Table(referred_table, table.metadata, autoload=True,
                                 autoload_with=self.bind,
+                                schema=sa_schema.BLANK_SCHEMA,
                                 **reflection_options
                                 )
                 for column in referred_columns:
diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py
index 4805015..3c77e7d 100644
--- a/lib/sqlalchemy/engine/result.py
+++ b/lib/sqlalchemy/engine/result.py
@@ -673,7 +673,7 @@ class ResultProxy(object):
         """Close this ResultProxy.
 
         This closes out the underlying DBAPI cursor corresonding
-        to the statement execution, if one is stil present.  Note that the
+        to the statement execution, if one is still present.  Note that the
         DBAPI cursor is automatically released when the :class:`.ResultProxy`
         exhausts all available rows.  :meth:`.ResultProxy.close` is generally
         an optional method except in the case when discarding a
diff --git a/lib/sqlalchemy/ext/automap.py b/lib/sqlalchemy/ext/automap.py
index 023d11c..bb1c5da 100644
--- a/lib/sqlalchemy/ext/automap.py
+++ b/lib/sqlalchemy/ext/automap.py
@@ -13,7 +13,7 @@ schema, typically though not necessarily one which is reflected.
 
 It is hoped that the :class:`.AutomapBase` system provides a quick
 and modernized solution to the problem that the very famous
-`SQLSoup <https://sqlsoup.readthedocs.org/en/latest/>`_
+`SQLSoup <https://sqlsoup.readthedocs.io/en/latest/>`_
 also tries to solve, that of generating a quick and rudimentary object
 model from an existing database on the fly.  By addressing the issue strictly
 at the mapper configuration level, and integrating fully with existing
diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py
index 97f720c..5863834 100644
--- a/lib/sqlalchemy/ext/mutable.py
+++ b/lib/sqlalchemy/ext/mutable.py
@@ -46,7 +46,7 @@ with any type whose target Python type may be mutable, including
 :class:`.PickleType`, :class:`.postgresql.ARRAY`, etc.
 
 When using the :mod:`sqlalchemy.ext.mutable` extension, the value itself
-tracks all parents which reference it.  Below, we illustrate the a simple
+tracks all parents which reference it.  Below, we illustrate a simple
 version of the :class:`.MutableDict` dictionary object, which applies
 the :class:`.Mutable` mixin to a plain Python dictionary::
 
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 37f60e1..b4389d0 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -112,7 +112,7 @@ def _register_attribute(
 
 @properties.ColumnProperty.strategy_for(instrument=False, deferred=False)
 class UninstrumentedColumnLoader(LoaderStrategy):
-    """Represent the a non-instrumented MapperProperty.
+    """Represent a non-instrumented MapperProperty.
 
     The polymorphic_on argument of mapper() often results in this,
     if the argument is against the with_polymorphic selectable.
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 5b703f7..bd0cbe5 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -15,6 +15,7 @@ from .sql.base import (
 
 
 from .sql.schema import (
+    BLANK_SCHEMA,
     CheckConstraint,
     Column,
     ColumnDefault,
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py
index d180dbc..51a0538 100644
--- a/lib/sqlalchemy/sql/default_comparator.py
+++ b/lib/sqlalchemy/sql/default_comparator.py
@@ -176,7 +176,7 @@ def _inv_impl(expr, op, **kw):
 
 def _neg_impl(expr, op, **kw):
     """See :meth:`.ColumnOperators.__neg__`."""
-    return UnaryExpression(expr, operator=operators.neg)
+    return UnaryExpression(expr, operator=operators.neg, type_=expr.type)
 
 
 def _match_impl(expr, op, other, **kw):
diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py
index c122ee4..f9c6d05 100644
--- a/lib/sqlalchemy/sql/schema.py
+++ b/lib/sqlalchemy/sql/schema.py
@@ -47,6 +47,17 @@ import types
 
 RETAIN_SCHEMA = util.symbol('retain_schema')
 
+BLANK_SCHEMA = util.symbol(
+    'blank_schema',
+    """Symbol indicating that a :class:`.Table` or :class:`.Sequence`
+    should have 'None' for its schema, even if the parent
+    :class:`.MetaData` has specified a schema.
+
+    .. versionadded:: 1.0.14
+
+    """
+)
+
 
 def _get_table_key(name, schema):
     if schema is None:
@@ -341,6 +352,17 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
         the table resides in a schema other than the default selected schema
         for the engine's database connection.  Defaults to ``None``.
 
+        If the owning :class:`.MetaData` of this :class:`.Table` specifies
+        its own :paramref:`.MetaData.schema` parameter, then that schema
+        name will be applied to this :class:`.Table` if the schema parameter
+        here is set to ``None``.  To set a blank schema name on a :class:`.Table`
+        that would otherwise use the schema set on the owning :class:`.MetaData`,
+        specify the special symbol :attr:`.BLANK_SCHEMA`.
+
+        .. versionadded:: 1.0.14  Added the :attr:`.BLANK_SCHEMA` symbol to
+           allow a :class:`.Table` to have a blank schema name even when the
+           parent :class:`.MetaData` specifies :paramref:`.MetaData.schema`.
+
         The quoting rules for the schema name are the same as those for the
         ``name`` parameter, in that quoting is applied for reserved words or
         case-sensitive names; to enable unconditional quoting for the
@@ -372,6 +394,8 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
         schema = kw.get('schema', None)
         if schema is None:
             schema = metadata.schema
+        elif schema is BLANK_SCHEMA:
+            schema = None
         keep_existing = kw.pop('keep_existing', False)
         extend_existing = kw.pop('extend_existing', False)
         if 'useexisting' in kw:
@@ -443,6 +467,8 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
         self.schema = kwargs.pop('schema', None)
         if self.schema is None:
             self.schema = metadata.schema
+        elif self.schema is BLANK_SCHEMA:
+            self.schema = None
         else:
             quote_schema = kwargs.pop('quote_schema', None)
             self.schema = quoted_name(self.schema, quote_schema)
@@ -836,8 +862,14 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
                         schema if referred_schema == self.schema else None)
                 table.append_constraint(
                     c.copy(schema=fk_constraint_schema, target_table=table))
-
             elif not c._type_bound:
+                # skip unique constraints that would be generated
+                # by the 'unique' flag on Column
+                if isinstance(c, UniqueConstraint) and \
+                    len(c.columns) == 1 and \
+                        list(c.columns)[0].unique:
+                    continue
+
                 table.append_constraint(
                     c.copy(schema=schema, target_table=table))
         for index in self.indexes:
@@ -2114,7 +2146,10 @@ class Sequence(DefaultGenerator):
          .. versionadded:: 1.0.7
 
         :param schema: Optional schema name for the sequence, if located
-         in a schema other than the default.
+         in a schema other than the default.  The rules for selecting the
+         schema name when a :class:`.MetaData` is also present are the same
+         as that of :paramref:`.Table.schema`.
+
         :param optional: boolean value, when ``True``, indicates that this
          :class:`.Sequence` object only needs to be explicitly generated
          on backends that don't provide another way to generate primary
@@ -2163,7 +2198,9 @@ class Sequence(DefaultGenerator):
         self.nomaxvalue = nomaxvalue
         self.cycle = cycle
         self.optional = optional
-        if metadata is not None and schema is None and metadata.schema:
+        if schema is BLANK_SCHEMA:
+            self.schema = schema = None
+        elif metadata is not None and schema is None and metadata.schema:
             self.schema = schema = metadata.schema
         else:
             self.schema = quoted_name(schema, quote_schema)
@@ -3296,8 +3333,21 @@ class MetaData(SchemaItem):
 
         :param schema:
            The default schema to use for the :class:`.Table`,
-           :class:`.Sequence`, and other objects associated with this
-           :class:`.MetaData`. Defaults to ``None``.
+           :class:`.Sequence`, and potentially other objects associated with
+           this :class:`.MetaData`. Defaults to ``None``.
+
+           When this value is set, any :class:`.Table` or :class:`.Sequence`
+           which specifies ``None`` for the schema parameter will instead
+           have this schema name defined.  To build a :class:`.Table`
+           or :class:`.Sequence` that still has ``None`` for the schema
+           even when this parameter is present, use the :attr:`.BLANK_SCHEMA`
+           symbol.
+
+           .. seealso::
+
+                :paramref:`.Table.schema`
+
+                :paramref:`.Sequence.schema`
 
         :param quote_schema:
             Sets the ``quote_schema`` flag for those :class:`.Table`,
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index b986fd5..0ad2d98 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -286,10 +286,35 @@ class FromClause(Selectable):
 
     _memoized_property = util.group_expirable_memoized_property(["_columns"])
 
+    @util.pending_deprecation(
+        '1.1',
+        message="``Table.count()`` is deprecated. Counting "
+        "rows requires that the correct column expression and "
+        "accommodations for joins, DISTINCT, etc. must be made, "
+        "otherwise results may not be what's expected. "
+        "Please use an appropriate ``func.count()`` expression "
+        "directly."
+    )
     @util.dependencies("sqlalchemy.sql.functions")
     def count(self, functions, whereclause=None, **params):
         """return a SELECT COUNT generated against this
-        :class:`.FromClause`."""
+        :class:`.FromClause`.
+
+        The function generates COUNT against the
+        first column in the primary key of the table, or against
+        the first column in the table overall.   Explicit use of
+        ``func.count()`` should be preferred::
+
+            row_count = conn.scalar(
+                select([func.count('*')]).select_from(table)
+            )
+
+
+        .. seealso::
+
+            :data:`.func`
+
+        """
 
         if self.primary_key:
             col = list(self.primary_key)[0]
@@ -1187,6 +1212,14 @@ class CTE(Generative, HasSuffixes, Alias):
             self._suffixes = _suffixes
         super(CTE, self).__init__(selectable, name=name)
 
+    def _copy_internals(self, clone=_clone, **kw):
+        super(CTE, self)._copy_internals(clone, **kw)
+        if self._cte_alias is not None:
+            self._cte_alias = self
+        self._restates = frozenset([
+            clone(elem, **kw) for elem in self._restates
+        ])
+
     def alias(self, name=None, flat=False):
         return CTE(
             self.original,
@@ -1353,21 +1386,6 @@ class TableClause(Immutable, FromClause):
         else:
             return []
 
-    @util.dependencies("sqlalchemy.sql.functions")
-    def count(self, functions, whereclause=None, **params):
-        """return a SELECT COUNT generated against this
-        :class:`.TableClause`."""
-
-        if self.primary_key:
-            col = list(self.primary_key)[0]
-        else:
-            col = list(self.columns)[0]
-        return Select(
-            [functions.func.count(col).label('tbl_row_count')],
-            whereclause,
-            from_obj=[self],
-            **params)
-
     @util.dependencies("sqlalchemy.sql.dml")
     def insert(self, dml, values=None, inline=False, **kwargs):
         """Generate an :func:`.insert` construct against this
diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py
index 2997a8d..7b1bfcb 100644
--- a/lib/sqlalchemy/sql/type_api.py
+++ b/lib/sqlalchemy/sql/type_api.py
@@ -1011,7 +1011,7 @@ class TypeDecorator(TypeEngine):
         the processing provided by ``self.impl`` is maintained.
 
         :param dialect: Dialect instance in use.
-        :param coltype: An SQLAlchemy data type
+        :param coltype: A SQLAlchemy data type
 
         This method is the reverse counterpart to the
         :meth:`bind_processor` method of this class.
diff --git a/lib/sqlalchemy/testing/plugin/plugin_base.py b/lib/sqlalchemy/testing/plugin/plugin_base.py
index 1ba0a80..cbe9f08 100644
--- a/lib/sqlalchemy/testing/plugin/plugin_base.py
+++ b/lib/sqlalchemy/testing/plugin/plugin_base.py
@@ -67,6 +67,9 @@ def setup_options(make_option):
                 dest="low_connections",
                 help="Use a low number of distinct connections - "
                 "i.e. for Oracle TNS")
+    make_option("--write-idents", type="string", dest="write_idents",
+                help="write out generated follower idents to <file>, "
+                "when -n<num> is used")
     make_option("--reversetop", action="store_true",
                 dest="reversetop", default=False,
                 help="Use a random-ordering set implementation in the ORM "
diff --git a/lib/sqlalchemy/testing/plugin/pytestplugin.py b/lib/sqlalchemy/testing/plugin/pytestplugin.py
index 5bb6b96..67ccb35 100644
--- a/lib/sqlalchemy/testing/plugin/pytestplugin.py
+++ b/lib/sqlalchemy/testing/plugin/pytestplugin.py
@@ -9,7 +9,7 @@ import pytest
 import argparse
 import inspect
 import collections
-import itertools
+import os
 
 try:
     import xdist  # noqa
@@ -43,6 +43,14 @@ def pytest_configure(config):
             config.slaveinput["follower_ident"]
         )
 
+        if config.option.write_idents:
+            with open(config.option.write_idents, "a") as file_:
+                file_.write(config.slaveinput["follower_ident"] + "\n")
+    else:
+        if config.option.write_idents and \
+                os.path.exists(config.option.write_idents):
+            os.remove(config.option.write_idents)
+
     plugin_base.pre_begin(config.option)
 
     plugin_base.set_coverage_flag(bool(getattr(config.option,
diff --git a/lib/sqlalchemy/testing/provision.py b/lib/sqlalchemy/testing/provision.py
index 4bba1be..88d1669 100644
--- a/lib/sqlalchemy/testing/provision.py
+++ b/lib/sqlalchemy/testing/provision.py
@@ -40,7 +40,6 @@ class register(object):
 
 
 def create_follower_db(follower_ident):
-
     for cfg in _configs_for_db_operation():
         _create_db(cfg, cfg.db, follower_ident)
 
@@ -271,9 +270,14 @@ def _oracle_drop_db(cfg, eng, ident):
         _ora_drop_ignore(conn, "%s_ts2" % ident)
 
 
-def reap_oracle_dbs(eng):
+def reap_oracle_dbs(eng, idents_file):
     log.info("Reaping Oracle dbs...")
     with eng.connect() as conn:
+        with open(idents_file) as file_:
+            idents = set(line.strip() for line in file_)
+
+        log.info("identifiers in file: %s", ", ".join(idents))
+
         to_reap = conn.execute(
             "select u.username from all_users u where username "
             "like 'TEST_%' and not exists (select username "
@@ -283,7 +287,7 @@ def reap_oracle_dbs(eng):
         for name in all_names:
             if name.endswith("_ts1") or name.endswith("_ts2"):
                 continue
-            else:
+            elif name in idents:
                 to_drop.add(name)
                 if "%s_ts1" % name in all_names:
                     to_drop.add("%s_ts1" % name)
diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py
index c29b81f..be5d1be 100644
--- a/lib/sqlalchemy/util/_collections.py
+++ b/lib/sqlalchemy/util/_collections.py
@@ -200,10 +200,10 @@ class Properties(object):
         self._data[key] = obj
 
     def __getstate__(self):
-        return {'_data': self.__dict__['_data']}
+        return {'_data': self._data}
 
     def __setstate__(self, state):
-        self.__dict__['_data'] = state['_data']
+        object.__setattr__(self, '_data', state['_data'])
 
     def __getattr__(self, key):
         try:
diff --git a/test/base/test_utils.py b/test/base/test_utils.py
index c7b3cd2..6ab3545 100644
--- a/test/base/test_utils.py
+++ b/test/base/test_utils.py
@@ -2187,3 +2187,38 @@ class TestClassProperty(fixtures.TestBase):
         eq_(B.something, {'foo': 1, 'bazz': 2})
 
 
+class TestProperties(fixtures.TestBase):
+
+    def test_pickle(self):
+        data = {'hello': 'bla'}
+        props = util.Properties(data)
+
+        for loader, dumper in picklers():
+            s = dumper(props)
+            p = loader(s)
+
+            eq_(props._data, p._data)
+            eq_(props.keys(), p.keys())
+
+    def test_pickle_immuatbleprops(self):
+        data = {'hello': 'bla'}
+        props = util.Properties(data).as_immutable()
+
+        for loader, dumper in picklers():
+            s = dumper(props)
+            p = loader(s)
+
+            eq_(props._data, p._data)
+            eq_(props.keys(), p.keys())
+
+    def test_pickle_orderedprops(self):
+        data = {'hello': 'bla'}
+        props = util.OrderedProperties()
+        props.update(data)
+
+        for loader, dumper in picklers():
+            s = dumper(props)
+            p = loader(s)
+
+            eq_(props._data, p._data)
+            eq_(props.keys(), p.keys())
diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py
index 52620bb..1171144 100644
--- a/test/dialect/postgresql/test_dialect.py
+++ b/test/dialect/postgresql/test_dialect.py
@@ -8,7 +8,7 @@ from sqlalchemy import testing
 import datetime
 from sqlalchemy import (
     Table, Column, select, MetaData, text, Integer, String, Sequence, Numeric,
-    DateTime, BigInteger, func, extract, SmallInteger)
+    DateTime, BigInteger, func, extract, SmallInteger, TypeDecorator)
 from sqlalchemy import exc, schema
 from sqlalchemy.dialects.postgresql import base as postgresql
 import logging
@@ -242,6 +242,15 @@ class MiscTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL):
         "postgresql >= 8.2", "requires standard_conforming_strings")
     def test_serial_integer(self):
 
+        class BITD(TypeDecorator):
+            impl = Integer
+
+            def load_dialect_impl(self, dialect):
+                if dialect.name == 'postgresql':
+                    return BigInteger()
+                else:
+                    return Integer()
+
         for version, type_, expected in [
             (None, Integer, 'SERIAL'),
             (None, BigInteger, 'BIGSERIAL'),
@@ -249,6 +258,16 @@ class MiscTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL):
             ((9, 2), SmallInteger, 'SMALLSERIAL'),
             (None, postgresql.INTEGER, 'SERIAL'),
             (None, postgresql.BIGINT, 'BIGSERIAL'),
+            (
+                None, Integer().with_variant(BigInteger(), 'postgresql'),
+                'BIGSERIAL'),
+            (
+                None, Integer().with_variant(postgresql.BIGINT, 'postgresql'),
+                'BIGSERIAL'),
+            (
+                (9, 2), Integer().with_variant(SmallInteger, 'postgresql'),
+                'SMALLSERIAL'),
+            (None, BITD(), 'BIGSERIAL')
         ]:
             m = MetaData()
 
diff --git a/test/dialect/postgresql/test_reflection.py b/test/dialect/postgresql/test_reflection.py
index ee87e73..34a23e8 100644
... 932 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