blob: 8ccc86876fd7ff7e54de994c17fdba82619767e8 [file] [log] [blame]
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "42af78d9",
"metadata": {},
"outputs": [],
"source": [
"# Execute this cell to install dependencies\n",
"%pip install sf-hamilton[visualization]"
]
},
{
"cell_type": "markdown",
"id": "9c98f181",
"metadata": {},
"source": [
"# Static validator dev [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/dagworks-inc/hamilton/blob/main/examples/validation/static_validator/notebook.ipynb) [![GitHub badge](https://img.shields.io/badge/github-view_source-2b3137?logo=github)](https://github.com/dagworks-inc/hamilton/blob/main/examples/validation/static_validator/notebook.ipynb)\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f35e3e0b",
"metadata": {
"ExecuteTime": {
"end_time": "2024-08-13T16:17:52.022254Z",
"start_time": "2024-08-13T16:17:51.439954Z"
}
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
" -->\n",
"<!-- Pages: 1 -->\n",
"<svg width=\"109pt\" height=\"165pt\"\n",
" viewBox=\"0.00 0.00 108.85 164.80\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 160.8)\">\n",
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-160.8 104.85,-160.8 104.85,4 -4,4\"/>\n",
"<g id=\"clust1\" class=\"cluster\">\n",
"<title>cluster__legend</title>\n",
"<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-73.8 8,-148.8 92.85,-148.8 92.85,-73.8 8,-73.8\"/>\n",
"<text text-anchor=\"middle\" x=\"50.42\" y=\"-131.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
"</g>\n",
"<!-- foo -->\n",
"<g id=\"node1\" class=\"node\">\n",
"<title>foo</title>\n",
"<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M65.42,-63.6C65.42,-63.6 35.42,-63.6 35.42,-63.6 29.42,-63.6 23.42,-57.6 23.42,-51.6 23.42,-51.6 23.42,-12 23.42,-12 23.42,-6 29.42,0 35.42,0 35.42,0 65.42,0 65.42,0 71.42,0 77.42,-6 77.42,-12 77.42,-12 77.42,-51.6 77.42,-51.6 77.42,-57.6 71.42,-63.6 65.42,-63.6\"/>\n",
"<text text-anchor=\"start\" x=\"39.92\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">foo</text>\n",
"<text text-anchor=\"start\" x=\"42.92\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
"</g>\n",
"<!-- function -->\n",
"<g id=\"node2\" class=\"node\">\n",
"<title>function</title>\n",
"<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-118.1C72.85,-118.1 28,-118.1 28,-118.1 22,-118.1 16,-112.1 16,-106.1 16,-106.1 16,-93.5 16,-93.5 16,-87.5 22,-81.5 28,-81.5 28,-81.5 72.85,-81.5 72.85,-81.5 78.85,-81.5 84.85,-87.5 84.85,-93.5 84.85,-93.5 84.85,-106.1 84.85,-106.1 84.85,-112.1 78.85,-118.1 72.85,-118.1\"/>\n",
"<text text-anchor=\"middle\" x=\"50.42\" y=\"-94\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
"</g>\n",
"</g>\n",
"</svg>\n"
],
"text/plain": [
"<graphviz.graphs.Digraph at 0x14f34ebe0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%cell_to_module good_module --display\n",
"from hamilton.function_modifiers import tag\n",
"\n",
"@tag(node_type=\"output\", table_name=\"my_table\")\n",
"def foo() -> str:\n",
" return \"Hello, world!\"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "af8dc9b5",
"metadata": {},
"outputs": [],
"source": [
"%load_ext hamilton.plugins.jupyter_magic"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "e8d725dc",
"metadata": {
"ExecuteTime": {
"end_time": "2024-08-13T16:18:06.041014Z",
"start_time": "2024-08-13T16:18:05.676209Z"
}
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
" -->\n",
"<!-- Pages: 1 -->\n",
"<svg width=\"109pt\" height=\"165pt\"\n",
" viewBox=\"0.00 0.00 108.85 164.80\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 160.8)\">\n",
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-160.8 104.85,-160.8 104.85,4 -4,4\"/>\n",
"<g id=\"clust1\" class=\"cluster\">\n",
"<title>cluster__legend</title>\n",
"<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-73.8 8,-148.8 92.85,-148.8 92.85,-73.8 8,-73.8\"/>\n",
"<text text-anchor=\"middle\" x=\"50.42\" y=\"-131.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
"</g>\n",
"<!-- foo -->\n",
"<g id=\"node1\" class=\"node\">\n",
"<title>foo</title>\n",
"<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M65.42,-63.6C65.42,-63.6 35.42,-63.6 35.42,-63.6 29.42,-63.6 23.42,-57.6 23.42,-51.6 23.42,-51.6 23.42,-12 23.42,-12 23.42,-6 29.42,0 35.42,0 35.42,0 65.42,0 65.42,0 71.42,0 77.42,-6 77.42,-12 77.42,-12 77.42,-51.6 77.42,-51.6 77.42,-57.6 71.42,-63.6 65.42,-63.6\"/>\n",
"<text text-anchor=\"start\" x=\"39.92\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">foo</text>\n",
"<text text-anchor=\"start\" x=\"42.92\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
"</g>\n",
"<!-- function -->\n",
"<g id=\"node2\" class=\"node\">\n",
"<title>function</title>\n",
"<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-118.1C72.85,-118.1 28,-118.1 28,-118.1 22,-118.1 16,-112.1 16,-106.1 16,-106.1 16,-93.5 16,-93.5 16,-87.5 22,-81.5 28,-81.5 28,-81.5 72.85,-81.5 72.85,-81.5 78.85,-81.5 84.85,-87.5 84.85,-93.5 84.85,-93.5 84.85,-106.1 84.85,-106.1 84.85,-112.1 78.85,-118.1 72.85,-118.1\"/>\n",
"<text text-anchor=\"middle\" x=\"50.42\" y=\"-94\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
"</g>\n",
"</g>\n",
"</svg>\n"
],
"text/plain": [
"<graphviz.graphs.Digraph at 0x14f359790>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%cell_to_module bad_module --display\n",
"from hamilton.function_modifiers import tag\n",
"\n",
"@tag(node_type=\"output\")\n",
"def foo() -> str:\n",
" return \"Hello, world!\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "085fe856",
"metadata": {
"ExecuteTime": {
"end_time": "2024-08-13T16:19:09.270965Z",
"start_time": "2024-08-13T16:19:09.266344Z"
}
},
"outputs": [],
"source": [
"# Validator\n",
"from typing import Optional\n",
"from hamilton.lifecycle import api\n",
"from hamilton.graph_types import HamiltonNode\n",
"\n",
"\n",
"class MyTagValidator(api.StaticValidator):\n",
" \"\"\"Static validator that is run right after the graph is built.\"\"\"\n",
"\n",
" def run_to_validate_node(\n",
" self, *, node: HamiltonNode, **future_kwargs\n",
" ) -> tuple[bool, Optional[str]]:\n",
" if node.tags.get(\"node_type\", \"\") == \"output\":\n",
" table_name = node.tags.get(\"table_name\")\n",
" if not table_name: # None or empty\n",
" error_msg = f\"Node {node.tags['module']}.{node.name} is an output node, but does not have a table_name tag.\"\n",
" return False, error_msg\n",
" return True, None\n",
"\n",
"tag_validator = MyTagValidator()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c0ef5e03",
"metadata": {
"ExecuteTime": {
"end_time": "2024-08-13T16:19:09.998394Z",
"start_time": "2024-08-13T16:19:09.975269Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'foo': 'Hello, world!'}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from hamilton import driver\n",
"\n",
"dr = (\n",
" driver.Builder()\n",
" .with_modules(good_module)\n",
" .with_adapters(tag_validator)\n",
" .build()\n",
")\n",
"dr.execute([good_module.foo])"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "6a452c8e",
"metadata": {
"ExecuteTime": {
"end_time": "2024-08-13T16:19:11.923694Z",
"start_time": "2024-08-13T16:19:10.870198Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"-------------------------------------------------------------------\n",
"Oh no an error! Need help with Hamilton?\n",
"Join our slack and ask for help! https://join.slack.com/t/hamilton-opensource/shared_invite/zt-2niepkra8-DGKGf_tTYhXuJWBTXtIs4g\n",
"-------------------------------------------------------------------\n",
"\n"
]
},
{
"ename": "ValidationException",
"evalue": "Node validation failed! 1 errors encountered:\n foo: Node bad_module.foo is an output node, but does not have a table_name tag.",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValidationException\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[7], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# this should error\u001b[39;00m\n\u001b[1;32m 2\u001b[0m dr \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m----> 3\u001b[0m \u001b[43mdriver\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mBuilder\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwith_modules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbad_module\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwith_adapters\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtag_validator\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbuild\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 7\u001b[0m )\n",
"File \u001b[0;32m~/dagworks/hamilton/hamilton/driver.py:1872\u001b[0m, in \u001b[0;36mBuilder.build\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1865\u001b[0m grouping_strategy \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgrouping_strategy \u001b[38;5;129;01mor\u001b[39;00m grouping\u001b[38;5;241m.\u001b[39mGroupByRepeatableBlocks()\n\u001b[1;32m 1866\u001b[0m graph_executor \u001b[38;5;241m=\u001b[39m TaskBasedGraphExecutor(\n\u001b[1;32m 1867\u001b[0m execution_manager\u001b[38;5;241m=\u001b[39mexecution_manager,\n\u001b[1;32m 1868\u001b[0m grouping_strategy\u001b[38;5;241m=\u001b[39mgrouping_strategy,\n\u001b[1;32m 1869\u001b[0m adapter\u001b[38;5;241m=\u001b[39mlifecycle_base\u001b[38;5;241m.\u001b[39mLifecycleAdapterSet(\u001b[38;5;241m*\u001b[39madapter),\n\u001b[1;32m 1870\u001b[0m )\n\u001b[0;32m-> 1872\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mDriver\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1873\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1874\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmodules\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1875\u001b[0m \u001b[43m \u001b[49m\u001b[43madapter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43madapter\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1876\u001b[0m \u001b[43m \u001b[49m\u001b[43m_materializers\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmaterializers\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1877\u001b[0m \u001b[43m \u001b[49m\u001b[43m_graph_executor\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgraph_executor\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1878\u001b[0m \u001b[43m \u001b[49m\u001b[43m_use_legacy_adapter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 1879\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/dagworks/hamilton/hamilton/driver.py:412\u001b[0m, in \u001b[0;36mDriver.__init__\u001b[0;34m(self, config, adapter, _materializers, _graph_executor, _use_legacy_adapter, *modules)\u001b[0m\n\u001b[1;32m 410\u001b[0m error \u001b[38;5;241m=\u001b[39m telemetry\u001b[38;5;241m.\u001b[39msanitize_error(\u001b[38;5;241m*\u001b[39msys\u001b[38;5;241m.\u001b[39mexc_info())\n\u001b[1;32m 411\u001b[0m logger\u001b[38;5;241m.\u001b[39merror(SLACK_ERROR_MESSAGE)\n\u001b[0;32m--> 412\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 413\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 414\u001b[0m \u001b[38;5;66;03m# TODO -- update this to use the lifecycle methods\u001b[39;00m\n\u001b[1;32m 415\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcapture_constructor_telemetry(error, modules, config, adapter)\n",
"File \u001b[0;32m~/dagworks/hamilton/hamilton/driver.py:399\u001b[0m, in \u001b[0;36mDriver.__init__\u001b[0;34m(self, config, adapter, _materializers, _graph_executor, _use_legacy_adapter, *modules)\u001b[0m\n\u001b[1;32m 393\u001b[0m materializer_factories, extractor_factories \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_materializers(\n\u001b[1;32m 394\u001b[0m _materializers\n\u001b[1;32m 395\u001b[0m )\n\u001b[1;32m 396\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgraph \u001b[38;5;241m=\u001b[39m materialization\u001b[38;5;241m.\u001b[39mmodify_graph(\n\u001b[1;32m 397\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgraph, materializer_factories, extractor_factories\n\u001b[1;32m 398\u001b[0m )\n\u001b[0;32m--> 399\u001b[0m \u001b[43mDriver\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_perform_graph_validations\u001b[49m\u001b[43m(\u001b[49m\u001b[43madapter\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgraph\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgraph\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgraph_modules\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodules\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 400\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m adapter\u001b[38;5;241m.\u001b[39mdoes_hook(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost_graph_construct\u001b[39m\u001b[38;5;124m\"\u001b[39m, is_async\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[1;32m 401\u001b[0m adapter\u001b[38;5;241m.\u001b[39mcall_all_lifecycle_hooks_sync(\n\u001b[1;32m 402\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost_graph_construct\u001b[39m\u001b[38;5;124m\"\u001b[39m, graph\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgraph, modules\u001b[38;5;241m=\u001b[39mmodules, config\u001b[38;5;241m=\u001b[39mconfig\n\u001b[1;32m 403\u001b[0m )\n",
"File \u001b[0;32m~/dagworks/hamilton/hamilton/driver.py:339\u001b[0m, in \u001b[0;36mDriver._perform_graph_validations\u001b[0;34m(adapter, graph, graph_modules)\u001b[0m\n\u001b[1;32m 329\u001b[0m errors \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 330\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnode_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00merror_delimiter\u001b[38;5;241m.\u001b[39mjoin([item\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mfor\u001b[39;00m\u001b[38;5;250m \u001b[39mitem\u001b[38;5;250m \u001b[39m\u001b[38;5;129;01min\u001b[39;00m\u001b[38;5;250m \u001b[39mmessages])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m node_name, messages \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28msorted\u001b[39m(\n\u001b[1;32m 332\u001b[0m node_validation_results\u001b[38;5;241m.\u001b[39mitems(), key\u001b[38;5;241m=\u001b[39moperator\u001b[38;5;241m.\u001b[39mitemgetter(\u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 333\u001b[0m )\n\u001b[1;32m 334\u001b[0m ]\n\u001b[1;32m 335\u001b[0m error_str \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m 336\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNode validation failed! \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlen\u001b[39m(errors)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m errors encountered:\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 337\u001b[0m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(errors)\n\u001b[1;32m 338\u001b[0m )\n\u001b[0;32m--> 339\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m lifecycle_base\u001b[38;5;241m.\u001b[39mValidationException(error_str)\n\u001b[1;32m 340\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m adapter\u001b[38;5;241m.\u001b[39mdoes_validation(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mvalidate_graph\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 341\u001b[0m validation_results \u001b[38;5;241m=\u001b[39m adapter\u001b[38;5;241m.\u001b[39mcall_all_validators_sync(\n\u001b[1;32m 342\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mvalidate_graph\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 343\u001b[0m output_only_failures\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 346\u001b[0m config\u001b[38;5;241m=\u001b[39mgraph\u001b[38;5;241m.\u001b[39mconfig,\n\u001b[1;32m 347\u001b[0m )\n",
"\u001b[0;31mValidationException\u001b[0m: Node validation failed! 1 errors encountered:\n foo: Node bad_module.foo is an output node, but does not have a table_name tag."
]
}
],
"source": [
"# this should error\n",
"dr = (\n",
" driver.Builder()\n",
" .with_modules(bad_module)\n",
" .with_adapters(tag_validator)\n",
" .build()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0f31407f",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}