Skip to content

Commit

Permalink
sentinel for tags without values (#20388)
Browse files Browse the repository at this point in the history
## Summary & Motivation

Adds a special sentinel value for tags that indicates "this tag is just
a string, not a key-value pair". How this sentinel will be used:
- In the CLI, when a selection like `--select tag:foo` is provided,
we'll interpret it as `AssetSelection.tag("foo", "__dagster_novalue")`
(implemented in this PR)
- The dbt integration will provide this value for all tags (because dbt
tags are strings).
- In the UI, we'll hide this sentinel value. I.e. a tags dict like
`{"foo": "fooval", "bar": "__dagster_novalue"}` will be rendered as
"foo=fooval, bar" in the UI.

## How I Tested These Changes
  • Loading branch information
sryza authored Mar 19, 2024
1 parent fbf5a8a commit 84e712f
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 3 deletions.
1 change: 1 addition & 0 deletions python_modules/dagster/dagster/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@
from dagster._core.storage.tags import (
MAX_RUNTIME_SECONDS_TAG as MAX_RUNTIME_SECONDS_TAG,
MEMOIZED_RUN_TAG as MEMOIZED_RUN_TAG,
TAG_NO_VALUE as TAG_NO_VALUE,
)
from dagster._core.storage.upath_io_manager import UPathIOManager as UPathIOManager
from dagster._core.types.config_schema import (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
fetch_sources,
parse_clause,
)
from dagster._core.storage.tags import TAG_NO_VALUE
from dagster._serdes.serdes import whitelist_for_serdes

from .asset_check_spec import AssetCheckKey
Expand Down Expand Up @@ -195,8 +196,16 @@ def tag_string(string: str, include_sources: bool = False) -> "AssetSelection":
include_sources (bool): If True, then include source assets matching the group in the
selection.
"""
key, value = string.split("=")
return TagAssetSelection(key=key, value=value, include_sources=include_sources)
split_by_equals_segments = string.split("=")
if len(split_by_equals_segments) == 1:
return TagAssetSelection(
key=string, value=TAG_NO_VALUE, include_sources=include_sources
)
elif len(split_by_equals_segments) == 2:
key, value = split_by_equals_segments
return TagAssetSelection(key=key, value=value, include_sources=include_sources)
else:
check.failed(f"Invalid tag selection string: {string}. Must have no more than one '='.")

@public
@staticmethod
Expand Down
3 changes: 3 additions & 0 deletions python_modules/dagster/dagster/_core/storage/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
]


TAG_NO_VALUE = "__dagster_no_value"


class TagType(Enum):
# Custom tag provided by a user
USER_PROVIDED = "USER_PROVIDED"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from dagster._core.definitions.assets import AssetsDefinition
from dagster._core.definitions.base_asset_graph import BaseAssetGraph
from dagster._core.definitions.events import AssetKey
from dagster._core.storage.tags import TAG_NO_VALUE
from dagster._serdes import deserialize_value
from dagster._serdes.serdes import _WHITELIST_MAP
from pydantic import ValidationError
Expand Down Expand Up @@ -711,6 +712,7 @@ def test_deserialize_old_all_asset_selection():

def test_from_string_tag():
assert AssetSelection.from_string("tag:foo=bar") == AssetSelection.tag("foo", "bar")
assert AssetSelection.from_string("tag:foo") == AssetSelection.tag("foo", TAG_NO_VALUE)


def test_tag():
Expand All @@ -736,10 +738,18 @@ def test_tag_string():
AssetSpec("asset2", tags={"foo": "fooval2"}),
AssetSpec("asset3", tags={"foo": "fooval", "bar": "barval"}),
AssetSpec("asset4", tags={"bar": "barval"}),
AssetSpec("asset5", tags={"baz": TAG_NO_VALUE}),
AssetSpec("asset6", tags={"baz": TAG_NO_VALUE, "bar": "barval"}),
]
)
def assets(): ...

assert AssetSelection.tag_string("foo=fooval").resolve([assets]) == {
AssetKey(k) for k in ["asset1", "asset3"]
AssetKey("asset1"),
AssetKey("asset3"),
}
assert AssetSelection.tag_string("foo").resolve([assets]) == set()
assert AssetSelection.tag_string("baz").resolve([assets]) == {
AssetKey("asset5"),
AssetKey("asset6"),
}

0 comments on commit 84e712f

Please sign in to comment.