Skip to content

Commit

Permalink
dbt_project.yml log-path respects project directory (dbt-labs#6908)
Browse files Browse the repository at this point in the history
dbt_project.yml log-path respects project directory
  • Loading branch information
MichelleArk authored Feb 14, 2023
1 parent 605c72e commit e5c468b
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 22 deletions.
24 changes: 5 additions & 19 deletions core/dbt/cli/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from dbt.config.profile import read_user_config
from dbt.contracts.project import UserConfig
from dbt.helper_types import WarnErrorOptions
from dbt.config.project import PartialProject
from dbt.exceptions import DbtProjectError
from dbt.cli.resolvers import default_project_dir, default_log_path


if os.name != "nt":
# https://bugs.python.org/issue41567
Expand Down Expand Up @@ -132,23 +132,9 @@ def assign_params(ctx, params_assigned_from_default):

# Default LOG_PATH from PROJECT_DIR, if available.
if getattr(self, "LOG_PATH", None) is None:
log_path = "logs"
project_dir = getattr(self, "PROJECT_DIR", None)
# If available, set LOG_PATH from log-path in dbt_project.yml
# Known limitations:
# 1. Using PartialProject here, so no jinja rendering of log-path.
# 2. Programmatic invocations of the cli via dbtRunner may pass a Project object directly,
# which is not being used here to extract log-path.
if project_dir:
try:
partial = PartialProject.from_project_root(
project_dir, verify_version=getattr(self, "VERSION_CHECK", True)
)
log_path = str(partial.project_dict.get("log-path", log_path))
except DbtProjectError:
pass

object.__setattr__(self, "LOG_PATH", log_path)
project_dir = getattr(self, "PROJECT_DIR", default_project_dir())
version_check = getattr(self, "VERSION_CHECK", True)
object.__setattr__(self, "LOG_PATH", default_log_path(project_dir, version_check))

# Support console DO NOT TRACK initiave
if os.getenv("DO_NOT_TRACK", "").lower() in ("1", "t", "true", "y", "yes"):
Expand Down
24 changes: 22 additions & 2 deletions core/dbt/cli/resolvers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
from pathlib import Path
from dbt.config.project import PartialProject
from dbt.exceptions import DbtProjectError


def default_project_dir():
def default_project_dir() -> Path:
paths = list(Path.cwd().parents)
paths.insert(0, Path.cwd())
return next((x for x in paths if (x / "dbt_project.yml").exists()), Path.cwd())


def default_profiles_dir():
def default_profiles_dir() -> Path:
return Path.cwd() if (Path.cwd() / "profiles.yml").exists() else Path.home() / ".dbt"


def default_log_path(project_dir: Path, verify_version: bool = False) -> Path:
"""If available, derive a default log path from dbt_project.yml. Otherwise, default to "logs".
Known limitations:
1. Using PartialProject here, so no jinja rendering of log-path.
2. Programmatic invocations of the cli via dbtRunner may pass a Project object directly,
which is not being taken into consideration here to extract a log-path.
"""
default_log_path = Path("logs")
try:
partial = PartialProject.from_project_root(str(project_dir), verify_version=verify_version)
partial_log_path = partial.project_dict.get("log-path") or default_log_path
default_log_path = Path(project_dir) / partial_log_path
except DbtProjectError:
pass

return default_log_path
Binary file modified core/dbt/docs/build/doctrees/environment.pickle
Binary file not shown.
35 changes: 35 additions & 0 deletions tests/functional/cli/test_resolvers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest
from dbt.cli.resolvers import default_log_path
from pathlib import Path


class TestDefaultLogPathNoProject:
def test_default_log_path_no_project(self):
expected_log_path = Path("logs")
actual_log_path = default_log_path("nonexistent_project_dir")

assert actual_log_path == expected_log_path


class TestDefaultLogPathWithProject:
@pytest.fixture(scope="class")
def project_config_update(self):
return {"log-path": "test_default_log_path"}

def test_default_log_path_with_project(self, project, project_config_update):
expected_log_path = Path(project.project_root) / "test_default_log_path"
actual_log_path = default_log_path(project.project_root)

assert actual_log_path == expected_log_path


class TestDefaultLogPathWithProjectNoConfiguredLogPath:
@pytest.fixture(scope="class")
def project_config_update(self):
return {"log-path": None}

def test_default_log_path_with_project(self, project, project_config_update):
expected_log_path = Path(project.project_root) / "logs"
actual_log_path = default_log_path(project.project_root)

assert actual_log_path == expected_log_path
3 changes: 2 additions & 1 deletion tests/unit/test_cli_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import click
from multiprocessing import get_context
from pathlib import Path
from typing import List

from dbt.cli.main import cli
Expand Down Expand Up @@ -42,7 +43,7 @@ def test_cli_group_flags_from_params(self, run_context, param):
def test_log_path_default(self, run_context):
flags = Flags(run_context)
assert hasattr(flags, "LOG_PATH")
assert getattr(flags, "LOG_PATH") == "logs"
assert getattr(flags, "LOG_PATH") == Path("logs")

@pytest.mark.parametrize(
"set_stats_param,do_not_track,expected_anonymous_usage_stats",
Expand Down

0 comments on commit e5c468b

Please sign in to comment.