from typing import Dict
from typing import Iterator
from typing import Optional
+from typing import Sequence
from typing import Set
-from typing import Tuple
from typing import TYPE_CHECKING
+from typing import Union
from sqlalchemy import inspect
from sqlalchemy.sql.schema import SchemaItem
from ..config import Config
+ from ..operations.ops import DowngradeOps
from ..operations.ops import MigrationScript
from ..operations.ops import UpgradeOps
from ..runtime.environment import NameFilterParentNames
def render_python_code(
- up_or_down_op: UpgradeOps,
+ up_or_down_op: Union[UpgradeOps, DowngradeOps],
sqlalchemy_module_prefix: str = "sa.",
alembic_module_prefix: str = "op.",
render_as_batch: bool = False,
- imports: Tuple[str, ...] = (),
+ imports: Sequence[str] = (),
render_item: Optional[RenderItemFn] = None,
migration_context: Optional[MigrationContext] = None,
+ user_module_prefix: Optional[str] = None,
) -> str:
"""Render Python code given an :class:`.UpgradeOps` or
:class:`.DowngradeOps` object.
This is a convenience function that can be used to test the
autogenerate output of a user-defined :class:`.MigrationScript` structure.
+ :param up_or_down_op: :class:`.UpgradeOps` or :class:`.DowngradeOps` object
+ :param sqlalchemy_module_prefix: module prefix for SQLAlchemy objects
+ :param alembic_module_prefix: module prefix for Alembic constructs
+ :param render_as_batch: use "batch operations" style for rendering
+ :param imports: sequence of import symbols to add
+ :param render_item: callable to render items
+ :param migration_context: optional :class:`.MigrationContext`
+ :param user_module_prefix: optional string prefix for user-defined types
+
+ .. versionadded:: 1.11.0
+
"""
opts = {
"sqlalchemy_module_prefix": sqlalchemy_module_prefix,
"alembic_module_prefix": alembic_module_prefix,
"render_item": render_item,
"render_as_batch": render_as_batch,
+ "user_module_prefix": user_module_prefix,
}
if migration_context is None:
--- /dev/null
+.. change::
+ :tags: bug, api, autogenerate
+ :tickets: 1235
+
+ Fixed issue where :func:`.autogenerate.render_python_code` function did not
+ provide a default value for the ``user_module_prefix`` variable, leading to
+ ``NoneType`` errors when autogenerate structures included user-defined
+ types. Added new parameter
+ :paramref:`.autogenerate.render_python_code.user_module_prefix` to allow
+ this to be set as well as to default to ``None``. Pull request courtesy
+ tangkikodo.
"sa.ARRAY(sa.DateTime(timezone=True))",
)
+ @config.combinations(None, "default", "my_module.")
+ def test_render_create_table_with_user_module_type(self, mod):
+ class MyType(UserDefinedType):
+ def get_col_spec(self):
+ return "MYTYPE"
+
+ type_ = MyType()
+ uo = ops.UpgradeOps(
+ ops=[ops.CreateTableOp("sometable", [Column("x", type_)])]
+ )
+ if mod != "default":
+ kw = {"user_module_prefix": mod}
+ else:
+ kw = {}
+ if mod and mod != "default":
+ prefix = mod
+ else:
+ prefix = f"{__name__}."
+
+ eq_(
+ autogenerate.render_python_code(uo, **kw),
+ "# ### commands auto generated by Alembic - please adjust! ###\n"
+ " op.create_table('sometable',\n"
+ f" sa.Column('x', {prefix}MyType(), nullable=True)\n"
+ " )\n"
+ " # ### end Alembic commands ###",
+ )
+
def test_render_array_no_context(self):
uo = ops.UpgradeOps(
ops=[