Print an ordered migration plan and return the formatted lines.
(
*,
config: dict[str, Any] | TortoiseConfig | None = None,
config_file: str | None = None,
app_labels: Sequence[str] | None = None,
target: str | None = None,
)
| 10 | |
| 11 | |
| 12 | async def plan( |
| 13 | *, |
| 14 | config: dict[str, Any] | TortoiseConfig | None = None, |
| 15 | config_file: str | None = None, |
| 16 | app_labels: Sequence[str] | None = None, |
| 17 | target: str | None = None, |
| 18 | ) -> list[str]: |
| 19 | """ |
| 20 | Print an ordered migration plan and return the formatted lines. |
| 21 | """ |
| 22 | if isinstance(config, TortoiseConfig): |
| 23 | config = config.to_dict() |
| 24 | if config_file: |
| 25 | config = Tortoise._get_config_from_config_file(config_file) |
| 26 | if not config: |
| 27 | raise ValueError("plan requires a config or config_file") |
| 28 | |
| 29 | await Tortoise.init(config=config, init_connections=False) |
| 30 | |
| 31 | configured_apps = config.get("apps", {}) |
| 32 | selected_apps = list(app_labels) if app_labels else list(configured_apps.keys()) |
| 33 | for label in selected_apps: |
| 34 | if label not in configured_apps: |
| 35 | raise ValueError(f"Unknown app label {label}") |
| 36 | |
| 37 | apps_config = {label: configured_apps[label] for label in selected_apps} |
| 38 | apps_by_connection: dict[str, dict[str, dict[str, Any]]] = {} |
| 39 | for label, app_config in apps_config.items(): |
| 40 | connection_name = app_config.get("default_connection", "default") |
| 41 | apps_by_connection.setdefault(connection_name, {})[label] = app_config |
| 42 | |
| 43 | targets = _parse_targets(target, selected_apps) |
| 44 | output: list[str] = [] |
| 45 | for connection_name, subset in apps_by_connection.items(): |
| 46 | connection = get_connection(connection_name) |
| 47 | executor = MigrationExecutor(connection, subset) |
| 48 | executor_targets = [t for t in targets if t.app_label in subset] |
| 49 | steps = await executor.plan(executor_targets if executor_targets else None) |
| 50 | output.extend(_format_steps(steps, connection_name)) |
| 51 | |
| 52 | for line in output: |
| 53 | print(line) |
| 54 | return output |
| 55 | |
| 56 | |
| 57 | def _format_steps(steps: list[PlanStep], connection_name: str) -> list[str]: |
nothing calls this directly
no test coverage detected
searching dependent graphs…