Skip to content

Commit

Permalink
Enable compare type by default
Browse files Browse the repository at this point in the history
Change the default value of :paramref:`.EnvironmentContext.configure.compare_type`
to ``True``.

Fixes: #1248
Change-Id: I6fd93de73f3b239dffddec98008083c10e154334
  • Loading branch information
CaselIT authored and zzzeek committed Aug 22, 2023
1 parent bf6f149 commit 8d8e0d8
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 30 deletions.
2 changes: 1 addition & 1 deletion alembic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
from . import context
from . import op

__version__ = "1.11.4"
__version__ = "1.12.0"
29 changes: 23 additions & 6 deletions alembic/context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ if TYPE_CHECKING:
from sqlalchemy.sql.schema import FetchedValue
from sqlalchemy.sql.schema import MetaData
from sqlalchemy.sql.schema import SchemaItem
from sqlalchemy.sql.type_api import TypeEngine

from .autogenerate.api import AutogenContext
from .config import Config
Expand Down Expand Up @@ -145,7 +146,19 @@ def configure(
[MigrationContext, Tuple[str, str], List[MigrateOperation]], None
]
] = None,
compare_type: bool = False,
compare_type: Union[
bool,
Callable[
[
MigrationContext,
Column[Any],
Column[Any],
TypeEngine,
TypeEngine,
],
Optional[bool],
],
] = True,
compare_server_default: Union[
bool,
Callable[
Expand Down Expand Up @@ -308,12 +321,16 @@ def configure(
to produce candidate upgrade/downgrade operations.
:param compare_type: Indicates type comparison behavior during
an autogenerate
operation. Defaults to ``False`` which disables type
comparison. Set to
``True`` to turn on default type comparison, which has varied
accuracy depending on backend. See :ref:`compare_types`
operation. Defaults to ``True`` turning on type comparison, which
has good accuracy on most backends. See :ref:`compare_types`
for an example as well as information on other type
comparison options.
comparison options. Set to ``False`` which disables type
comparison. A callable can also be passed to provide custom type
comparison, see :ref:`compare_types` for additional details.
.. versionchanged:: 1.12.0 The default value of
:paramref:`.EnvironmentContext.configure.compare_type` has been
changed to ``True``.
.. seealso::
Expand Down
31 changes: 23 additions & 8 deletions alembic/runtime/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from sqlalchemy.sql.elements import ClauseElement
from sqlalchemy.sql.schema import MetaData
from sqlalchemy.sql.schema import SchemaItem
from sqlalchemy.sql.type_api import TypeEngine

from .migration import MigrationInfo
from ..autogenerate.api import AutogenContext
Expand Down Expand Up @@ -92,6 +93,17 @@
Optional[bool],
]

CompareType = Callable[
[
MigrationContext,
"Column[Any]",
"Column[Any]",
"TypeEngine[Any]",
"TypeEngine[Any]",
],
Optional[bool],
]


class EnvironmentContext(util.ModuleClsProxy):

Expand Down Expand Up @@ -410,7 +422,7 @@ def configure(
process_revision_directives: Optional[
ProcessRevisionDirectiveFn
] = None,
compare_type: bool = False,
compare_type: Union[bool, CompareType] = True,
compare_server_default: Union[bool, CompareServerDefault] = False,
render_item: Optional[RenderItemFn] = None,
literal_binds: bool = False,
Expand Down Expand Up @@ -548,12 +560,16 @@ def configure(
to produce candidate upgrade/downgrade operations.
:param compare_type: Indicates type comparison behavior during
an autogenerate
operation. Defaults to ``False`` which disables type
comparison. Set to
``True`` to turn on default type comparison, which has varied
accuracy depending on backend. See :ref:`compare_types`
operation. Defaults to ``True`` turning on type comparison, which
has good accuracy on most backends. See :ref:`compare_types`
for an example as well as information on other type
comparison options.
comparison options. Set to ``False`` which disables type
comparison. A callable can also be passed to provide custom type
comparison, see :ref:`compare_types` for additional details.
.. versionchanged:: 1.12.0 The default value of
:paramref:`.EnvironmentContext.configure.compare_type` has been
changed to ``True``.
.. seealso::
Expand Down Expand Up @@ -880,8 +896,7 @@ def process_revision_directives(context, revision, directives):

if render_item is not None:
opts["render_item"] = render_item
if compare_type is not None:
opts["compare_type"] = compare_type
opts["compare_type"] = compare_type
if compare_server_default is not None:
opts["compare_server_default"] = compare_server_default
opts["script"] = self.script
Expand Down
2 changes: 1 addition & 1 deletion alembic/runtime/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def __init__(
else:
self.output_buffer = opts.get("output_buffer", sys.stdout)

self._user_compare_type = opts.get("compare_type", False)
self._user_compare_type = opts.get("compare_type", True)
self._user_compare_server_default = opts.get(
"compare_server_default", False
)
Expand Down
26 changes: 15 additions & 11 deletions docs/build/autogenerate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ Autogenerate **will detect**:

Autogenerate can **optionally detect**:

* Change of column type. This will occur if you set
the :paramref:`.EnvironmentContext.configure.compare_type` parameter to
``True``. The default implementation will reliably detect major changes,
* Change of column type. This will occur by default unless the parameter
:paramref:`.EnvironmentContext.configure.compare_type` is set to ``False``.
The default implementation will reliably detect major changes,
such as between :class:`.Numeric` and :class:`.String`, as well as
accommodate for the types generated by SQLAlchemy's "generic" types such as
:class:`.Boolean`. Arguments that are shared between both types, such as
Expand Down Expand Up @@ -587,15 +587,19 @@ Comparing Types
^^^^^^^^^^^^^^^^

The default type comparison logic will work for SQLAlchemy built in types as
well as basic user defined types. This logic is only enabled if the
:paramref:`.EnvironmentContext.configure.compare_type` parameter
is set to True::
well as basic user defined types. This logic is enabled by default.
It can be disabled by setting the
:paramref:`.EnvironmentContext.configure.compare_type` to ``False``::

context.configure(
# ...
compare_type = True
compare_type = False
)

.. versionchanged:: 1.12.0 The default value of
:paramref:`.EnvironmentContext.configure.compare_type` has been changed
to ``True``.

.. note::

The default type comparison logic (which is end-user extensible) currently
Expand All @@ -604,7 +608,7 @@ is set to True::

* First, it compares the outer type of each column such as ``VARCHAR``
or ``TEXT``. Dialect implementations can have synonyms that are considered
equivalent- this is because some databases support types by converting them
equivalent, this is because some databases support types by converting them
to another type. For example, NUMERIC and DECIMAL are considered equivalent
on all backends, while on the Oracle backend the additional synonyms
BIGINT, INTEGER, NUMBER, SMALLINT are added to this list of equivalents
Expand Down Expand Up @@ -670,10 +674,10 @@ will proceed::

The boolean return values for the above
``compare_against_backend`` method, which is part of SQLAlchemy and not
Alembic,are **the opposite** of that of the
Alembic, are **the opposite** of that of the
:paramref:`.EnvironmentContext.configure.compare_type` callable, returning
``True`` for types that are the same vs. ``False`` for types that are
different.The :paramref:`.EnvironmentContext.configure.compare_type`
different. The :paramref:`.EnvironmentContext.configure.compare_type`
callable on the other hand should return ``True`` for types that are
**different**.

Expand All @@ -683,7 +687,7 @@ type itself implementing ``compare_against_backend`` is that the
:paramref:`.EnvironmentContext.configure.compare_type` callable is favored
first; if it returns ``None``, then the ``compare_against_backend`` method
will be used, if present on the metadata type. If that returns ``None``,
then a basic check for type equivalence is run.
then the default check for type equivalence is run.

.. _post_write_hooks:

Expand Down
9 changes: 9 additions & 0 deletions docs/build/unreleased/1248.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. change::
:tags: usecase, autogenerate
:tickets: 1248

Change the default value of
:paramref:`.EnvironmentContext.configure.compare_type` to ``True``.
As Alembic's autogenerate for types was dramatically improved in
version 1.4 released in 2020, the type comparison feature is now much
more reliable so is now enabled by default.
11 changes: 8 additions & 3 deletions tests/test_autogen_diffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1755,9 +1755,14 @@ def test_compare_metadata_schema(self):
diffs[4][3],
)

eq_(diffs[5][0][0], "modify_nullable")
eq_(diffs[5][0][5], False)
eq_(diffs[5][0][6], True)
eq_(diffs[5][0][0], "modify_type")
eq_(diffs[5][0][1:4], ("test_schema", "order", "amount"))
eq_(diffs[5][0][5].precision, 8)
eq_(diffs[5][0][6].precision, 10)

eq_(diffs[5][1][0], "modify_nullable")
eq_(diffs[5][1][5], False)
eq_(diffs[5][1][6], True)


class OrigObjectTest(TestBase):
Expand Down

0 comments on commit 8d8e0d8

Please sign in to comment.