From 3dc1aff9da9ddee2278d8039e48d7ce32deeda35 Mon Sep 17 00:00:00 2001 From: Jacob Beck Date: Tue, 9 Jul 2019 10:21:09 -0600 Subject: [PATCH] convert some oneOf checks into if-else chains to get better errors --- core/dbt/contracts/graph/parsed.py | 39 +++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/core/dbt/contracts/graph/parsed.py b/core/dbt/contracts/graph/parsed.py index cb0f9a3dc06..d86de54986a 100644 --- a/core/dbt/contracts/graph/parsed.py +++ b/core/dbt/contracts/graph/parsed.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import Optional, Union, List, Dict, Any +from typing import Optional, Union, List, Dict, Any, Type, Tuple from hologram import JsonSchemaMixin from hologram.helpers import StrEnum, NewPatternType @@ -302,11 +302,48 @@ class IntermediateSnapshotNode(ParsedNode): config: NodeConfig +def _create_if_else_chain( + key: str, criteria: List[Tuple[str, Type[JsonSchemaMixin]]] +) -> dict: + """Mutate a given schema key that contains a 'oneOf' to instead be an + 'if-then-else' chain. This results is much better/more consistent errors + from jsonschema. + """ + result = schema = {} + criteria = criteria[:] + while criteria: + if_clause, then_clause = criteria.pop() + schema['if'] = {'properties': { + key: {'enum': [if_clause]} + }} + schema['then'] = then_clause.json_schema() + schema['else'] = {} + schema = schema['else'] + schema['additionalProperties'] = False + schema['required'] = ['invalid'] + return result + + @dataclass class ParsedSnapshotNode(ParsedNode): resource_type: SnapshotType config: Union[CheckSnapshotConfig, TimestampSnapshotConfig] + @classmethod + def json_schema(cls): + schema = super().json_schema() + + # mess with config + configs = [ + (CheckStrategy.Check, CheckSnapshotConfig), + (TimestampStrategy.Timestamp, TimestampSnapshotConfig), + ] + + schema['properties']['config'] = _create_if_else_chain( + 'strategy', configs + ) + return schema + # The parsed node update is only the 'patch', not the test. The test became a # regular parsed node. Note that description and columns must be present, but