| { |
| "cells": [ |
| { |
| "cell_type": "markdown", |
| "id": "7fb27b941602401d91542211134fc71a", |
| "metadata": {}, |
| "source": [ |
| "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing,\nsoftware distributed under the License is distributed on an\n\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, either express or implied. See the License for the\nspecific language governing permissions and limitations\nunder the License." |
| ] |
| }, |
| { |
| "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/apache/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", |
| "\n", |
| "from hamilton.graph_types import HamiltonNode\n", |
| "from hamilton.lifecycle import api\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, str | None]:\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", |
| "\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 = driver.Builder().with_modules(good_module).with_adapters(tag_validator).build()\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 = driver.Builder().with_modules(bad_module).with_adapters(tag_validator).build()" |
| ] |
| }, |
| { |
| "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 |
| } |