Skip to content

Commit

Permalink
/* PR_START p--release-0.207.1-updates 00.3 */ Update flow for checki…
Browse files Browse the repository at this point in the history
…ng dbt-adapter package installation.
  • Loading branch information
plypaul committed Jan 24, 2025
1 parent 8809980 commit 1a0a19a
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 10 deletions.
22 changes: 17 additions & 5 deletions dbt-metricflow/dbt_metricflow/cli/cli_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from metricflow_semantics.mf_logging.lazy_formattable import LazyFormat
from metricflow_semantics.model.semantic_manifest_lookup import SemanticManifestLookup

from dbt_metricflow.cli import PACKAGE_NAME
from dbt_metricflow.cli.dbt_connectors.adapter_backed_client import AdapterBackedSqlClient
from dbt_metricflow.cli.dbt_connectors.dbt_config_accessor import dbtArtifacts, dbtProjectMetadata
from metricflow.engine.metricflow_engine import MetricFlowEngine
Expand All @@ -35,11 +36,22 @@ def setup(self) -> None:
The dbt_artifacts construct must be loaded in order for logging configuration to work correctly.
"""
dbt_project_path = pathlib.Path.cwd()
self._dbt_project_metadata = dbtProjectMetadata.load_from_project_path(dbt_project_path)

# self.log_file_path invokes the dbtRunner. If this is done after the configure_logging call all of the
# dbt CLI logging configuration could be overridden, resulting in lots of things printing to console
self._configure_logging(log_file_path=self.log_file_path)
try:
self._dbt_project_metadata = dbtProjectMetadata.load_from_project_path(dbt_project_path)

# self.log_file_path invokes the dbtRunner. If this is done after the configure_logging call all of the
# dbt CLI logging configuration could be overridden, resulting in lots of things printing to console
self._configure_logging(log_file_path=self.log_file_path)
except Exception as e:
exception_message = str(e)
if exception_message.find("Could not find adapter type") != -1:
raise RuntimeError(
f"Got an error during setup, potentially due to a missing adapter package. Has the appropriate "
f"adapter package (`{PACKAGE_NAME}[dbt-*]`) for the dbt project {str(dbt_project_path)!r} been "
f"installed? If not please install it (e.g. `pip install '{PACKAGE_NAME}[dbt-duckdb]')."
) from e
else:
raise e

def _get_dbt_project_metadata(self) -> dbtProjectMetadata:
if self._dbt_project_metadata is None:
Expand Down
60 changes: 55 additions & 5 deletions dbt-metricflow/dbt_metricflow/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def tutorial(ctx: click.core.Context, cfg: CLIConfiguration, message: bool, clea

sample_dbt_project_path = (current_directory / tutorial_project_name).absolute()
click.secho(
"Unable to detect a dbt project. Please run this command from the root directory of your dbt project.",
"Unable to detect a dbt project. Please run `mf tutorial` from the root directory of your dbt project.",
fg="yellow",
)
click.confirm(
Expand All @@ -197,20 +197,20 @@ def tutorial(ctx: click.core.Context, cfg: CLIConfiguration, message: bool, clea
{click.style(str(sample_dbt_project_path), bold=True)}
However, the `dbt-metricflow[dbt-duckdb]` package must be installed beforehand. e.g. `pip install
'dbt-metricflow[dbt-duckdb]'`. You can break out of the tutorial if you need to install the package.
e.g. press <CTRL>+c
Do you want to create the sample project now?
"""
).rstrip(),
abort=True,
)

_check_duckdb_package_installed_for_sample_project()

if dbtMetricFlowTutorialHelper.check_if_path_exists([sample_dbt_project_path]):
click.confirm(
click.style(
textwrap.dedent(
f"""\
The path {str(sample_dbt_project_path)!r} already exists.
Do you want to overwrite it?
"""
Expand Down Expand Up @@ -307,6 +307,56 @@ def tutorial(ctx: click.core.Context, cfg: CLIConfiguration, message: bool, clea
exit()


def _check_duckdb_package_installed_for_sample_project(yes: bool = False) -> None:
"""Check if the DuckDB adapter package is installed and prompt user to install it if not.
The `yes` argument is later used for scripting cases.
"""
click.echo(
textwrap.dedent(
"""\
Since the sample project uses DuckDB, the `dbt-metricflow[dbt-duckdb]` package must be installed beforehand.
"""
).rstrip(),
)

duckdb_adapter_package_name = "dbt-duckdb"
dbt_duckdb_package_version = None
try:
dbt_duckdb_package_version = importlib.metadata.version(duckdb_adapter_package_name)
except importlib.metadata.PackageNotFoundError:
pass

if dbt_duckdb_package_version is not None:
click.secho(
f"* Detected installed package {duckdb_adapter_package_name!r} {dbt_duckdb_package_version}",
bold=True,
fg="green",
)
return

click.secho("* Did not detect package is installed", bold=True, fg="red")

if yes:
return

exit_tutorial = click.confirm(
textwrap.dedent(
"""\
As the package was not detected as installed, it's recommended to install the package first before
generating the sample project. e.g. `pip install 'dbt-metricflow[dbt-duckdb]'`. Otherwise, there may be
errors that prevent you from generating the sample project and running the tutorial.
Do you want to exit the tutorial so that you can install the package?
"""
).rstrip(),
)
if exit_tutorial:
exit(0)


@cli.command()
@query_options
@click.option(
Expand Down

0 comments on commit 1a0a19a

Please sign in to comment.