mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-19 09:51:27 +00:00
Compare commits
10 Commits
v1.6.13
...
test-docs-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
734b6429c7 | ||
|
|
a75b2c0a90 | ||
|
|
6b6ae22434 | ||
|
|
287f443ec9 | ||
|
|
aea2c4a29b | ||
|
|
21ffe31270 | ||
|
|
70c9074625 | ||
|
|
9fca33cb29 | ||
|
|
6360247d39 | ||
|
|
f0fbb0e551 |
@@ -7,7 +7,8 @@ from dbt.dataclass_schema import (
|
|||||||
ValidationError,
|
ValidationError,
|
||||||
register_pattern,
|
register_pattern,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.unparsed import AdditionalPropertiesAllowed
|
from dbt.contracts.graph.unparsed import AdditionalPropertiesAllowed, Docs
|
||||||
|
from dbt.contracts.graph.utils import validate_color
|
||||||
from dbt.exceptions import InternalException, CompilationException
|
from dbt.exceptions import InternalException, CompilationException
|
||||||
from dbt.contracts.util import Replaceable, list_str
|
from dbt.contracts.util import Replaceable, list_str
|
||||||
from dbt import hooks
|
from dbt import hooks
|
||||||
@@ -285,7 +286,7 @@ class BaseConfig(AdditionalPropertiesAllowed, Replaceable):
|
|||||||
# 'meta' moved here from node
|
# 'meta' moved here from node
|
||||||
mergebehavior = {
|
mergebehavior = {
|
||||||
"append": ["pre-hook", "pre_hook", "post-hook", "post_hook", "tags"],
|
"append": ["pre-hook", "pre_hook", "post-hook", "post_hook", "tags"],
|
||||||
"update": ["quoting", "column_types", "meta"],
|
"update": ["quoting", "column_types", "meta", "docs"],
|
||||||
"dict_key_append": ["grants"],
|
"dict_key_append": ["grants"],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,6 +461,20 @@ class NodeConfig(NodeAndTestConfig):
|
|||||||
grants: Dict[str, Any] = field(
|
grants: Dict[str, Any] = field(
|
||||||
default_factory=dict, metadata=MergeBehavior.DictKeyAppend.meta()
|
default_factory=dict, metadata=MergeBehavior.DictKeyAppend.meta()
|
||||||
)
|
)
|
||||||
|
docs: Docs = field(
|
||||||
|
default_factory=lambda: Docs(show=True),
|
||||||
|
metadata=MergeBehavior.Update.meta(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# we validate that node_color has a suitable value to prevent dbt-docs from crashing
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.docs.node_color:
|
||||||
|
node_color = self.docs.node_color
|
||||||
|
if not validate_color(node_color):
|
||||||
|
raise ValidationError(
|
||||||
|
f"Invalid color name for docs.node_color: {node_color}. "
|
||||||
|
"It is neither a valid HTML color name nor a valid HEX code."
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __pre_deserialize__(cls, data):
|
def __pre_deserialize__(cls, data):
|
||||||
|
|||||||
@@ -157,7 +157,6 @@ class ParsedNodeMixins(dbtClassMixin):
|
|||||||
self.created_at = time.time()
|
self.created_at = time.time()
|
||||||
self.description = patch.description
|
self.description = patch.description
|
||||||
self.columns = patch.columns
|
self.columns = patch.columns
|
||||||
self.docs = patch.docs
|
|
||||||
|
|
||||||
def get_materialization(self):
|
def get_materialization(self):
|
||||||
return self.config.materialized
|
return self.config.materialized
|
||||||
@@ -203,7 +202,7 @@ class ParsedNodeDefaults(NodeInfoMixin, ParsedNodeMandatory):
|
|||||||
description: str = field(default="")
|
description: str = field(default="")
|
||||||
columns: Dict[str, ColumnInfo] = field(default_factory=dict)
|
columns: Dict[str, ColumnInfo] = field(default_factory=dict)
|
||||||
meta: Dict[str, Any] = field(default_factory=dict)
|
meta: Dict[str, Any] = field(default_factory=dict)
|
||||||
docs: Docs = field(default_factory=Docs)
|
docs: Docs = field(default_factory=lambda: Docs(show=True))
|
||||||
patch_path: Optional[str] = None
|
patch_path: Optional[str] = None
|
||||||
compiled_path: Optional[str] = None
|
compiled_path: Optional[str] = None
|
||||||
build_path: Optional[str] = None
|
build_path: Optional[str] = None
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class UnparsedRunHook(UnparsedNode):
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Docs(dbtClassMixin, Replaceable):
|
class Docs(dbtClassMixin, Replaceable):
|
||||||
show: bool = True
|
show: bool = True
|
||||||
|
node_color: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
153
core/dbt/contracts/graph/utils.py
Normal file
153
core/dbt/contracts/graph/utils.py
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
HTML_COLORS = [
|
||||||
|
"aliceblue",
|
||||||
|
"antiquewhite",
|
||||||
|
"aqua",
|
||||||
|
"aquamarine",
|
||||||
|
"azure",
|
||||||
|
"beige",
|
||||||
|
"bisque",
|
||||||
|
"black",
|
||||||
|
"blanchedalmond",
|
||||||
|
"blue",
|
||||||
|
"blueviolet",
|
||||||
|
"brown",
|
||||||
|
"burlywood",
|
||||||
|
"cadetblue",
|
||||||
|
"chartreuse",
|
||||||
|
"chocolate",
|
||||||
|
"coral",
|
||||||
|
"cornflowerblue",
|
||||||
|
"cornsilk",
|
||||||
|
"crimson",
|
||||||
|
"cyan",
|
||||||
|
"darkblue",
|
||||||
|
"darkcyan",
|
||||||
|
"darkgoldenrod",
|
||||||
|
"darkgray",
|
||||||
|
"darkgreen",
|
||||||
|
"darkkhaki",
|
||||||
|
"darkmagenta",
|
||||||
|
"darkolivegreen",
|
||||||
|
"darkorange",
|
||||||
|
"darkorchid",
|
||||||
|
"darkred",
|
||||||
|
"darksalmon",
|
||||||
|
"darkseagreen",
|
||||||
|
"darkslateblue",
|
||||||
|
"darkslategray",
|
||||||
|
"darkturquoise",
|
||||||
|
"darkviolet",
|
||||||
|
"deeppink",
|
||||||
|
"deepskyblue",
|
||||||
|
"dimgray",
|
||||||
|
"dodgerblue",
|
||||||
|
"firebrick",
|
||||||
|
"floralwhite",
|
||||||
|
"forestgreen",
|
||||||
|
"fuchsia",
|
||||||
|
"gainsboro",
|
||||||
|
"ghostwhite",
|
||||||
|
"gold",
|
||||||
|
"goldenrod",
|
||||||
|
"gray",
|
||||||
|
"green",
|
||||||
|
"greenyellow",
|
||||||
|
"honeydew",
|
||||||
|
"hotpink",
|
||||||
|
"indianred",
|
||||||
|
"indigo",
|
||||||
|
"ivory",
|
||||||
|
"khaki",
|
||||||
|
"lavender",
|
||||||
|
"lavenderblush",
|
||||||
|
"lawngreen",
|
||||||
|
"lemonchiffon",
|
||||||
|
"lightblue",
|
||||||
|
"lightcoral",
|
||||||
|
"lightcyan",
|
||||||
|
"lightgoldenrodyellow",
|
||||||
|
"lightgray",
|
||||||
|
"lightgreen",
|
||||||
|
"lightpink",
|
||||||
|
"lightsalmon",
|
||||||
|
"lightsalmon",
|
||||||
|
"lightseagreen",
|
||||||
|
"lightskyblue",
|
||||||
|
"lightslategray",
|
||||||
|
"lightsteelblue",
|
||||||
|
"lightyellow",
|
||||||
|
"lime",
|
||||||
|
"limegreen",
|
||||||
|
"linen",
|
||||||
|
"magenta",
|
||||||
|
"maroon",
|
||||||
|
"mediumaquamarine",
|
||||||
|
"mediumblue",
|
||||||
|
"mediumorchid",
|
||||||
|
"mediumpurple",
|
||||||
|
"mediumseagreen",
|
||||||
|
"mediumslateblue",
|
||||||
|
"mediumslateblue",
|
||||||
|
"mediumspringgreen",
|
||||||
|
"mediumturquoise",
|
||||||
|
"mediumvioletred",
|
||||||
|
"midnightblue",
|
||||||
|
"mintcream",
|
||||||
|
"mistyrose",
|
||||||
|
"moccasin",
|
||||||
|
"navajowhite",
|
||||||
|
"navy",
|
||||||
|
"oldlace",
|
||||||
|
"olive",
|
||||||
|
"olivedrab",
|
||||||
|
"orange",
|
||||||
|
"orangered",
|
||||||
|
"orchid",
|
||||||
|
"palegoldenrod",
|
||||||
|
"palegreen",
|
||||||
|
"paleturquoise",
|
||||||
|
"palevioletred",
|
||||||
|
"papayawhip",
|
||||||
|
"peachpuff",
|
||||||
|
"peru",
|
||||||
|
"pink",
|
||||||
|
"plum",
|
||||||
|
"powderblue",
|
||||||
|
"purple",
|
||||||
|
"rebeccapurple",
|
||||||
|
"red",
|
||||||
|
"rosybrown",
|
||||||
|
"royalblue",
|
||||||
|
"saddlebrown",
|
||||||
|
"salmon",
|
||||||
|
"sandybrown",
|
||||||
|
"seagreen",
|
||||||
|
"seashell",
|
||||||
|
"sienna",
|
||||||
|
"silver",
|
||||||
|
"skyblue",
|
||||||
|
"slateblue",
|
||||||
|
"slategray",
|
||||||
|
"snow",
|
||||||
|
"springgreen",
|
||||||
|
"steelblue",
|
||||||
|
"tan",
|
||||||
|
"teal",
|
||||||
|
"thistle",
|
||||||
|
"tomato",
|
||||||
|
"turquoise",
|
||||||
|
"violet",
|
||||||
|
"wheat",
|
||||||
|
"white",
|
||||||
|
"whitesmoke",
|
||||||
|
"yellow",
|
||||||
|
"yellowgreen",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def validate_color(color: str) -> bool:
|
||||||
|
match_hex = re.search(r"^#(?:[0-9a-f]{3}){1,2}$", color.lower())
|
||||||
|
match_html_color_name = color.lower() in HTML_COLORS
|
||||||
|
return bool(match_hex or match_html_color_name)
|
||||||
@@ -17,7 +17,7 @@ from dbt.config import Project, RuntimeConfig
|
|||||||
from dbt.context.context_config import ContextConfig
|
from dbt.context.context_config import ContextConfig
|
||||||
from dbt.contracts.graph.manifest import Manifest
|
from dbt.contracts.graph.manifest import Manifest
|
||||||
from dbt.contracts.graph.parsed import HasUniqueID, ManifestNodes
|
from dbt.contracts.graph.parsed import HasUniqueID, ManifestNodes
|
||||||
from dbt.contracts.graph.unparsed import UnparsedNode
|
from dbt.contracts.graph.unparsed import UnparsedNode, Docs
|
||||||
from dbt.exceptions import ParsingException, validator_error_message, InternalException
|
from dbt.exceptions import ParsingException, validator_error_message, InternalException
|
||||||
from dbt import hooks
|
from dbt import hooks
|
||||||
from dbt.node_types import NodeType
|
from dbt.node_types import NodeType
|
||||||
@@ -287,6 +287,11 @@ class ConfiguredParser(
|
|||||||
if "meta" in config_dict and config_dict["meta"]:
|
if "meta" in config_dict and config_dict["meta"]:
|
||||||
parsed_node.meta = config_dict["meta"]
|
parsed_node.meta = config_dict["meta"]
|
||||||
|
|
||||||
|
# If we have docs in the config, copy to node level, for backwards
|
||||||
|
# compatibility with earlier node-only config.
|
||||||
|
if "docs" in config_dict and config_dict["docs"]:
|
||||||
|
parsed_node.docs = Docs(config_dict["docs"])
|
||||||
|
|
||||||
# unrendered_config is used to compare the original database/schema/alias
|
# unrendered_config is used to compare the original database/schema/alias
|
||||||
# values and to handle 'same_config' and 'same_contents' calls
|
# values and to handle 'same_config' and 'same_contents' calls
|
||||||
parsed_node.unrendered_config = config.build_config_dict(rendered=False)
|
parsed_node.unrendered_config = config.build_config_dict(rendered=False)
|
||||||
|
|||||||
@@ -797,6 +797,7 @@ class NonSourceParser(YamlDocsReader, Generic[NonSourceTarget, Parsed]):
|
|||||||
if self.key != "macros":
|
if self.key != "macros":
|
||||||
# macros don't have the 'config' key support yet
|
# macros don't have the 'config' key support yet
|
||||||
self.normalize_meta_attribute(data, path)
|
self.normalize_meta_attribute(data, path)
|
||||||
|
self.normalize_docs_attribute(data, path)
|
||||||
node = self._target_type().from_dict(data)
|
node = self._target_type().from_dict(data)
|
||||||
except (ValidationError, JSONValidationException) as exc:
|
except (ValidationError, JSONValidationException) as exc:
|
||||||
msg = error_context(path, self.key, data, exc)
|
msg = error_context(path, self.key, data, exc)
|
||||||
@@ -804,21 +805,27 @@ class NonSourceParser(YamlDocsReader, Generic[NonSourceTarget, Parsed]):
|
|||||||
else:
|
else:
|
||||||
yield node
|
yield node
|
||||||
|
|
||||||
# We want to raise an error if 'meta' is in two places, and move 'meta'
|
# We want to raise an error if some attributes are in two places, and move them
|
||||||
# from toplevel to config if necessary
|
# from toplevel to config if necessary
|
||||||
def normalize_meta_attribute(self, data, path):
|
def normalize_attribute(self, data, path, attribute):
|
||||||
if "meta" in data:
|
if attribute in data:
|
||||||
if "config" in data and "meta" in data["config"]:
|
if "config" in data and attribute in data["config"]:
|
||||||
raise ParsingException(
|
raise ParsingException(
|
||||||
f"""
|
f"""
|
||||||
In {path}: found meta dictionary in 'config' dictionary and as top-level key.
|
In {path}: found {attribute} dictionary in 'config' dictionary and as top-level key.
|
||||||
Remove the top-level key and define it under 'config' dictionary only.
|
Remove the top-level key and define it under 'config' dictionary only.
|
||||||
""".strip()
|
""".strip()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if "config" not in data:
|
if "config" not in data:
|
||||||
data["config"] = {}
|
data["config"] = {}
|
||||||
data["config"]["meta"] = data.pop("meta")
|
data["config"][attribute] = data.pop(attribute)
|
||||||
|
|
||||||
|
def normalize_meta_attribute(self, data, path):
|
||||||
|
return self.normalize_attribute(data, path, "meta")
|
||||||
|
|
||||||
|
def normalize_docs_attribute(self, data, path):
|
||||||
|
return self.normalize_attribute(data, path, "docs")
|
||||||
|
|
||||||
def patch_node_config(self, node, patch):
|
def patch_node_config(self, node, patch):
|
||||||
# Get the ContextConfig that's used in calculating the config
|
# Get the ContextConfig that's used in calculating the config
|
||||||
|
|||||||
Reference in New Issue
Block a user