| { |
| "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 [](https://colab.research.google.com/github/dagworks-inc/hamilton/blob/main/examples/validation/static_validator/notebook.ipynb) [](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 |
| } |