Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Update CLI for group creation to use explicit option names for group owner properties #72

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pip install dbt-meshify
# create a group of all models tagged with "finance"
# leaf nodes and nodes with cross-group dependencies will be `public`
# public nodes will also have contracts added to them
dbt-meshify group finance --owner name Monopoly Man -s +tag:finance
dbt-meshify group finance --owner-name "Monopoly Man" -s +tag:finance

# optionally use the add-version operation to add a new version to a model
dbt-meshify operation add-version -s fct_orders
Expand Down
67 changes: 66 additions & 1 deletion dbt_meshify/cli.py
Original file line number Diff line number Diff line change
@@ -1 +1,66 @@
# TODO add the logic for each meshify command to independent tasks here to make cli thinner
import functools

import click

# define common parameters
project_path = click.option(
"--project-path",
type=click.Path(exists=True),
default=".",
help="The path to the dbt project to operate on. Defaults to the current directory.",
)

exclude = click.option(
"--exclude",
"-e",
default=None,
help="The dbt selection syntax specifying the resources to exclude in the operation",
)

group_yml_path = click.option(
"--group-yml-path",
type=click.Path(exists=False),
help="An optional path to store the new group YAML definition.",
)

select = click.option(
"--select",
"-s",
default=None,
help="The dbt selection syntax specifying the resources to include in the operation",
)

selector = click.option(
"--selector",
default=None,
help="The name of the YML selector specifying the resources to include in the operation",
)

owner_name = click.option(
"--owner-name",
help="The group Owner's name.",
)

owner_email = click.option(
"--owner-email",
help="The group Owner's email address.",
)

owner_properties = click.option(
"--owner-properties",
help="Additional properties to assign to a group Owner.",
)


def owner(func):
"""Add click options and argument validation for creating Owner objects."""

@functools.wraps(func)
def wrapper_decorator(*args, **kwargs):
if kwargs.get('owner_name') is None and kwargs.get('owner_email') is None:
raise click.UsageError(
"Groups require an Owner to be defined using --owner-name and/or --owner-email."
)
return func(*args, **kwargs)

return wrapper_decorator
76 changes: 29 additions & 47 deletions dbt_meshify/main.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,25 @@
import os
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
from typing import Optional

import click
import yaml
from dbt.contracts.graph.unparsed import Owner

from .cli import (
exclude,
group_yml_path,
owner,
owner_email,
owner_name,
owner_properties,
project_path,
select,
selector,
)
from .dbt_projects import DbtProject, DbtProjectHolder, DbtSubProject
from .storage.yaml_editors import DbtMeshModelConstructor

# define common parameters
project_path = click.option(
"--project-path",
type=click.Path(exists=True),
default=".",
help="The path to the dbt project to operate on. Defaults to the current directory.",
)

exclude = click.option(
"--exclude",
"-e",
default=None,
help="The dbt selection syntax specifying the resources to exclude in the operation",
)

group_yml_path = click.option(
"--group-yml-path",
type=click.Path(exists=False),
help="An optional path to store the new group YAML definition.",
)

select = click.option(
"--select",
"-s",
default=None,
help="The dbt selection syntax specifying the resources to include in the operation",
)

owner = click.option(
"--owner",
nargs=2,
multiple=True,
type=click.Tuple([str, str]),
help="A tuple of Owner information for the group. For example " "`--owner name example`",
)

selector = click.option(
"--selector",
default=None,
help="The name of the YML selector specifying the resources to include in the operation",
)


# define cli group
@click.group()
Expand Down Expand Up @@ -187,14 +157,19 @@ def add_version(select, exclude, project_path, selector, prerelease, defined_in)
@select
@selector
@click.argument("name")
@owner_name
@owner_email
@owner_properties
@owner
@group_yml_path
def create_group(
name,
project_path: os.PathLike,
owner: List[Tuple[str, str]],
group_yml_path: os.PathLike,
select: str,
owner_name: Optional[str] = None,
owner_email: Optional[str] = None,
owner_properties: Optional[str] = None,
exclude: Optional[str] = None,
selector: Optional[str] = None,
):
Expand All @@ -216,12 +191,14 @@ def create_group(
"The provided group-yml-path is not contained within the provided dbt project."
)

owner: Owner = Owner(**{key: value for key, value in owner})
group_owner: Owner = Owner(
name=owner_name, email=owner_email, _extra=yaml.safe_load(owner_properties or '{}')
)

grouper = ResourceGrouper(project)
grouper.add_group(
name=name,
owner=owner,
owner=group_owner,
select=select,
exclude=exclude,
selector=selector,
Expand All @@ -235,16 +212,21 @@ def create_group(
@select
@selector
@click.argument("name")
@owner_name
@owner_email
@owner_properties
@owner
@group_yml_path
@click.pass_context
def group(
ctx,
name,
project_path: os.PathLike,
owner: List[Tuple[str, str]],
group_yml_path: os.PathLike,
select: str,
owner_name: Optional[str] = None,
owner_email: Optional[str] = None,
owner_properties: Optional[str] = None,
exclude: Optional[str] = None,
selector: Optional[str] = None,
):
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Here's how that might look for the process of creating a separate `finance` subp
# create a group of all models tagged with "finance"
# leaf nodes and nodes with cross-group dependencies will be `public`
# public nodes will also have contracts added to them
dbt-meshify group finance --owner name Monopoly Man -s +tag:finance
dbt-meshify group finance --owner-name "Monopoly Man" -s +tag:finance

# optionally use the add-version operation to add a new version to a model
dbt-meshify operation add-version -s fct_orders
Expand Down
10 changes: 4 additions & 6 deletions tests/integration/test_create_group_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ def test_create_group_command(model_yml, start_group_yml, end_group_yml):
"shared_model",
"--project-path",
proj_path_string,
"--owner",
"name",
"--owner-name",
"Shaina Fake",
"--owner",
"email",
"--owner-email",
"fake@example.com",
],
)
Expand Down Expand Up @@ -97,10 +95,10 @@ def test_group_group_owner_properties(name, email, end_group_yml):
args = ["test_group", "--select", "shared_model", "--project-path", proj_path_string]

if name:
args += ["--owner", "name", name]
args += ["--owner-name", name]

if email:
args += ["--owner", "email", email]
args += ["--owner-email", email]

runner = CliRunner()
result = runner.invoke(create_group, args)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/test_group_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ def test_group_command(select, expected_public_contracted_models):
group,
[
"test_group",
"--owner",
"name",
"--owner-name",
"Teenage Mutant Jinja Turtles",
"--select",
select,
Expand Down