{ "cells": [ { "cell_type": "markdown", "id": "af71fbfb", "metadata": {}, "source": [ "# Notebook 3 - reports, benchmark signals, and review gates\n", "\n", "This walkthrough mirrors `examples/05_programmatic_report.py` and `examples/06_benchmark.py`. It treats conversion reports as CI-ready data, demonstrates warning-code gates, and validates a small synthetic benchmark.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "d0fe5d61", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:00.334118Z", "iopub.status.busy": "2026-07-12T14:43:00.333335Z", "iopub.status.idle": "2026-07-12T14:43:01.173151Z", "shell.execute_reply": "2026-07-12T14:43:01.171689Z" } }, "outputs": [], "source": [ "import importlib.util\n", "import json\n", "import tempfile\n", "import time\n", "from collections import Counter\n", "from pathlib import Path\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "from sql2sqlx import ConversionOptions, convert_directory\n", "\n", "ROOT = next(\n", " path for path in [Path.cwd(), *Path.cwd().parents] if (path / \"pyproject.toml\").exists()\n", ")\n", "EXAMPLES = ROOT / \"examples\"\n", "HELPER = EXAMPLES / \"_notebook_benchmark_helper.py\"\n", "spec = importlib.util.spec_from_file_location(\"notebook_benchmark_helper\", HELPER)\n", "assert spec is not None and spec.loader is not None\n", "bench = importlib.util.module_from_spec(spec)\n", "spec.loader.exec_module(bench)" ] }, { "cell_type": "markdown", "id": "0f7e5f07", "metadata": {}, "source": [ "## Treat warning codes as review gates\n", "\n", "The report is structured data, so migrations can fail CI on selected warning codes while allowing intentionally reviewed warnings to pass.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "4fcb3ddb", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:01.177144Z", "iopub.status.busy": "2026-07-12T14:43:01.176533Z", "iopub.status.idle": "2026-07-12T14:43:01.431253Z", "shell.execute_reply": "2026-07-12T14:43:01.427763Z" } }, "outputs": [ { "data": { "text/plain": [ "{'warning_counts': {'ORDER_ASSUMED': 3,\n", " 'SCRIPT_FILE': 1,\n", " 'SCRIPT_WRITES': 1,\n", " 'CREATE_NO_AS': 1},\n", " 'blocking_findings': [],\n", " 'failures': 0}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result = convert_directory(str(EXAMPLES / \"sql\"))\n", "warning_counts = Counter(warning.code for warning in result.report.warnings)\n", "blocking_codes = {\"FALLBACK_OPERATIONS\", \"DUPLICATE_TARGET\", \"SELF_REFERENCE\"}\n", "blockers = [warning for warning in result.report.warnings if warning.code in blocking_codes]\n", "{\n", " \"warning_counts\": dict(warning_counts),\n", " \"blocking_findings\": [(warning.path, warning.line, warning.code) for warning in blockers],\n", " \"failures\": len(result.report.failures),\n", "}" ] }, { "cell_type": "markdown", "id": "0c6b7268", "metadata": {}, "source": [ "## Inspect JSON report fields\n", "\n", "`to_dict()` is the same representation written by the CLI `--report` flag. It includes action counts, warning details, failures, dependency rewrites, and timing data.\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "40aa136b", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:01.438256Z", "iopub.status.busy": "2026-07-12T14:43:01.437547Z", "iopub.status.idle": "2026-07-12T14:43:01.448745Z", "shell.execute_reply": "2026-07-12T14:43:01.447445Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"files_read\": 8,\n", " \"statements\": 11,\n", " \"actions_by_type\": {\n", " \"operations\": 6,\n", " \"view\": 1,\n", " \"table\": 2\n", " },\n", " \"refs_rewritten\": 7,\n", " \"refs_unresolved\": [],\n", " \"warnings\": [\n", " {\n", " \"code\": \"ORDER_ASSUMED\",\n", " \"message\": \"Table marts.order_facts is written by statements in multiple files (maintenance/backfill_script.sql, marts/order_facts.sql); their relative execution order was inferred from sorted file paths - verify the generated dependency chain.\",\n", " \"path\": \"maintenance/backfill_script.sql\",\n", " \"line\": 0\n", " },\n", " {\n", " \"code\": \"ORDER_ASSUMED\",\n", " \"message\": \"Table staging.orders is written by statements in multiple files (maintenance/cleanup.sql, staging/stg_orders.sql); their relative execution order was inferred from sorted file paths - verify the generated dependency chain.\",\n", " \"path\": \"maintenance/cleanup.sql\",\n", " \"line\": 0\n", " },\n", " {\n", " \"code\": \"ORDER_ASSUMED\",\n", " \"message\": \"Table staging.customers is written by statements in multiple files (maintenance/cleanup.sql, staging/stg_customers.sql); their relative execution order was inferred from sorted file paths - verify the generated dependency chain.\",\n", " \"path\": \"maintenance/cleanup.sql\",\n", " \"line\": 0\n", " },\n", " {\n", " \"code\": \"SCRIPT_FILE\",\n", " \"message\": \"File requires shared BigQuery script context (variable state); the whole file was kept as one operations action so statement order and scope are preserved.\",\n", " \"path\": \"maintenance/backfill_script.sql\",\n", " \"line\": 3\n", " },\n", " {\n", " \"code\": \"SCRIPT_WRITES\",\n", " \"message\": \"Script writes: marts.order_facts. Downstream readers are ordered after this script; ordering between multiple writers of the same table follows corpus order.\",\n", " \"path\": \"maintenance/backfill_script.sql\",\n", " \"line\": 3\n", " },\n", " {\n", " \"code\": \"CREATE_NO_AS\",\n", " \"message\": \"Plain CREATE TABLE raw.events (no AS query) kept as operations; use --plain-create declaration to emit a source declaration instead.\",\n", " \n" ] } ], "source": [ "report_dict = result.report.to_dict()\n", "print(json.dumps(report_dict, indent=2)[:2000])\n", "assert report_dict[\"statements\"] >= len(result.files)\n", "assert report_dict[\"actions_by_type\"]\n", "assert report_dict[\"failures\"] == {}" ] }, { "cell_type": "markdown", "id": "80395b14", "metadata": {}, "source": [ "## Visualize warning counts\n", "\n", "A warning chart is a compact review artifact for pull requests. A value of zero is still meaningful: it shows that the checked sample corpus had no warnings.\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "979aa7d3", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:01.451686Z", "iopub.status.busy": "2026-07-12T14:43:01.451397Z", "iopub.status.idle": "2026-07-12T14:43:01.731021Z", "shell.execute_reply": "2026-07-12T14:43:01.729931Z" } }, "outputs": [ { "data": { "image/png": "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C7MODg6IiYlRa4uNjYWIwN7evsDH8fDwwPPnzzWOlWPatGlISEhQfUVERPynuomIiIio9NBamPX29sb9+/dx584dVVtgYCD09fXRtGlTVVtqaiqysrLyPE5oaChMTU1hbW2da79SqYSFhYXaFxERERGVDVoLs+3bt0e9evUwevRo3L59GyEhIZg+fTqGDx8OW1tbAEB8fDxMTEywadMmAMCyZcuwaNEihIeHIyYmBuvXr8fChQvxwQcfwMjISFunQkRERERaorUwq6+vj3379sHa2hpvvfUW/P390aNHDyxbtkw1RqFQQKlUqp7uNWzYMCQlJaFbt27w8PDAypUr8f333+Orr77S1mkQERERkRZp9XG2jo6O2LZtW579lpaWao+vLVeuHGbNmoVZs2aVRHlEREREVMppdTcDIiIiIqL/gmGWiIiIiHQWwywRERER6SyGWSIiIiLSWQyzRERERKSzGGaJiIiISGcxzBIRERGRzmKYJSIiIiKdxTBLRERERDqLYZaIiIiIdBbDLBERERHpLIZZIiIiItJZDLNEREREpLMYZomIiIhIZzHMEhEREZHOYpglIiIiIp3FMEtEREREOothloiIiIh0FsMsEREREekshlkiIiIi0lkMs0RERESksxhmiYiIiEhnMcwSERERkc5imCUiIiIincUwS0REREQ6y0DbBURHR+PkyZMwNjaGj48PzMzMimUOEREREZU9Wg2zAQEBGDlyJBo1aoT4+HhER0fjwIEDqFevXpHOISIiIqKySWvLDGJjYzFy5EjMmTMHhw8fRmhoKFq0aIF33323SOcQERERUdmltTD7+++/IysrC2PGjAEAKBQKTJo0CZcuXcLly5eLbA4RERERlV1aW2YQFhYGZ2dnmJqaqto8PT1VfXXq1CmSOWlpaUhLS1N9n5CQAABITEwsmhMpgKTUrBJ7LSpZUoLvo3/ie6ps4vuJipo23lN8P5VdJfl+yslpIvLKsVoLswkJCbC2tlZrs7S0hL6+vipwFsWcefPmYdasWRrtTk5Or1k50T98ZqntCqgs4fuJihrfU1SUtPB+SkpKgqVl/q+rtTBrYmKC58+fq7WlpKQgKysLJiYmRTZn2rRp+PDDD1XfZ2dnIy4uDjY2NlAoFP/xLOjfEhMT4eTkhIiICFhYWGi7HNJxfD9RUeL7iYoa31PFR0SQlJQE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48ePo3379qhTpw6+++47eHp64urVq/j666+RmJiIHTt2wMbGRttlUinGNbNa8uzZM8ycORP169dHtWrV0KVLFwQFBQEAbGxsMHPmTKxatQpHjhzB+++/j/feew/u7u5o06YNPD098ccff6iO9cEHH6BRo0bo1asXLly4wCBLRCVq586duHjxIkaPHq3tUkgHeXt749ixYzA1NUWrVq1gZWWFIUOGwNfXF4GBgQyy9Eq8MqsFFy5cQJcuXdCpUyf07t0bqampWLlyJfbv349FixZhypQpyMzMRN26dXHt2jVMmjQJX375JaysrBAREYFPPvkEAQEB6NOnDxYvXsy7OImoRGVlZSE2NhaXL1/GunXrcPjwYfz888+qx40Sva7U1FRkZGTA3Nxc26WQDmGYLWFJSUlwd3fHjBkz8N5776n1TZw4EcuWLcORI0fQsmVL/Pnnn+jQoQN27tyJbt26qY09dOgQ1q9fj88//xy1atUqwTMgojfdiRMnMHbsWFSpUgWdO3fGwIEDYWFhoe2yiOgNxTBbwtauXYsvvvgCDx8+hEKhUOvLyMhA/fr1YWVlhePHjwMAunTpgmvXruHq1aswMjLSRslEREREpRbXzJawy5cvw8HBQSPIAoChoSE++ugjnDhxAlFRUQCA7777DhEREVi8eHFJl0pERERU6jHMljArKyuEh4cjPT091/5WrVoBgOppXzVr1sTkyZMRHR1dYjUSERER6QqG2RLWoUMHJCUl4eeff861Py0tDQDUHu83f/58fPfddyVSHxEREZEu4ZpZLWjTpg3CwsJw/vx5ODk5qfVNnToVZ86cQXBwsJaqIyIiItIdvDKrBWvXroW+vj5atWqFQ4cOITs7G0+ePMHUqVPxyy+/4Mcff9R2iUREREQ6gWFWC6pVq4aTJ0/C3d0d7du3h7GxMapUqYLY2Fj8/fffcHFx0XaJRERERDqBywy0LD4+HjExMahSpQqMjY21XQ4RERGRTmGYJSIiIiKdxWUGRERERKSzGGaJiIiISGcxzBIRERGRzmKYJSIiIiKdxTBLRERERDqLYZaIiIiIdBbDLBERERHpLIZZIiIiItJZDLNERKXQ6dOncebMGW2X8drOnTuHU6dOabsMInoDGGi7ACIi0rR8+XIYGBigSZMm2i7ltfz444+Ij49Hs2bNtF0KEZVxDLNERKVQs2bNoKfHD8+IiF6FYZaICEB6ejp27NiBd955B1ZWVgCAwMBAZGZmokOHDgCA58+fY+/evfD398ezZ89w9OhRAICpqSnc3Nzg6uqqdszw8HDcuXMHbdq0walTp/D48WP06NEDp0+fhqmpKWrWrInQ0FCkpaWhadOmMDc3V81t2LAhFAqF6vvjx4+/cg4AJCcn4+jRozA1NUX9+vURHh6OjIyMV14hvXjxIu7duwd3d3eN88jMzMSpU6fw5MkTuLu7w83NTWP+ixcvcPToUZiYmKB+/fp5vk5oaCju37+PqlWrol69emrnSET0OhhmiYgAGBkZ4cMPP0R2djYGDBgAEUHfvn2RmpqKZ8+ewdDQEIGBgRg7diz69OmD6Oho/P777wBehtwTJ06gS5cu2Lhxo+qY+/fvx8KFC+Hg4AAzMzM4ODjA398fixYtwqNHj/Ds2TPUqFED9+/fR2JiIk6cOIEqVaoA0FxmUJA5N27cwNtvvw0zMzNUr14dN27cgJ2dHVxcXPIMs0+ePEHPnj1x9epVNG7cGHfu3ME777yDJUuWAADu37+PDh06ID09Ha6urjh58iR69+6NtWvXqo5x+/ZttG7dGsbGxqhevTquX7+OChUqwMXFRTUmLi4O3bt3x4MHD1C3bl1cvnwZlSpVwq5du2BtbV1kP0cievMwzBIR/Z9WrVrh8OHDGDBgAC5dugQAsLOzQ0hICJo3b47Dhw/Dx8cHenp6qF+/PgICAlRzY2JiULduXezatQv+/v6q9qioKCxYsACDBg1Se60bN27g4sWLqFq1KrKystC0aVMsXboU3377bZ71vWrOhx9+CE9PT+zduxcGBgY4c+YMmjdvrhYq/2306NFISkpCeHi4KlTu2rVL1T9p0iTY29vjjz/+gFKpxNWrV9GgQQN06NABffr0AQBMnjwZtWvXVr3uqVOn0KJFC7XXHTt2LBwcHBAUFAR9fX1kZGSgc+fO+Pzzz7F8+fJX/myIiPLCMEtE9H98fX2xaNEiAMDhw4fh6+sLc3NzBAcHq8LskCFDVOMzMjJw7tw5REVFISMjA05OTjh79qxamC1fvrxGkAWATp06oWrVqgAAfX19eHt748aNG/nWl9+clJQU7N+/HwcPHoSBwctf7U2aNIGPj0+ex0tISMCuXbvw66+/ql0dzak/NTUVu3btwq5du6BUKgEAtWvXRvfu3REQEIA+ffogJSUFe/fuxYEDB1Sv26xZM7Rs2VJ1vKSkJPz222+YMWMGdu7cCRGBiKBq1aoIDg7O95yJiF6FYZaI6P/4+vrivffew8OHD3H48GG0adMG5ubm2LRpE8aNG4dLly7B19cXAHDhwgX4+fnBzMwMrq6uMDMzQ0xMDGJiYtSOaW9vn+trlS9fXu17pVKJ1NTUfOvLb05ERAQAoFq1ampjqlWrhpSUlFyP9/DhQ2RnZ2uskc3x4MEDiAicnZ3V2l1cXHDgwAHV64qIxutWr15drbasrCyEhITg+vXrauNatGiRx9kSERUMwywR0f+pVauW6qPwY8eOYe7cuTA3N8fYsWPx119/wcLCAl5eXgCAzz77DB06dFBbO9q2bVuIiNoxS+oGp5ygGx8fr9b+7NkzGBsb5zon50a3p0+f5tpvZ2cH4OV613+Ki4uDra0tAMDGxkb1Ov9+XRMTEwCAhYUFAGDixIlo3759QU6HiKjAuO8LEdE/tGrVCsuWLYOenh5q166NKlWqoGLFivjmm29U62UB4PHjx6hVq5ZqXmRkpFYfEmBrawtXV1e19a6JiYk4fPhwnnMqVaqE2rVrq920BgCxsbEAAGtra7i7u2PHjh2qvrS0NOzZswfe3t4AXoZZNzc31c1wwMsg+8/lA5UrV4aHhwdWrVqlUUNkZGShzpOI6N94ZZaI6B98fX0REBCA3r17q66q+vr6Yv369fjuu+9U47p164aFCxfC0NAQenp6+P7772FkZKStsgEA8+bNQ9++fZGWloaaNWti7dq1MDAwyPfq8KpVq9CxY0ckJSWhXbt2uHPnDs6dO4dDhw4BAJYsWQI/Pz9kZGTA09MTmzZtglKpxOTJk1XHWLBgAXr27Im0tDS4urpizZo1Gn8WP/74I9555x107NgR/v7+eP78OQ4ePIimTZti7ty5xfMHQkRvBIZZIqJ/6NChA/r27at209aAAQOQkpKCTp06qdpmzJiBKlWq4NixYzA2NsaKFSsQHh6u9pF+rVq10LFjR43XaNmypcb6Vy8vL7U9Y//90ISCzOnRowf++OMPBAQE4Pr165g9ezZ++uknjb1o/11LWFgY1q1bh1OnTsHDw0PtKmv79u1x5swZbNq0SbX92OjRo1GuXDnVmK5du+LQoUPYvHkzbty4ga+++gpRUVFITk5WjWnatCmuXr2K9evX49SpU7C3t8eMGTNUa5CJiF6XQv69wIuIiHRSQkICzM3NVSE4OTkZLi4umDVrFsaMGaPl6oiIigfDLBFRGXHhwgVMmDABvXr1gkKhwLp165Ceno4zZ86oXUklIipLGGaJiMqQs2fPYvv27UhISICnpydGjBih2lWAiKgsYpglIiIiIp3FrbmIiIiISGcxzBIRERGRzmKYJSIiIiKdxTBLRERERDqLYZaIiIiIdBbDLBERERHpLIZZIiIiItJZDLNEREREpLMYZomIiIhIZ/0/zJwP1P0Zw9sAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(8, 3))\n", "labels = list(warning_counts) or [\"none\"]\n", "values = [warning_counts[label] for label in labels] if warning_counts else [0]\n", "ax.bar(labels, values, color=\"#F28E2B\")\n", "ax.set_title(\"Warning-code counts\")\n", "ax.set_ylabel(\"count\")\n", "ax.set_xlabel(\"warning code\")\n", "ax.tick_params(axis=\"x\", rotation=30)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "cdf9e809", "metadata": {}, "source": [ "## Run a small synthetic benchmark\n", "\n", "This benchmark intentionally stays small enough for documentation builds. It uses the same generator pattern as the standalone benchmark example: multiple files, chained CTAS statements, metadata clauses, and append statements.\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "db3ed629", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:01.735203Z", "iopub.status.busy": "2026-07-12T14:43:01.734863Z", "iopub.status.idle": "2026-07-12T14:43:01.993390Z", "shell.execute_reply": "2026-07-12T14:43:01.985142Z" } }, "outputs": [ { "data": { "text/plain": [ "{'files': 3,\n", " 'statements_per_file': 8,\n", " 'lines': 279,\n", " 'size_bytes': 8181,\n", " 'actions': 30,\n", " 'seconds': 0.2158,\n", " 'lines_per_second': 1293.1,\n", " 'failures': 0}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "with tempfile.TemporaryDirectory(prefix=\"sql2sqlx_nb_bench_\") as tmp:\n", " corpus = Path(tmp)\n", " lines = bench.generate(corpus, files=3, statements=8)\n", " size = sum(path.stat().st_size for path in corpus.rglob(\"*.sql\"))\n", " start = time.perf_counter()\n", " bench_result = convert_directory(str(corpus), options=ConversionOptions(jobs=0))\n", " seconds = time.perf_counter() - start\n", "\n", "benchmark = {\n", " \"files\": 3,\n", " \"statements_per_file\": 8,\n", " \"lines\": lines,\n", " \"size_bytes\": size,\n", " \"actions\": sum(bench_result.report.actions_by_type.values()),\n", " \"seconds\": round(seconds, 4),\n", " \"lines_per_second\": round(lines / seconds, 1),\n", " \"failures\": len(bench_result.report.failures),\n", "}\n", "benchmark" ] }, { "cell_type": "markdown", "id": "7ca7e72e", "metadata": {}, "source": [ "## Validate benchmark outputs\n", "\n", "The generated corpus has one base table plus one append operation and eight CTAS statements per file, so the action count is deterministic: `files * (statements_per_file + 2)`.\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "a4ddbd09", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:43:02.006339Z", "iopub.status.busy": "2026-07-12T14:43:02.005105Z", "iopub.status.idle": "2026-07-12T14:43:02.225165Z", "shell.execute_reply": "2026-07-12T14:43:02.222579Z" } }, "outputs": [ { "data": { "image/png": "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0RpD5s+fb/TbPERERFRxsi5+vXTpEjw9PfXGPT09cenSpYr2JHFycgLwcLbmUbdv35aWKVVjSFRUFLKysqTH9evXK3A0RERE9DSygkmTJk0wb948FBcXS2PFxcWYN28emjRpolhzTk5O8PLywqFDh3TGDxw4gPbt2ytaY4harYZGo9F5EBERUeWRFUy++eYbrFmzBl5eXujTpw969+4NT09PrF27FkuXLlW0wfHjxyM6OhrHjh1DUVERPvvsM9y4cQOjRo1SvIaIiIhMy+hrTB7VqVMnJCcnY+3atTh//jwAYNKkSRg2bBgcHByM3s6WLVswduxY6TqPPn36wNraGtOmTcO0adMAAJGRkUhPT0f37t2Rn5+PevXq4bvvvtOZmVGqhoiIiEzL6PuYVIb8/HxkZ2frjVerVg3VqlXTGSspKUFOTg5q1qxZ5vaUqikL72NCRERVwXNxH5PH5eXl4dKlS7h7967essdvklYWtVoNtVptVK2FhcVTw4RSNURERGQasoJJbGwsBg8erPcpl1ImnIQhIiKi55isi1/Hjx+PsLAwpKeno7CwUO9BREREJIesGZNr165hzpw5qFGjhtL9EBERURUma8akadOmSElJUboXIiIiquJkzZiMGTMG4eHhWLRoERo1aqT3ZXyurq6KNEdERERVi6xgEhERAQDo0qWLweW8+JWIiIjkkBVMEhMTle6DiIiISF4w8fb2VroPIiIiIvk3WAOAK1eu4OLFixBCoFmzZvDy8lKqLyIiIqqCZAUTrVaLESNGYOvWrQAAlUoFIQQGDhyIlStX8lt4iYiISBZZHxeeOHEizp8/j7i4OOTl5SE3NxdxcXE4f/48Jk2apHSPREREVEXICibff/89vv32W3Tr1g22trawtbVFt27dsGXLFuzYsUPpHomIiKiKkBVMcnNz4ezsrDfu7OyM3NzcCjdFREREVZOsYNK+fXvMmTNH53txCgsLMXv2bLRv316x5oiIiKhqkXXx6+LFi9GjRw989913aN26NQDg1KlTKC4uxs8//6xog0RERFR1yAomrVu3RlJSEtasWYNz585BpVKhR48eGDZsGOzt7ZXukYiIiKoI2fcxsbe3x4QJExRshYiIiKo6WdeYZGdnS/cwedTWrVuRnZ1d4aaIiIioapIVTKZOnYp79+7pjWdmZmL69OkV7YmIiIiqKFnB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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "{'files': 3,\n", " 'statements_per_file': 8,\n", " 'lines': 279,\n", " 'size_bytes': 8181,\n", " 'actions': 30,\n", " 'seconds': 0.2158,\n", " 'lines_per_second': 1293.1,\n", " 'failures': 0}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "expected_actions = benchmark[\"files\"] * (benchmark[\"statements_per_file\"] + 2)\n", "assert benchmark[\"actions\"] == expected_actions\n", "assert benchmark[\"failures\"] == 0\n", "assert benchmark[\"lines_per_second\"] > 0\n", "\n", "fig, ax = plt.subplots(figsize=(6, 3))\n", "ax.bar([\"lines/s\"], [benchmark[\"lines_per_second\"]], color=\"#76B7B2\")\n", "ax.set_title(\"Small synthetic conversion throughput\")\n", "ax.set_ylabel(\"lines per second\")\n", "plt.show()\n", "benchmark" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.13" } }, "nbformat": 4, "nbformat_minor": 5 }