From: Federico Caselli Date: Mon, 14 Sep 2020 21:36:14 +0000 (+0200) Subject: Make :class:`_orm.registry` ``bind`` a private parameter. X-Git-Tag: rel_1_4_0b1~93^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43b486917bceb130419abdfbfafbd14a8cd503ca;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Make :class:`_orm.registry` ``bind`` a private parameter. Explicitly deprecate ``bind`` from :func:`_orm.declarative_base` and :func:`_orm.as_declarative`. Some other documentation cleanup on declarative documentation. Change-Id: I3f7918d23833b2778ab7009ac5018841deb19f75 --- diff --git a/doc/build/orm/basic_relationships.rst b/doc/build/orm/basic_relationships.rst index 0ea699180b..d058d8b70e 100644 --- a/doc/build/orm/basic_relationships.rst +++ b/doc/build/orm/basic_relationships.rst @@ -487,7 +487,7 @@ other arguments which depend upon the columns present on an as-yet undefined class may also be specified either as Python functions, or more commonly as strings. For most of these arguments except that of the main argument, string inputs are -**evaluated as Python expressions using Python's built-in eval() function.**, +**evaluated as Python expressions using Python's built-in eval() function**, as they are intended to recieve complete SQL expressions. .. warning:: As the Python ``eval()`` function is used to interpret the @@ -629,10 +629,10 @@ class were available, we could also apply it afterwards:: Late-Evaluation for a many-to-many relationship ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Many-to-many relationships include a reference to an additional, non-mapped +Many-to-many relationships include a reference to an additional, typically non-mapped :class:`_schema.Table` object that is typically present in the :class:`_schema.MetaData` collection referred towards by the :class:`_orm.registry`. The late-evaluation -system includes support for having this attribute also be specified as a +system also includes support for having this attribute be specified as a string argument which will be resolved from this :class:`_schema.MetaData` collection. Below we specify an association table ``keyword_author``, sharing the :class:`_schema.MetaData` collection associated with our diff --git a/doc/build/orm/declarative_config.rst b/doc/build/orm/declarative_config.rst index bf5bd14f63..48c270b4ed 100644 --- a/doc/build/orm/declarative_config.rst +++ b/doc/build/orm/declarative_config.rst @@ -140,7 +140,8 @@ Things to note above: before the other, we can refer to the remote class using its string name. This functionality also extends into the area of other arguments specified on the :func:`_orm.relationship` such as the "primary join" and "order by" - arguments. See the next section for details on this. + arguments. See the section :ref:`orm_declarative_relationship_eval` for + details on this. .. _orm_declarative_mapper_options: diff --git a/doc/build/orm/declarative_mixins.rst b/doc/build/orm/declarative_mixins.rst index c5912181dc..560bda1341 100644 --- a/doc/build/orm/declarative_mixins.rst +++ b/doc/build/orm/declarative_mixins.rst @@ -194,7 +194,7 @@ Using Advanced Relationship Arguments (e.g. ``primaryjoin``, etc.) :func:`~sqlalchemy.orm.relationship` definitions which require explicit primaryjoin, order_by etc. expressions should in all but the most simplistic cases use **late bound** forms -for these arguments, meaning, using either the string form or a lambda. +for these arguments, meaning, using either the string form or a function/lambda. The reason for this is that the related :class:`_schema.Column` objects which are to be configured using ``@declared_attr`` are not available to another ``@declared_attr`` attribute; while the methods will work and return new @@ -301,7 +301,7 @@ units such as :func:`.association_proxy`. The usage of be tailored specifically to the target subclass. An example is when constructing multiple :func:`.association_proxy` attributes which each target a different type of child object. Below is an -:func:`.association_proxy` / mixin example which provides a scalar list of +:func:`.association_proxy` mixin example which provides a scalar list of string values to an implementing class:: from sqlalchemy import Column, Integer, ForeignKey, String diff --git a/doc/build/orm/extensions/declarative/relationships.rst b/doc/build/orm/extensions/declarative/relationships.rst index a5884ef108..c5c83b1711 100644 --- a/doc/build/orm/extensions/declarative/relationships.rst +++ b/doc/build/orm/extensions/declarative/relationships.rst @@ -19,5 +19,5 @@ This section is moved to :ref:`orm_declarative_relationship_eval`. Configuring Many-to-Many Relationships ====================================== -this section is moved to :ref:`orm_declarative_relationship_secondary_eval`. +This section is moved to :ref:`orm_declarative_relationship_secondary_eval`. diff --git a/doc/build/orm/mapping_styles.rst b/doc/build/orm/mapping_styles.rst index 29045dbb73..5e3c5154aa 100644 --- a/doc/build/orm/mapping_styles.rst +++ b/doc/build/orm/mapping_styles.rst @@ -350,7 +350,7 @@ that a :meth:`_orm.registry` is present. In "classical" form, the table metadata is created separately with the :class:`_schema.Table` construct, then associated with the ``User`` class via -the :func:`.mapper` function:: +the :meth:`_orm.registry.map_imperatively` method:: from sqlalchemy import Table, Column, Integer, String, ForeignKey from sqlalchemy.orm import registry @@ -505,7 +505,7 @@ When mapping with the :ref:`imperative ` style, the class is passed directly as the :paramref:`_orm.registry.map_imperatively.class_` argument. -the table, or other from clause object +The table, or other from clause object -------------------------------------- In the vast majority of common cases this is an instance of @@ -594,8 +594,8 @@ Default Constructor The :class:`_orm.registry` applies a default constructor, i.e. ``__init__`` method, to all mapped classes that don't explicitly have their own ``__init__`` method. The behavior of this method is such that it provides -a convenient keyword constructor that will accept as keywords the attributes -that are named. E.g.:: +a convenient keyword constructor that will accept as optional keyword arguments +all the attributes that are named. E.g.:: from sqlalchemy.orm import declarative_base diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py index 1a38fc7562..c2308a5ccc 100644 --- a/lib/sqlalchemy/exc.py +++ b/lib/sqlalchemy/exc.py @@ -645,7 +645,7 @@ class RemovedIn20Warning(SADeprecationWarning): class MovedIn20Warning(RemovedIn20Warning): - """subtype of RemovedIn20Warning to indicate an API that moved only.""" + """Subtype of RemovedIn20Warning to indicate an API that moved only.""" class SAPendingDeprecationWarning(PendingDeprecationWarning): diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py index 1df916e036..68de18c2e4 100644 --- a/lib/sqlalchemy/orm/decl_api.py +++ b/lib/sqlalchemy/orm/decl_api.py @@ -363,8 +363,15 @@ def declarative_base( """ + if bind is not None: + # util.deprecated_params does not work + util.warn_deprecated_20( + 'The "bind" argument to declarative_base is' + "deprecated and will be removed in SQLAlchemy 2.0.", + ) + return registry( - bind=bind, + _bind=bind, metadata=metadata, class_registry=class_registry, constructor=constructor, @@ -406,10 +413,10 @@ class registry(object): def __init__( self, - bind=None, metadata=None, class_registry=None, constructor=_declarative_constructor, + _bind=None, ): r"""Construct a new :class:`_orm.registry` @@ -435,19 +442,10 @@ class registry(object): to share the same registry of class names for simplified inter-base relationships. - :param bind: An optional - :class:`~sqlalchemy.engine.Connectable`, will be assigned - the ``bind`` attribute on the :class:`~sqlalchemy.schema.MetaData` - instance. - - .. deprecated:: 1.4 The "bind" argument to registry is - deprecated and will be removed in SQLAlchemy 2.0. - - """ lcl_metadata = metadata or MetaData() - if bind: - lcl_metadata.bind = bind + if _bind: + lcl_metadata.bind = _bind if class_registry is None: class_registry = weakref.WeakValueDictionary() @@ -700,6 +698,13 @@ class registry(object): return _mapper(self, class_, local_table, kw) +@util.deprecated_params( + bind=( + "2.0", + 'The "bind" argument to declarative_base is' + "deprecated and will be removed in SQLAlchemy 2.0.", + ) +) def as_declarative(**kw): """ Class decorator which will adapt a given class into a @@ -735,7 +740,7 @@ def as_declarative(**kw): ) return registry( - bind=bind, metadata=metadata, class_registry=class_registry + _bind=bind, metadata=metadata, class_registry=class_registry ).as_declarative_base(**kw) diff --git a/test/orm/test_deprecations.py b/test/orm/test_deprecations.py index 0622d8916e..08dad2e1b7 100644 --- a/test/orm/test_deprecations.py +++ b/test/orm/test_deprecations.py @@ -14,6 +14,7 @@ from sqlalchemy import testing from sqlalchemy import text from sqlalchemy import true from sqlalchemy.orm import aliased +from sqlalchemy.orm import as_declarative from sqlalchemy.orm import attributes from sqlalchemy.orm import collections from sqlalchemy.orm import column_property @@ -21,6 +22,8 @@ from sqlalchemy.orm import configure_mappers from sqlalchemy.orm import contains_alias from sqlalchemy.orm import contains_eager from sqlalchemy.orm import create_session +from sqlalchemy.orm import declarative_base +from sqlalchemy.orm import declared_attr from sqlalchemy.orm import defer from sqlalchemy.orm import deferred from sqlalchemy.orm import eagerload @@ -2126,3 +2129,30 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): User.name.like("%j%") ) eq_(list(q2), [(True,), (False,), (False,), (False,)]) + + +class DeclarativeBind(fixtures.TestBase): + def test_declarative_base(self): + with testing.expect_deprecated_20( + 'The "bind" argument to declarative_base is' + "deprecated and will be removed in SQLAlchemy 2.0.", + ): + Base = declarative_base(bind=testing.db) + + is_true(Base.metadata.bind is testing.db) + + def test_as_declarative(self): + with testing.expect_deprecated_20( + 'The "bind" argument to declarative_base is' + "deprecated and will be removed in SQLAlchemy 2.0.", + ): + + @as_declarative(bind=testing.db) + class Base(object): + @declared_attr + def __tablename__(cls): + return cls.__name__.lower() + + id = Column(Integer, primary_key=True) + + is_true(Base.metadata.bind is testing.db)