| { |
| "cells": [ |
| { |
| "cell_type": "code", |
| "id": "initial_id", |
| "metadata": { |
| "collapsed": true, |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:17:40.744646Z", |
| "start_time": "2024-08-13T16:17:32.149272Z" |
| } |
| }, |
| "source": "%load_ext hamilton.plugins.jupyter_magic", |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "/Users/stefankrawczyk/.pyenv/versions/knowledge_retrieval-py39/lib/python3.9/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n", |
| " warnings.warn(\n" |
| ] |
| } |
| ], |
| "execution_count": 1 |
| }, |
| { |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:17:52.022254Z", |
| "start_time": "2024-08-13T16:17:51.439954Z" |
| } |
| }, |
| "cell_type": "code", |
| "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" |
| ], |
| "id": "acac6adfe569cbc", |
| "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" |
| } |
| ], |
| "execution_count": 2 |
| }, |
| { |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:18:06.041014Z", |
| "start_time": "2024-08-13T16:18:05.676209Z" |
| } |
| }, |
| "cell_type": "code", |
| "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!\"" |
| ], |
| "id": "667a78a28d435a0f", |
| "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" |
| } |
| ], |
| "execution_count": 3 |
| }, |
| { |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:19:09.270965Z", |
| "start_time": "2024-08-13T16:19:09.266344Z" |
| } |
| }, |
| "cell_type": "code", |
| "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()" |
| ], |
| "id": "b4303b258c107981", |
| "outputs": [], |
| "execution_count": 5 |
| }, |
| { |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:19:09.998394Z", |
| "start_time": "2024-08-13T16:19:09.975269Z" |
| } |
| }, |
| "cell_type": "code", |
| "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])" |
| ], |
| "id": "63cfc94d37dff5b", |
| "outputs": [ |
| { |
| "data": { |
| "text/plain": [ |
| "{'foo': 'Hello, world!'}" |
| ] |
| }, |
| "execution_count": 6, |
| "metadata": {}, |
| "output_type": "execute_result" |
| } |
| ], |
| "execution_count": 6 |
| }, |
| { |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-08-13T16:19:11.923694Z", |
| "start_time": "2024-08-13T16:19:10.870198Z" |
| } |
| }, |
| "cell_type": "code", |
| "source": [ |
| "# this should error\n", |
| "dr = (\n", |
| " driver.Builder()\n", |
| " .with_modules(bad_module)\n", |
| " .with_adapters(tag_validator)\n", |
| " .build()\n", |
| ")" |
| ], |
| "id": "58c203af8cd4e793", |
| "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." |
| ] |
| } |
| ], |
| "execution_count": 7 |
| }, |
| { |
| "metadata": {}, |
| "cell_type": "code", |
| "outputs": [], |
| "execution_count": null, |
| "source": "", |
| "id": "b508258007d9283c" |
| } |
| ], |
| "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 |
| } |