| name | create-etl-steps |
| description | Create vanilla meadow, garden, and grapher ETL step files from the wizard's cookiecutter templates, given a snapshot path. |
| triggers | ["create etl steps","create meadow garden grapher","create pipeline steps","scaffold etl steps"] |
| metadata | {"internal":true} |
Create ETL Steps
Create meadow, garden, and grapher step files from the wizard's vanilla cookiecutter templates for a given snapshot.
Inputs
Required:
snapshot_path — in the format namespace/version/short_name (e.g. washu/2026-04-22/pm25_air_pollution)
Optional:
dag_file — which DAG file to add entries to (e.g. environment, climate). If not provided, ask the user.
Workflow
1. Parse the snapshot path
Extract:
namespace — e.g. washu
version — e.g. 2026-04-22
short_name — e.g. pm25_air_pollution
2. Find the snapshot file extension
Look in snapshots/<namespace>/<version>/ for a .dvc file matching <short_name>.*. The part between <short_name>. and .dvc is the file_extension.
For example: pm25_air_pollution.csv.dvc → file_extension = csv
The full snapshot filename (used in meadow) is <short_name>.<file_extension>.
3. Determine the DAG file
If the user has not specified a DAG file, list the available files in dag/ (excluding archive/) and ask the user which one to use.
4. Create directories
Create the following directories (if they don't exist):
etl/steps/data/meadow/<namespace>/<version>/
etl/steps/data/garden/<namespace>/<version>/
etl/steps/data/grapher/<namespace>/<version>/
5. Write the step files
Meadow — etl/steps/data/meadow/<namespace>/<version>/<short_name>.py
"""Load a snapshot and create a meadow dataset."""
from etl.helpers import PathFinder
paths = PathFinder(__file__)
def run() -> None:
snap = paths.load_snapshot("<short_name>.<file_extension>")
tb = snap.read()
tables = [
tb.format(["country", "year"])
]
ds_meadow = paths.create_dataset(tables=tables, default_metadata=snap.metadata)
ds_meadow.save()
Garden — etl/steps/data/garden/<namespace>/<version>/<short_name>.py
"""Load a meadow dataset and create a garden dataset."""
from etl.helpers import PathFinder
paths = PathFinder(__file__)
def run() -> None:
ds_meadow = paths.load_dataset("<short_name>")
tb = ds_meadow.read("<short_name>")
tb = paths.regions.harmonize_names(tb=tb)
tb = tb.format(["country", "year"])
ds_garden = paths.create_dataset(tables=[tb], default_metadata=ds_meadow.metadata)
ds_garden.save()
Garden metadata — etl/steps/data/garden/<namespace>/<version>/<short_name>.meta.yml
definitions:
common:
presentation:
topic_tags:
dataset:
update_period_days: 365
owners:
- <canonical OWID name of the user, from `git config user.name` via `etl.owners.resolve_owner`>
tables:
<short_name>:
variables:
{}
Garden countries file — etl/steps/data/garden/<namespace>/<version>/<short_name>.countries.json
{}
Garden excluded countries file — etl/steps/data/garden/<namespace>/<version>/<short_name>.excluded_countries.json
[]
Grapher — etl/steps/data/grapher/<namespace>/<version>/<short_name>.py
"""Load a garden dataset and create a grapher dataset."""
from etl.helpers import PathFinder
paths = PathFinder(__file__)
def run() -> None:
ds_garden = paths.load_dataset("<short_name>")
tb = ds_garden.read("<short_name>", reset_index=False)
ds_grapher = paths.create_dataset(tables=[tb], default_metadata=ds_garden.metadata)
ds_grapher.save()
6. Add DAG entries
Append the following entries to dag/<dag_file>.yml under the steps: key. Use ruamel_load / ruamel_dump to preserve comments:
data://meadow/<namespace>/<version>/<short_name>:
- snapshot://<namespace>/<version>/<short_name>.<file_extension>
data://garden/<namespace>/<version>/<short_name>:
- data://meadow/<namespace>/<version>/<short_name>
data://grapher/<namespace>/<version>/<short_name>:
- data://garden/<namespace>/<version>/<short_name>
To append cleanly while preserving YAML comments, use the Python helper:
from etl.files import ruamel_load, ruamel_dump
dag_path = "dag/<dag_file>.yml"
with open(dag_path, "r") as f:
data = ruamel_load(f)
data["steps"]["data://meadow/<namespace>/<version>/<short_name>"] = ["snapshot://<namespace>/<version>/<short_name>.<file_extension>"]
data["steps"]["data://garden/<namespace>/<version>/<short_name>"] = ["data://meadow/<namespace>/<version>/<short_name>"]
data["steps"]["data://grapher/<namespace>/<version>/<short_name>"] = ["data://garden/<namespace>/<version>/<short_name>"]
with open(dag_path, "w") as f:
f.write(ruamel_dump(data))
7. Report to the user
List all files created and the DAG entries added. Suggest running:
.venv/bin/etlr <namespace>/<version>/<short_name> --private