Skip to content

Commit

Permalink
Log actions, storage tests (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
kokorin authored Jul 2, 2024
1 parent e7470bc commit 777d706
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
15 changes: 11 additions & 4 deletions dbt_pumpkin/plan.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from abc import abstractmethod
from dataclasses import dataclass
from pathlib import Path
Expand All @@ -6,6 +7,8 @@
from dbt_pumpkin.exception import PumpkinError, ResourceNotFoundError
from dbt_pumpkin.storage import Storage

logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class Action:
Expand Down Expand Up @@ -60,14 +63,14 @@ class BootstrapResource(Action):

def __post_init__(self):
if self.resource_type == ResourceType.SOURCE:
msg = "Sources must be initialized manually"
msg = "Sources must be bootstrapped manually"
raise PumpkinError(msg)

def affected_files(self) -> set[Path]:
return {self.path}

def describe(self) -> str:
return f"Initialize {self.resource_type}:{self.resource_name} at {self.path}"
return f"Bootstrap {self.resource_type}:{self.resource_name} at {self.path}"

def execute(self, files: dict[Path, dict]):
to_file = files.setdefault(self.path, {"version": 2})
Expand All @@ -83,9 +86,13 @@ def _affected_files(self) -> set[Path]:
return {f for a in self.actions for f in a.affected_files()}

def execute(self, storage: Storage):
files = storage.load_yaml(self._affected_files())
affected_files = self._affected_files()
logger.info("Files affected by plan: %s", len(affected_files))

files = storage.load_yaml(affected_files)

for action in self.actions:
for index, action in enumerate(self.actions):
logger.info("Action %s: %s", index + 1, action.describe())
action.execute(files)

storage.save_yaml(files)
Expand Down
24 changes: 20 additions & 4 deletions dbt_pumpkin/storage.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import logging
from abc import abstractmethod
from pathlib import Path
from typing import Any

from ruamel.yaml import YAML

logger = logging.getLogger(__name__)


class Storage:
@abstractmethod
Expand All @@ -22,13 +25,26 @@ def __init__(self, root_dir: Path, *, read_only: bool):
self._yaml = YAML(typ="safe")

def load_yaml(self, files: set[Path]) -> dict[Path, Any]:
return {file: self._yaml.load(self._root_dir / file) for file in files if file.exists()}
result: dict[Path, Any] = {}

for file in files:
resolved_file = self._root_dir / file
if not resolved_file.exists():
logger.debug("File doesn't exist, skipping: %s", resolved_file)
continue

logger.debug("Loading file: %s", resolved_file)
result[file] = self._yaml.load(resolved_file)

return result

def save_yaml(self, files: dict[Path, Any]):
if self._read_only:
return

for file, content in files.items():
file_path = self._root_dir / file
file_path.parent.mkdir(exist_ok=True)
self._yaml.dump(content, file_path)
resolved_file = self._root_dir / file
logger.debug("Saving file: %s", resolved_file)
resolved_file = self._root_dir / file
resolved_file.parent.mkdir(exist_ok=True)
self._yaml.dump(content, resolved_file)
36 changes: 36 additions & 0 deletions tests/test_storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import textwrap
from pathlib import Path

import yaml

from dbt_pumpkin.storage import DiskStorage


def test_load_yaml(tmp_path):
(tmp_path / "schema.yml").write_text(
textwrap.dedent("""\
version: 2
models:
- name: my_model
""")
)

files = DiskStorage(tmp_path, read_only=False).load_yaml({Path("schema.yml"), Path("absent.yml")})
assert files == {Path("schema.yml"): {"version": 2, "models": [{"name": "my_model"}]}}


def test_save_yaml(tmp_path):
DiskStorage(tmp_path, read_only=False).save_yaml(
{Path("schema.yml"): {"version": 2, "models": [{"name": "my_other_model"}]}}
)

actual = yaml.safe_load((tmp_path / "schema.yml").read_text())
assert actual == {"version": 2, "models": [{"name": "my_other_model"}]}


def test_save_yaml_read_only(tmp_path):
DiskStorage(tmp_path, read_only=True).save_yaml(
{Path("schema.yml"): {"version": 2, "models": [{"name": "my_other_model"}]}}
)

assert not (tmp_path / "schema.yml").exists()

0 comments on commit 777d706

Please sign in to comment.