Scaffolding

iceberg_ops.scaffolding

Project scaffolding helpers used by the iceberg-ops init and iceberg-ops revision CLI commands.

Public API

init_project(target_dir, *, force=False, config_name=..., migrations_dir=None)

Create the migrations/ directory, an iceberg-ops.yaml stub, and append .gitignore entries for local state.

create_revision(*, message, migrations_dir, namespace=None)

Scaffold a new NNNN_<slug>.py migration file with the next sequential version number.

iceberg_ops.scaffolding.init_project(target_dir, *, force=False, config_name='iceberg-ops.yaml', migrations_dir=None)[source]

Scaffold a new iceberg-ops project.

Creates the migrations directory (with an empty __init__.py), a stub config file, and appends .gitignore entries for local runtime state to <target_dir>/.gitignore. Idempotent: running twice without force is a safe no-op on existing files; the migrations directory is always ensured. Files are written as UTF-8.

Parameters:
  • target_dir (str | Path) – Project root. Must already exist.

  • force (bool, default: False) – If True, overwrite an existing config file and migrations/__init__.py. Never deletes user-authored migration files. Default: False.

  • config_name (str | Path, default: 'iceberg-ops.yaml') – Config file path, relative to target_dir (or absolute). Missing parent directories are created. Default: "iceberg-ops.yaml".

  • migrations_dir (str | Path | None, default: None) – Migrations directory, relative to target_dir (or absolute). Default: migrations/ next to the config file. Any other location is written into the generated config as migrations_dir (relative to the config file).

Raises:

FileNotFoundError – If target_dir does not exist.

Return type:

None

Notes

The .gitignore block is keyed off the marker comment # iceberg-ops local data so re-running init does not duplicate the entries even with force=True. The block is appended as bytes, so existing .gitignore content is kept byte-for-byte whatever its encoding.

iceberg_ops.scaffolding.create_revision(*, message, migrations_dir, namespace=None)[source]

Scaffold a new migration file with the next sequential version.

Scans migrations_dir (or the namespace subdirectory if it exists) for files the runner discovers (NNNN_<slug>.py with a non-empty slug), picks max(NNNN) + 1 (or "0001" if empty), slugifies message, and writes a BaseMigration skeleton.

Parameters:
  • message (str) – Short human-readable description. Used as the description class attribute and as the filename slug (lowercased, non-alphanumeric runs collapsed to _, leading / trailing _ stripped, capped at 50 characters).

  • migrations_dir (str | Path) – Directory where migration files live. Must already exist.

  • namespace (str | None, default: None) – If given and <migrations_dir>/<namespace>/ exists, the new file is written to that subdirectory and the version counter is scoped to it. Otherwise the flat migrations_dir is used.

Returns:

Absolute path of the newly created file.

Return type:

str

Raises:
  • FileNotFoundError – If migrations_dir does not exist.

  • FileExistsError – If the target file already exists (e.g. another process wrote the same version concurrently); it is never overwritten.

Notes

The version counter is per-directory: a flat migrations/ and a migrations/<namespace>/ subdirectory each have their own 0001... series. This matches the runner’s namespace-scoped discovery rule.

A degenerate message whose slug collapses to the empty string (e.g. "!!!") falls back to the literal slug "migration".