From 7d5a50dcd55d7fdd785c63512c61ac9a06020d00 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 31 Jan 2023 21:21:59 -0500 Subject: [PATCH 1/8] Create protobuf message representations of graph nodes --- .../unreleased/Features-20230131-212702.yaml | 6 + core/dbt/constants.py | 2 + core/dbt/contracts/graph/README.md | 28 + core/dbt/contracts/graph/model_config.py | 91 ++- core/dbt/contracts/graph/nodes.proto | 588 +++++++++++++ core/dbt/contracts/graph/nodes.py | 244 +++++- core/dbt/contracts/graph/proto_nodes.py | 772 ++++++++++++++++++ core/dbt/contracts/graph/unparsed.py | 48 ++ core/dbt/contracts/graph/utils.py | 19 + core/dbt/events/README.md | 4 + core/dbt/events/types.proto | 2 - core/dbt/parser/manifest.py | 8 +- core/dbt/task/parse.py | 0 core/dbt/utils.py | 7 + core/setup.py | 2 +- dev-requirements.txt | 2 +- tests/unit/test_proto_nodes.py | 378 +++++++++ 17 files changed, 2182 insertions(+), 19 deletions(-) create mode 100644 .changes/unreleased/Features-20230131-212702.yaml create mode 100644 core/dbt/contracts/graph/README.md create mode 100644 core/dbt/contracts/graph/nodes.proto create mode 100644 core/dbt/contracts/graph/proto_nodes.py delete mode 100644 core/dbt/task/parse.py create mode 100644 tests/unit/test_proto_nodes.py diff --git a/.changes/unreleased/Features-20230131-212702.yaml b/.changes/unreleased/Features-20230131-212702.yaml new file mode 100644 index 00000000000..7d7a27868f0 --- /dev/null +++ b/.changes/unreleased/Features-20230131-212702.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Crate protobuf representation of nodes +time: 2023-01-31T21:27:02.209758-05:00 +custom: + Author: gshank + Issue: "6391" diff --git a/core/dbt/constants.py b/core/dbt/constants.py index 63213476e54..a055db3a571 100644 --- a/core/dbt/constants.py +++ b/core/dbt/constants.py @@ -8,3 +8,5 @@ PIN_PACKAGE_URL = ( "https://docs.getdbt.com/docs/package-management#section-specifying-package-versions" ) + +MANIFEST_FILE_NAME = "manifest.json" diff --git a/core/dbt/contracts/graph/README.md b/core/dbt/contracts/graph/README.md new file mode 100644 index 00000000000..964c4ca8b9f --- /dev/null +++ b/core/dbt/contracts/graph/README.md @@ -0,0 +1,28 @@ +# nodes.proto messages + +For new fields in a node or node config to be included in the protobuf serialized output, +the messages in nodes.proto need to be updated. + +Then proto.nodes need to be compiled: ```protoc --python_betterproto_out . nodes.proto``` + +In order to use optional fields (really necessary for nodes and configs) we had to use +a beta version of betterproto. This version has a bug in the way that it writes the +names of some generated classes, so we will have to update the name of the rpc node from +RpcNode to RPCNode in the generated file. + +In addition, betterproto now always creates the generated python file as an __init__.py +file in a subdirectory. For now, I'm moving it up from proto_nodes/__init__.py to proto_nodes.py. + +# updating nodes.py and model_config.py for nodes.proto changes + +Protobuf python messages objects are created to "to_msg" methods. There is often a list +of attributes to set in a "msg_attributes" method, but this isn't entirely consistent. +If a class has a small number of additional attributes they are sometimes set directly. +Some attributes aren't handled well by the "get_msg_attribute_value" utility function, +in which case they are set directly. This is particularly true of lists or dictionaries +of objects, which need to be converted using a "to_msg" method. + +The utility class "get_msg_attribute_value" does a couple of common conversions of +attribute values, such as getting the string value of an enum or converting dictionaries to +dictionaries of strings. A few common more elaborate conversions are also performed, such as +"columns". diff --git a/core/dbt/contracts/graph/model_config.py b/core/dbt/contracts/graph/model_config.py index 407c5435786..8c608aa2a0a 100644 --- a/core/dbt/contracts/graph/model_config.py +++ b/core/dbt/contracts/graph/model_config.py @@ -8,11 +8,12 @@ register_pattern, ) from dbt.contracts.graph.unparsed import AdditionalPropertiesAllowed, Docs -from dbt.contracts.graph.utils import validate_color +from dbt.contracts.graph.utils import validate_color, get_msg_attribute_value from dbt.exceptions import DbtInternalError, CompilationError from dbt.contracts.util import Replaceable, list_str from dbt import hooks from dbt.node_types import NodeType +from dbt.contracts.graph import proto_nodes M = TypeVar("M", bound="Metadata") @@ -195,6 +196,9 @@ class Hook(dbtClassMixin, Replaceable): transaction: bool = True index: Optional[int] = None + def to_msg(self): + return proto_nodes.Hook(sql=self.sql, transaction=self.transaction, index=self.index) + T = TypeVar("T", bound="BaseConfig") @@ -404,9 +408,15 @@ class NodeAndTestConfig(BaseConfig): metadata=MergeBehavior.Update.meta(), ) + @classmethod + def msg_attributes(self): + return ["enabled", "alias", "schema", "database", "tags", "meta"] + @dataclass class NodeConfig(NodeAndTestConfig): + """This config is used by ModelNode, AnalysisNode, RPCNode, SqlNode, HookNode""" + # Note: if any new fields are added with MergeBehavior, also update the # 'mergebehavior' dictionary materialized: str = "view" @@ -447,6 +457,35 @@ class NodeConfig(NodeAndTestConfig): metadata=MergeBehavior.Update.meta(), ) + @classmethod + def msg_attributes(self): + return [ + "materialized", + "incremental_strategy", + "persist_docs", + "quoting", + "full_refresh", + "unique_key", + "on_schema_change", + "grants", + "packages", + "docs", + ] + + def to_msg(self): + # Get matching msg config class + config_name = type(self).__name__ + msg_cls = getattr(proto_nodes, config_name) + msg_config = msg_cls() + + for cls in [NodeAndTestConfig, NodeConfig]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg_config, attribute, value) + msg_config.post_hook = [hk.to_msg() for hk in self.post_hook] + msg_config.pre_hook = [hk.to_msg() for hk in self.pre_hook] + return msg_config + # we validate that node_color has a suitable value to prevent dbt-docs from crashing def __post_init__(self): if self.docs.node_color: @@ -495,6 +534,11 @@ class SeedConfig(NodeConfig): materialized: str = "seed" quote_columns: Optional[bool] = None + def to_msg(self): + msg = super().to_msg() + msg.quote_columns = self.quote_columns + return msg + @classmethod def validate(cls, data): super().validate(data) @@ -502,8 +546,11 @@ def validate(cls, data): raise ValidationError("A seed must have a materialized value of 'seed'") +# This is used in both GenericTestNode and SingularTestNode, but some +# of these attributes seem specific to GenericTestNode. @dataclass class TestConfig(NodeAndTestConfig): + __test__ = False # this is repeated because of a different default schema: Optional[str] = field( default="dbt_test__audit", @@ -518,6 +565,27 @@ class TestConfig(NodeAndTestConfig): warn_if: str = "!= 0" error_if: str = "!= 0" + @classmethod + def msg_attributes(self): + return [ + "materialized", + "severity", + "store_failures", + "where", + "limit", + "fail_calc", + "warn_if", + "error_if", + ] + + def to_msg(self): + msg_config = proto_nodes.TestConfig() + for cls in [NodeAndTestConfig, TestConfig]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg_config, attribute, value) + return msg_config + @classmethod def same_contents(cls, unrendered: Dict[str, Any], other: Dict[str, Any]) -> bool: """This is like __eq__, except it explicitly checks certain fields.""" @@ -563,6 +631,27 @@ class SnapshotConfig(EmptySnapshotConfig): # Not using Optional because of serialization issues with a Union of str and List[str] check_cols: Union[str, List[str], None] = None + @classmethod + def msg_attributes(self): + return ["strategy", "unique_key", "target_schema", "target_database"] + + def to_msg(self): + msg_config = super().to_msg() # Uses NodeConfig to_msg + for attribute in self.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg_config, attribute, value) + msg_config.check_cols = self.normalize_check_cols() + return msg_config + + def normalize_check_cols(self): + """Ensure that check_cols is always a list""" + if self.check_cols is None: + return [] + elif isinstance(self.check_cols, str): + return [self.check_cols] + else: + return self.check_cols + @classmethod def validate(cls, data): super().validate(data) diff --git a/core/dbt/contracts/graph/nodes.proto b/core/dbt/contracts/graph/nodes.proto new file mode 100644 index 00000000000..b18d40fb54e --- /dev/null +++ b/core/dbt/contracts/graph/nodes.proto @@ -0,0 +1,588 @@ +syntax = "proto3"; + +package proto_nodes; + + +message ListOfStrings { + repeated string value = 1; +} + +message Hook { + string sql = 1; + bool transaction = 2; + optional int index = 3; +} + +message Docs { + bool show = 1; + optional string node_color = 2; +} + +message MacroDependsOn { + repeated string macros = 1; +} + +message DependsOn { + repeated string macros = 1; + repeated string nodes = 2; +} + +message MacroArgument { + string name = 1; + optional string type = 2; + string description = 3; +} + +message Quoting { + optional string database = 1; + optional string schema = 2; + optional string identifier = 3; + optional string column = 4; +} + +message Time { + optional int32 count = 1; + optional string period = 2; +} + +message FreshnessThreshold { + optional Time warn_after = 1; + optional Time error_after = 2; + optional string filter = 3; +} + +message ExposureOwner { + string email = 1; + optional string name = 2; +} + +message MetricFilter { + string field = 1; + string operator = 2; + string value = 3; +} + +message MetricTime { + optional int32 count = 1; + optional string period = 2; +} + +message NodeConfig { + bool enabled = 1; + optional string alias = 2; + optional string schema = 3; + optional string database = 4; + repeated string tags = 5; + map meta = 6; + string materialized = 7; + optional string incremental_strategy = 8; + map persist_docs = 9; + Hook post_hook = 10; + Hook pre_hook = 11; + map quoting = 12; + map column_types = 13; + optional bool full_refresh = 14; + optional string unique_key = 15; + string on_schema_change = 16; + map grants = 17; + repeated string packages = 18; + Docs docs = 19; +} + +message SeedConfig { + bool enabled = 1; + optional string alias = 2; + optional string schema = 3; + optional string database = 4; + repeated string tags = 5; + map meta = 6; + string materialized = 7; + optional string incremental_strategy = 8; + map persist_docs = 9; + // post_hook = 10; + // pre_hook = 11; + map quoting = 12; + map column_types = 13; + optional bool full_refresh = 14; + optional string unique_key = 15; + string on_schema_change = 16; + map grants = 17; + repeated string packages = 18; + Docs docs = 19; + optional bool quote_columns = 20; +} + +message TestConfig { + bool enabled = 1; + optional string alias = 2; + optional string schema = 3; + optional string database = 4; + repeated string tags = 5; + map meta = 6; + string materialized = 8; + string severity = 9; + optional bool store_failures = 10; + optional string where = 11; + optional int32 limit = 12; + string fail_calc = 13; + string warn_if = 14; + string error_if = 15; +} + +// NodeConfig plus strategy, target_schema, target_database, check_cols +message SnapshotConfig { + bool enabled = 1; + optional string alias = 2; + optional string schema = 3; + optional string database = 4; + repeated string tags = 5; + map meta = 6; + string materialized = 7; + optional string incremental_strategy = 8; + map persist_docs = 9; + // post_hook = 10; + // pre_hook = 11; + map quoting = 12; + map column_types = 13; + optional bool full_refresh = 14; + optional string unique_key = 15; + string on_schema_change = 16; + map grants = 17; + repeated string packages = 18; + Docs docs = 19; + optional string strategy = 20; + optional string target_schema = 21; + optional string target_database = 22; + repeated string check_cols = 23; +} + +message SourceConfig { + bool enabled = 1; +} + +message ExposureConfig { + bool enabled = 1; +} + +message MetricConfig { + bool enabled = 1; +} + +message ColumnInfo { + string name = 1; + string description = 2; + map meta = 3; + optional string data_type = 4; + optional bool quote = 5; + repeated string tags = 6; + map _extra = 7; +} + + +// There are three nodes that are exactly the same as this one (AnalysisNode, RPCNode, and +// SqlNOde), and one with only one additional attribute (HookNode). Making separate messages +// for now, but we can revisit later. If we clean up the config classes, some of those +// nodes might end up with different config classes, which would require separate node messages. +message ModelNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + NodeConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + +// This should be exactly the same as ModelNode +message AnalysisNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + NodeConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + +// This should be exactly the same as ModelNode +message RPCNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + NodeConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + + +// This should be exactly the same as ModelNode +message SqlNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + NodeConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + +// This should be the same as ModelNode plus additional "index" attribute +message HookNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + NodeConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; + optional int32 index = 29; +} + + +message SeedNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + SeedConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string root_path = 22; +} + + +// Same as ModelNode except config is TestConfig +message SingularTestNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + TestConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + +message TestMetadata { + string name = 1; + map kwargs = 2; + optional string namespace = 3; +} + +// Same as ModelNode except config is TestConfig, and has test_metadata +// and column_name attributes. +message GenericTestNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + TestConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; + TestMetadata test_metadata = 29; + optional string column_name = 30; +} + +// SnapshotNode - Sames as ModelNode except with SnapshotConfig +message SnapshotNode { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string alias = 10; + SnapshotConfig config = 11; + repeated string tags = 12; + string description = 13; + map columns = 14; + map meta = 15; + Docs docs = 16; + string patch_path = 17; + bool deferred = 18; + map unrendered_config = 19; + string relation_name = 20; + string raw_code = 21; + string language = 22; + repeated ListOfStrings refs = 23; + repeated ListOfStrings sources = 24; + repeated ListOfStrings metrics = 25; + DependsOn depends_on = 26; + bool compiled = 27; + string compiled_code = 28; +} + +// Macro - BaseNode plus additional attributes +message Macro { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + string macro_sql = 7; + MacroDependsOn depends_on = 8; + string description = 9; + map meta = 10; + Docs docs = 11; + optional string patch_path = 12; + repeated MacroArgument arguments = 13; + repeated string supported_languages = 14; +} + +// Documentation - BaseNode plus block_contents +message Documentation { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + string block_contents = 7; +} + +message SourceDefinition { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + optional string database = 8; + string schema = 9; + string source_name = 10; + string source_description = 11; + string loader = 12; + string identifier = 13; + Quoting quoting = 14; + optional string loaded_at_field = 15; + optional FreshnessThreshold freshness = 16; + // optional ExternalTable external = 17; + string description = 18; + map columns = 19; + map meta = 20; + map source_meta = 21; + repeated string tags = 22; + SourceConfig config = 23; + optional string patch_path = 24; + map unrendered_config = 25; + optional string relation_name = 26; +} + +message Exposure { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + string type = 8; + ExposureOwner owner = 9; + string description = 10; + optional string label = 11; + optional string maturity = 12; + map meta = 13; + repeated string tags = 14; + ExposureConfig config = 15; + map unrendered_config = 16; + optional string url = 17; + DependsOn depends_on = 18; + repeated ListOfStrings refs = 24; + repeated ListOfStrings sources = 25; + repeated ListOfStrings metrics = 26; +} + +message Metric { + string name = 1; + string resource_type = 2; + string package_name = 3; + string path = 4; + string original_file_path = 5; + string unique_id = 6; + repeated string fqn = 7; + string description = 8; + string label = 9; + string calculation_method = 10; + string expression = 11; + repeated MetricFilter filters = 12; + repeated string time_grains = 13; + repeated string dimensions = 14; + optional string timestamp = 15; + optional MetricTime window = 16; + optional string model = 17; + optional string model_unique_id = 18; + map meta = 19; + repeated string tags = 20; + MetricConfig config = 21; + map unrendered_config = 22; + repeated ListOfStrings refs = 24; + repeated ListOfStrings sources = 25; + repeated ListOfStrings metrics = 26; + DependsOn depends_on = 27; +} diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index b0b6d85655e..4fc986fe149 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -35,6 +35,7 @@ MetricTime, ) from dbt.contracts.util import Replaceable, AdditionalPropertiesMixin +from dbt.contracts.graph.utils import get_msg_attribute_value from dbt.events.proto_types import NodeInfo from dbt.events.functions import warn_or_error from dbt.exceptions import ParsingError @@ -49,6 +50,7 @@ from dbt.node_types import ModelLanguage, NodeType from dbt.utils import cast_dict_to_dict_of_strings +from dbt.contracts.graph import proto_nodes from .model_config import ( NodeConfig, @@ -95,6 +97,18 @@ class BaseNode(dbtClassMixin, Replaceable): original_file_path: str unique_id: str + @classmethod + def msg_attributes(self): + """Attributes of this class that are included in protobuf definitions""" + return [ + "name", + "resource_type", + "package_name", + "path", + "original_file_path", + "unique_id", + ] + @property def search_name(self): return self.name @@ -134,6 +148,10 @@ class GraphNode(BaseNode): fqn: List[str] + @classmethod + def msg_attributes(self): + return ["fqn"] + def same_fqn(self, other) -> bool: return self.fqn == other.fqn @@ -150,6 +168,18 @@ class ColumnInfo(AdditionalPropertiesMixin, ExtensibleDbtClassMixin, Replaceable tags: List[str] = field(default_factory=list) _extra: Dict[str, Any] = field(default_factory=dict) + def to_msg(self): + column_info_msg = proto_nodes.ColumnInfo( + name=self.name, + description=self.description, + meta=cast_dict_to_dict_of_strings(self.meta), + data_type=self.data_type, + quote=self.quote, + tags=self.tags, + _extra=cast_dict_to_dict_of_strings(self._extra), + ) + return column_info_msg + # Metrics, exposures, @dataclass @@ -179,6 +209,9 @@ def add_macro(self, value: str): if value not in self.macros: self.macros.append(value) + def to_msg(self): + return proto_nodes.MacroDependsOn(macros=self.macros) + @dataclass class DependsOn(MacroDependsOn): @@ -188,13 +221,20 @@ def add_node(self, value: str): if value not in self.nodes: self.nodes.append(value) + def to_msg(self): + return proto_nodes.DependsOn(nodes=self.nodes, macros=self.macros) + @dataclass class ParsedNodeMandatory(GraphNode, HasRelationMetadata, Replaceable): alias: str - checksum: FileHash + checksum: FileHash # not included in protobuf messages config: NodeConfig = field(default_factory=NodeConfig) + @classmethod + def msg_attributes(self): + return ["fqn", "database", "schema", "alias", "config"] + @property def identifier(self): return self.alias @@ -249,6 +289,22 @@ class ParsedNode(NodeInfoMixin, ParsedNodeMandatory, SerializableType): relation_name: Optional[str] = None raw_code: str = "" + @classmethod + def msg_attributes(self): + # Does not included created_at, config_call_dict, build_path + return [ + "tags", + "description", + "columns", + "meta", + "docs", + "patch_path", + "deferred", + "unrendered_config", + "relation_name", + "raw_code", + ] + def write_node(self, target_path: str, subdirectory: str, payload: str): if os.path.basename(self.path) == os.path.basename(self.original_file_path): # One-to-one relationship of nodes to files. @@ -401,6 +457,19 @@ class CompiledNode(ParsedNode): extra_ctes: List[InjectedCTE] = field(default_factory=list) _pre_injected_sql: Optional[str] = None + @classmethod + def msg_attributes(self): + # Does not include extra_ctes_injected, extra_ctes, _pre_injected_sql, compiled_path + return [ + "language", + "refs", + "sources", + "metrics", + "depends_on", + "compiled", + "compiled_code", + ] + @property def empty(self): return not self.raw_code.strip() @@ -438,6 +507,19 @@ def depends_on_nodes(self): def depends_on_macros(self): return self.depends_on.macros + def to_msg(self): + + # Get matching msg node class + node_name = type(self).__name__ + msg_cls = getattr(proto_nodes, node_name) + msg_node = msg_cls() + + for cls in [BaseNode, GraphNode, ParsedNodeMandatory, ParsedNode, CompiledNode]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg_node, attribute, value) + return msg_node + # ==================================== # CompiledNode subclasses @@ -454,13 +536,18 @@ class HookNode(CompiledNode): resource_type: NodeType = field(metadata={"restrict": [NodeType.Operation]}) index: Optional[int] = None + def to_msg(self): + msg = super().to_msg() + msg.index = self.index + return msg + @dataclass class ModelNode(CompiledNode): resource_type: NodeType = field(metadata={"restrict": [NodeType.Model]}) -# TODO: rm? +# TODO: this node type should probably be removed when the rpc server is no longer supported @dataclass class RPCNode(CompiledNode): resource_type: NodeType = field(metadata={"restrict": [NodeType.RPCCall]}) @@ -485,6 +572,15 @@ class SeedNode(ParsedNode): # No SQLDefaults! root_path: Optional[str] = None depends_on: MacroDependsOn = field(default_factory=MacroDependsOn) + def to_msg(self): + seed_node = proto_nodes.SeedNode() + for cls in [BaseNode, ParsedNodeMandatory, ParsedNode]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(seed_node, attribute, value) + seed_node.root_path = self.root_path + return seed_node + def same_seeds(self, other: "SeedNode") -> bool: # for seeds, we check the hashes. If the hashes are different types, # no match. If the hashes are both the same 'path', log a warning and @@ -608,6 +704,8 @@ class SingularTestNode(TestShouldStoreFailures, CompiledNode): # refactor the various configs. config: TestConfig = field(default_factory=TestConfig) # type: ignore + # no to_msg method because the CompiledNode default works fine + @property def test_node_type(self): return "singular" @@ -620,6 +718,7 @@ def test_node_type(self): @dataclass class TestMetadata(dbtClassMixin, Replaceable): + __test__ = False name: str # kwargs are the args that are left in the test builder after # removing configs. They are set from the test builder when @@ -639,11 +738,16 @@ class HasTestMetadata(dbtClassMixin): class GenericTestNode(TestShouldStoreFailures, CompiledNode, HasTestMetadata): resource_type: NodeType = field(metadata={"restrict": [NodeType.Test]}) column_name: Optional[str] = None - file_key_name: Optional[str] = None + file_key_name: Optional[str] = None # Not included in protobuf message # Was not able to make mypy happy and keep the code working. We need to # refactor the various configs. config: TestConfig = field(default_factory=TestConfig) # type: ignore + def to_msg(self): + msg = super().to_msg() + msg.column_name = self.column_name + return msg + def same_contents(self, other) -> bool: if other is None: return False @@ -697,6 +801,29 @@ class Macro(BaseNode): created_at: float = field(default_factory=lambda: time.time()) supported_languages: Optional[List[ModelLanguage]] = None + @classmethod + def msg_attributes(self): + return ["macro_sql", "depends_on", "description", "meta", "docs", "patch_path"] + + def to_msg(self): + msg = proto_nodes.Macro() + for cls in [BaseNode, Macro]: + for attribute in cls.msg_attributes(): + value = getattr(self, attribute) + if value is None: + continue + setattr(msg, attribute, value) + arguments = [ + proto_nodes.MacroArgument(name=ma.name, description=ma.description, type=ma.type) + for ma in self.arguments + ] + msg.arguments = arguments + supported_languages = [] + if isinstance(self.supported_languages, list): + supported_languages = [ml.value for ml in self.supported_languages] + msg.supported_languages = supported_languages + return msg + def patch(self, patch: "ParsedMacroPatch"): self.patch_path: Optional[str] = patch.file_id self.description = patch.description @@ -727,6 +854,15 @@ class Documentation(BaseNode): block_contents: str resource_type: NodeType = field(metadata={"restrict": [NodeType.Documentation]}) + def to_msg(self): + msg = proto_nodes.Documentation() + for cls in [BaseNode]: + for attribute in cls.msg_attributes(): + value = getattr(self, attribute) + setattr(msg, attribute, value) + msg.block_contents = self.block_contents + return msg + @property def search_name(self): return self.name @@ -821,6 +957,39 @@ class SourceDefinition(NodeInfoMixin, ParsedSourceMandatory): relation_name: Optional[str] = None created_at: float = field(default_factory=lambda: time.time()) + @classmethod + def msg_attributes(self): + return [ + "source_name", + "source_description", + "loader", + "identifier", + "resource_type", + "quoting", + "loaded_at_field", + "freshness", + "external", + "description", + "columns", + "meta", + "source_meta", + "tags", + "config", + "patch_path", + "unrendered_config", + "relation_name", + "database", + "schema", + ] + + def to_msg(self): + msg = proto_nodes.SourceDefinition() + for cls in [BaseNode, GraphNode, SourceDefinition]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg, attribute, value) + return msg + def __post_serialize__(self, dct): if "_event_status" in dct: del dct["_event_status"] @@ -943,6 +1112,32 @@ class Exposure(GraphNode): metrics: List[List[str]] = field(default_factory=list) created_at: float = field(default_factory=lambda: time.time()) + @classmethod + def msg_attributes(self): + return [ + "type", + "description", + "label", + "maturity", + "meta", + "tags", + "config", + "unrendered_config", + "url", + "depends_on", + "refs", + "sources", + "metrics", + ] + + def to_msg(self): + msg = proto_nodes.Exposure() + for cls in [BaseNode, GraphNode, Exposure]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg, attribute, value) + return msg + @property def depends_on_nodes(self): return self.depends_on.nodes @@ -1003,15 +1198,8 @@ def same_contents(self, old: Optional["Exposure"]) -> bool: # ==================================== -@dataclass -class MetricReference(dbtClassMixin, Replaceable): - sql: Optional[Union[str, int]] - unique_id: Optional[str] - - @dataclass class Metric(GraphNode): - name: str description: str label: str calculation_method: str @@ -1028,12 +1216,44 @@ class Metric(GraphNode): tags: List[str] = field(default_factory=list) config: MetricConfig = field(default_factory=MetricConfig) unrendered_config: Dict[str, Any] = field(default_factory=dict) - sources: List[List[str]] = field(default_factory=list) - depends_on: DependsOn = field(default_factory=DependsOn) refs: List[List[str]] = field(default_factory=list) + sources: List[List[str]] = field(default_factory=list) metrics: List[List[str]] = field(default_factory=list) + depends_on: DependsOn = field(default_factory=DependsOn) created_at: float = field(default_factory=lambda: time.time()) + @classmethod + def msg_attributes(self): + return [ + "description", + "label", + "calculation_method", + "expression", + "time_grains", + "dimensions", + "timestamp", + "window", + "model", + "model_unique_id", + "meta", + "tags", + "config", + "unrendered_config", + "refs", + "sources", + "metrics", + "depends_on", + ] + + def to_msg(self): + msg = proto_nodes.Metric() + for cls in [BaseNode, GraphNode, Metric]: + for attribute in cls.msg_attributes(): + value = get_msg_attribute_value(self, attribute) + setattr(msg, attribute, value) + msg.filters = [mf.to_msg() for mf in self.filters] + return msg + @property def depends_on_nodes(self): return self.depends_on.nodes diff --git a/core/dbt/contracts/graph/proto_nodes.py b/core/dbt/contracts/graph/proto_nodes.py new file mode 100644 index 00000000000..8886d108c79 --- /dev/null +++ b/core/dbt/contracts/graph/proto_nodes.py @@ -0,0 +1,772 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: nodes.proto +# plugin: python-betterproto +from dataclasses import dataclass +from typing import ( + Dict, + List, + Optional, +) + +import betterproto + + +@dataclass(eq=False, repr=False) +class ListOfStrings(betterproto.Message): + value: List[str] = betterproto.string_field(1) + + +@dataclass(eq=False, repr=False) +class Docs(betterproto.Message): + show: bool = betterproto.bool_field(1) + node_color: str = betterproto.string_field(2) + + +@dataclass(eq=False, repr=False) +class MacroDependsOn(betterproto.Message): + macros: List[str] = betterproto.string_field(1) + + +@dataclass(eq=False, repr=False) +class DependsOn(betterproto.Message): + macros: List[str] = betterproto.string_field(1) + nodes: List[str] = betterproto.string_field(2) + + +@dataclass(eq=False, repr=False) +class MacroArgument(betterproto.Message): + name: str = betterproto.string_field(1) + type: Optional[str] = betterproto.string_field(2, optional=True, group="_type") + description: str = betterproto.string_field(3) + + +@dataclass(eq=False, repr=False) +class Quoting(betterproto.Message): + database: Optional[str] = betterproto.string_field(1, optional=True, group="_database") + schema: Optional[str] = betterproto.string_field(2, optional=True, group="_schema") + identifier: Optional[str] = betterproto.string_field(3, optional=True, group="_identifier") + column: Optional[str] = betterproto.string_field(4, optional=True, group="_column") + + +@dataclass(eq=False, repr=False) +class Time(betterproto.Message): + count: Optional[int] = betterproto.int32_field(1, optional=True, group="_count") + period: Optional[str] = betterproto.string_field(2, optional=True, group="_period") + + +@dataclass(eq=False, repr=False) +class FreshnessThreshold(betterproto.Message): + warn_after: Optional["Time"] = betterproto.message_field(1, optional=True, group="_warn_after") + error_after: Optional["Time"] = betterproto.message_field( + 2, optional=True, group="_error_after" + ) + filter: Optional[str] = betterproto.string_field(3, optional=True, group="_filter") + + +@dataclass(eq=False, repr=False) +class ExposureOwner(betterproto.Message): + email: str = betterproto.string_field(1) + name: Optional[str] = betterproto.string_field(2, optional=True, group="_name") + + +@dataclass(eq=False, repr=False) +class MetricFilter(betterproto.Message): + field: str = betterproto.string_field(1) + operator: str = betterproto.string_field(2) + value: str = betterproto.string_field(3) + + +@dataclass(eq=False, repr=False) +class MetricTime(betterproto.Message): + count: Optional[int] = betterproto.int32_field(1, optional=True, group="_count") + period: Optional[str] = betterproto.string_field(2, optional=True, group="_period") + + +@dataclass(eq=False, repr=False) +class NodeConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + alias: Optional[str] = betterproto.string_field(2, optional=True, group="_alias") + schema: Optional[str] = betterproto.string_field(3, optional=True, group="_schema") + database: Optional[str] = betterproto.string_field(4, optional=True, group="_database") + tags: List[str] = betterproto.string_field(5) + meta: Dict[str, str] = betterproto.map_field( + 6, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + materialized: str = betterproto.string_field(7) + incremental_strategy: Optional[str] = betterproto.string_field( + 8, optional=True, group="_incremental_strategy" + ) + persist_docs: Dict[str, str] = betterproto.map_field( + 9, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + quoting: Dict[str, str] = betterproto.map_field( + 12, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + """post_hook = 10; pre_hook = 11;""" + + column_types: Dict[str, str] = betterproto.map_field( + 13, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + full_refresh: Optional[bool] = betterproto.bool_field(14, optional=True, group="_full_refresh") + unique_key: Optional[str] = betterproto.string_field(15, optional=True, group="_unique_key") + on_schema_change: str = betterproto.string_field(16) + grants: Dict[str, str] = betterproto.map_field( + 17, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + packages: List[str] = betterproto.string_field(18) + docs: "Docs" = betterproto.message_field(19) + + +@dataclass(eq=False, repr=False) +class SeedConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + alias: Optional[str] = betterproto.string_field(2, optional=True, group="_alias") + schema: Optional[str] = betterproto.string_field(3, optional=True, group="_schema") + database: Optional[str] = betterproto.string_field(4, optional=True, group="_database") + tags: List[str] = betterproto.string_field(5) + meta: Dict[str, str] = betterproto.map_field( + 6, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + materialized: str = betterproto.string_field(7) + incremental_strategy: Optional[str] = betterproto.string_field( + 8, optional=True, group="_incremental_strategy" + ) + persist_docs: Dict[str, str] = betterproto.map_field( + 9, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + quoting: Dict[str, str] = betterproto.map_field( + 12, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + """post_hook = 10; pre_hook = 11;""" + + column_types: Dict[str, str] = betterproto.map_field( + 13, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + full_refresh: Optional[bool] = betterproto.bool_field(14, optional=True, group="_full_refresh") + unique_key: Optional[str] = betterproto.string_field(15, optional=True, group="_unique_key") + on_schema_change: str = betterproto.string_field(16) + grants: Dict[str, str] = betterproto.map_field( + 17, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + packages: List[str] = betterproto.string_field(18) + docs: "Docs" = betterproto.message_field(19) + quote_columns: Optional[bool] = betterproto.bool_field( + 20, optional=True, group="_quote_columns" + ) + + +@dataclass(eq=False, repr=False) +class TestConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + alias: Optional[str] = betterproto.string_field(2, optional=True, group="_alias") + schema: Optional[str] = betterproto.string_field(3, optional=True, group="_schema") + database: Optional[str] = betterproto.string_field(4, optional=True, group="_database") + tags: List[str] = betterproto.string_field(5) + meta: Dict[str, str] = betterproto.map_field( + 6, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + materialized: str = betterproto.string_field(8) + severity: str = betterproto.string_field(9) + store_failures: Optional[bool] = betterproto.bool_field( + 10, optional=True, group="_store_failures" + ) + where: Optional[str] = betterproto.string_field(11, optional=True, group="_where") + limit: Optional[int] = betterproto.int32_field(12, optional=True, group="_limit") + fail_calc: str = betterproto.string_field(13) + warn_if: str = betterproto.string_field(14) + error_if: str = betterproto.string_field(15) + + +@dataclass(eq=False, repr=False) +class SnapshotConfig(betterproto.Message): + """NodeConfig plus strategy, target_schema, target_database, check_cols""" + + enabled: bool = betterproto.bool_field(1) + alias: Optional[str] = betterproto.string_field(2, optional=True, group="_alias") + schema: Optional[str] = betterproto.string_field(3, optional=True, group="_schema") + database: Optional[str] = betterproto.string_field(4, optional=True, group="_database") + tags: List[str] = betterproto.string_field(5) + meta: Dict[str, str] = betterproto.map_field( + 6, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + materialized: str = betterproto.string_field(7) + incremental_strategy: Optional[str] = betterproto.string_field( + 8, optional=True, group="_incremental_strategy" + ) + persist_docs: Dict[str, str] = betterproto.map_field( + 9, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + quoting: Dict[str, str] = betterproto.map_field( + 12, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + """post_hook = 10; pre_hook = 11;""" + + column_types: Dict[str, str] = betterproto.map_field( + 13, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + full_refresh: Optional[bool] = betterproto.bool_field(14, optional=True, group="_full_refresh") + unique_key: Optional[str] = betterproto.string_field(15, optional=True, group="_unique_key") + on_schema_change: str = betterproto.string_field(16) + grants: Dict[str, str] = betterproto.map_field( + 17, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + packages: List[str] = betterproto.string_field(18) + docs: "Docs" = betterproto.message_field(19) + strategy: Optional[str] = betterproto.string_field(20, optional=True, group="_strategy") + target_schema: Optional[str] = betterproto.string_field( + 21, optional=True, group="_target_schema" + ) + target_database: Optional[str] = betterproto.string_field( + 22, optional=True, group="_target_database" + ) + check_cols: List[str] = betterproto.string_field(23) + + +@dataclass(eq=False, repr=False) +class SourceConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + + +@dataclass(eq=False, repr=False) +class ExposureConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + + +@dataclass(eq=False, repr=False) +class MetricConfig(betterproto.Message): + enabled: bool = betterproto.bool_field(1) + + +@dataclass(eq=False, repr=False) +class ColumnInfo(betterproto.Message): + name: str = betterproto.string_field(1) + description: str = betterproto.string_field(2) + meta: Dict[str, str] = betterproto.map_field( + 3, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + data_type: str = betterproto.string_field(4) + quote: Optional[bool] = betterproto.bool_field(5, optional=True, group="_quote") + tags: List[str] = betterproto.string_field(6) + extra: Dict[str, str] = betterproto.map_field( + 7, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + + +@dataclass(eq=False, repr=False) +class ModelNode(betterproto.Message): + """ + There are three nodes that are exactly the same as this one (AnalysisNode, + RPCNode, and SqlNOde), and one with only one additional attribute + (HookNode). Making separate messages for now, but we can revisit later. If + we clean up the config classes, some of those nodes might end up with + different config classes, which would require separate node messages. + """ + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "NodeConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class AnalysisNode(betterproto.Message): + """This should be exactly the same as ModelNode""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "NodeConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class RPCNode(betterproto.Message): + """This should be exactly the same as ModelNode""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "NodeConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class SqlNode(betterproto.Message): + """This should be exactly the same as ModelNode""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "NodeConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class HookNode(betterproto.Message): + """ + This should be the same as ModelNode plus additional "index" attribute + """ + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "NodeConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + index: Optional[int] = betterproto.int32_field(29, optional=True, group="_index") + + +@dataclass(eq=False, repr=False) +class SeedNode(betterproto.Message): + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "SeedConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + root_path: str = betterproto.string_field(22) + + +@dataclass(eq=False, repr=False) +class SingularTestNode(betterproto.Message): + """Same as ModelNode except config is TestConfig""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "TestConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class TestMetadata(betterproto.Message): + name: str = betterproto.string_field(1) + kwargs: Dict[str, str] = betterproto.map_field( + 2, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + namespace: Optional[str] = betterproto.string_field(3, optional=True, group="_namespace") + + +@dataclass(eq=False, repr=False) +class GenericTestNode(betterproto.Message): + """ + Same as ModelNode except config is TestConfig, and has test_metadata and + column_name attributes. + """ + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "TestConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + test_metadata: "TestMetadata" = betterproto.message_field(29) + column_name: Optional[str] = betterproto.string_field(30, optional=True, group="_column_name") + + +@dataclass(eq=False, repr=False) +class SnapshotNode(betterproto.Message): + """SnapshotNode - Sames as ModelNode except with SnapshotConfig""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + alias: str = betterproto.string_field(10) + config: "SnapshotConfig" = betterproto.message_field(11) + tags: List[str] = betterproto.string_field(12) + description: str = betterproto.string_field(13) + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 14, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 15, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(16) + patch_path: str = betterproto.string_field(17) + deferred: bool = betterproto.bool_field(18) + unrendered_config: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: str = betterproto.string_field(20) + raw_code: str = betterproto.string_field(21) + language: str = betterproto.string_field(22) + refs: List["ListOfStrings"] = betterproto.message_field(23) + sources: List["ListOfStrings"] = betterproto.message_field(24) + metrics: List["ListOfStrings"] = betterproto.message_field(25) + depends_on: "DependsOn" = betterproto.message_field(26) + compiled: bool = betterproto.bool_field(27) + compiled_code: str = betterproto.string_field(28) + + +@dataclass(eq=False, repr=False) +class Macro(betterproto.Message): + """Macro - BaseNode plus additional attributes""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + macro_sql: str = betterproto.string_field(7) + depends_on: "MacroDependsOn" = betterproto.message_field(8) + description: str = betterproto.string_field(9) + meta: Dict[str, str] = betterproto.map_field( + 10, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + docs: "Docs" = betterproto.message_field(11) + patch_path: Optional[str] = betterproto.string_field(12, optional=True, group="_patch_path") + arguments: List["MacroArgument"] = betterproto.message_field(13) + supported_languages: List[str] = betterproto.string_field(14) + + +@dataclass(eq=False, repr=False) +class Documentation(betterproto.Message): + """Documentation - BaseNode plus block_contents""" + + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + block_contents: str = betterproto.string_field(7) + + +@dataclass(eq=False, repr=False) +class SourceDefinition(betterproto.Message): + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + database: Optional[str] = betterproto.string_field(8, optional=True, group="_database") + schema: str = betterproto.string_field(9) + source_name: str = betterproto.string_field(10) + source_description: str = betterproto.string_field(11) + loader: str = betterproto.string_field(12) + identifier: str = betterproto.string_field(13) + quoting: "Quoting" = betterproto.message_field(14) + loaded_at_field: Optional[str] = betterproto.string_field( + 15, optional=True, group="_loaded_at_field" + ) + freshness: Optional["FreshnessThreshold"] = betterproto.message_field( + 16, optional=True, group="_freshness" + ) + description: str = betterproto.string_field(18) + """optional ExternalTable external = 17;""" + + columns: Dict[str, "ColumnInfo"] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE + ) + meta: Dict[str, str] = betterproto.map_field( + 20, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + source_meta: Dict[str, str] = betterproto.map_field( + 21, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + tags: List[str] = betterproto.string_field(22) + config: "SourceConfig" = betterproto.message_field(23) + patch_path: Optional[str] = betterproto.string_field(24, optional=True, group="_patch_path") + unrendered_config: Dict[str, str] = betterproto.map_field( + 25, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + relation_name: Optional[str] = betterproto.string_field( + 26, optional=True, group="_relation_name" + ) + + +@dataclass(eq=False, repr=False) +class Exposure(betterproto.Message): + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + type: str = betterproto.string_field(8) + owner: "ExposureOwner" = betterproto.message_field(9) + description: str = betterproto.string_field(10) + label: Optional[str] = betterproto.string_field(11, optional=True, group="_label") + maturity: Optional[str] = betterproto.string_field(12, optional=True, group="_maturity") + meta: Dict[str, str] = betterproto.map_field( + 13, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + tags: List[str] = betterproto.string_field(14) + config: "ExposureConfig" = betterproto.message_field(15) + unrendered_config: Dict[str, str] = betterproto.map_field( + 16, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + url: Optional[str] = betterproto.string_field(17, optional=True, group="_url") + depends_on: "DependsOn" = betterproto.message_field(18) + refs: List["ListOfStrings"] = betterproto.message_field(24) + sources: List["ListOfStrings"] = betterproto.message_field(25) + metrics: List["ListOfStrings"] = betterproto.message_field(26) + + +@dataclass(eq=False, repr=False) +class Metric(betterproto.Message): + name: str = betterproto.string_field(1) + resource_type: str = betterproto.string_field(2) + package_name: str = betterproto.string_field(3) + path: str = betterproto.string_field(4) + original_file_path: str = betterproto.string_field(5) + unique_id: str = betterproto.string_field(6) + fqn: List[str] = betterproto.string_field(7) + description: str = betterproto.string_field(8) + label: str = betterproto.string_field(9) + calculation_method: str = betterproto.string_field(10) + expression: str = betterproto.string_field(11) + filters: List["MetricFilter"] = betterproto.message_field(12) + time_grains: List[str] = betterproto.string_field(13) + dimensions: List[str] = betterproto.string_field(14) + timestamp: Optional[str] = betterproto.string_field(15, optional=True, group="_timestamp") + window: Optional["MetricTime"] = betterproto.message_field(16, optional=True, group="_window") + model: Optional[str] = betterproto.string_field(17, optional=True, group="_model") + model_unique_id: Optional[str] = betterproto.string_field( + 18, optional=True, group="_model_unique_id" + ) + meta: Dict[str, str] = betterproto.map_field( + 19, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + tags: List[str] = betterproto.string_field(20) + config: "MetricConfig" = betterproto.message_field(21) + unrendered_config: Dict[str, str] = betterproto.map_field( + 22, betterproto.TYPE_STRING, betterproto.TYPE_STRING + ) + refs: List["ListOfStrings"] = betterproto.message_field(24) + sources: List["ListOfStrings"] = betterproto.message_field(25) + metrics: List["ListOfStrings"] = betterproto.message_field(26) + depends_on: "DependsOn" = betterproto.message_field(27) diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index 6521e644542..3cbd53b763d 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -8,6 +8,7 @@ Replaceable, rename_metric_attr, ) +from dbt.contracts.graph import proto_nodes # trigger the PathEncoder import dbt.helper_types # noqa:F401 @@ -86,6 +87,12 @@ class Docs(dbtClassMixin, Replaceable): show: bool = True node_color: Optional[str] = None + def to_msg(self): + return proto_nodes.Docs( + show=self.show, + node_color=self.node_color, + ) + @dataclass class HasDocs(AdditionalPropertiesMixin, ExtensibleDbtClassMixin, Replaceable): @@ -157,6 +164,11 @@ class MacroArgument(dbtClassMixin): type: Optional[str] = None description: str = "" + def to_msg(self): + return proto_nodes.MacroArgument( + name=self.name, type=self.type, description=self.description + ) + @dataclass class UnparsedMacroUpdate(HasConfig, HasDocs, HasYamlMetadata): @@ -177,6 +189,12 @@ class Time(dbtClassMixin, Mergeable): count: Optional[int] = None period: Optional[TimePeriod] = None + def to_msg(self): + return proto_nodes.Time( + count=self.count, + period=(None if not self.period else self.period.value), + ) + def exceeded(self, actual_age: float) -> bool: if self.period is None or self.count is None: return False @@ -194,6 +212,14 @@ class FreshnessThreshold(dbtClassMixin, Mergeable): error_after: Optional[Time] = field(default_factory=Time) filter: Optional[str] = None + def to_msg(self): + msg = proto_nodes.FreshnessThreshold(filter=self.filter) + if self.warn_after: + msg.warn_after = self.warn_after.to_msg() + if self.error_after: + msg.error_after = self.error_after.to_msg() + return msg + def status(self, age: float) -> "dbt.contracts.results.FreshnessStatus": from dbt.contracts.results import FreshnessStatus @@ -244,6 +270,14 @@ class Quoting(dbtClassMixin, Mergeable): identifier: Optional[bool] = None column: Optional[bool] = None + def to_msg(self): + return proto_nodes.Quoting( + database=self.database, + schema=self.schema, + identifier=self.identifier, + column=self.column, + ) + @dataclass class UnparsedSourceTableDefinition(HasColumnTests, HasTests): @@ -428,6 +462,12 @@ class ExposureOwner(dbtClassMixin, Replaceable): email: str name: Optional[str] = None + def to_msg(self): + return proto_nodes.ExposureOwner( + email=self.email, + name=self.name, + ) + @dataclass class UnparsedExposure(dbtClassMixin, Replaceable): @@ -459,6 +499,9 @@ class MetricFilter(dbtClassMixin, Replaceable): # TODO : Can we make this Any? value: str + def to_msg(self): + return proto_nodes.MetricFilter(field=self.field, operator=self.operator, value=self.value) + class MetricTimePeriod(StrEnum): day = "day" @@ -475,6 +518,11 @@ class MetricTime(dbtClassMixin, Mergeable): count: Optional[int] = None period: Optional[MetricTimePeriod] = None + def to_msg(self): + return proto_nodes.MetricTime( + count=self.count, period=(self.period.value if self.period else None) + ) + def __bool__(self): return self.count is not None and self.period is not None diff --git a/core/dbt/contracts/graph/utils.py b/core/dbt/contracts/graph/utils.py index c1003b2d9d9..931b1cdbe04 100644 --- a/core/dbt/contracts/graph/utils.py +++ b/core/dbt/contracts/graph/utils.py @@ -1,4 +1,23 @@ import re +import enum +from dbt.utils import cast_dict_to_dict_of_strings + + +def get_msg_attribute_value(obj, attribute): + orig_value = getattr(obj, attribute) + value = orig_value + if isinstance(orig_value, enum.Enum): + value = orig_value.value + elif hasattr(value, "to_msg"): + value = value.to_msg() + elif attribute == "columns": + value = {} + for k, v in orig_value: + value[k] = orig_value.to_msg() + elif isinstance(orig_value, dict): + value = cast_dict_to_dict_of_strings(value) + return value + HTML_COLORS = [ "aliceblue", diff --git a/core/dbt/events/README.md b/core/dbt/events/README.md index 52edd7d35d4..28ff5005c3f 100644 --- a/core/dbt/events/README.md +++ b/core/dbt/events/README.md @@ -51,3 +51,7 @@ logger = AdapterLogger("") ## Compiling types.proto After adding a new message in types.proto, in the core/dbt/events directory: ```protoc --python_betterproto_out . types.proto``` + +After switching to the 2.0.0b5 release of betterproto, there is now a bug where it generates incorrectly named python classes when the names have acronyms like SQL or YAML in them. For now, I'm renaming these. The bug has been fixed in the repo, so hopefully there will be a new release at some point. (SQL, YAML, GET get turned int Sql, Yaml, Get). + +In addition, betterproto now puts the generated file in proto_types/__init__.py. I'm moving it to proto_types.py diff --git a/core/dbt/events/types.proto b/core/dbt/events/types.proto index 5e595621104..3ef0d752fd4 100644 --- a/core/dbt/events/types.proto +++ b/core/dbt/events/types.proto @@ -1579,10 +1579,8 @@ message LogFreshnessResultMsg { LogFreshnessResult data = 2; } - // Skipped Q019, Q020, Q021 - // Q022 message LogCancelLine { string conn_name = 1; diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index 6385fb6ec72..6b915cec1ee 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -49,6 +49,7 @@ from dbt.contracts.files import FileHash, ParseFileType, SchemaSourceFile from dbt.parser.read_files import read_files, load_source_file from dbt.parser.partial import PartialParsing, special_override_macros +from dbt.constants import MANIFEST_FILE_NAME from dbt.contracts.graph.manifest import ( Manifest, Disabled, @@ -85,7 +86,6 @@ from dbt.dataclass_schema import StrEnum, dbtClassMixin -MANIFEST_FILE_NAME = "manifest.json" PARTIAL_PARSE_FILE_NAME = "partial_parse.msgpack" PARSING_STATE = DbtProcessState("parsing") PERF_INFO_FILE_NAME = "perf_info.json" @@ -408,6 +408,9 @@ def load(self): # write out the fully parsed manifest self.write_manifest_for_partial_parse() + # write out manifest.json + parsed_manifest_path = os.path.join(self.root_project.target_path, MANIFEST_FILE_NAME) + self.manifest.write(parsed_manifest_path) return self.manifest @@ -583,7 +586,8 @@ def is_partial_parsable(self, manifest: Manifest) -> Tuple[bool, Optional[str]]: ) fire_event( Note( - msg=f"previous checksum: {self.manifest.state_check.vars_hash.checksum}, current checksum: {manifest.state_check.vars_hash.checksum}" + msg=f"previous checksum: {manifest.state_check.vars_hash.checksum}, " + f"current checksum: {self.manifest.state_check.vars_hash.checksum}" ), level=EventLevel.DEBUG, ) diff --git a/core/dbt/task/parse.py b/core/dbt/task/parse.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/core/dbt/utils.py b/core/dbt/utils.py index 27309c4b373..51ac8c3693b 100644 --- a/core/dbt/utils.py +++ b/core/dbt/utils.py @@ -694,3 +694,10 @@ def cast_dict_to_dict_of_strings(dct): for k, v in dct.items(): new_dct[str(k)] = str(v) return new_dct + + +def cast_to_bool(bool_value: Optional[bool]) -> bool: + if bool_value is None: + return False + else: + return True diff --git a/core/setup.py b/core/setup.py index f48fa4f3237..eed56e059b8 100644 --- a/core/setup.py +++ b/core/setup.py @@ -48,7 +48,7 @@ install_requires=[ "Jinja2==3.1.2", "agate>=1.6,<1.7.1", - "betterproto==1.2.5", + "betterproto==2.0.0b5", "click>=7.0,<9", "colorama>=0.3.9,<0.4.7", "hologram>=0.0.14,<=0.0.15", diff --git a/dev-requirements.txt b/dev-requirements.txt index ada2d734b61..936d40c4a5f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,4 +1,4 @@ -betterproto[compiler]==1.2.5 +betterproto[compiler]==2.0.0b5 black==22.10.0 bumpversion docutils diff --git a/tests/unit/test_proto_nodes.py b/tests/unit/test_proto_nodes.py new file mode 100644 index 00000000000..ce5d9e33e62 --- /dev/null +++ b/tests/unit/test_proto_nodes.py @@ -0,0 +1,378 @@ +from dbt.contracts.graph.nodes import ( + ModelNode, + AnalysisNode, + RPCNode, + SqlNode, + HookNode, + SeedNode, + SingularTestNode, + GenericTestNode, + TestMetadata, + SnapshotNode, + Macro, + Documentation, + SourceDefinition, + Exposure, + Metric, +) +from dbt.contracts.graph.model_config import ( + NodeConfig, + SeedConfig, + TestConfig, + SnapshotConfig, + SourceConfig, + ExposureConfig, + MetricConfig, +) +from dbt.contracts.graph.unparsed import ExposureOwner, MetricFilter +from dbt.node_types import NodeType, ModelLanguage +from dbt.contracts.files import FileHash + + +def test_nodes(): + # Create NodeConfig for use in the next 5 nodes + node_config = NodeConfig( + enabled=True, + alias=None, + schema="my_schema", + database="my_database", + tags=["one", "two", "three"], + meta={"one": 1, "two": 2}, + materialized="table", + incremental_strategy=None, + full_refresh=None, + on_schema_change="ignore", + packages=["one", "two", "three"], + ) + # Create a dummy ModelNode + model_node = ModelNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + language="sql", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.Model, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=node_config, + ) + assert model_node + # Get a matching proto message + proto_model_msg = model_node.to_msg() + assert proto_model_msg + + # Create a dummy AnalysisNode + analysis_node = AnalysisNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + language="sql", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.Analysis, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=node_config, + ) + assert analysis_node + # Get a matching proto message + proto_analysis_msg = analysis_node.to_msg() + assert proto_analysis_msg + + # Create a dummy RPCNode + rpc_node = RPCNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + language="sql", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.RPCCall, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=node_config, + ) + assert rpc_node + # Get a matching proto message + proto_rpc_msg = rpc_node.to_msg() + assert proto_rpc_msg + + # Create a dummy SqlNode + sql_node = SqlNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + language="sql", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.SqlOperation, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=node_config, + ) + assert sql_node + # Get a matching proto message + proto_sql_msg = sql_node.to_msg() + assert proto_sql_msg + + # Create a dummy HookNode + hook_node = HookNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="hook.test.my_hook", + raw_code="select 1 from fun", + language="sql", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_hook", + resource_type=NodeType.Operation, + alias="my_hook", + checksum=FileHash.from_contents("select 1 from fun"), + config=node_config, + index=1, + ) + assert hook_node + # Get a matching proto message + proto_hook_msg = hook_node.to_msg() + assert proto_hook_msg + assert proto_hook_msg.index + + # Create a dummy SeedNode + seed_config = SeedConfig( + enabled=True, + alias=None, + schema="my_schema", + database="my_database", + tags=["one", "two", "three"], + meta={"one": 1, "two": 2}, + ) + seed_node = SeedNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.seed.my_node", + raw_code="", + package_name="test", + path="seed.csv", + original_file_path="seeds/seed.csv", + name="seed", + resource_type=NodeType.Seed, + alias="seed", + checksum=FileHash.from_contents("test"), + root_path="some_path", + config=seed_config, + ) + assert seed_node + # Get a matching proto message + proto_seed_msg = seed_node.to_msg() + assert proto_seed_msg + assert proto_seed_msg.root_path + + # config for SingularTestNode and GenericTestNode + test_config = TestConfig( + enabled=True, + alias=None, + schema="my_schema", + database="my_database", + tags=["one", "two", "three"], + meta={"one": 1, "two": 2}, + ) + + # Create a dummy SingularTestNode + singular_test_node = SingularTestNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.Test, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=test_config, + ) + assert singular_test_node + # Get a matching proto message + proto_singular_test_msg = singular_test_node.to_msg() + assert proto_singular_test_msg + + # Create a dummy GenericTestNode + test_metadata = TestMetadata( + name="my_test", + kwargs={"one": 1, "two": "another"}, + ) + generic_test_node = GenericTestNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_node", + raw_code="select 1 from fun", + package_name="test", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_node", + resource_type=NodeType.Test, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=test_config, + test_metadata=test_metadata, + column_name="some_column", + ) + assert generic_test_node + # Get a matching proto message + proto_generic_test_msg = generic_test_node.to_msg() + assert proto_generic_test_msg + assert proto_generic_test_msg.column_name + + # Create SnapshotConfig and SnapshotNode + snapshot_config = SnapshotConfig( + enabled=True, + alias=None, + schema="my_schema", + database="my_database", + tags=["one", "two", "three"], + meta={"one": 1, "two": 2}, + materialized="table", + incremental_strategy=None, + full_refresh=None, + on_schema_change="ignore", + packages=["one", "two", "three"], + strategy="check", + target_schema="some_schema", + target_database="some_database", + check_cols="id", + ) + snapshot_node = SnapshotNode( + database="testdb", + schema="testschema", + fqn=["my", "test"], + unique_id="test.model.my_test", + raw_code="select 1 from fun", + language="sql", + package_name="my_project", + path="my_node.sql", + original_file_path="models/my_node.sql", + name="my_test", + resource_type=NodeType.Snapshot, + alias="my_node", + checksum=FileHash.from_contents("select 1 from fun"), + config=snapshot_config, + ) + assert snapshot_node + # Get a matching proto message + proto_snapshot_msg = snapshot_node.to_msg() + assert proto_snapshot_msg + assert proto_snapshot_msg.config.target_schema + + # Create a dummy Macro + macro = Macro( + name="my_macro", + resource_type=NodeType.Macro, + package_name="my_project", + path="my_macro.sql", + original_file_path="macros/my_macro.sql", + unique_id="macro.my_project.my_macro", + macro_sql="{{ }}", + description="my macro", + supported_languages=[ModelLanguage.sql], + ) + proto_macro_msg = macro.to_msg() + assert proto_macro_msg + assert proto_macro_msg.supported_languages == ["sql"] + + # Create a dummy Documentation + doc = Documentation( + name="my_doc", + resource_type=NodeType.Macro, + package_name="my_project", + path="readme.md", + original_file_path="models/readme.md", + unique_id="doc.my_project.my_doc", + block_contents="this is my special doc", + ) + proto_doc_msg = doc.to_msg() + assert proto_doc_msg + assert proto_doc_msg.block_contents + + # Dummy SourceDefinition + source = SourceDefinition( + name="my_source", + resource_type=NodeType.Source, + package_name="my_project", + path="source.yml", + original_file_path="source.yml", + unique_id="source.my_project.my_source", + fqn=["sources", "my_source"], + database="my_database", + schema="my_schema", + source_name="my_source", + source_description="my source", + loader="loader", + identifier="my_source", + config=SourceConfig(enabled=True), + ) + proto_source_msg = source.to_msg() + assert proto_source_msg + assert proto_source_msg.source_name + + # Dummy Exposure + exposure = Exposure( + name="my_exposure", + resource_type=NodeType.Exposure, + package_name="my_project", + path="exposure.yml", + original_file_path="exposure.yml", + unique_id="exposure.my_project.my_exposure", + fqn=["my", "exposure"], + config=ExposureConfig(enabled=True), + type="dashboard", + owner=ExposureOwner(email="someone@somewhere"), + description="my exposure", + ) + proto_exposure_msg = exposure.to_msg() + assert proto_exposure_msg + assert proto_exposure_msg.type + + # Dummy Metric + metric = Metric( + name="my_metric", + resource_type=NodeType.Metric, + package_name="my_project", + path="metrics.yml", + original_file_path="metrics.yml", + unique_id="metric.my_project.my_metric", + fqn=["my", "metric"], + config=MetricConfig(enabled=True), + description="my metric", + label="my label", + calculation_method="*", + expression="select 1 as fun", + filters=[MetricFilter(field="sum", operator="sum", value="sum")], + time_grains=["day", "minute"], + dimensions=["day", "minute"], + ) + proto_metric_msg = metric.to_msg() + assert proto_metric_msg + assert proto_metric_msg.label From 659ce584a94c1db7019a6b08b7edf0bf003551b5 Mon Sep 17 00:00:00 2001 From: Github Build Bot Date: Mon, 27 Feb 2023 22:22:28 +0000 Subject: [PATCH 2/8] Add generated CLI API docs --- .../docs/build/doctrees/environment.pickle | Bin 207366 -> 207366 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/core/dbt/docs/build/doctrees/environment.pickle b/core/dbt/docs/build/doctrees/environment.pickle index 45eeb69e648060a873b75fb7b0fabd51ef3f11bd..146017154e6705edcbc10091962d372e3dfbd4cd 100644 GIT binary patch delta 33 ncmZp>!qawzXG4=b+kbD5n`;D`JLKCt!qawzXG4=b+uzTR?w|H Date: Mon, 27 Feb 2023 17:50:04 -0500 Subject: [PATCH 3/8] Update nodes --- core/dbt/contracts/graph/nodes.proto | 41 ++++++++++++----- core/dbt/contracts/graph/nodes.py | 6 +++ core/dbt/contracts/graph/proto_nodes.py | 59 ++++++++++++++++++------- core/dbt/contracts/graph/unparsed.py | 2 +- tests/unit/test_proto_nodes.py | 4 +- 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/core/dbt/contracts/graph/nodes.proto b/core/dbt/contracts/graph/nodes.proto index b18d40fb54e..13661486867 100644 --- a/core/dbt/contracts/graph/nodes.proto +++ b/core/dbt/contracts/graph/nodes.proto @@ -10,7 +10,7 @@ message ListOfStrings { message Hook { string sql = 1; bool transaction = 2; - optional int index = 3; + optional int32 index = 3; } message Docs { @@ -212,9 +212,12 @@ message ModelNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; + string access = 31; } -// This should be exactly the same as ModelNode +// This should be exactly the same as ModelNode w/o access message AnalysisNode { string name = 1; string resource_type = 2; @@ -244,9 +247,11 @@ message AnalysisNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; } -// This should be exactly the same as ModelNode +// This should be exactly the same as ModelNode w/o access message RPCNode { string name = 1; string resource_type = 2; @@ -276,10 +281,12 @@ message RPCNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; } -// This should be exactly the same as ModelNode +// This should be exactly the same as ModelNode w/o access message SqlNode { string name = 1; string resource_type = 2; @@ -309,9 +316,11 @@ message SqlNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; } -// This should be the same as ModelNode plus additional "index" attribute +// This should be the same as ModelNode (w/o access) plus additional "index" attribute message HookNode { string name = 1; string resource_type = 2; @@ -341,7 +350,9 @@ message HookNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; - optional int32 index = 29; + bool contract = 29; + string group = 30; + optional int32 index = 31; } @@ -368,10 +379,11 @@ message SeedNode { string relation_name = 20; string raw_code = 21; string root_path = 22; + string group = 23; } -// Same as ModelNode except config is TestConfig +// Same as ModelNode w/o access except config is TestConfig message SingularTestNode { string name = 1; string resource_type = 2; @@ -401,6 +413,8 @@ message SingularTestNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; } message TestMetadata { @@ -409,7 +423,7 @@ message TestMetadata { optional string namespace = 3; } -// Same as ModelNode except config is TestConfig, and has test_metadata +// Same as ModelNode w/o access except config is TestConfig, and has test_metadata // and column_name attributes. message GenericTestNode { string name = 1; @@ -440,11 +454,13 @@ message GenericTestNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; - TestMetadata test_metadata = 29; - optional string column_name = 30; + bool contract = 29; + string group = 30; + TestMetadata test_metadata = 31; + optional string column_name = 32; } -// SnapshotNode - Sames as ModelNode except with SnapshotConfig +// SnapshotNode - Sames as ModelNode w/o access except with SnapshotConfig message SnapshotNode { string name = 1; string resource_type = 2; @@ -474,6 +490,8 @@ message SnapshotNode { DependsOn depends_on = 26; bool compiled = 27; string compiled_code = 28; + bool contract = 29; + string group = 30; } // Macro - BaseNode plus additional attributes @@ -585,4 +603,5 @@ message Metric { repeated ListOfStrings sources = 25; repeated ListOfStrings metrics = 26; DependsOn depends_on = 27; + string group = 28; } diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index c71b257c67a..c729d6ee556 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -308,6 +308,7 @@ def msg_attributes(self): "unrendered_config", "relation_name", "raw_code", + "group", ] def write_node(self, target_path: str, subdirectory: str, payload: str): @@ -575,6 +576,11 @@ class ModelNode(CompiledNode): resource_type: NodeType = field(metadata={"restrict": [NodeType.Model]}) access: AccessType = AccessType.Protected + def to_msg(self): + msg = super().to_msg() + msg.access = self.access + return msg + # TODO: this node type should probably be removed when the rpc server is no longer supported @dataclass diff --git a/core/dbt/contracts/graph/proto_nodes.py b/core/dbt/contracts/graph/proto_nodes.py index 8886d108c79..9689e8b3494 100644 --- a/core/dbt/contracts/graph/proto_nodes.py +++ b/core/dbt/contracts/graph/proto_nodes.py @@ -16,10 +16,17 @@ class ListOfStrings(betterproto.Message): value: List[str] = betterproto.string_field(1) +@dataclass(eq=False, repr=False) +class Hook(betterproto.Message): + sql: str = betterproto.string_field(1) + transaction: bool = betterproto.bool_field(2) + index: Optional[int] = betterproto.int32_field(3, optional=True, group="_index") + + @dataclass(eq=False, repr=False) class Docs(betterproto.Message): show: bool = betterproto.bool_field(1) - node_color: str = betterproto.string_field(2) + node_color: Optional[str] = betterproto.string_field(2, optional=True, group="_node_color") @dataclass(eq=False, repr=False) @@ -99,11 +106,11 @@ class NodeConfig(betterproto.Message): persist_docs: Dict[str, str] = betterproto.map_field( 9, betterproto.TYPE_STRING, betterproto.TYPE_STRING ) + post_hook: "Hook" = betterproto.message_field(10) + pre_hook: "Hook" = betterproto.message_field(11) quoting: Dict[str, str] = betterproto.map_field( 12, betterproto.TYPE_STRING, betterproto.TYPE_STRING ) - """post_hook = 10; pre_hook = 11;""" - column_types: Dict[str, str] = betterproto.map_field( 13, betterproto.TYPE_STRING, betterproto.TYPE_STRING ) @@ -244,7 +251,7 @@ class ColumnInfo(betterproto.Message): meta: Dict[str, str] = betterproto.map_field( 3, betterproto.TYPE_STRING, betterproto.TYPE_STRING ) - data_type: str = betterproto.string_field(4) + data_type: Optional[str] = betterproto.string_field(4, optional=True, group="_data_type") quote: Optional[bool] = betterproto.bool_field(5, optional=True, group="_quote") tags: List[str] = betterproto.string_field(6) extra: Dict[str, str] = betterproto.map_field( @@ -296,11 +303,14 @@ class ModelNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) + access: str = betterproto.string_field(31) @dataclass(eq=False, repr=False) class AnalysisNode(betterproto.Message): - """This should be exactly the same as ModelNode""" + """This should be exactly the same as ModelNode w/o access""" name: str = betterproto.string_field(1) resource_type: str = betterproto.string_field(2) @@ -336,11 +346,13 @@ class AnalysisNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) @dataclass(eq=False, repr=False) class RPCNode(betterproto.Message): - """This should be exactly the same as ModelNode""" + """This should be exactly the same as ModelNode w/o access""" name: str = betterproto.string_field(1) resource_type: str = betterproto.string_field(2) @@ -376,11 +388,13 @@ class RPCNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) @dataclass(eq=False, repr=False) class SqlNode(betterproto.Message): - """This should be exactly the same as ModelNode""" + """This should be exactly the same as ModelNode w/o access""" name: str = betterproto.string_field(1) resource_type: str = betterproto.string_field(2) @@ -416,12 +430,15 @@ class SqlNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) @dataclass(eq=False, repr=False) class HookNode(betterproto.Message): """ - This should be the same as ModelNode plus additional "index" attribute + This should be the same as ModelNode (w/o access) plus additional "index" + attribute """ name: str = betterproto.string_field(1) @@ -458,7 +475,9 @@ class HookNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) - index: Optional[int] = betterproto.int32_field(29, optional=True, group="_index") + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) + index: Optional[int] = betterproto.int32_field(31, optional=True, group="_index") @dataclass(eq=False, repr=False) @@ -491,11 +510,12 @@ class SeedNode(betterproto.Message): relation_name: str = betterproto.string_field(20) raw_code: str = betterproto.string_field(21) root_path: str = betterproto.string_field(22) + group: str = betterproto.string_field(23) @dataclass(eq=False, repr=False) class SingularTestNode(betterproto.Message): - """Same as ModelNode except config is TestConfig""" + """Same as ModelNode w/o access except config is TestConfig""" name: str = betterproto.string_field(1) resource_type: str = betterproto.string_field(2) @@ -531,6 +551,8 @@ class SingularTestNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) @dataclass(eq=False, repr=False) @@ -545,8 +567,8 @@ class TestMetadata(betterproto.Message): @dataclass(eq=False, repr=False) class GenericTestNode(betterproto.Message): """ - Same as ModelNode except config is TestConfig, and has test_metadata and - column_name attributes. + Same as ModelNode w/o access except config is TestConfig, and has + test_metadata and column_name attributes. """ name: str = betterproto.string_field(1) @@ -583,13 +605,17 @@ class GenericTestNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) - test_metadata: "TestMetadata" = betterproto.message_field(29) - column_name: Optional[str] = betterproto.string_field(30, optional=True, group="_column_name") + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) + test_metadata: "TestMetadata" = betterproto.message_field(31) + column_name: Optional[str] = betterproto.string_field(32, optional=True, group="_column_name") @dataclass(eq=False, repr=False) class SnapshotNode(betterproto.Message): - """SnapshotNode - Sames as ModelNode except with SnapshotConfig""" + """ + SnapshotNode - Sames as ModelNode w/o access except with SnapshotConfig + """ name: str = betterproto.string_field(1) resource_type: str = betterproto.string_field(2) @@ -625,6 +651,8 @@ class SnapshotNode(betterproto.Message): depends_on: "DependsOn" = betterproto.message_field(26) compiled: bool = betterproto.bool_field(27) compiled_code: str = betterproto.string_field(28) + contract: bool = betterproto.bool_field(29) + group: str = betterproto.string_field(30) @dataclass(eq=False, repr=False) @@ -770,3 +798,4 @@ class Metric(betterproto.Message): sources: List["ListOfStrings"] = betterproto.message_field(25) metrics: List["ListOfStrings"] = betterproto.message_field(26) depends_on: "DependsOn" = betterproto.message_field(27) + group: str = betterproto.string_field(28) diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index 9c94715d813..493bd8d5e13 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -466,7 +466,7 @@ class Owner(AdditionalPropertiesAllowed, Replaceable): name: Optional[str] = None def to_msg(self): - return proto_nodes.ExposureOwner( + return proto_nodes.Owner( email=self.email, name=self.name, ) diff --git a/tests/unit/test_proto_nodes.py b/tests/unit/test_proto_nodes.py index ce5d9e33e62..4f2d500d834 100644 --- a/tests/unit/test_proto_nodes.py +++ b/tests/unit/test_proto_nodes.py @@ -24,7 +24,7 @@ ExposureConfig, MetricConfig, ) -from dbt.contracts.graph.unparsed import ExposureOwner, MetricFilter +from dbt.contracts.graph.unparsed import Owner, MetricFilter from dbt.node_types import NodeType, ModelLanguage from dbt.contracts.files import FileHash @@ -348,7 +348,7 @@ def test_nodes(): fqn=["my", "exposure"], config=ExposureConfig(enabled=True), type="dashboard", - owner=ExposureOwner(email="someone@somewhere"), + owner=Owner(email="someone@somewhere"), description="my exposure", ) proto_exposure_msg = exposure.to_msg() From 12997e483a6851c48f645aaf714833eb960e1da3 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Mon, 27 Feb 2023 18:13:43 -0500 Subject: [PATCH 4/8] Run new version of betterproto on events --- core/dbt/events/README.md | 3 + core/dbt/events/proto_types.py | 829 +++++++++++++++++---------------- core/dbt/events/types.py | 2 +- core/dbt/parser/schemas.py | 4 +- tests/unit/test_events.py | 2 +- 5 files changed, 423 insertions(+), 417 deletions(-) diff --git a/core/dbt/events/README.md b/core/dbt/events/README.md index 28ff5005c3f..d22453c0b84 100644 --- a/core/dbt/events/README.md +++ b/core/dbt/events/README.md @@ -53,5 +53,8 @@ logger = AdapterLogger("") After adding a new message in types.proto, in the core/dbt/events directory: ```protoc --python_betterproto_out . types.proto``` After switching to the 2.0.0b5 release of betterproto, there is now a bug where it generates incorrectly named python classes when the names have acronyms like SQL or YAML in them. For now, I'm renaming these. The bug has been fixed in the repo, so hopefully there will be a new release at some point. (SQL, YAML, GET get turned int Sql, Yaml, Get). + A search and replace s/Sql/SQL/g and s/Yaml/YAML/g, GetRequest/GETRequest, GetResponse/GETResponse should clean it up. + +In addition it now changes "@dataclass" to "@dataclass(eq=False, repr=False)" In addition, betterproto now puts the generated file in proto_types/__init__.py. I'm moving it to proto_types.py diff --git a/core/dbt/events/proto_types.py b/core/dbt/events/proto_types.py index bd6610f0d6d..8e9da80e27f 100644 --- a/core/dbt/events/proto_types.py +++ b/core/dbt/events/proto_types.py @@ -3,12 +3,15 @@ # plugin: python-betterproto from dataclasses import dataclass from datetime import datetime -from typing import Dict, List +from typing import ( + Dict, + List, +) import betterproto -@dataclass +@dataclass(eq=False, repr=False) class EventInfo(betterproto.Message): """Common event info""" @@ -26,7 +29,7 @@ class EventInfo(betterproto.Message): category: str = betterproto.string_field(10) -@dataclass +@dataclass(eq=False, repr=False) class TimingInfoMsg(betterproto.Message): """TimingInfo""" @@ -35,7 +38,7 @@ class TimingInfoMsg(betterproto.Message): completed_at: datetime = betterproto.message_field(3) -@dataclass +@dataclass(eq=False, repr=False) class NodeInfo(betterproto.Message): """NodeInfo""" @@ -52,7 +55,7 @@ class NodeInfo(betterproto.Message): ) -@dataclass +@dataclass(eq=False, repr=False) class RunResultMsg(betterproto.Message): """RunResult""" @@ -67,7 +70,7 @@ class RunResultMsg(betterproto.Message): num_failures: int = betterproto.int32_field(7) -@dataclass +@dataclass(eq=False, repr=False) class ReferenceKeyMsg(betterproto.Message): """ReferenceKey""" @@ -76,21 +79,21 @@ class ReferenceKeyMsg(betterproto.Message): identifier: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ListOfStrings(betterproto.Message): """ListOfStrings""" value: List[str] = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GenericMessage(betterproto.Message): """GenericMessage, used for deserializing only""" info: "EventInfo" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MainReportVersion(betterproto.Message): """A001""" @@ -98,13 +101,13 @@ class MainReportVersion(betterproto.Message): log_version: int = betterproto.int32_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainReportVersionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainReportVersion" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainReportArgs(betterproto.Message): """A002""" @@ -113,26 +116,26 @@ class MainReportArgs(betterproto.Message): ) -@dataclass +@dataclass(eq=False, repr=False) class MainReportArgsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainReportArgs" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainTrackingUserState(betterproto.Message): """A003""" user_state: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MainTrackingUserStateMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainTrackingUserState" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MergedFromState(betterproto.Message): """A004""" @@ -140,13 +143,13 @@ class MergedFromState(betterproto.Message): sample: List[str] = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MergedFromStateMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MergedFromState" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MissingProfileTarget(betterproto.Message): """A005""" @@ -154,39 +157,39 @@ class MissingProfileTarget(betterproto.Message): target_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MissingProfileTargetMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MissingProfileTarget" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InvalidOptionYAML(betterproto.Message): """A008""" option_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class InvalidOptionYAMLMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InvalidOptionYAML" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogDbtProjectError(betterproto.Message): """A009""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class LogDbtProjectErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogDbtProjectError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogDbtProfileError(betterproto.Message): """A011""" @@ -194,52 +197,52 @@ class LogDbtProfileError(betterproto.Message): profiles: List[str] = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogDbtProfileErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogDbtProfileError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class StarterProjectPath(betterproto.Message): """A017""" dir: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class StarterProjectPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "StarterProjectPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfigFolderDirectory(betterproto.Message): """A018""" dir: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ConfigFolderDirectoryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConfigFolderDirectory" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NoSampleProfileFound(betterproto.Message): """A019""" adapter: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NoSampleProfileFoundMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NoSampleProfileFound" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithSample(betterproto.Message): """A020""" @@ -247,13 +250,13 @@ class ProfileWrittenWithSample(betterproto.Message): path: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithSampleMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProfileWrittenWithSample" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithTargetTemplateYAML(betterproto.Message): """A021""" @@ -261,13 +264,13 @@ class ProfileWrittenWithTargetTemplateYAML(betterproto.Message): path: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithTargetTemplateYAMLMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProfileWrittenWithTargetTemplateYAML" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithProjectTemplateYAML(betterproto.Message): """A022""" @@ -275,52 +278,52 @@ class ProfileWrittenWithProjectTemplateYAML(betterproto.Message): path: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProfileWrittenWithProjectTemplateYAMLMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProfileWrittenWithProjectTemplateYAML" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SettingUpProfile(betterproto.Message): """A023""" pass -@dataclass +@dataclass(eq=False, repr=False) class SettingUpProfileMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SettingUpProfile" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InvalidProfileTemplateYAML(betterproto.Message): """A024""" pass -@dataclass +@dataclass(eq=False, repr=False) class InvalidProfileTemplateYAMLMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InvalidProfileTemplateYAML" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProjectNameAlreadyExists(betterproto.Message): """A025""" name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ProjectNameAlreadyExistsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProjectNameAlreadyExists" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProjectCreated(betterproto.Message): """A026""" @@ -329,13 +332,13 @@ class ProjectCreated(betterproto.Message): slack_url: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ProjectCreatedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProjectCreated" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PackageRedirectDeprecation(betterproto.Message): """D001""" @@ -343,26 +346,26 @@ class PackageRedirectDeprecation(betterproto.Message): new_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PackageRedirectDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PackageRedirectDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PackageInstallPathDeprecation(betterproto.Message): """D002""" pass -@dataclass +@dataclass(eq=False, repr=False) class PackageInstallPathDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PackageInstallPathDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfigSourcePathDeprecation(betterproto.Message): """D003""" @@ -370,13 +373,13 @@ class ConfigSourcePathDeprecation(betterproto.Message): exp_path: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfigSourcePathDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConfigSourcePathDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfigDataPathDeprecation(betterproto.Message): """D004""" @@ -384,13 +387,13 @@ class ConfigDataPathDeprecation(betterproto.Message): exp_path: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfigDataPathDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConfigDataPathDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterDeprecationWarning(betterproto.Message): """D005""" @@ -398,39 +401,39 @@ class AdapterDeprecationWarning(betterproto.Message): new_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterDeprecationWarningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterDeprecationWarning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MetricAttributesRenamed(betterproto.Message): """D006""" metric_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MetricAttributesRenamedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MetricAttributesRenamed" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ExposureNameDeprecation(betterproto.Message): """D007""" exposure: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ExposureNameDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ExposureNameDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InternalDeprecation(betterproto.Message): """D008""" @@ -440,13 +443,13 @@ class InternalDeprecation(betterproto.Message): version: str = betterproto.string_field(4) -@dataclass +@dataclass(eq=False, repr=False) class InternalDeprecationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InternalDeprecation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventDebug(betterproto.Message): """E001""" @@ -456,13 +459,13 @@ class AdapterEventDebug(betterproto.Message): args: List[str] = betterproto.string_field(4) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventDebugMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterEventDebug" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventInfo(betterproto.Message): """E002""" @@ -472,13 +475,13 @@ class AdapterEventInfo(betterproto.Message): args: List[str] = betterproto.string_field(4) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterEventInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventWarning(betterproto.Message): """E003""" @@ -488,13 +491,13 @@ class AdapterEventWarning(betterproto.Message): args: List[str] = betterproto.string_field(4) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventWarningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterEventWarning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventError(betterproto.Message): """E004""" @@ -505,13 +508,13 @@ class AdapterEventError(betterproto.Message): exc_info: str = betterproto.string_field(5) -@dataclass +@dataclass(eq=False, repr=False) class AdapterEventErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterEventError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NewConnection(betterproto.Message): """E005""" @@ -520,13 +523,13 @@ class NewConnection(betterproto.Message): conn_name: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class NewConnectionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NewConnection" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionReused(betterproto.Message): """E006""" @@ -534,39 +537,39 @@ class ConnectionReused(betterproto.Message): orig_conn_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionReusedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionReused" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionLeftOpenInCleanup(betterproto.Message): """E007""" conn_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionLeftOpenInCleanupMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionLeftOpen" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionClosedInCleanup(betterproto.Message): """E008""" conn_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionClosedInCleanupMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionClosedInCleanup" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RollbackFailed(betterproto.Message): """E009""" @@ -575,13 +578,13 @@ class RollbackFailed(betterproto.Message): exc_info: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class RollbackFailedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RollbackFailed" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionClosed(betterproto.Message): """E010""" @@ -589,13 +592,13 @@ class ConnectionClosed(betterproto.Message): conn_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionClosedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionClosed" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionLeftOpen(betterproto.Message): """E011""" @@ -603,13 +606,13 @@ class ConnectionLeftOpen(betterproto.Message): conn_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionLeftOpenMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionLeftOpen" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class Rollback(betterproto.Message): """E012""" @@ -617,13 +620,13 @@ class Rollback(betterproto.Message): conn_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RollbackMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "Rollback" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CacheMiss(betterproto.Message): """E013""" @@ -632,13 +635,13 @@ class CacheMiss(betterproto.Message): schema: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class CacheMissMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CacheMiss" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ListRelations(betterproto.Message): """E014""" @@ -647,13 +650,13 @@ class ListRelations(betterproto.Message): relations: List["ReferenceKeyMsg"] = betterproto.message_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ListRelationsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ListRelations" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionUsed(betterproto.Message): """E015""" @@ -662,13 +665,13 @@ class ConnectionUsed(betterproto.Message): conn_name: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ConnectionUsedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConnectionUsed" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLQuery(betterproto.Message): """E016""" @@ -677,13 +680,13 @@ class SQLQuery(betterproto.Message): sql: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class SQLQueryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SQLQuery" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLQueryStatus(betterproto.Message): """E017""" @@ -692,13 +695,13 @@ class SQLQueryStatus(betterproto.Message): elapsed: float = betterproto.float_field(3) -@dataclass +@dataclass(eq=False, repr=False) class SQLQueryStatusMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SQLQueryStatus" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLCommit(betterproto.Message): """E018""" @@ -706,13 +709,13 @@ class SQLCommit(betterproto.Message): conn_name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLCommitMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SQLCommit" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ColTypeChange(betterproto.Message): """E019""" @@ -721,39 +724,39 @@ class ColTypeChange(betterproto.Message): table: "ReferenceKeyMsg" = betterproto.message_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ColTypeChangeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ColTypeChange" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SchemaCreation(betterproto.Message): """E020""" relation: "ReferenceKeyMsg" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SchemaCreationMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SchemaCreation" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SchemaDrop(betterproto.Message): """E021""" relation: "ReferenceKeyMsg" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SchemaDropMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SchemaDrop" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CacheAction(betterproto.Message): """E022""" @@ -764,13 +767,13 @@ class CacheAction(betterproto.Message): ref_list: List["ReferenceKeyMsg"] = betterproto.message_field(5) -@dataclass +@dataclass(eq=False, repr=False) class CacheActionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CacheAction" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CacheDumpGraph(betterproto.Message): """E031""" @@ -781,39 +784,39 @@ class CacheDumpGraph(betterproto.Message): action: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class CacheDumpGraphMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CacheDumpGraph" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AdapterImportError(betterproto.Message): """E035""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class AdapterImportErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AdapterImportError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PluginLoadError(betterproto.Message): """E036""" exc_info: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class PluginLoadErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PluginLoadError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NewConnectionOpening(betterproto.Message): """E037""" @@ -821,13 +824,13 @@ class NewConnectionOpening(betterproto.Message): connection_state: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NewConnectionOpeningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NewConnectionOpening" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CodeExecution(betterproto.Message): """E038""" @@ -835,13 +838,13 @@ class CodeExecution(betterproto.Message): code_content: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CodeExecutionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CodeExecution" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CodeExecutionStatus(betterproto.Message): """E039""" @@ -849,91 +852,91 @@ class CodeExecutionStatus(betterproto.Message): elapsed: float = betterproto.float_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CodeExecutionStatusMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CodeExecutionStatus" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CatalogGenerationError(betterproto.Message): """E040""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class CatalogGenerationErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CatalogGenerationError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class WriteCatalogFailure(betterproto.Message): """E041""" num_exceptions: int = betterproto.int32_field(1) -@dataclass +@dataclass(eq=False, repr=False) class WriteCatalogFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "WriteCatalogFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CatalogWritten(betterproto.Message): """E042""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class CatalogWrittenMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CatalogWritten" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CannotGenerateDocs(betterproto.Message): """E043""" pass -@dataclass +@dataclass(eq=False, repr=False) class CannotGenerateDocsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CannotGenerateDocs" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class BuildingCatalog(betterproto.Message): """E044""" pass -@dataclass +@dataclass(eq=False, repr=False) class BuildingCatalogMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "BuildingCatalog" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DatabaseErrorRunningHook(betterproto.Message): """E045""" hook_type: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DatabaseErrorRunningHookMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DatabaseErrorRunningHook" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class HooksRunning(betterproto.Message): """E046""" @@ -941,13 +944,13 @@ class HooksRunning(betterproto.Message): hook_type: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class HooksRunningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "HooksRunning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FinishedRunningStats(betterproto.Message): """E047""" @@ -956,13 +959,13 @@ class FinishedRunningStats(betterproto.Message): execution_time: float = betterproto.float_field(3) -@dataclass +@dataclass(eq=False, repr=False) class FinishedRunningStatsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FinishedRunningStats" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InvalidValueForField(betterproto.Message): """I008""" @@ -970,13 +973,13 @@ class InvalidValueForField(betterproto.Message): field_value: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InvalidValueForFieldMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InvalidValueForField" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ValidationWarning(betterproto.Message): """I009""" @@ -985,65 +988,65 @@ class ValidationWarning(betterproto.Message): node_name: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ValidationWarningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ValidationWarning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ParsePerfInfoPath(betterproto.Message): """I010""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ParsePerfInfoPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ParsePerfInfoPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GenericTestFileParse(betterproto.Message): """I011""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GenericTestFileParseMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GenericTestFileParse" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MacroFileParse(betterproto.Message): """I012""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MacroFileParseMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MacroFileParse" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingErrorProcessingFile(betterproto.Message): """I014""" file: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingErrorProcessingFileMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingErrorProcessingFile" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingError(betterproto.Message): """I016""" @@ -1052,39 +1055,39 @@ class PartialParsingError(betterproto.Message): ) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingSkipParsing(betterproto.Message): """I017""" pass -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingSkipParsingMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingSkipParsing" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class UnableToPartialParse(betterproto.Message): """I024""" reason: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class UnableToPartialParseMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "UnableToPartialParse" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class StateCheckVarsHash(betterproto.Message): """I025""" @@ -1095,26 +1098,26 @@ class StateCheckVarsHash(betterproto.Message): version: str = betterproto.string_field(5) -@dataclass +@dataclass(eq=False, repr=False) class StateCheckVarsHashMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "StateCheckVarsHash" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingNotEnabled(betterproto.Message): """I028""" pass -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingNotEnabledMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingNotEnabled" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ParsedFileLoadFailed(betterproto.Message): """I029""" @@ -1123,13 +1126,13 @@ class ParsedFileLoadFailed(betterproto.Message): exc_info: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ParsedFileLoadFailedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ParsedFileLoadFailed" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingEnabled(betterproto.Message): """I040""" @@ -1138,13 +1141,13 @@ class PartialParsingEnabled(betterproto.Message): changed: int = betterproto.int32_field(3) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingEnabledMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingEnabled" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingFile(betterproto.Message): """I041""" @@ -1152,13 +1155,13 @@ class PartialParsingFile(betterproto.Message): operation: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class PartialParsingFileMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "PartialParsingFile" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InvalidDisabledTargetInTestNode(betterproto.Message): """I050""" @@ -1170,26 +1173,26 @@ class InvalidDisabledTargetInTestNode(betterproto.Message): target_package: str = betterproto.string_field(6) -@dataclass +@dataclass(eq=False, repr=False) class InvalidDisabledTargetInTestNodeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InvalidDisabledTargetInTestNode" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class UnusedResourceConfigPath(betterproto.Message): """I051""" unused_config_paths: List[str] = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class UnusedResourceConfigPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "UnusedResourceConfigPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedIncreased(betterproto.Message): """I052""" @@ -1197,13 +1200,13 @@ class SeedIncreased(betterproto.Message): name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedIncreasedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SeedIncreased" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitSamePath(betterproto.Message): """I053""" @@ -1211,13 +1214,13 @@ class SeedExceedsLimitSamePath(betterproto.Message): name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitSamePathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SeedExceedsLimitSamePath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitAndPathChanged(betterproto.Message): """I054""" @@ -1225,13 +1228,13 @@ class SeedExceedsLimitAndPathChanged(betterproto.Message): name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitAndPathChangedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SeedExceedsLimitAndPathChanged" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitChecksumChanged(betterproto.Message): """I055""" @@ -1240,26 +1243,26 @@ class SeedExceedsLimitChecksumChanged(betterproto.Message): checksum_name: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class SeedExceedsLimitChecksumChangedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SeedExceedsLimitChecksumChanged" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class UnusedTables(betterproto.Message): """I056""" unused_tables: List[str] = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class UnusedTablesMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "UnusedTables" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class WrongResourceSchemaFile(betterproto.Message): """I057""" @@ -1270,14 +1273,14 @@ class WrongResourceSchemaFile(betterproto.Message): file_path: str = betterproto.string_field(5) -@dataclass +@dataclass(eq=False, repr=False) class WrongResourceSchemaFileMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "WrongResourceSchemaFile" = betterproto.message_field(2) -@dataclass -class NoNodeForYamlKey(betterproto.Message): +@dataclass(eq=False, repr=False) +class NoNodeForYAMLKey(betterproto.Message): """I058""" patch_name: str = betterproto.string_field(1) @@ -1285,26 +1288,26 @@ class NoNodeForYamlKey(betterproto.Message): file_path: str = betterproto.string_field(3) -@dataclass -class NoNodeForYamlKeyMsg(betterproto.Message): +@dataclass(eq=False, repr=False) +class NoNodeForYAMLKeyMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) - data: "NoNodeForYamlKey" = betterproto.message_field(2) + data: "NoNodeForYAMLKey" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MacroNotFoundForPatch(betterproto.Message): """I059""" patch_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MacroNotFoundForPatchMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MacroNotFoundForPatch" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeNotFoundOrDisabled(betterproto.Message): """I060""" @@ -1317,13 +1320,13 @@ class NodeNotFoundOrDisabled(betterproto.Message): disabled: str = betterproto.string_field(7) -@dataclass +@dataclass(eq=False, repr=False) class NodeNotFoundOrDisabledMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeNotFoundOrDisabled" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogWarning(betterproto.Message): """I061""" @@ -1331,13 +1334,13 @@ class JinjaLogWarning(betterproto.Message): msg: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogWarningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "JinjaLogWarning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogInfo(betterproto.Message): """I062""" @@ -1345,13 +1348,13 @@ class JinjaLogInfo(betterproto.Message): msg: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "JinjaLogInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogDebug(betterproto.Message): """I063""" @@ -1359,78 +1362,78 @@ class JinjaLogDebug(betterproto.Message): msg: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class JinjaLogDebugMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "JinjaLogDebug" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitSparseCheckoutSubdirectory(betterproto.Message): """M001""" subdir: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitSparseCheckoutSubdirectoryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitSparseCheckoutSubdirectory" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressCheckoutRevision(betterproto.Message): """M002""" revision: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressCheckoutRevisionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitProgressCheckoutRevision" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressUpdatingExistingDependency(betterproto.Message): """M003""" dir: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressUpdatingExistingDependencyMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitProgressUpdatingExistingDependency" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressPullingNewDependency(betterproto.Message): """M004""" dir: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressPullingNewDependencyMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitProgressPullingNewDependency" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitNothingToDo(betterproto.Message): """M005""" sha: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitNothingToDoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitNothingToDo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressUpdatedCheckoutRange(betterproto.Message): """M006""" @@ -1438,39 +1441,39 @@ class GitProgressUpdatedCheckoutRange(betterproto.Message): end_sha: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressUpdatedCheckoutRangeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitProgressUpdatedCheckoutRange" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressCheckedOutAt(betterproto.Message): """M007""" end_sha: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class GitProgressCheckedOutAtMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GitProgressCheckedOutAt" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryProgressGETRequest(betterproto.Message): """M008""" url: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryProgressGETRequestMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryProgressGETRequest" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryProgressGETResponse(betterproto.Message): """M009""" @@ -1478,13 +1481,13 @@ class RegistryProgressGETResponse(betterproto.Message): resp_code: int = betterproto.int32_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryProgressGETResponseMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryProgressGETResponse" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SelectorReportInvalidSelector(betterproto.Message): """M010""" @@ -1493,104 +1496,104 @@ class SelectorReportInvalidSelector(betterproto.Message): raw_spec: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class SelectorReportInvalidSelectorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SelectorReportInvalidSelector" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsNoPackagesFound(betterproto.Message): """M013""" pass -@dataclass +@dataclass(eq=False, repr=False) class DepsNoPackagesFoundMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsNoPackagesFound" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsStartPackageInstall(betterproto.Message): """M014""" package_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsStartPackageInstallMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsStartPackageInstall" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsInstallInfo(betterproto.Message): """M015""" version_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsInstallInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsInstallInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsUpdateAvailable(betterproto.Message): """M016""" version_latest: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsUpdateAvailableMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsUpdateAvailable" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsUpToDate(betterproto.Message): """M017""" pass -@dataclass +@dataclass(eq=False, repr=False) class DepsUpToDateMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsUpToDate" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsListSubdirectory(betterproto.Message): """M018""" subdirectory: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsListSubdirectoryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsListSubdirectory" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsNotifyUpdatesAvailable(betterproto.Message): """M019""" packages: "ListOfStrings" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsNotifyUpdatesAvailableMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsNotifyUpdatesAvailable" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RetryExternalCall(betterproto.Message): """M020""" @@ -1598,39 +1601,39 @@ class RetryExternalCall(betterproto.Message): max: int = betterproto.int32_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RetryExternalCallMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RetryExternalCall" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RecordRetryException(betterproto.Message): """M021""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RecordRetryExceptionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RecordRetryException" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryIndexProgressGETRequest(betterproto.Message): """M022""" url: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryIndexProgressGETRequestMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryIndexProgressGETRequest" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryIndexProgressGETResponse(betterproto.Message): """M023""" @@ -1638,78 +1641,78 @@ class RegistryIndexProgressGETResponse(betterproto.Message): resp_code: int = betterproto.int32_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryIndexProgressGETResponseMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryIndexProgressGETResponse" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseUnexpectedType(betterproto.Message): """M024""" response: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseUnexpectedTypeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryResponseUnexpectedType" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseMissingTopKeys(betterproto.Message): """M025""" response: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseMissingTopKeysMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryResponseMissingTopKeys" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseMissingNestedKeys(betterproto.Message): """M026""" response: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseMissingNestedKeysMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryResponseMissingNestedKeys" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseExtraNestedKeys(betterproto.Message): """m027""" response: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RegistryResponseExtraNestedKeysMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RegistryResponseExtraNestedKeys" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsSetDownloadDirectory(betterproto.Message): """M028""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DepsSetDownloadDirectoryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsSetDownloadDirectory" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsUnpinned(betterproto.Message): """M029""" @@ -1717,78 +1720,78 @@ class DepsUnpinned(betterproto.Message): git: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsUnpinnedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsUnpinned" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NoNodesForSelectionCriteria(betterproto.Message): """M030""" spec_raw: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NoNodesForSelectionCriteriaMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NoNodesForSelectionCriteria" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunningOperationCaughtError(betterproto.Message): """Q001""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RunningOperationCaughtErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunningOperationCaughtError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CompileComplete(betterproto.Message): """Q002""" pass -@dataclass +@dataclass(eq=False, repr=False) class CompileCompleteMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CompileComplete" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FreshnessCheckComplete(betterproto.Message): """Q003""" pass -@dataclass +@dataclass(eq=False, repr=False) class FreshnessCheckCompleteMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FreshnessCheckComplete" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SeedHeader(betterproto.Message): """Q004""" header: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SeedHeaderMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SeedHeader" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLRunnerException(betterproto.Message): """Q006""" @@ -1796,13 +1799,13 @@ class SQLRunnerException(betterproto.Message): exc_info: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLRunnerExceptionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SQLRunnerException" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogTestResult(betterproto.Message): """Q007""" @@ -1815,13 +1818,13 @@ class LogTestResult(betterproto.Message): num_failures: int = betterproto.int32_field(7) -@dataclass +@dataclass(eq=False, repr=False) class LogTestResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogTestResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogStartLine(betterproto.Message): """Q011""" @@ -1831,13 +1834,13 @@ class LogStartLine(betterproto.Message): total: int = betterproto.int32_field(4) -@dataclass +@dataclass(eq=False, repr=False) class LogStartLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogStartLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogModelResult(betterproto.Message): """Q012""" @@ -1849,13 +1852,13 @@ class LogModelResult(betterproto.Message): execution_time: float = betterproto.float_field(6) -@dataclass +@dataclass(eq=False, repr=False) class LogModelResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogModelResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogSnapshotResult(betterproto.Message): """Q015""" @@ -1870,13 +1873,13 @@ class LogSnapshotResult(betterproto.Message): ) -@dataclass +@dataclass(eq=False, repr=False) class LogSnapshotResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogSnapshotResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogSeedResult(betterproto.Message): """Q016""" @@ -1890,13 +1893,13 @@ class LogSeedResult(betterproto.Message): relation: str = betterproto.string_field(8) -@dataclass +@dataclass(eq=False, repr=False) class LogSeedResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogSeedResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogFreshnessResult(betterproto.Message): """Q018""" @@ -1909,52 +1912,52 @@ class LogFreshnessResult(betterproto.Message): table_name: str = betterproto.string_field(7) -@dataclass +@dataclass(eq=False, repr=False) class LogFreshnessResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogFreshnessResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogCancelLine(betterproto.Message): """Q022""" conn_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class LogCancelLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogCancelLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DefaultSelector(betterproto.Message): """Q023""" name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DefaultSelectorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DefaultSelector" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeStart(betterproto.Message): """Q024""" node_info: "NodeInfo" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NodeStartMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeStart" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeFinished(betterproto.Message): """Q025""" @@ -1962,26 +1965,26 @@ class NodeFinished(betterproto.Message): run_result: "RunResultMsg" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeFinishedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeFinished" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class QueryCancelationUnsupported(betterproto.Message): """Q026""" type: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class QueryCancelationUnsupportedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "QueryCancelationUnsupported" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConcurrencyLine(betterproto.Message): """Q027""" @@ -1990,52 +1993,52 @@ class ConcurrencyLine(betterproto.Message): node_count: int = betterproto.int32_field(3) -@dataclass +@dataclass(eq=False, repr=False) class ConcurrencyLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConcurrencyLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class WritingInjectedSQLForNode(betterproto.Message): """Q029""" node_info: "NodeInfo" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class WritingInjectedSQLForNodeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "WritingInjectedSQLForNode" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeCompiling(betterproto.Message): """Q030""" node_info: "NodeInfo" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NodeCompilingMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeCompiling" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeExecuting(betterproto.Message): """Q031""" node_info: "NodeInfo" = betterproto.message_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NodeExecutingMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeExecuting" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogHookStartLine(betterproto.Message): """Q032""" @@ -2045,13 +2048,13 @@ class LogHookStartLine(betterproto.Message): total: int = betterproto.int32_field(4) -@dataclass +@dataclass(eq=False, repr=False) class LogHookStartLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogHookStartLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogHookEndLine(betterproto.Message): """Q033""" @@ -2063,13 +2066,13 @@ class LogHookEndLine(betterproto.Message): execution_time: float = betterproto.float_field(6) -@dataclass +@dataclass(eq=False, repr=False) class LogHookEndLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogHookEndLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SkippingDetails(betterproto.Message): """Q034""" @@ -2081,39 +2084,39 @@ class SkippingDetails(betterproto.Message): total: int = betterproto.int32_field(6) -@dataclass +@dataclass(eq=False, repr=False) class SkippingDetailsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SkippingDetails" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NothingToDo(betterproto.Message): """Q035""" pass -@dataclass +@dataclass(eq=False, repr=False) class NothingToDoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NothingToDo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunningOperationUncaughtError(betterproto.Message): """Q036""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RunningOperationUncaughtErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunningOperationUncaughtError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class EndRunResult(betterproto.Message): """Q037""" @@ -2123,26 +2126,26 @@ class EndRunResult(betterproto.Message): success: bool = betterproto.bool_field(4) -@dataclass +@dataclass(eq=False, repr=False) class EndRunResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "EndRunResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NoNodesSelected(betterproto.Message): """Q038""" pass -@dataclass +@dataclass(eq=False, repr=False) class NoNodesSelectedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NoNodesSelected" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CatchableExceptionOnRun(betterproto.Message): """W002""" @@ -2151,13 +2154,13 @@ class CatchableExceptionOnRun(betterproto.Message): exc_info: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class CatchableExceptionOnRunMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CatchableExceptionOnRun" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InternalErrorOnRun(betterproto.Message): """W003""" @@ -2165,13 +2168,13 @@ class InternalErrorOnRun(betterproto.Message): exc: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class InternalErrorOnRunMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "InternalErrorOnRun" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class GenericExceptionOnRun(betterproto.Message): """W004""" @@ -2180,13 +2183,13 @@ class GenericExceptionOnRun(betterproto.Message): exc: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class GenericExceptionOnRunMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "GenericExceptionOnRun" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class NodeConnectionReleaseError(betterproto.Message): """W005""" @@ -2195,78 +2198,78 @@ class NodeConnectionReleaseError(betterproto.Message): exc_info: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class NodeConnectionReleaseErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "NodeConnectionReleaseError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FoundStats(betterproto.Message): """W006""" stat_line: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class FoundStatsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FoundStats" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainKeyboardInterrupt(betterproto.Message): """Z001""" pass -@dataclass +@dataclass(eq=False, repr=False) class MainKeyboardInterruptMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainKeyboardInterrupt" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainEncounteredError(betterproto.Message): """Z002""" exc: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MainEncounteredErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainEncounteredError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class MainStackTrace(betterproto.Message): """Z003""" stack_trace: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class MainStackTraceMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "MainStackTrace" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemErrorRetrievingModTime(betterproto.Message): """Z004""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SystemErrorRetrievingModTimeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemErrorRetrievingModTime" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemCouldNotWrite(betterproto.Message): """Z005""" @@ -2275,65 +2278,65 @@ class SystemCouldNotWrite(betterproto.Message): exc: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class SystemCouldNotWriteMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemCouldNotWrite" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemExecutingCmd(betterproto.Message): """Z006""" cmd: List[str] = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SystemExecutingCmdMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemExecutingCmd" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemStdOut(betterproto.Message): """Z007""" bmsg: bytes = betterproto.bytes_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SystemStdOutMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemStdOut" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemStdErr(betterproto.Message): """Z008""" bmsg: bytes = betterproto.bytes_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SystemStdErrMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemStdErr" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SystemReportReturnCode(betterproto.Message): """Z009""" returncode: int = betterproto.int32_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SystemReportReturnCodeMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SystemReportReturnCode" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class TimingInfoCollected(betterproto.Message): """Z010""" @@ -2341,78 +2344,78 @@ class TimingInfoCollected(betterproto.Message): timing_info: "TimingInfoMsg" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class TimingInfoCollectedMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "TimingInfoCollected" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogDebugStackTrace(betterproto.Message): """Z011""" exc_info: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class LogDebugStackTraceMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogDebugStackTrace" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CheckCleanPath(betterproto.Message): """Z012""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class CheckCleanPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CheckCleanPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ConfirmCleanPath(betterproto.Message): """Z013""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ConfirmCleanPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ConfirmCleanPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ProtectedCleanPath(betterproto.Message): """Z014""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ProtectedCleanPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ProtectedCleanPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FinishedCleanPaths(betterproto.Message): """Z015""" pass -@dataclass +@dataclass(eq=False, repr=False) class FinishedCleanPathsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FinishedCleanPaths" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class OpenCommand(betterproto.Message): """Z016""" @@ -2420,26 +2423,26 @@ class OpenCommand(betterproto.Message): profiles_dir: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class OpenCommandMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "OpenCommand" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class Formatting(betterproto.Message): """Z017""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class FormattingMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "Formatting" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsPort(betterproto.Message): """Z018""" @@ -2447,39 +2450,39 @@ class ServingDocsPort(betterproto.Message): port: int = betterproto.int32_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsPortMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ServingDocsPort" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsAccessInfo(betterproto.Message): """Z019""" port: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsAccessInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ServingDocsAccessInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsExitInfo(betterproto.Message): """Z020""" pass -@dataclass +@dataclass(eq=False, repr=False) class ServingDocsExitInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ServingDocsExitInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunResultWarning(betterproto.Message): """Z021""" @@ -2488,13 +2491,13 @@ class RunResultWarning(betterproto.Message): path: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class RunResultWarningMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunResultWarning" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunResultFailure(betterproto.Message): """Z022""" @@ -2503,13 +2506,13 @@ class RunResultFailure(betterproto.Message): path: str = betterproto.string_field(3) -@dataclass +@dataclass(eq=False, repr=False) class RunResultFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunResultFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class StatsLine(betterproto.Message): """Z023""" @@ -2518,91 +2521,91 @@ class StatsLine(betterproto.Message): ) -@dataclass +@dataclass(eq=False, repr=False) class StatsLineMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "StatsLine" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunResultError(betterproto.Message): """Z024""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RunResultErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunResultError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunResultErrorNoMessage(betterproto.Message): """Z025""" status: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RunResultErrorNoMessageMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunResultErrorNoMessage" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SQLCompiledPath(betterproto.Message): """Z026""" path: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SQLCompiledPathMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SQLCompiledPath" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class CheckNodeTestFailure(betterproto.Message): """Z027""" relation_name: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class CheckNodeTestFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "CheckNodeTestFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FirstRunResultError(betterproto.Message): """Z028""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class FirstRunResultErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FirstRunResultError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class AfterFirstRunResultError(betterproto.Message): """Z029""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class AfterFirstRunResultErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "AfterFirstRunResultError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class EndOfRunSummary(betterproto.Message): """Z030""" @@ -2611,13 +2614,13 @@ class EndOfRunSummary(betterproto.Message): keyboard_interrupt: bool = betterproto.bool_field(3) -@dataclass +@dataclass(eq=False, repr=False) class EndOfRunSummaryMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "EndOfRunSummary" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class LogSkipBecauseError(betterproto.Message): """Z034""" @@ -2627,267 +2630,267 @@ class LogSkipBecauseError(betterproto.Message): total: int = betterproto.int32_field(4) -@dataclass +@dataclass(eq=False, repr=False) class LogSkipBecauseErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "LogSkipBecauseError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class EnsureGitInstalled(betterproto.Message): """Z036""" pass -@dataclass +@dataclass(eq=False, repr=False) class EnsureGitInstalledMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "EnsureGitInstalled" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsCreatingLocalSymlink(betterproto.Message): """Z037""" pass -@dataclass +@dataclass(eq=False, repr=False) class DepsCreatingLocalSymlinkMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsCreatingLocalSymlink" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DepsSymlinkNotAvailable(betterproto.Message): """Z038""" pass -@dataclass +@dataclass(eq=False, repr=False) class DepsSymlinkNotAvailableMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DepsSymlinkNotAvailable" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DisableTracking(betterproto.Message): """Z039""" pass -@dataclass +@dataclass(eq=False, repr=False) class DisableTrackingMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DisableTracking" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SendingEvent(betterproto.Message): """Z040""" kwargs: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class SendingEventMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SendingEvent" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class SendEventFailure(betterproto.Message): """Z041""" pass -@dataclass +@dataclass(eq=False, repr=False) class SendEventFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "SendEventFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FlushEvents(betterproto.Message): """Z042""" pass -@dataclass +@dataclass(eq=False, repr=False) class FlushEventsMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FlushEvents" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class FlushEventsFailure(betterproto.Message): """Z043""" pass -@dataclass +@dataclass(eq=False, repr=False) class FlushEventsFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "FlushEventsFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class TrackingInitializeFailure(betterproto.Message): """Z044""" exc_info: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class TrackingInitializeFailureMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "TrackingInitializeFailure" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class RunResultWarningMessage(betterproto.Message): """Z046""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class RunResultWarningMessageMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "RunResultWarningMessage" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DebugCmdOut(betterproto.Message): """Z047""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DebugCmdOutMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DebugCmdOut" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class DebugCmdResult(betterproto.Message): """Z048""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class DebugCmdResultMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "DebugCmdResult" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class ListCmdOut(betterproto.Message): """Z049""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class ListCmdOutMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "ListCmdOut" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class Note(betterproto.Message): """Z050""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class NoteMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "Note" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestInfo(betterproto.Message): """T001""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "IntegrationTestInfo" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestDebug(betterproto.Message): """T002""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestDebugMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "IntegrationTestDebug" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestWarn(betterproto.Message): """T003""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestWarnMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "IntegrationTestWarn" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestError(betterproto.Message): """T004""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestErrorMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "IntegrationTestError" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestException(betterproto.Message): """T005""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class IntegrationTestExceptionMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "IntegrationTestException" = betterproto.message_field(2) -@dataclass +@dataclass(eq=False, repr=False) class UnitTestInfo(betterproto.Message): """T006""" msg: str = betterproto.string_field(1) -@dataclass +@dataclass(eq=False, repr=False) class UnitTestInfoMsg(betterproto.Message): info: "EventInfo" = betterproto.message_field(1) data: "UnitTestInfo" = betterproto.message_field(2) diff --git a/core/dbt/events/types.py b/core/dbt/events/types.py index 848a8d4b029..8ba19eb6aaf 100644 --- a/core/dbt/events/types.py +++ b/core/dbt/events/types.py @@ -1044,7 +1044,7 @@ def message(self) -> str: @dataclass -class NoNodeForYamlKey(WarnLevel, pt.NoNodeForYamlKey): +class NoNodeForYAMLKey(WarnLevel, pt.NoNodeForYAMLKey): def code(self): return "I058" diff --git a/core/dbt/parser/schemas.py b/core/dbt/parser/schemas.py index dac4895ccac..daf0205911f 100644 --- a/core/dbt/parser/schemas.py +++ b/core/dbt/parser/schemas.py @@ -71,7 +71,7 @@ YamlParseListError, ) from dbt.events.functions import warn_or_error -from dbt.events.types import WrongResourceSchemaFile, NoNodeForYamlKey, MacroNotFoundForPatch +from dbt.events.types import WrongResourceSchemaFile, NoNodeForYAMLKey, MacroNotFoundForPatch from dbt.node_types import NodeType from dbt.parser.base import SimpleParser from dbt.parser.search import FileBlock @@ -935,7 +935,7 @@ def parse_patch(self, block: TargetBlock[NodeTarget], refs: ParserRef) -> None: node.patch(patch) else: warn_or_error( - NoNodeForYamlKey( + NoNodeForYAMLKey( patch_name=patch.name, yaml_key=patch.yaml_key, file_path=source_file.path.original_file_path, diff --git a/tests/unit/test_events.py b/tests/unit/test_events.py index e70a095fa2b..99f78ae81cf 100644 --- a/tests/unit/test_events.py +++ b/tests/unit/test_events.py @@ -204,7 +204,7 @@ def test_event_codes(self): types.WrongResourceSchemaFile( patch_name="", resource_type="", file_path="", plural_resource_type="" ), - types.NoNodeForYamlKey(patch_name="", yaml_key="", file_path=""), + types.NoNodeForYAMLKey(patch_name="", yaml_key="", file_path=""), types.MacroNotFoundForPatch(patch_name=""), types.NodeNotFoundOrDisabled( original_file_path="", From dc0d229568a2af8a0789dcdea2a78c89c50692f2 Mon Sep 17 00:00:00 2001 From: Github Build Bot Date: Tue, 28 Feb 2023 16:55:21 +0000 Subject: [PATCH 5/8] Add generated CLI API docs --- .../docs/build/doctrees/environment.pickle | Bin 207878 -> 207878 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/core/dbt/docs/build/doctrees/environment.pickle b/core/dbt/docs/build/doctrees/environment.pickle index e74fd454bfbe01d569fdec9ec5fff1e057241603..c9247cc819e359beb6b1186579a186952774b84e 100644 GIT binary patch delta 32 mcmZp>!P9nwXG60*YfqinnT+NR`SuQZMj&R|-XYIi#{&S{atrhT delta 32 mcmZp>!P9nwXG60*tL2GVg?`N)^6ee+j6lq^y+fY4jt2nT9SiyZ From 3088de3fb29bf8a879ad03c5a02e4b309abc7b1c Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 28 Feb 2023 11:59:53 -0500 Subject: [PATCH 6/8] Add group to Metric node --- core/dbt/contracts/graph/nodes.py | 1 + tests/unit/test_proto_nodes.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index c729d6ee556..997f5e6fbbc 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -1280,6 +1280,7 @@ def msg_attributes(self): "sources", "metrics", "depends_on", + "group", ] def to_msg(self): diff --git a/tests/unit/test_proto_nodes.py b/tests/unit/test_proto_nodes.py index 4f2d500d834..8a332548e10 100644 --- a/tests/unit/test_proto_nodes.py +++ b/tests/unit/test_proto_nodes.py @@ -60,11 +60,13 @@ def test_nodes(): alias="my_node", checksum=FileHash.from_contents("select 1 from fun"), config=node_config, + group="analytics", ) assert model_node # Get a matching proto message proto_model_msg = model_node.to_msg() assert proto_model_msg + assert proto_model_msg.group == "analytics" # Create a dummy AnalysisNode analysis_node = AnalysisNode( @@ -372,7 +374,9 @@ def test_nodes(): filters=[MetricFilter(field="sum", operator="sum", value="sum")], time_grains=["day", "minute"], dimensions=["day", "minute"], + group="analytics", ) proto_metric_msg = metric.to_msg() assert proto_metric_msg assert proto_metric_msg.label + assert proto_metric_msg.group == "analytics" From a66075b55c76d29f3da42c0d2c737447e13010b4 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 28 Feb 2023 12:33:54 -0500 Subject: [PATCH 7/8] Update test for existence of manifest.json --- tests/functional/docs/test_generate.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/functional/docs/test_generate.py b/tests/functional/docs/test_generate.py index 566fb1a9912..2fd8c14b4b3 100644 --- a/tests/functional/docs/test_generate.py +++ b/tests/functional/docs/test_generate.py @@ -1,9 +1,18 @@ -import os +import pytest -from dbt.tests.util import run_dbt +from dbt.tests.util import run_dbt, get_manifest class TestGenerate: - def test_generate_no_manifest_on_no_compile(self, project): + @pytest.fixture(scope="class") + def models(self): + return {"my_model.sql": "select 1 as fun"} + + def test_manifest_not_compiled(self, project): run_dbt(["docs", "generate", "--no-compile"]) - assert not os.path.exists("./target/manifest.json") + # manifest.json is written out in parsing now, but it + # shouldn't be compiled because of the --no-compile flag + manifest = get_manifest(project.project_root) + model_id = "model.test.my_model" + assert model_id in manifest.nodes + assert manifest.nodes[model_id].compiled is False From 0466cc26ee2e94ec5284184f54a74a2477cace1f Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 28 Feb 2023 13:58:56 -0500 Subject: [PATCH 8/8] Move check of invalid groups earlier in parsing --- core/dbt/parser/manifest.py | 43 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index dbf86b92e34..aff86713d81 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -398,6 +398,7 @@ def load(self): self.process_refs(self.root_project.project_name) self.process_docs(self.root_project) self.process_metrics(self.root_project) + self.check_valid_group_config() # update tracking data self._perf_info.process_manifest_elapsed = time.perf_counter() - start_process @@ -988,6 +989,26 @@ def process_nodes(self): self.manifest.rebuild_ref_lookup() + def check_valid_group_config(self): + manifest = self.manifest + group_names = {group.name for group in manifest.groups.values()} + + for metric in manifest.metrics.values(): + self.check_valid_group_config_node(metric, group_names) + + for node in manifest.nodes.values(): + self.check_valid_group_config_node(node, group_names) + + def check_valid_group_config_node( + self, groupable_node: Union[Metric, ManifestNode], valid_group_names: Set[str] + ): + groupable_node_group = groupable_node.group + if groupable_node_group and groupable_node_group not in valid_group_names: + raise dbt.exceptions.ParsingError( + f"Invalid group '{groupable_node_group}', expected one of {sorted(list(valid_group_names))}", + node=groupable_node, + ) + def write_perf_info(self, target_path: str): path = os.path.join(target_path, PERF_INFO_FILE_NAME) write_file(path, json.dumps(self._perf_info, cls=dbt.utils.JSONEncoder, indent=4)) @@ -1067,27 +1088,6 @@ def _check_resource_uniqueness( alias_resources[full_node_name] = node -def _check_valid_group_config(manifest: Manifest): - group_names = {group.name for group in manifest.groups.values()} - - for metric in manifest.metrics.values(): - _check_valid_group_config_node(metric, group_names) - - for node in manifest.nodes.values(): - _check_valid_group_config_node(node, group_names) - - -def _check_valid_group_config_node( - groupable_node: Union[Metric, ManifestNode], valid_group_names: Set[str] -): - groupable_node_group = groupable_node.group - if groupable_node_group and groupable_node_group not in valid_group_names: - raise dbt.exceptions.ParsingError( - f"Invalid group '{groupable_node_group}', expected one of {sorted(list(valid_group_names))}", - node=groupable_node, - ) - - def _warn_for_unused_resource_config_paths(manifest: Manifest, config: RuntimeConfig) -> None: resource_fqns: Mapping[str, PathSet] = manifest.get_resource_fqns() disabled_fqns: PathSet = frozenset( @@ -1099,7 +1099,6 @@ def _warn_for_unused_resource_config_paths(manifest: Manifest, config: RuntimeCo def _check_manifest(manifest: Manifest, config: RuntimeConfig) -> None: _check_resource_uniqueness(manifest, config) _warn_for_unused_resource_config_paths(manifest, config) - _check_valid_group_config(manifest) def _get_node_column(node, column_name):