From fc4ad9e90b5435d6c9a57390355d8a2cb5c28d5c Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 10:01:19 -0700
Subject: [PATCH 01/15] BUILD.bazel

---
 BUILD => BUILD.bazel                                           | 0
 projects/activitypub_relay/{BUILD => BUILD.bazel}              | 0
 projects/aloe/{BUILD => BUILD.bazel}                           | 0
 projects/anosql-migrations/{BUILD => BUILD.bazel}              | 0
 projects/anosql/{BUILD => BUILD.bazel}                         | 0
 projects/archiver/{BUILD => BUILD.bazel}                       | 3 ++-
 projects/async_cache/{BUILD => BUILD.bazel}                    | 0
 projects/calf/{BUILD => BUILD.bazel}                           | 0
 projects/calf/tests/python/{BUILD => BUILD.bazel}              | 0
 projects/cherry-shim/{BUILD => BUILD.bazel}                    | 0
 projects/clusterctrl/{BUILD => BUILD.bazel}                    | 0
 projects/damm/{BUILD => BUILD.bazel}                           | 0
 projects/datalog-shell/{BUILD => BUILD.bazel}                  | 0
 projects/datalog/{BUILD => BUILD.bazel}                        | 0
 projects/flowmetal/{BUILD => BUILD.bazel}                      | 0
 projects/flowmetal/scratch/{BUILD => BUILD.bazel}              | 0
 projects/gandi/{BUILD => BUILD.bazel}                          | 0
 projects/gh-unnotifier/{BUILD => BUILD.bazel}                  | 0
 projects/jobq/{BUILD => BUILD.bazel}                           | 0
 projects/jobqd/{BUILD => BUILD.bazel}                          | 0
 projects/lilith/{BUILD => BUILD.bazel}                         | 0
 projects/octodash/{BUILD => BUILD.bazel}                       | 0
 projects/octostep/{BUILD => BUILD.bazel}                       | 0
 projects/proquint/{BUILD => BUILD.bazel}                       | 0
 projects/public_dns/{BUILD => BUILD.bazel}                     | 0
 projects/ratchet/{BUILD => BUILD.bazel}                        | 0
 projects/reqman/{BUILD => BUILD.bazel}                         | 0
 projects/shoggoth/{BUILD => BUILD.bazel}                       | 0
 projects/smith/{BUILD => BUILD.bazel}                          | 0
 projects/templater/{BUILD => BUILD.bazel}                      | 0
 projects/tentacles/{BUILD => BUILD.bazel}                      | 0
 .../src/python/tentacles/static/css/{BUILD => BUILD.bazel}     | 0
 projects/vfs/{BUILD => BUILD.bazel}                            | 0
 projects/yamlschema/{BUILD => BUILD.bazel}                     | 0
 tools/autoflake/{BUILD => BUILD.bazel}                         | 0
 tools/black/{BUILD => BUILD.bazel}                             | 0
 tools/build_rules/{BUILD => BUILD.bazel}                       | 0
 tools/flake8/{BUILD => BUILD.bazel}                            | 0
 tools/isort/{BUILD => BUILD.bazel}                             | 0
 tools/openapi/{BUILD => BUILD.bazel}                           | 0
 tools/python/{BUILD => BUILD.bazel}                            | 0
 tools/sass/{BUILD => BUILD.bazel}                              | 0
 tools/sphinx/{BUILD => BUILD.bazel}                            | 0
 tools/unify/{BUILD => BUILD.bazel}                             | 0
 tools/xfmt/{BUILD => BUILD.bazel}                              | 0
 tools/yamllint/{BUILD => BUILD.bazel}                          | 0
 46 files changed, 2 insertions(+), 1 deletion(-)
 rename BUILD => BUILD.bazel (100%)
 rename projects/activitypub_relay/{BUILD => BUILD.bazel} (100%)
 rename projects/aloe/{BUILD => BUILD.bazel} (100%)
 rename projects/anosql-migrations/{BUILD => BUILD.bazel} (100%)
 rename projects/anosql/{BUILD => BUILD.bazel} (100%)
 rename projects/archiver/{BUILD => BUILD.bazel} (86%)
 rename projects/async_cache/{BUILD => BUILD.bazel} (100%)
 rename projects/calf/{BUILD => BUILD.bazel} (100%)
 rename projects/calf/tests/python/{BUILD => BUILD.bazel} (100%)
 rename projects/cherry-shim/{BUILD => BUILD.bazel} (100%)
 rename projects/clusterctrl/{BUILD => BUILD.bazel} (100%)
 rename projects/damm/{BUILD => BUILD.bazel} (100%)
 rename projects/datalog-shell/{BUILD => BUILD.bazel} (100%)
 rename projects/datalog/{BUILD => BUILD.bazel} (100%)
 rename projects/flowmetal/{BUILD => BUILD.bazel} (100%)
 rename projects/flowmetal/scratch/{BUILD => BUILD.bazel} (100%)
 rename projects/gandi/{BUILD => BUILD.bazel} (100%)
 rename projects/gh-unnotifier/{BUILD => BUILD.bazel} (100%)
 rename projects/jobq/{BUILD => BUILD.bazel} (100%)
 rename projects/jobqd/{BUILD => BUILD.bazel} (100%)
 rename projects/lilith/{BUILD => BUILD.bazel} (100%)
 rename projects/octodash/{BUILD => BUILD.bazel} (100%)
 rename projects/octostep/{BUILD => BUILD.bazel} (100%)
 rename projects/proquint/{BUILD => BUILD.bazel} (100%)
 rename projects/public_dns/{BUILD => BUILD.bazel} (100%)
 rename projects/ratchet/{BUILD => BUILD.bazel} (100%)
 rename projects/reqman/{BUILD => BUILD.bazel} (100%)
 rename projects/shoggoth/{BUILD => BUILD.bazel} (100%)
 rename projects/smith/{BUILD => BUILD.bazel} (100%)
 rename projects/templater/{BUILD => BUILD.bazel} (100%)
 rename projects/tentacles/{BUILD => BUILD.bazel} (100%)
 rename projects/tentacles/src/python/tentacles/static/css/{BUILD => BUILD.bazel} (100%)
 rename projects/vfs/{BUILD => BUILD.bazel} (100%)
 rename projects/yamlschema/{BUILD => BUILD.bazel} (100%)
 rename tools/autoflake/{BUILD => BUILD.bazel} (100%)
 rename tools/black/{BUILD => BUILD.bazel} (100%)
 rename tools/build_rules/{BUILD => BUILD.bazel} (100%)
 rename tools/flake8/{BUILD => BUILD.bazel} (100%)
 rename tools/isort/{BUILD => BUILD.bazel} (100%)
 rename tools/openapi/{BUILD => BUILD.bazel} (100%)
 rename tools/python/{BUILD => BUILD.bazel} (100%)
 rename tools/sass/{BUILD => BUILD.bazel} (100%)
 rename tools/sphinx/{BUILD => BUILD.bazel} (100%)
 rename tools/unify/{BUILD => BUILD.bazel} (100%)
 rename tools/xfmt/{BUILD => BUILD.bazel} (100%)
 rename tools/yamllint/{BUILD => BUILD.bazel} (100%)

diff --git a/BUILD b/BUILD.bazel
similarity index 100%
rename from BUILD
rename to BUILD.bazel
diff --git a/projects/activitypub_relay/BUILD b/projects/activitypub_relay/BUILD.bazel
similarity index 100%
rename from projects/activitypub_relay/BUILD
rename to projects/activitypub_relay/BUILD.bazel
diff --git a/projects/aloe/BUILD b/projects/aloe/BUILD.bazel
similarity index 100%
rename from projects/aloe/BUILD
rename to projects/aloe/BUILD.bazel
diff --git a/projects/anosql-migrations/BUILD b/projects/anosql-migrations/BUILD.bazel
similarity index 100%
rename from projects/anosql-migrations/BUILD
rename to projects/anosql-migrations/BUILD.bazel
diff --git a/projects/anosql/BUILD b/projects/anosql/BUILD.bazel
similarity index 100%
rename from projects/anosql/BUILD
rename to projects/anosql/BUILD.bazel
diff --git a/projects/archiver/BUILD b/projects/archiver/BUILD.bazel
similarity index 86%
rename from projects/archiver/BUILD
rename to projects/archiver/BUILD.bazel
index 667dc8e..9b9da65 100644
--- a/projects/archiver/BUILD
+++ b/projects/archiver/BUILD.bazel
@@ -15,5 +15,6 @@ zapp_binary(
     deps = [
         py_requirement("ExifRead"),
         py_requirement("yaspin"),
-    ]
+    ],
+    shebang = "/usr/bin/env python3"
 )
diff --git a/projects/async_cache/BUILD b/projects/async_cache/BUILD.bazel
similarity index 100%
rename from projects/async_cache/BUILD
rename to projects/async_cache/BUILD.bazel
diff --git a/projects/calf/BUILD b/projects/calf/BUILD.bazel
similarity index 100%
rename from projects/calf/BUILD
rename to projects/calf/BUILD.bazel
diff --git a/projects/calf/tests/python/BUILD b/projects/calf/tests/python/BUILD.bazel
similarity index 100%
rename from projects/calf/tests/python/BUILD
rename to projects/calf/tests/python/BUILD.bazel
diff --git a/projects/cherry-shim/BUILD b/projects/cherry-shim/BUILD.bazel
similarity index 100%
rename from projects/cherry-shim/BUILD
rename to projects/cherry-shim/BUILD.bazel
diff --git a/projects/clusterctrl/BUILD b/projects/clusterctrl/BUILD.bazel
similarity index 100%
rename from projects/clusterctrl/BUILD
rename to projects/clusterctrl/BUILD.bazel
diff --git a/projects/damm/BUILD b/projects/damm/BUILD.bazel
similarity index 100%
rename from projects/damm/BUILD
rename to projects/damm/BUILD.bazel
diff --git a/projects/datalog-shell/BUILD b/projects/datalog-shell/BUILD.bazel
similarity index 100%
rename from projects/datalog-shell/BUILD
rename to projects/datalog-shell/BUILD.bazel
diff --git a/projects/datalog/BUILD b/projects/datalog/BUILD.bazel
similarity index 100%
rename from projects/datalog/BUILD
rename to projects/datalog/BUILD.bazel
diff --git a/projects/flowmetal/BUILD b/projects/flowmetal/BUILD.bazel
similarity index 100%
rename from projects/flowmetal/BUILD
rename to projects/flowmetal/BUILD.bazel
diff --git a/projects/flowmetal/scratch/BUILD b/projects/flowmetal/scratch/BUILD.bazel
similarity index 100%
rename from projects/flowmetal/scratch/BUILD
rename to projects/flowmetal/scratch/BUILD.bazel
diff --git a/projects/gandi/BUILD b/projects/gandi/BUILD.bazel
similarity index 100%
rename from projects/gandi/BUILD
rename to projects/gandi/BUILD.bazel
diff --git a/projects/gh-unnotifier/BUILD b/projects/gh-unnotifier/BUILD.bazel
similarity index 100%
rename from projects/gh-unnotifier/BUILD
rename to projects/gh-unnotifier/BUILD.bazel
diff --git a/projects/jobq/BUILD b/projects/jobq/BUILD.bazel
similarity index 100%
rename from projects/jobq/BUILD
rename to projects/jobq/BUILD.bazel
diff --git a/projects/jobqd/BUILD b/projects/jobqd/BUILD.bazel
similarity index 100%
rename from projects/jobqd/BUILD
rename to projects/jobqd/BUILD.bazel
diff --git a/projects/lilith/BUILD b/projects/lilith/BUILD.bazel
similarity index 100%
rename from projects/lilith/BUILD
rename to projects/lilith/BUILD.bazel
diff --git a/projects/octodash/BUILD b/projects/octodash/BUILD.bazel
similarity index 100%
rename from projects/octodash/BUILD
rename to projects/octodash/BUILD.bazel
diff --git a/projects/octostep/BUILD b/projects/octostep/BUILD.bazel
similarity index 100%
rename from projects/octostep/BUILD
rename to projects/octostep/BUILD.bazel
diff --git a/projects/proquint/BUILD b/projects/proquint/BUILD.bazel
similarity index 100%
rename from projects/proquint/BUILD
rename to projects/proquint/BUILD.bazel
diff --git a/projects/public_dns/BUILD b/projects/public_dns/BUILD.bazel
similarity index 100%
rename from projects/public_dns/BUILD
rename to projects/public_dns/BUILD.bazel
diff --git a/projects/ratchet/BUILD b/projects/ratchet/BUILD.bazel
similarity index 100%
rename from projects/ratchet/BUILD
rename to projects/ratchet/BUILD.bazel
diff --git a/projects/reqman/BUILD b/projects/reqman/BUILD.bazel
similarity index 100%
rename from projects/reqman/BUILD
rename to projects/reqman/BUILD.bazel
diff --git a/projects/shoggoth/BUILD b/projects/shoggoth/BUILD.bazel
similarity index 100%
rename from projects/shoggoth/BUILD
rename to projects/shoggoth/BUILD.bazel
diff --git a/projects/smith/BUILD b/projects/smith/BUILD.bazel
similarity index 100%
rename from projects/smith/BUILD
rename to projects/smith/BUILD.bazel
diff --git a/projects/templater/BUILD b/projects/templater/BUILD.bazel
similarity index 100%
rename from projects/templater/BUILD
rename to projects/templater/BUILD.bazel
diff --git a/projects/tentacles/BUILD b/projects/tentacles/BUILD.bazel
similarity index 100%
rename from projects/tentacles/BUILD
rename to projects/tentacles/BUILD.bazel
diff --git a/projects/tentacles/src/python/tentacles/static/css/BUILD b/projects/tentacles/src/python/tentacles/static/css/BUILD.bazel
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/BUILD
rename to projects/tentacles/src/python/tentacles/static/css/BUILD.bazel
diff --git a/projects/vfs/BUILD b/projects/vfs/BUILD.bazel
similarity index 100%
rename from projects/vfs/BUILD
rename to projects/vfs/BUILD.bazel
diff --git a/projects/yamlschema/BUILD b/projects/yamlschema/BUILD.bazel
similarity index 100%
rename from projects/yamlschema/BUILD
rename to projects/yamlschema/BUILD.bazel
diff --git a/tools/autoflake/BUILD b/tools/autoflake/BUILD.bazel
similarity index 100%
rename from tools/autoflake/BUILD
rename to tools/autoflake/BUILD.bazel
diff --git a/tools/black/BUILD b/tools/black/BUILD.bazel
similarity index 100%
rename from tools/black/BUILD
rename to tools/black/BUILD.bazel
diff --git a/tools/build_rules/BUILD b/tools/build_rules/BUILD.bazel
similarity index 100%
rename from tools/build_rules/BUILD
rename to tools/build_rules/BUILD.bazel
diff --git a/tools/flake8/BUILD b/tools/flake8/BUILD.bazel
similarity index 100%
rename from tools/flake8/BUILD
rename to tools/flake8/BUILD.bazel
diff --git a/tools/isort/BUILD b/tools/isort/BUILD.bazel
similarity index 100%
rename from tools/isort/BUILD
rename to tools/isort/BUILD.bazel
diff --git a/tools/openapi/BUILD b/tools/openapi/BUILD.bazel
similarity index 100%
rename from tools/openapi/BUILD
rename to tools/openapi/BUILD.bazel
diff --git a/tools/python/BUILD b/tools/python/BUILD.bazel
similarity index 100%
rename from tools/python/BUILD
rename to tools/python/BUILD.bazel
diff --git a/tools/sass/BUILD b/tools/sass/BUILD.bazel
similarity index 100%
rename from tools/sass/BUILD
rename to tools/sass/BUILD.bazel
diff --git a/tools/sphinx/BUILD b/tools/sphinx/BUILD.bazel
similarity index 100%
rename from tools/sphinx/BUILD
rename to tools/sphinx/BUILD.bazel
diff --git a/tools/unify/BUILD b/tools/unify/BUILD.bazel
similarity index 100%
rename from tools/unify/BUILD
rename to tools/unify/BUILD.bazel
diff --git a/tools/xfmt/BUILD b/tools/xfmt/BUILD.bazel
similarity index 100%
rename from tools/xfmt/BUILD
rename to tools/xfmt/BUILD.bazel
diff --git a/tools/yamllint/BUILD b/tools/yamllint/BUILD.bazel
similarity index 100%
rename from tools/yamllint/BUILD
rename to tools/yamllint/BUILD.bazel

From bfafe8bc3aee80182960f0d469ffd5b97d56b315 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 11:17:32 -0700
Subject: [PATCH 02/15] setuptools, not Maven

---
 .bazeliskrc                                   |  1 -
 .bazelversion                                 |  1 +
 .../src/{python => }/relay/__init__.py        |  0
 .../src/{python => }/relay/__main__.py        |  0
 .../src/{python => }/relay/application.py     |  0
 .../src/{python => }/relay/config.py          |  0
 .../src/{python => }/relay/database.py        |  0
 .../src/{python => }/relay/http_debug.py      |  0
 .../src/{python => }/relay/misc.py            |  0
 .../src/{python => }/relay/processors.py      |  0
 .../src/{python => }/relay/views.py           |  0
 .../aloe/src/{python => }/aloe/__main__.py    |  0
 .../src/{python => }/aloe/cursedlogger.py     |  0
 projects/aloe/src/{python => }/aloe/icmp.py   |  0
 .../src/{python => }/anosql_migrations.py     |  0
 .../test/{python => }/test_migrations.py      |  0
 .../src/{python => }/anosql/__init__.py       |  0
 .../{python => }/anosql/adapters/__init__.py  |  0
 .../{python => }/anosql/adapters/psycopg2.py  |  0
 .../{python => }/anosql/adapters/sqlite3.py   |  0
 .../anosql/src/{python => }/anosql/core.py    |  0
 .../src/{python => }/anosql/exceptions.py     |  0
 .../src/{python => }/anosql/patterns.py       |  0
 projects/anosql/test/{python => }/__init__.py |  0
 .../{python => }/blogdb/data/blogs_data.csv   |  0
 .../{python => }/blogdb/data/users_data.csv   |  0
 .../{python => }/blogdb/sql/blogs/blogs.sql   |  0
 .../blogdb/sql/blogs/blogs_pg.sql             |  0
 .../blogdb/sql/blogs/blogs_sqlite.sql         |  0
 .../{python => }/blogdb/sql/users/users.sql   |  0
 projects/anosql/test/{python => }/conftest.py |  0
 .../anosql/test/{python => }/test_psycopg2.py |  0
 .../anosql/test/{python => }/test_simple.py   |  0
 .../anosql/test/{python => }/test_sqlite3.py  |  0
 .../src/{python => }/async_cache/__init__.py  |  0
 .../src/{python => }/async_cache/key.py       |  0
 .../src/{python => }/async_cache/lru.py       |  0
 .../src/{python => }/async_cache/ttl.py       |  0
 .../async_cache/test/{python => }/test_lru.py |  0
 .../async_cache/test/{python => }/test_ttl.py |  0
 projects/bazelshim/BUILD.bazel                |  3 +
 projects/bazelshim/src/bazelshim/__main__.py  | 68 +++++++++++++++++++
 .../src/{python => }/bussard/__init__.py      |  0
 .../bussard/src/{python => }/bussard/bfmt     |  0
 .../bussard/src/{python => }/bussard/bparse   |  0
 .../src/{python => }/bussard/gen/__init__.py  |  0
 .../src/{python => }/bussard/reader.py        |  0
 .../test/{python => }/bussard/test_reader.py  |  0
 .../calf/src/{python => }/calf/__init__.py    |  0
 .../calf/src/{python => }/calf/analyzer.py    |  0
 .../calf/src/{python => }/calf/cursedrepl.py  |  0
 .../calf/src/{python => }/calf/grammar.py     |  0
 .../calf/src/{python => }/calf/io/reader.py   |  0
 projects/calf/src/{python => }/calf/lexer.py  |  0
 .../calf/src/{python => }/calf/packages.py    |  0
 projects/calf/src/{python => }/calf/parser.py |  0
 projects/calf/src/{python => }/calf/reader.py |  0
 projects/calf/src/{python => }/calf/token.py  |  0
 projects/calf/src/{python => }/calf/types.py  |  0
 projects/calf/src/{python => }/calf/util.py   |  0
 .../src/{python => }/cherry_shim.py           |  0
 .../src/{python => }/clusterctrl/__main__.py  |  0
 .../src/{python => }/clusterctrl/cmd/alert.py |  0
 .../src/{python => }/clusterctrl/cmd/fan.py   |  0
 .../src/{python => }/clusterctrl/cmd/hub.py   |  0
 .../src/{python => }/clusterctrl/cmd/led.py   |  0
 .../src/{python => }/clusterctrl/cmd/power.py |  0
 .../src/{python => }/clusterctrl/cmd/save.py  |  0
 .../src/{python => }/clusterctrl/driver.py    |  0
 .../test/{python => }/test_driver.py          |  0
 projects/damm/src/{python => }/damm.py        |  0
 projects/damm/test/{python => }/test_damm.py  |  0
 .../damm/test/{python => }/test_hypothesis.py |  0
 .../{python => }/datalog/shell/__main__.py    |  0
 projects/datalog/src/{python => }/__init__.py |  0
 .../src/{python => }/datalog/__init__.py      |  0
 .../src/{python => }/datalog/debris.py        |  0
 .../datalog/src/{python => }/datalog/easy.py  |  0
 .../src/{python => }/datalog/evaluator.py     |  0
 .../src/{python => }/datalog/parser.py        |  0
 .../src/{python => }/datalog/reader.py        |  0
 .../datalog/src/{python => }/datalog/types.py |  0
 .../{python => }/test_datalog_evaluator.py    |  0
 .../test/{python => }/test_datalog_reader.py  |  0
 .../src/{python => }/flowmetal/__main__.py    |  0
 .../src/{python => }/flowmetal/db/base.py     |  0
 .../src/{python => }/flowmetal/db/redis.py    |  0
 .../src/{python => }/flowmetal/frontend.py    |  0
 .../src/{python => }/flowmetal/interpreter.py |  0
 .../src/{python => }/flowmetal/models.py      |  0
 .../src/{python => }/flowmetal/reaper.py      |  0
 .../src/{python => }/flowmetal/scheduler.py   |  0
 .../gandi/src/{python => }/gandi/__init__.py  |  0
 .../gandi/src/{python => }/gandi/client.py    |  0
 .../src/{python => }/gcode_interpreter.py     |  0
 .../src/{python => }/ghunnotif/__main__.py    |  0
 .../jobq/src/{python => }/jobq/__init__.py    |  0
 projects/jobq/test/{python => }/test_jobq.py  |  0
 .../jobqd/src/{python => }/jobqd/__main__.py  |  0
 .../jobqd/src/{python => }/jobqd/openapi.yaml |  0
 .../jobqd/src/{python => }/jobqd/rest/api.py  |  0
 projects/lilith/test/{python => }/conftest.py |  0
 .../test/{python => }/test_interpreter.py     |  0
 .../lilith/test/{python => }/test_parser.py   |  0
 .../lilith/test/{python => }/test_reader.py   |  0
 .../src/{python => }/proquint/__init__.py     |  0
 .../src/{python => }/proquint/__main__.py     |  0
 .../test/{python => }/test_examples.py        |  0
 .../test/{python => }/test_hypothesis.py      |  0
 .../src/{python => }/updater/__init__.py      |  0
 .../src/{python => }/updater/__main__.py      |  0
 .../test/{python => }/test_parsing.py         |  0
 .../src/{python => }/ratchet/__init__.py      |  0
 .../{python => }/ratchet/backend/sqlite.py    |  0
 .../src/{python => }/reqman/__main__.py       |  0
 .../shoggoth/src/{python => }/ichor/NOTES.md  |  0
 .../src/{python => }/ichor/__init__.py        |  0
 .../src/{python => }/ichor/__main__.py        |  0
 .../src/{python => }/ichor/assembler.py       |  0
 .../src/{python => }/ichor/bootstrap.py       |  0
 .../src/{python => }/ichor/interpreter.py     |  0
 .../shoggoth/src/{python => }/ichor/isa.py    |  0
 .../shoggoth/src/{python => }/ichor/state.py  |  0
 .../shoggoth/src/{python => }/ichor/typing.py |  0
 .../src/{python => }/shoggoth/analyzer.py     |  0
 .../src/{python => }/shoggoth/parser.py       |  0
 .../src/{python => }/shoggoth/reader.py       |  0
 .../{python => }/shoggoth/repl/__main__.py    |  0
 .../src/{python => }/shoggoth/types.py        |  0
 .../test/{python => }/ichor/fixtures.py       |  0
 .../test/{python => }/ichor/test_assembler.py |  0
 .../test/{python => }/ichor/test_bootstrap.py |  0
 .../{python => }/ichor/test_interpreter.py    |  0
 .../test/{python => }/ichor/test_parsers.py   |  0
 .../test/{python => }/ichor/test_state.py     |  0
 .../test/{python => }/shogoth/test_parser.py  |  0
 .../smith/src/{python => }/smith/__main__.py  |  0
 .../tentacles/test/{python => }/conftest.py   |  0
 .../tentacles/test/{python => }/test_gcode.py |  0
 .../tentacles/test/{python => }/test_store.py |  0
 .../test/{python => }/test_store_users.py     |  0
 projects/vfs/src/{python => }/vfs/__init__.py |  0
 projects/vfs/src/{python => }/vfs/impl.py     |  0
 .../src/{python => }/yamlschema/__init__.py   |  0
 .../test/{python => }/test_yamlschema.py      |  0
 tools/build_rules/prelude_bazel               |  7 --
 tools/python/BUILD.bazel                      |  3 -
 tools/python/defs.bzl                         | 12 ++--
 tools/python/test_licenses.py                 | 10 ++-
 149 files changed, 85 insertions(+), 20 deletions(-)
 delete mode 100644 .bazeliskrc
 create mode 100644 .bazelversion
 rename projects/activitypub_relay/src/{python => }/relay/__init__.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/__main__.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/application.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/config.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/database.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/http_debug.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/misc.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/processors.py (100%)
 rename projects/activitypub_relay/src/{python => }/relay/views.py (100%)
 rename projects/aloe/src/{python => }/aloe/__main__.py (100%)
 rename projects/aloe/src/{python => }/aloe/cursedlogger.py (100%)
 rename projects/aloe/src/{python => }/aloe/icmp.py (100%)
 rename projects/anosql-migrations/src/{python => }/anosql_migrations.py (100%)
 rename projects/anosql-migrations/test/{python => }/test_migrations.py (100%)
 rename projects/anosql/src/{python => }/anosql/__init__.py (100%)
 rename projects/anosql/src/{python => }/anosql/adapters/__init__.py (100%)
 rename projects/anosql/src/{python => }/anosql/adapters/psycopg2.py (100%)
 rename projects/anosql/src/{python => }/anosql/adapters/sqlite3.py (100%)
 rename projects/anosql/src/{python => }/anosql/core.py (100%)
 rename projects/anosql/src/{python => }/anosql/exceptions.py (100%)
 rename projects/anosql/src/{python => }/anosql/patterns.py (100%)
 rename projects/anosql/test/{python => }/__init__.py (100%)
 rename projects/anosql/test/{python => }/blogdb/data/blogs_data.csv (100%)
 rename projects/anosql/test/{python => }/blogdb/data/users_data.csv (100%)
 rename projects/anosql/test/{python => }/blogdb/sql/blogs/blogs.sql (100%)
 rename projects/anosql/test/{python => }/blogdb/sql/blogs/blogs_pg.sql (100%)
 rename projects/anosql/test/{python => }/blogdb/sql/blogs/blogs_sqlite.sql (100%)
 rename projects/anosql/test/{python => }/blogdb/sql/users/users.sql (100%)
 rename projects/anosql/test/{python => }/conftest.py (100%)
 rename projects/anosql/test/{python => }/test_psycopg2.py (100%)
 rename projects/anosql/test/{python => }/test_simple.py (100%)
 rename projects/anosql/test/{python => }/test_sqlite3.py (100%)
 rename projects/async_cache/src/{python => }/async_cache/__init__.py (100%)
 rename projects/async_cache/src/{python => }/async_cache/key.py (100%)
 rename projects/async_cache/src/{python => }/async_cache/lru.py (100%)
 rename projects/async_cache/src/{python => }/async_cache/ttl.py (100%)
 rename projects/async_cache/test/{python => }/test_lru.py (100%)
 rename projects/async_cache/test/{python => }/test_ttl.py (100%)
 create mode 100644 projects/bazelshim/BUILD.bazel
 create mode 100644 projects/bazelshim/src/bazelshim/__main__.py
 rename projects/bussard/src/{python => }/bussard/__init__.py (100%)
 rename projects/bussard/src/{python => }/bussard/bfmt (100%)
 rename projects/bussard/src/{python => }/bussard/bparse (100%)
 rename projects/bussard/src/{python => }/bussard/gen/__init__.py (100%)
 rename projects/bussard/src/{python => }/bussard/reader.py (100%)
 rename projects/bussard/test/{python => }/bussard/test_reader.py (100%)
 rename projects/calf/src/{python => }/calf/__init__.py (100%)
 rename projects/calf/src/{python => }/calf/analyzer.py (100%)
 rename projects/calf/src/{python => }/calf/cursedrepl.py (100%)
 rename projects/calf/src/{python => }/calf/grammar.py (100%)
 rename projects/calf/src/{python => }/calf/io/reader.py (100%)
 rename projects/calf/src/{python => }/calf/lexer.py (100%)
 rename projects/calf/src/{python => }/calf/packages.py (100%)
 rename projects/calf/src/{python => }/calf/parser.py (100%)
 rename projects/calf/src/{python => }/calf/reader.py (100%)
 rename projects/calf/src/{python => }/calf/token.py (100%)
 rename projects/calf/src/{python => }/calf/types.py (100%)
 rename projects/calf/src/{python => }/calf/util.py (100%)
 rename projects/cherry-shim/src/{python => }/cherry_shim.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/__main__.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/alert.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/fan.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/hub.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/led.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/power.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/cmd/save.py (100%)
 rename projects/clusterctrl/src/{python => }/clusterctrl/driver.py (100%)
 rename projects/clusterctrl/test/{python => }/test_driver.py (100%)
 rename projects/damm/src/{python => }/damm.py (100%)
 rename projects/damm/test/{python => }/test_damm.py (100%)
 rename projects/damm/test/{python => }/test_hypothesis.py (100%)
 rename projects/datalog-shell/src/{python => }/datalog/shell/__main__.py (100%)
 rename projects/datalog/src/{python => }/__init__.py (100%)
 rename projects/datalog/src/{python => }/datalog/__init__.py (100%)
 rename projects/datalog/src/{python => }/datalog/debris.py (100%)
 rename projects/datalog/src/{python => }/datalog/easy.py (100%)
 rename projects/datalog/src/{python => }/datalog/evaluator.py (100%)
 rename projects/datalog/src/{python => }/datalog/parser.py (100%)
 rename projects/datalog/src/{python => }/datalog/reader.py (100%)
 rename projects/datalog/src/{python => }/datalog/types.py (100%)
 rename projects/datalog/test/{python => }/test_datalog_evaluator.py (100%)
 rename projects/datalog/test/{python => }/test_datalog_reader.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/__main__.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/db/base.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/db/redis.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/frontend.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/interpreter.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/models.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/reaper.py (100%)
 rename projects/flowmetal/src/{python => }/flowmetal/scheduler.py (100%)
 rename projects/gandi/src/{python => }/gandi/__init__.py (100%)
 rename projects/gandi/src/{python => }/gandi/client.py (100%)
 rename projects/gcode-interpreter/src/{python => }/gcode_interpreter.py (100%)
 rename projects/gh-unnotifier/src/{python => }/ghunnotif/__main__.py (100%)
 rename projects/jobq/src/{python => }/jobq/__init__.py (100%)
 rename projects/jobq/test/{python => }/test_jobq.py (100%)
 rename projects/jobqd/src/{python => }/jobqd/__main__.py (100%)
 rename projects/jobqd/src/{python => }/jobqd/openapi.yaml (100%)
 rename projects/jobqd/src/{python => }/jobqd/rest/api.py (100%)
 rename projects/lilith/test/{python => }/conftest.py (100%)
 rename projects/lilith/test/{python => }/test_interpreter.py (100%)
 rename projects/lilith/test/{python => }/test_parser.py (100%)
 rename projects/lilith/test/{python => }/test_reader.py (100%)
 rename projects/proquint/src/{python => }/proquint/__init__.py (100%)
 rename projects/proquint/src/{python => }/proquint/__main__.py (100%)
 rename projects/proquint/test/{python => }/test_examples.py (100%)
 rename projects/proquint/test/{python => }/test_hypothesis.py (100%)
 rename projects/public_dns/src/{python => }/updater/__init__.py (100%)
 rename projects/public_dns/src/{python => }/updater/__main__.py (100%)
 rename projects/public_dns/test/{python => }/test_parsing.py (100%)
 rename projects/ratchet/src/{python => }/ratchet/__init__.py (100%)
 rename projects/ratchet/src/{python => }/ratchet/backend/sqlite.py (100%)
 rename projects/reqman/src/{python => }/reqman/__main__.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/NOTES.md (100%)
 rename projects/shoggoth/src/{python => }/ichor/__init__.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/__main__.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/assembler.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/bootstrap.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/interpreter.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/isa.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/state.py (100%)
 rename projects/shoggoth/src/{python => }/ichor/typing.py (100%)
 rename projects/shoggoth/src/{python => }/shoggoth/analyzer.py (100%)
 rename projects/shoggoth/src/{python => }/shoggoth/parser.py (100%)
 rename projects/shoggoth/src/{python => }/shoggoth/reader.py (100%)
 rename projects/shoggoth/src/{python => }/shoggoth/repl/__main__.py (100%)
 rename projects/shoggoth/src/{python => }/shoggoth/types.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/fixtures.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/test_assembler.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/test_bootstrap.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/test_interpreter.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/test_parsers.py (100%)
 rename projects/shoggoth/test/{python => }/ichor/test_state.py (100%)
 rename projects/shoggoth/test/{python => }/shogoth/test_parser.py (100%)
 rename projects/smith/src/{python => }/smith/__main__.py (100%)
 rename projects/tentacles/test/{python => }/conftest.py (100%)
 rename projects/tentacles/test/{python => }/test_gcode.py (100%)
 rename projects/tentacles/test/{python => }/test_store.py (100%)
 rename projects/tentacles/test/{python => }/test_store_users.py (100%)
 rename projects/vfs/src/{python => }/vfs/__init__.py (100%)
 rename projects/vfs/src/{python => }/vfs/impl.py (100%)
 rename projects/yamlschema/src/{python => }/yamlschema/__init__.py (100%)
 rename projects/yamlschema/test/{python => }/test_yamlschema.py (100%)

diff --git a/.bazeliskrc b/.bazeliskrc
deleted file mode 100644
index afe0b46..0000000
--- a/.bazeliskrc
+++ /dev/null
@@ -1 +0,0 @@
-USE_BAZEL_VERSION=6.2.0
diff --git a/.bazelversion b/.bazelversion
new file mode 100644
index 0000000..66ce77b
--- /dev/null
+++ b/.bazelversion
@@ -0,0 +1 @@
+7.0.0
diff --git a/projects/activitypub_relay/src/python/relay/__init__.py b/projects/activitypub_relay/src/relay/__init__.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/__init__.py
rename to projects/activitypub_relay/src/relay/__init__.py
diff --git a/projects/activitypub_relay/src/python/relay/__main__.py b/projects/activitypub_relay/src/relay/__main__.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/__main__.py
rename to projects/activitypub_relay/src/relay/__main__.py
diff --git a/projects/activitypub_relay/src/python/relay/application.py b/projects/activitypub_relay/src/relay/application.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/application.py
rename to projects/activitypub_relay/src/relay/application.py
diff --git a/projects/activitypub_relay/src/python/relay/config.py b/projects/activitypub_relay/src/relay/config.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/config.py
rename to projects/activitypub_relay/src/relay/config.py
diff --git a/projects/activitypub_relay/src/python/relay/database.py b/projects/activitypub_relay/src/relay/database.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/database.py
rename to projects/activitypub_relay/src/relay/database.py
diff --git a/projects/activitypub_relay/src/python/relay/http_debug.py b/projects/activitypub_relay/src/relay/http_debug.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/http_debug.py
rename to projects/activitypub_relay/src/relay/http_debug.py
diff --git a/projects/activitypub_relay/src/python/relay/misc.py b/projects/activitypub_relay/src/relay/misc.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/misc.py
rename to projects/activitypub_relay/src/relay/misc.py
diff --git a/projects/activitypub_relay/src/python/relay/processors.py b/projects/activitypub_relay/src/relay/processors.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/processors.py
rename to projects/activitypub_relay/src/relay/processors.py
diff --git a/projects/activitypub_relay/src/python/relay/views.py b/projects/activitypub_relay/src/relay/views.py
similarity index 100%
rename from projects/activitypub_relay/src/python/relay/views.py
rename to projects/activitypub_relay/src/relay/views.py
diff --git a/projects/aloe/src/python/aloe/__main__.py b/projects/aloe/src/aloe/__main__.py
similarity index 100%
rename from projects/aloe/src/python/aloe/__main__.py
rename to projects/aloe/src/aloe/__main__.py
diff --git a/projects/aloe/src/python/aloe/cursedlogger.py b/projects/aloe/src/aloe/cursedlogger.py
similarity index 100%
rename from projects/aloe/src/python/aloe/cursedlogger.py
rename to projects/aloe/src/aloe/cursedlogger.py
diff --git a/projects/aloe/src/python/aloe/icmp.py b/projects/aloe/src/aloe/icmp.py
similarity index 100%
rename from projects/aloe/src/python/aloe/icmp.py
rename to projects/aloe/src/aloe/icmp.py
diff --git a/projects/anosql-migrations/src/python/anosql_migrations.py b/projects/anosql-migrations/src/anosql_migrations.py
similarity index 100%
rename from projects/anosql-migrations/src/python/anosql_migrations.py
rename to projects/anosql-migrations/src/anosql_migrations.py
diff --git a/projects/anosql-migrations/test/python/test_migrations.py b/projects/anosql-migrations/test/test_migrations.py
similarity index 100%
rename from projects/anosql-migrations/test/python/test_migrations.py
rename to projects/anosql-migrations/test/test_migrations.py
diff --git a/projects/anosql/src/python/anosql/__init__.py b/projects/anosql/src/anosql/__init__.py
similarity index 100%
rename from projects/anosql/src/python/anosql/__init__.py
rename to projects/anosql/src/anosql/__init__.py
diff --git a/projects/anosql/src/python/anosql/adapters/__init__.py b/projects/anosql/src/anosql/adapters/__init__.py
similarity index 100%
rename from projects/anosql/src/python/anosql/adapters/__init__.py
rename to projects/anosql/src/anosql/adapters/__init__.py
diff --git a/projects/anosql/src/python/anosql/adapters/psycopg2.py b/projects/anosql/src/anosql/adapters/psycopg2.py
similarity index 100%
rename from projects/anosql/src/python/anosql/adapters/psycopg2.py
rename to projects/anosql/src/anosql/adapters/psycopg2.py
diff --git a/projects/anosql/src/python/anosql/adapters/sqlite3.py b/projects/anosql/src/anosql/adapters/sqlite3.py
similarity index 100%
rename from projects/anosql/src/python/anosql/adapters/sqlite3.py
rename to projects/anosql/src/anosql/adapters/sqlite3.py
diff --git a/projects/anosql/src/python/anosql/core.py b/projects/anosql/src/anosql/core.py
similarity index 100%
rename from projects/anosql/src/python/anosql/core.py
rename to projects/anosql/src/anosql/core.py
diff --git a/projects/anosql/src/python/anosql/exceptions.py b/projects/anosql/src/anosql/exceptions.py
similarity index 100%
rename from projects/anosql/src/python/anosql/exceptions.py
rename to projects/anosql/src/anosql/exceptions.py
diff --git a/projects/anosql/src/python/anosql/patterns.py b/projects/anosql/src/anosql/patterns.py
similarity index 100%
rename from projects/anosql/src/python/anosql/patterns.py
rename to projects/anosql/src/anosql/patterns.py
diff --git a/projects/anosql/test/python/__init__.py b/projects/anosql/test/__init__.py
similarity index 100%
rename from projects/anosql/test/python/__init__.py
rename to projects/anosql/test/__init__.py
diff --git a/projects/anosql/test/python/blogdb/data/blogs_data.csv b/projects/anosql/test/blogdb/data/blogs_data.csv
similarity index 100%
rename from projects/anosql/test/python/blogdb/data/blogs_data.csv
rename to projects/anosql/test/blogdb/data/blogs_data.csv
diff --git a/projects/anosql/test/python/blogdb/data/users_data.csv b/projects/anosql/test/blogdb/data/users_data.csv
similarity index 100%
rename from projects/anosql/test/python/blogdb/data/users_data.csv
rename to projects/anosql/test/blogdb/data/users_data.csv
diff --git a/projects/anosql/test/python/blogdb/sql/blogs/blogs.sql b/projects/anosql/test/blogdb/sql/blogs/blogs.sql
similarity index 100%
rename from projects/anosql/test/python/blogdb/sql/blogs/blogs.sql
rename to projects/anosql/test/blogdb/sql/blogs/blogs.sql
diff --git a/projects/anosql/test/python/blogdb/sql/blogs/blogs_pg.sql b/projects/anosql/test/blogdb/sql/blogs/blogs_pg.sql
similarity index 100%
rename from projects/anosql/test/python/blogdb/sql/blogs/blogs_pg.sql
rename to projects/anosql/test/blogdb/sql/blogs/blogs_pg.sql
diff --git a/projects/anosql/test/python/blogdb/sql/blogs/blogs_sqlite.sql b/projects/anosql/test/blogdb/sql/blogs/blogs_sqlite.sql
similarity index 100%
rename from projects/anosql/test/python/blogdb/sql/blogs/blogs_sqlite.sql
rename to projects/anosql/test/blogdb/sql/blogs/blogs_sqlite.sql
diff --git a/projects/anosql/test/python/blogdb/sql/users/users.sql b/projects/anosql/test/blogdb/sql/users/users.sql
similarity index 100%
rename from projects/anosql/test/python/blogdb/sql/users/users.sql
rename to projects/anosql/test/blogdb/sql/users/users.sql
diff --git a/projects/anosql/test/python/conftest.py b/projects/anosql/test/conftest.py
similarity index 100%
rename from projects/anosql/test/python/conftest.py
rename to projects/anosql/test/conftest.py
diff --git a/projects/anosql/test/python/test_psycopg2.py b/projects/anosql/test/test_psycopg2.py
similarity index 100%
rename from projects/anosql/test/python/test_psycopg2.py
rename to projects/anosql/test/test_psycopg2.py
diff --git a/projects/anosql/test/python/test_simple.py b/projects/anosql/test/test_simple.py
similarity index 100%
rename from projects/anosql/test/python/test_simple.py
rename to projects/anosql/test/test_simple.py
diff --git a/projects/anosql/test/python/test_sqlite3.py b/projects/anosql/test/test_sqlite3.py
similarity index 100%
rename from projects/anosql/test/python/test_sqlite3.py
rename to projects/anosql/test/test_sqlite3.py
diff --git a/projects/async_cache/src/python/async_cache/__init__.py b/projects/async_cache/src/async_cache/__init__.py
similarity index 100%
rename from projects/async_cache/src/python/async_cache/__init__.py
rename to projects/async_cache/src/async_cache/__init__.py
diff --git a/projects/async_cache/src/python/async_cache/key.py b/projects/async_cache/src/async_cache/key.py
similarity index 100%
rename from projects/async_cache/src/python/async_cache/key.py
rename to projects/async_cache/src/async_cache/key.py
diff --git a/projects/async_cache/src/python/async_cache/lru.py b/projects/async_cache/src/async_cache/lru.py
similarity index 100%
rename from projects/async_cache/src/python/async_cache/lru.py
rename to projects/async_cache/src/async_cache/lru.py
diff --git a/projects/async_cache/src/python/async_cache/ttl.py b/projects/async_cache/src/async_cache/ttl.py
similarity index 100%
rename from projects/async_cache/src/python/async_cache/ttl.py
rename to projects/async_cache/src/async_cache/ttl.py
diff --git a/projects/async_cache/test/python/test_lru.py b/projects/async_cache/test/test_lru.py
similarity index 100%
rename from projects/async_cache/test/python/test_lru.py
rename to projects/async_cache/test/test_lru.py
diff --git a/projects/async_cache/test/python/test_ttl.py b/projects/async_cache/test/test_ttl.py
similarity index 100%
rename from projects/async_cache/test/python/test_ttl.py
rename to projects/async_cache/test/test_ttl.py
diff --git a/projects/bazelshim/BUILD.bazel b/projects/bazelshim/BUILD.bazel
new file mode 100644
index 0000000..f5177f6
--- /dev/null
+++ b/projects/bazelshim/BUILD.bazel
@@ -0,0 +1,3 @@
+py_project(
+    name = "bazelshim",
+)
diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
new file mode 100644
index 0000000..9cc9f21
--- /dev/null
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+
+# A Bazel wrapper
+#
+# This script exists to allow for the setting of environment viariables and other context flags to Bazel on behalf of
+# the user. Consequently it has some magical (partial) knowledge of Bazel's CLI options since it's really a CLI shim.
+
+import sys
+from typing import List, Optional
+from shlex import split as shlex
+from dataclasses import dataclass
+
+VERBS = ["sync", "build", "aquery", "query", "cquery", "run", "test", "coverage", "dump", "fetch", "help", "info", "mod",]
+
+def normalize_opts(args: List[str]) -> List[str]:
+    acc = []
+
+    if args[0].endswith("bazel") or args[0].endswith("bazelis"):
+        acc.append(args.pop(0))
+
+    while len(args) >= 2:
+        if args[0] == "--":
+            # Break
+            acc.extend(args)
+            break
+
+        elif args[0].contains("="):
+            # If it's a k/v form pass it through
+            acc.append(args.pop(0))
+
+        elif args[0].startswith("--no"):
+            # Convert --no<foo> args to --<foo>=no
+            acc.append("--" + args.pop(0).lstrip("--no") + "=false")
+
+        elif args[0].startswith("--") and not args[1].startswith("--") and args[1] not in VERBS:
+            # If the next thing isn't an opt, assume it's a '--a b' form
+            acc.append(args[0] + "=" + args[1])
+            args.pop(0)
+            args.pop(0)
+
+        elif args[0].startswith("--"):
+            # Assume it's a boolean true flag
+            acc.append(args.pop(0) + "=true")
+
+        elif args[0] in VERBS:
+            acc.append(args.pop(0))
+
+        else:
+            raise ValueError(repr(args))
+
+    return acc
+
+assert normalize_opts(shlex("bazel clean")) == ["bazel", "clean"]
+assert normalize_opts(shlex("bazel --client_debug clean")) == ["bazel", "--client_debug=true", "clean"]
+assert normalize_opts(shlex("bazel build //foo:bar //baz:*")) == ["bazel", "build", "//foo:bar", "//baz:*"]
+assert normalize_opts(shlex("bazel test //foo:bar //baz:* -- -vvv")) == ["bazel", "test", "//foo:bar", "//baz:*", "--", "-vvv"]
+assert normalize_opts(shlex("bazel run //foo:bar -- --foo=bar --baz=qux")) == ["bazel", "run", "//foo:bar", "--", "--foo=bar", "--baz=qux"]
+
+@dataclass
+class BazelCli:
+    startup_opts: List[str]
+    command: Optional[str]
+    command_opts: List[str]
+    subprocess_opts: List[str]
+
+    @classmethod
+    def parse_cli(cls, args: List[str]) -> BazelCLI:
+        pass
diff --git a/projects/bussard/src/python/bussard/__init__.py b/projects/bussard/src/bussard/__init__.py
similarity index 100%
rename from projects/bussard/src/python/bussard/__init__.py
rename to projects/bussard/src/bussard/__init__.py
diff --git a/projects/bussard/src/python/bussard/bfmt b/projects/bussard/src/bussard/bfmt
similarity index 100%
rename from projects/bussard/src/python/bussard/bfmt
rename to projects/bussard/src/bussard/bfmt
diff --git a/projects/bussard/src/python/bussard/bparse b/projects/bussard/src/bussard/bparse
similarity index 100%
rename from projects/bussard/src/python/bussard/bparse
rename to projects/bussard/src/bussard/bparse
diff --git a/projects/bussard/src/python/bussard/gen/__init__.py b/projects/bussard/src/bussard/gen/__init__.py
similarity index 100%
rename from projects/bussard/src/python/bussard/gen/__init__.py
rename to projects/bussard/src/bussard/gen/__init__.py
diff --git a/projects/bussard/src/python/bussard/reader.py b/projects/bussard/src/bussard/reader.py
similarity index 100%
rename from projects/bussard/src/python/bussard/reader.py
rename to projects/bussard/src/bussard/reader.py
diff --git a/projects/bussard/test/python/bussard/test_reader.py b/projects/bussard/test/bussard/test_reader.py
similarity index 100%
rename from projects/bussard/test/python/bussard/test_reader.py
rename to projects/bussard/test/bussard/test_reader.py
diff --git a/projects/calf/src/python/calf/__init__.py b/projects/calf/src/calf/__init__.py
similarity index 100%
rename from projects/calf/src/python/calf/__init__.py
rename to projects/calf/src/calf/__init__.py
diff --git a/projects/calf/src/python/calf/analyzer.py b/projects/calf/src/calf/analyzer.py
similarity index 100%
rename from projects/calf/src/python/calf/analyzer.py
rename to projects/calf/src/calf/analyzer.py
diff --git a/projects/calf/src/python/calf/cursedrepl.py b/projects/calf/src/calf/cursedrepl.py
similarity index 100%
rename from projects/calf/src/python/calf/cursedrepl.py
rename to projects/calf/src/calf/cursedrepl.py
diff --git a/projects/calf/src/python/calf/grammar.py b/projects/calf/src/calf/grammar.py
similarity index 100%
rename from projects/calf/src/python/calf/grammar.py
rename to projects/calf/src/calf/grammar.py
diff --git a/projects/calf/src/python/calf/io/reader.py b/projects/calf/src/calf/io/reader.py
similarity index 100%
rename from projects/calf/src/python/calf/io/reader.py
rename to projects/calf/src/calf/io/reader.py
diff --git a/projects/calf/src/python/calf/lexer.py b/projects/calf/src/calf/lexer.py
similarity index 100%
rename from projects/calf/src/python/calf/lexer.py
rename to projects/calf/src/calf/lexer.py
diff --git a/projects/calf/src/python/calf/packages.py b/projects/calf/src/calf/packages.py
similarity index 100%
rename from projects/calf/src/python/calf/packages.py
rename to projects/calf/src/calf/packages.py
diff --git a/projects/calf/src/python/calf/parser.py b/projects/calf/src/calf/parser.py
similarity index 100%
rename from projects/calf/src/python/calf/parser.py
rename to projects/calf/src/calf/parser.py
diff --git a/projects/calf/src/python/calf/reader.py b/projects/calf/src/calf/reader.py
similarity index 100%
rename from projects/calf/src/python/calf/reader.py
rename to projects/calf/src/calf/reader.py
diff --git a/projects/calf/src/python/calf/token.py b/projects/calf/src/calf/token.py
similarity index 100%
rename from projects/calf/src/python/calf/token.py
rename to projects/calf/src/calf/token.py
diff --git a/projects/calf/src/python/calf/types.py b/projects/calf/src/calf/types.py
similarity index 100%
rename from projects/calf/src/python/calf/types.py
rename to projects/calf/src/calf/types.py
diff --git a/projects/calf/src/python/calf/util.py b/projects/calf/src/calf/util.py
similarity index 100%
rename from projects/calf/src/python/calf/util.py
rename to projects/calf/src/calf/util.py
diff --git a/projects/cherry-shim/src/python/cherry_shim.py b/projects/cherry-shim/src/cherry_shim.py
similarity index 100%
rename from projects/cherry-shim/src/python/cherry_shim.py
rename to projects/cherry-shim/src/cherry_shim.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/__main__.py b/projects/clusterctrl/src/clusterctrl/__main__.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/__main__.py
rename to projects/clusterctrl/src/clusterctrl/__main__.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/alert.py b/projects/clusterctrl/src/clusterctrl/cmd/alert.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/alert.py
rename to projects/clusterctrl/src/clusterctrl/cmd/alert.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/fan.py b/projects/clusterctrl/src/clusterctrl/cmd/fan.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/fan.py
rename to projects/clusterctrl/src/clusterctrl/cmd/fan.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/hub.py b/projects/clusterctrl/src/clusterctrl/cmd/hub.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/hub.py
rename to projects/clusterctrl/src/clusterctrl/cmd/hub.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/led.py b/projects/clusterctrl/src/clusterctrl/cmd/led.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/led.py
rename to projects/clusterctrl/src/clusterctrl/cmd/led.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/power.py b/projects/clusterctrl/src/clusterctrl/cmd/power.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/power.py
rename to projects/clusterctrl/src/clusterctrl/cmd/power.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/cmd/save.py b/projects/clusterctrl/src/clusterctrl/cmd/save.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/cmd/save.py
rename to projects/clusterctrl/src/clusterctrl/cmd/save.py
diff --git a/projects/clusterctrl/src/python/clusterctrl/driver.py b/projects/clusterctrl/src/clusterctrl/driver.py
similarity index 100%
rename from projects/clusterctrl/src/python/clusterctrl/driver.py
rename to projects/clusterctrl/src/clusterctrl/driver.py
diff --git a/projects/clusterctrl/test/python/test_driver.py b/projects/clusterctrl/test/test_driver.py
similarity index 100%
rename from projects/clusterctrl/test/python/test_driver.py
rename to projects/clusterctrl/test/test_driver.py
diff --git a/projects/damm/src/python/damm.py b/projects/damm/src/damm.py
similarity index 100%
rename from projects/damm/src/python/damm.py
rename to projects/damm/src/damm.py
diff --git a/projects/damm/test/python/test_damm.py b/projects/damm/test/test_damm.py
similarity index 100%
rename from projects/damm/test/python/test_damm.py
rename to projects/damm/test/test_damm.py
diff --git a/projects/damm/test/python/test_hypothesis.py b/projects/damm/test/test_hypothesis.py
similarity index 100%
rename from projects/damm/test/python/test_hypothesis.py
rename to projects/damm/test/test_hypothesis.py
diff --git a/projects/datalog-shell/src/python/datalog/shell/__main__.py b/projects/datalog-shell/src/datalog/shell/__main__.py
similarity index 100%
rename from projects/datalog-shell/src/python/datalog/shell/__main__.py
rename to projects/datalog-shell/src/datalog/shell/__main__.py
diff --git a/projects/datalog/src/python/__init__.py b/projects/datalog/src/__init__.py
similarity index 100%
rename from projects/datalog/src/python/__init__.py
rename to projects/datalog/src/__init__.py
diff --git a/projects/datalog/src/python/datalog/__init__.py b/projects/datalog/src/datalog/__init__.py
similarity index 100%
rename from projects/datalog/src/python/datalog/__init__.py
rename to projects/datalog/src/datalog/__init__.py
diff --git a/projects/datalog/src/python/datalog/debris.py b/projects/datalog/src/datalog/debris.py
similarity index 100%
rename from projects/datalog/src/python/datalog/debris.py
rename to projects/datalog/src/datalog/debris.py
diff --git a/projects/datalog/src/python/datalog/easy.py b/projects/datalog/src/datalog/easy.py
similarity index 100%
rename from projects/datalog/src/python/datalog/easy.py
rename to projects/datalog/src/datalog/easy.py
diff --git a/projects/datalog/src/python/datalog/evaluator.py b/projects/datalog/src/datalog/evaluator.py
similarity index 100%
rename from projects/datalog/src/python/datalog/evaluator.py
rename to projects/datalog/src/datalog/evaluator.py
diff --git a/projects/datalog/src/python/datalog/parser.py b/projects/datalog/src/datalog/parser.py
similarity index 100%
rename from projects/datalog/src/python/datalog/parser.py
rename to projects/datalog/src/datalog/parser.py
diff --git a/projects/datalog/src/python/datalog/reader.py b/projects/datalog/src/datalog/reader.py
similarity index 100%
rename from projects/datalog/src/python/datalog/reader.py
rename to projects/datalog/src/datalog/reader.py
diff --git a/projects/datalog/src/python/datalog/types.py b/projects/datalog/src/datalog/types.py
similarity index 100%
rename from projects/datalog/src/python/datalog/types.py
rename to projects/datalog/src/datalog/types.py
diff --git a/projects/datalog/test/python/test_datalog_evaluator.py b/projects/datalog/test/test_datalog_evaluator.py
similarity index 100%
rename from projects/datalog/test/python/test_datalog_evaluator.py
rename to projects/datalog/test/test_datalog_evaluator.py
diff --git a/projects/datalog/test/python/test_datalog_reader.py b/projects/datalog/test/test_datalog_reader.py
similarity index 100%
rename from projects/datalog/test/python/test_datalog_reader.py
rename to projects/datalog/test/test_datalog_reader.py
diff --git a/projects/flowmetal/src/python/flowmetal/__main__.py b/projects/flowmetal/src/flowmetal/__main__.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/__main__.py
rename to projects/flowmetal/src/flowmetal/__main__.py
diff --git a/projects/flowmetal/src/python/flowmetal/db/base.py b/projects/flowmetal/src/flowmetal/db/base.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/db/base.py
rename to projects/flowmetal/src/flowmetal/db/base.py
diff --git a/projects/flowmetal/src/python/flowmetal/db/redis.py b/projects/flowmetal/src/flowmetal/db/redis.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/db/redis.py
rename to projects/flowmetal/src/flowmetal/db/redis.py
diff --git a/projects/flowmetal/src/python/flowmetal/frontend.py b/projects/flowmetal/src/flowmetal/frontend.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/frontend.py
rename to projects/flowmetal/src/flowmetal/frontend.py
diff --git a/projects/flowmetal/src/python/flowmetal/interpreter.py b/projects/flowmetal/src/flowmetal/interpreter.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/interpreter.py
rename to projects/flowmetal/src/flowmetal/interpreter.py
diff --git a/projects/flowmetal/src/python/flowmetal/models.py b/projects/flowmetal/src/flowmetal/models.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/models.py
rename to projects/flowmetal/src/flowmetal/models.py
diff --git a/projects/flowmetal/src/python/flowmetal/reaper.py b/projects/flowmetal/src/flowmetal/reaper.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/reaper.py
rename to projects/flowmetal/src/flowmetal/reaper.py
diff --git a/projects/flowmetal/src/python/flowmetal/scheduler.py b/projects/flowmetal/src/flowmetal/scheduler.py
similarity index 100%
rename from projects/flowmetal/src/python/flowmetal/scheduler.py
rename to projects/flowmetal/src/flowmetal/scheduler.py
diff --git a/projects/gandi/src/python/gandi/__init__.py b/projects/gandi/src/gandi/__init__.py
similarity index 100%
rename from projects/gandi/src/python/gandi/__init__.py
rename to projects/gandi/src/gandi/__init__.py
diff --git a/projects/gandi/src/python/gandi/client.py b/projects/gandi/src/gandi/client.py
similarity index 100%
rename from projects/gandi/src/python/gandi/client.py
rename to projects/gandi/src/gandi/client.py
diff --git a/projects/gcode-interpreter/src/python/gcode_interpreter.py b/projects/gcode-interpreter/src/gcode_interpreter.py
similarity index 100%
rename from projects/gcode-interpreter/src/python/gcode_interpreter.py
rename to projects/gcode-interpreter/src/gcode_interpreter.py
diff --git a/projects/gh-unnotifier/src/python/ghunnotif/__main__.py b/projects/gh-unnotifier/src/ghunnotif/__main__.py
similarity index 100%
rename from projects/gh-unnotifier/src/python/ghunnotif/__main__.py
rename to projects/gh-unnotifier/src/ghunnotif/__main__.py
diff --git a/projects/jobq/src/python/jobq/__init__.py b/projects/jobq/src/jobq/__init__.py
similarity index 100%
rename from projects/jobq/src/python/jobq/__init__.py
rename to projects/jobq/src/jobq/__init__.py
diff --git a/projects/jobq/test/python/test_jobq.py b/projects/jobq/test/test_jobq.py
similarity index 100%
rename from projects/jobq/test/python/test_jobq.py
rename to projects/jobq/test/test_jobq.py
diff --git a/projects/jobqd/src/python/jobqd/__main__.py b/projects/jobqd/src/jobqd/__main__.py
similarity index 100%
rename from projects/jobqd/src/python/jobqd/__main__.py
rename to projects/jobqd/src/jobqd/__main__.py
diff --git a/projects/jobqd/src/python/jobqd/openapi.yaml b/projects/jobqd/src/jobqd/openapi.yaml
similarity index 100%
rename from projects/jobqd/src/python/jobqd/openapi.yaml
rename to projects/jobqd/src/jobqd/openapi.yaml
diff --git a/projects/jobqd/src/python/jobqd/rest/api.py b/projects/jobqd/src/jobqd/rest/api.py
similarity index 100%
rename from projects/jobqd/src/python/jobqd/rest/api.py
rename to projects/jobqd/src/jobqd/rest/api.py
diff --git a/projects/lilith/test/python/conftest.py b/projects/lilith/test/conftest.py
similarity index 100%
rename from projects/lilith/test/python/conftest.py
rename to projects/lilith/test/conftest.py
diff --git a/projects/lilith/test/python/test_interpreter.py b/projects/lilith/test/test_interpreter.py
similarity index 100%
rename from projects/lilith/test/python/test_interpreter.py
rename to projects/lilith/test/test_interpreter.py
diff --git a/projects/lilith/test/python/test_parser.py b/projects/lilith/test/test_parser.py
similarity index 100%
rename from projects/lilith/test/python/test_parser.py
rename to projects/lilith/test/test_parser.py
diff --git a/projects/lilith/test/python/test_reader.py b/projects/lilith/test/test_reader.py
similarity index 100%
rename from projects/lilith/test/python/test_reader.py
rename to projects/lilith/test/test_reader.py
diff --git a/projects/proquint/src/python/proquint/__init__.py b/projects/proquint/src/proquint/__init__.py
similarity index 100%
rename from projects/proquint/src/python/proquint/__init__.py
rename to projects/proquint/src/proquint/__init__.py
diff --git a/projects/proquint/src/python/proquint/__main__.py b/projects/proquint/src/proquint/__main__.py
similarity index 100%
rename from projects/proquint/src/python/proquint/__main__.py
rename to projects/proquint/src/proquint/__main__.py
diff --git a/projects/proquint/test/python/test_examples.py b/projects/proquint/test/test_examples.py
similarity index 100%
rename from projects/proquint/test/python/test_examples.py
rename to projects/proquint/test/test_examples.py
diff --git a/projects/proquint/test/python/test_hypothesis.py b/projects/proquint/test/test_hypothesis.py
similarity index 100%
rename from projects/proquint/test/python/test_hypothesis.py
rename to projects/proquint/test/test_hypothesis.py
diff --git a/projects/public_dns/src/python/updater/__init__.py b/projects/public_dns/src/updater/__init__.py
similarity index 100%
rename from projects/public_dns/src/python/updater/__init__.py
rename to projects/public_dns/src/updater/__init__.py
diff --git a/projects/public_dns/src/python/updater/__main__.py b/projects/public_dns/src/updater/__main__.py
similarity index 100%
rename from projects/public_dns/src/python/updater/__main__.py
rename to projects/public_dns/src/updater/__main__.py
diff --git a/projects/public_dns/test/python/test_parsing.py b/projects/public_dns/test/test_parsing.py
similarity index 100%
rename from projects/public_dns/test/python/test_parsing.py
rename to projects/public_dns/test/test_parsing.py
diff --git a/projects/ratchet/src/python/ratchet/__init__.py b/projects/ratchet/src/ratchet/__init__.py
similarity index 100%
rename from projects/ratchet/src/python/ratchet/__init__.py
rename to projects/ratchet/src/ratchet/__init__.py
diff --git a/projects/ratchet/src/python/ratchet/backend/sqlite.py b/projects/ratchet/src/ratchet/backend/sqlite.py
similarity index 100%
rename from projects/ratchet/src/python/ratchet/backend/sqlite.py
rename to projects/ratchet/src/ratchet/backend/sqlite.py
diff --git a/projects/reqman/src/python/reqman/__main__.py b/projects/reqman/src/reqman/__main__.py
similarity index 100%
rename from projects/reqman/src/python/reqman/__main__.py
rename to projects/reqman/src/reqman/__main__.py
diff --git a/projects/shoggoth/src/python/ichor/NOTES.md b/projects/shoggoth/src/ichor/NOTES.md
similarity index 100%
rename from projects/shoggoth/src/python/ichor/NOTES.md
rename to projects/shoggoth/src/ichor/NOTES.md
diff --git a/projects/shoggoth/src/python/ichor/__init__.py b/projects/shoggoth/src/ichor/__init__.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/__init__.py
rename to projects/shoggoth/src/ichor/__init__.py
diff --git a/projects/shoggoth/src/python/ichor/__main__.py b/projects/shoggoth/src/ichor/__main__.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/__main__.py
rename to projects/shoggoth/src/ichor/__main__.py
diff --git a/projects/shoggoth/src/python/ichor/assembler.py b/projects/shoggoth/src/ichor/assembler.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/assembler.py
rename to projects/shoggoth/src/ichor/assembler.py
diff --git a/projects/shoggoth/src/python/ichor/bootstrap.py b/projects/shoggoth/src/ichor/bootstrap.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/bootstrap.py
rename to projects/shoggoth/src/ichor/bootstrap.py
diff --git a/projects/shoggoth/src/python/ichor/interpreter.py b/projects/shoggoth/src/ichor/interpreter.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/interpreter.py
rename to projects/shoggoth/src/ichor/interpreter.py
diff --git a/projects/shoggoth/src/python/ichor/isa.py b/projects/shoggoth/src/ichor/isa.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/isa.py
rename to projects/shoggoth/src/ichor/isa.py
diff --git a/projects/shoggoth/src/python/ichor/state.py b/projects/shoggoth/src/ichor/state.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/state.py
rename to projects/shoggoth/src/ichor/state.py
diff --git a/projects/shoggoth/src/python/ichor/typing.py b/projects/shoggoth/src/ichor/typing.py
similarity index 100%
rename from projects/shoggoth/src/python/ichor/typing.py
rename to projects/shoggoth/src/ichor/typing.py
diff --git a/projects/shoggoth/src/python/shoggoth/analyzer.py b/projects/shoggoth/src/shoggoth/analyzer.py
similarity index 100%
rename from projects/shoggoth/src/python/shoggoth/analyzer.py
rename to projects/shoggoth/src/shoggoth/analyzer.py
diff --git a/projects/shoggoth/src/python/shoggoth/parser.py b/projects/shoggoth/src/shoggoth/parser.py
similarity index 100%
rename from projects/shoggoth/src/python/shoggoth/parser.py
rename to projects/shoggoth/src/shoggoth/parser.py
diff --git a/projects/shoggoth/src/python/shoggoth/reader.py b/projects/shoggoth/src/shoggoth/reader.py
similarity index 100%
rename from projects/shoggoth/src/python/shoggoth/reader.py
rename to projects/shoggoth/src/shoggoth/reader.py
diff --git a/projects/shoggoth/src/python/shoggoth/repl/__main__.py b/projects/shoggoth/src/shoggoth/repl/__main__.py
similarity index 100%
rename from projects/shoggoth/src/python/shoggoth/repl/__main__.py
rename to projects/shoggoth/src/shoggoth/repl/__main__.py
diff --git a/projects/shoggoth/src/python/shoggoth/types.py b/projects/shoggoth/src/shoggoth/types.py
similarity index 100%
rename from projects/shoggoth/src/python/shoggoth/types.py
rename to projects/shoggoth/src/shoggoth/types.py
diff --git a/projects/shoggoth/test/python/ichor/fixtures.py b/projects/shoggoth/test/ichor/fixtures.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/fixtures.py
rename to projects/shoggoth/test/ichor/fixtures.py
diff --git a/projects/shoggoth/test/python/ichor/test_assembler.py b/projects/shoggoth/test/ichor/test_assembler.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/test_assembler.py
rename to projects/shoggoth/test/ichor/test_assembler.py
diff --git a/projects/shoggoth/test/python/ichor/test_bootstrap.py b/projects/shoggoth/test/ichor/test_bootstrap.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/test_bootstrap.py
rename to projects/shoggoth/test/ichor/test_bootstrap.py
diff --git a/projects/shoggoth/test/python/ichor/test_interpreter.py b/projects/shoggoth/test/ichor/test_interpreter.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/test_interpreter.py
rename to projects/shoggoth/test/ichor/test_interpreter.py
diff --git a/projects/shoggoth/test/python/ichor/test_parsers.py b/projects/shoggoth/test/ichor/test_parsers.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/test_parsers.py
rename to projects/shoggoth/test/ichor/test_parsers.py
diff --git a/projects/shoggoth/test/python/ichor/test_state.py b/projects/shoggoth/test/ichor/test_state.py
similarity index 100%
rename from projects/shoggoth/test/python/ichor/test_state.py
rename to projects/shoggoth/test/ichor/test_state.py
diff --git a/projects/shoggoth/test/python/shogoth/test_parser.py b/projects/shoggoth/test/shogoth/test_parser.py
similarity index 100%
rename from projects/shoggoth/test/python/shogoth/test_parser.py
rename to projects/shoggoth/test/shogoth/test_parser.py
diff --git a/projects/smith/src/python/smith/__main__.py b/projects/smith/src/smith/__main__.py
similarity index 100%
rename from projects/smith/src/python/smith/__main__.py
rename to projects/smith/src/smith/__main__.py
diff --git a/projects/tentacles/test/python/conftest.py b/projects/tentacles/test/conftest.py
similarity index 100%
rename from projects/tentacles/test/python/conftest.py
rename to projects/tentacles/test/conftest.py
diff --git a/projects/tentacles/test/python/test_gcode.py b/projects/tentacles/test/test_gcode.py
similarity index 100%
rename from projects/tentacles/test/python/test_gcode.py
rename to projects/tentacles/test/test_gcode.py
diff --git a/projects/tentacles/test/python/test_store.py b/projects/tentacles/test/test_store.py
similarity index 100%
rename from projects/tentacles/test/python/test_store.py
rename to projects/tentacles/test/test_store.py
diff --git a/projects/tentacles/test/python/test_store_users.py b/projects/tentacles/test/test_store_users.py
similarity index 100%
rename from projects/tentacles/test/python/test_store_users.py
rename to projects/tentacles/test/test_store_users.py
diff --git a/projects/vfs/src/python/vfs/__init__.py b/projects/vfs/src/vfs/__init__.py
similarity index 100%
rename from projects/vfs/src/python/vfs/__init__.py
rename to projects/vfs/src/vfs/__init__.py
diff --git a/projects/vfs/src/python/vfs/impl.py b/projects/vfs/src/vfs/impl.py
similarity index 100%
rename from projects/vfs/src/python/vfs/impl.py
rename to projects/vfs/src/vfs/impl.py
diff --git a/projects/yamlschema/src/python/yamlschema/__init__.py b/projects/yamlschema/src/yamlschema/__init__.py
similarity index 100%
rename from projects/yamlschema/src/python/yamlschema/__init__.py
rename to projects/yamlschema/src/yamlschema/__init__.py
diff --git a/projects/yamlschema/test/python/test_yamlschema.py b/projects/yamlschema/test/test_yamlschema.py
similarity index 100%
rename from projects/yamlschema/test/python/test_yamlschema.py
rename to projects/yamlschema/test/test_yamlschema.py
diff --git a/tools/build_rules/prelude_bazel b/tools/build_rules/prelude_bazel
index 97565b3..2b615ad 100644
--- a/tools/build_rules/prelude_bazel
+++ b/tools/build_rules/prelude_bazel
@@ -36,10 +36,3 @@ load("//tools/build_rules:webp.bzl",
 load("@rules_zapp//zapp:zapp.bzl",
      "zapp_binary",
 )
-
-load(
-    "@io_bazel_rules_docker//container:container.bzl",
-    "container_image",
-    "container_bundle",
-    "container_push",
-)
diff --git a/tools/python/BUILD.bazel b/tools/python/BUILD.bazel
index 181f52e..860a229 100644
--- a/tools/python/BUILD.bazel
+++ b/tools/python/BUILD.bazel
@@ -40,8 +40,5 @@ py_pytest(
     srcs = [
         "test_licenses.py",
     ],
-    data = [
-        "requirements.txt",
-    ],
     deps = all_requirements,
 )
diff --git a/tools/python/defs.bzl b/tools/python/defs.bzl
index 4e750bd..5c87d12 100644
--- a/tools/python/defs.bzl
+++ b/tools/python/defs.bzl
@@ -170,7 +170,7 @@ def py_project(name=None,
     """
     A helper for defining conventionally-formatted python project.
 
-    Assumes that there's a {src,test}/{resources,python} where src/ is a library and test/ is local tests only.
+    Assumes that there's a {src,test}/ where src/ is a library and test/ is local tests only.
 
     Each test_*.py source generates its own implicit test target. This allows for automatic test parallelism. Non
     test_*.py files are implicitly srcs for the generated test targets. This is the same as making them implicitly a
@@ -179,28 +179,26 @@ def py_project(name=None,
     """
 
     lib_srcs = (lib_srcs or []) + \
-        native.glob(["src/python/**/*.py"],
+        native.glob(["src/**/*.py"],
                     exclude=[
                         "**/*.pyc",
                     ])
 
     lib_data = (lib_data or []) + \
-        native.glob(["src/resources/**/*",
-                     "src/python/**/*"],
+        native.glob(["src/**/*"],
                     exclude=[
                         "**/*.py",
                         "**/*.pyc",
                     ])
 
     test_srcs = (test_srcs or []) + \
-        native.glob(["test/python/**/*.py"],
+        native.glob(["test/**/*.py"],
                     exclude=[
                         "**/*.pyc",
                     ])
 
     test_data = (test_data or []) + \
-        native.glob(["test/resources/**/*",
-                     "test/python/**/*"],
+        native.glob(["test/**/*"],
                     exclude=[
                         "**/*.py",
                         "**/*.pyc",
diff --git a/tools/python/test_licenses.py b/tools/python/test_licenses.py
index 32e7246..32e9515 100644
--- a/tools/python/test_licenses.py
+++ b/tools/python/test_licenses.py
@@ -22,8 +22,11 @@ APPROVED_LICENSES = [
     MPL20 := "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
     PSFL := "License :: OSI Approved :: Python Software Foundation License",
     LGPL := "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
-    LGPL3 := "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
+    LGPL3 := 'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
+    LGPL3P := "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
     ISCL := "License :: OSI Approved :: ISC License (ISCL)",
+    ZOPE := 'License :: OSI Approved :: Zope Public License',
+    PUBLIC := 'License :: Public Domain',
 ]
 
 UNAPPROVED_LICENSES = [
@@ -35,6 +38,7 @@ UNAPPROVED_LICENSES = [
 # This data is GARBO.
 LICENSES_BY_LOWERNAME = {
     "apache 2.0": APACHE,
+    "apache 2": APACHE,
     "apache": APACHE,
     "http://www.apache.org/licenses/license-2.0": APACHE,
     "bsd 3": BSD,
@@ -61,6 +65,8 @@ APPROVED_PACKAGES = [
     "yamllint",  # WARNING: YAMLLINT IS GLP3"d.
     "Flask_Log_Request_ID",  # MIT, currently depended on as a git dep.
     "anosql",  # BSD
+    "pathable", # Apache 2
+    "proquint", # MIT
 ]
 
 
@@ -126,7 +132,7 @@ def licenses(dist: DistInfoDistribution):
     if not lics:
         lics.append(license)
 
-    return lics
+    return [l.strip() for l in lics]
 
 
 @pytest.mark.parametrize(

From 20b662a1426537c4bf6f0b664b1644d6237a6d10 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 11:18:33 -0700
Subject: [PATCH 03/15] fix

---
 projects/activitypub_relay/BUILD.bazel | 2 +-
 projects/aloe/BUILD.bazel              | 2 +-
 projects/calf/BUILD.bazel              | 2 +-
 projects/clusterctrl/BUILD.bazel       | 2 +-
 projects/datalog-shell/BUILD.bazel     | 2 +-
 projects/flowmetal/BUILD.bazel         | 4 ++--
 projects/gandi/BUILD.bazel             | 2 +-
 projects/gh-unnotifier/BUILD.bazel     | 2 +-
 projects/jobqd/BUILD.bazel             | 4 ++--
 projects/lilith/BUILD.bazel            | 2 +-
 projects/proquint/BUILD.bazel          | 2 +-
 projects/public_dns/BUILD.bazel        | 2 +-
 projects/ratchet/BUILD.bazel           | 2 +-
 projects/reqman/BUILD.bazel            | 2 +-
 projects/shoggoth/BUILD.bazel          | 4 ++--
 projects/smith/BUILD.bazel             | 2 +-
 projects/tentacles/BUILD.bazel         | 4 ++--
 17 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/projects/activitypub_relay/BUILD.bazel b/projects/activitypub_relay/BUILD.bazel
index 2996201..bc5205a 100644
--- a/projects/activitypub_relay/BUILD.bazel
+++ b/projects/activitypub_relay/BUILD.bazel
@@ -10,6 +10,6 @@ py_project(
         py_requirement("pyyaml"),
         py_requirement("retry"),
     ],
-    main = "src/python/relay/__main__.py",
+    main = "src/relay/__main__.py",
     shebang = "/usr/bin/env python3"
 )
diff --git a/projects/aloe/BUILD.bazel b/projects/aloe/BUILD.bazel
index 97107d9..70e6342 100644
--- a/projects/aloe/BUILD.bazel
+++ b/projects/aloe/BUILD.bazel
@@ -4,7 +4,7 @@ py_project(
 
 zapp_binary(
     name = "aloe",
-    main = "src/python/aloe/__main__.py",
+    main = "src/aloe/__main__.py",
     deps = [
         ":lib",
         py_requirement("icmplib"),
diff --git a/projects/calf/BUILD.bazel b/projects/calf/BUILD.bazel
index c1e87be..baed3a6 100644
--- a/projects/calf/BUILD.bazel
+++ b/projects/calf/BUILD.bazel
@@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_library(
     name = "lib",
-    srcs = glob(["src/python/**/*.py"]),
+    srcs = glob(["src/**/*.py"]),
     imports = ["src/python"],
     deps = [
         py_requirement("pyrsistent"),
diff --git a/projects/clusterctrl/BUILD.bazel b/projects/clusterctrl/BUILD.bazel
index 0f44e22..9de3323 100644
--- a/projects/clusterctrl/BUILD.bazel
+++ b/projects/clusterctrl/BUILD.bazel
@@ -7,7 +7,7 @@ py_project(
 
 zapp_binary(
     name = "clusterctrl",
-    main = "src/python/clusterctrl/__main__.py",
+    main = "src/clusterctrl/__main__.py",
     imports = [
         "src/python",
     ],
diff --git a/projects/datalog-shell/BUILD.bazel b/projects/datalog-shell/BUILD.bazel
index 0a4e2d9..f849f1d 100644
--- a/projects/datalog-shell/BUILD.bazel
+++ b/projects/datalog-shell/BUILD.bazel
@@ -1,6 +1,6 @@
 zapp_binary(
     name = "datalog-shell",
-    main = "src/python/datalog/shell/__main__.py",
+    main = "src/datalog/shell/__main__.py",
     imports = [
         "src/python"
     ],
diff --git a/projects/flowmetal/BUILD.bazel b/projects/flowmetal/BUILD.bazel
index 1df43c3..6110e78 100644
--- a/projects/flowmetal/BUILD.bazel
+++ b/projects/flowmetal/BUILD.bazel
@@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_library(
     name = "lib",
-    srcs = glob(["src/python/flowmetal/*.py"]),
+    srcs = glob(["src/flowmetal/*.py"]),
     imports = [
         "src/python"
     ],
@@ -17,5 +17,5 @@ py_binary(
         py_requirement("click"),
         py_requirement("redis"),
     ],
-    main = "src/python/flowmetal/__main__.py",
+    main = "src/flowmetal/__main__.py",
 )
diff --git a/projects/gandi/BUILD.bazel b/projects/gandi/BUILD.bazel
index 936b3c7..e887cbb 100644
--- a/projects/gandi/BUILD.bazel
+++ b/projects/gandi/BUILD.bazel
@@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_library(
     name = "gandi",
-    srcs = glob(["src/python/gandi/client.py"]),
+    srcs = glob(["src/gandi/client.py"]),
     imports = [
         "src/python",
     ],
diff --git a/projects/gh-unnotifier/BUILD.bazel b/projects/gh-unnotifier/BUILD.bazel
index a820dab..6373c3e 100644
--- a/projects/gh-unnotifier/BUILD.bazel
+++ b/projects/gh-unnotifier/BUILD.bazel
@@ -1,6 +1,6 @@
 py_project(
     name = "gh-unnotifier",
-    main = "src/python/ghunnotif/__main__.py",
+    main = "src/ghunnotif/__main__.py",
     main_deps = [
         py_requirement("click"),
         py_requirement("requests"),
diff --git a/projects/jobqd/BUILD.bazel b/projects/jobqd/BUILD.bazel
index 71d56e8..5b1e36d 100644
--- a/projects/jobqd/BUILD.bazel
+++ b/projects/jobqd/BUILD.bazel
@@ -1,6 +1,6 @@
 zapp_binary(
     name = "jobqd",
-    main = "src/python/jobqd/__main__.py",
+    main = "src/jobqd/__main__.py",
     imports = [
         "src/python",
     ],
@@ -13,7 +13,7 @@ zapp_binary(
 py_library(
     name = "client",
     srcs = [
-        "src/python/jobqd/rest/api.py",
+        "src/jobqd/rest/api.py",
     ],
     imports = [
         "src/python",
diff --git a/projects/lilith/BUILD.bazel b/projects/lilith/BUILD.bazel
index c7909ad..858526e 100644
--- a/projects/lilith/BUILD.bazel
+++ b/projects/lilith/BUILD.bazel
@@ -1,6 +1,6 @@
 py_project(
     name = "lilith",
-    main = "src/python/lilith/__main__.py",
+    main = "src/lilith/__main__.py",
     lib_deps = [
         py_requirement("lark"),
         py_requirement("pyyaml"),
diff --git a/projects/proquint/BUILD.bazel b/projects/proquint/BUILD.bazel
index c55fdfd..c94e574 100644
--- a/projects/proquint/BUILD.bazel
+++ b/projects/proquint/BUILD.bazel
@@ -7,7 +7,7 @@ py_project(
 
 zapp_binary(
     name = "qint",
-    main = "src/python/proquint/__main__.py",
+    main = "src/proquint/__main__.py",
     shebang = "#!/usr/bin/env python3",
     imports = [
         "src/python",
diff --git a/projects/public_dns/BUILD.bazel b/projects/public_dns/BUILD.bazel
index 989fd2e..487b8bb 100644
--- a/projects/public_dns/BUILD.bazel
+++ b/projects/public_dns/BUILD.bazel
@@ -1,6 +1,6 @@
 py_project(
     name = "updater",
-    main = "src/python/updater/__main__.py",
+    main = "src/updater/__main__.py",
     shebang = "/usr/bin/env python3",
     lib_deps = [
         "//projects/gandi",
diff --git a/projects/ratchet/BUILD.bazel b/projects/ratchet/BUILD.bazel
index fe5d756..f2e5198 100644
--- a/projects/ratchet/BUILD.bazel
+++ b/projects/ratchet/BUILD.bazel
@@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"])
 
 py_library(
     name = "lib",
-    srcs = glob(["src/python/**/*.py"]),
+    srcs = glob(["src/**/*.py"]),
     imports = ["src/python"],
     deps = [
     ]
diff --git a/projects/reqman/BUILD.bazel b/projects/reqman/BUILD.bazel
index fc2cb8b..ef2d306 100644
--- a/projects/reqman/BUILD.bazel
+++ b/projects/reqman/BUILD.bazel
@@ -1,6 +1,6 @@
 zapp_binary(
     name = "reqman",
-    main = "src/python/reqman/__main__.py",
+    main = "src/reqman/__main__.py",
     imports = [
         "src/python",
     ],
diff --git a/projects/shoggoth/BUILD.bazel b/projects/shoggoth/BUILD.bazel
index 563d7bb..3e46607 100644
--- a/projects/shoggoth/BUILD.bazel
+++ b/projects/shoggoth/BUILD.bazel
@@ -1,6 +1,6 @@
 py_project(
     name = "shoggoth",
-    main = "src/python/shoggoth/repl/__main__.py",
+    main = "src/shoggoth/repl/__main__.py",
     main_deps = [
         py_requirement("prompt_toolkit"),
         py_requirement("yaspin"),
@@ -17,7 +17,7 @@ py_project(
 
 zapp_binary(
     name ="ichor",
-    main = "src/python/ichor/__main__.py",
+    main = "src/ichor/__main__.py",
     shebang ="/usr/bin/env python3",
     deps = [
         ":lib",
diff --git a/projects/smith/BUILD.bazel b/projects/smith/BUILD.bazel
index f69a080..8936098 100644
--- a/projects/smith/BUILD.bazel
+++ b/projects/smith/BUILD.bazel
@@ -7,5 +7,5 @@ py_project(
     main_deps = [
         py_requirement("click"),
     ],
-    main = "src/python/smith/__main__.py",
+    main = "src/smith/__main__.py",
 )
diff --git a/projects/tentacles/BUILD.bazel b/projects/tentacles/BUILD.bazel
index 349c659..7ee4194 100644
--- a/projects/tentacles/BUILD.bazel
+++ b/projects/tentacles/BUILD.bazel
@@ -2,7 +2,7 @@ py_project(
     name = "tentacles",
     shebang = "/usr/bin/env python3",
     zip_safe = False,
-    main = "src/python/tentacles/__main__.py",
+    main = "src/tentacles/__main__.py",
     main_deps = [
         "//projects/anosql",
         "//projects/anosql-migrations",
@@ -15,6 +15,6 @@ py_project(
         py_requirement("cherrypy"),
     ],
     lib_data = [
-        "//projects/tentacles/src/python/tentacles/static/css",
+        "//projects/tentacles/src/tentacles/static/css",
     ],
 )

From c1de143471bafe646f909c1ff730b9fd89391bd7 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 11:19:46 -0700
Subject: [PATCH 04/15] m0ar

---
 projects/tentacles/src/{python => }/fastmail.py     |   0
 projects/tentacles/src/{python => }/gcode.py        |   0
 .../src/{python => }/tentacles/__init__.py          |   0
 .../src/{python => }/tentacles/__main__.py          |   0
 .../{python => }/tentacles/blueprints/admin_ui.py   |   0
 .../src/{python => }/tentacles/blueprints/api.py    |   0
 .../{python => }/tentacles/blueprints/file_ui.py    |   0
 .../src/{python => }/tentacles/blueprints/job_ui.py |   0
 .../{python => }/tentacles/blueprints/user_ui.py    |   0
 .../src/{python => }/tentacles/blueprints/util.py   |   0
 projects/tentacles/src/{python => }/tentacles/db.py |   0
 .../tentacles/src/{python => }/tentacles/globals.py |   0
 .../src/{python => }/tentacles/sql/__init__.py      |   0
 .../src/{python => }/tentacles/sql/emails.sql       |   0
 .../src/{python => }/tentacles/sql/files.sql        |   0
 .../src/{python => }/tentacles/sql/jobs.sql         |   0
 .../src/{python => }/tentacles/sql/migrations.sql   |   0
 .../src/{python => }/tentacles/sql/printers.sql     |   0
 .../src/{python => }/tentacles/sql/user_keys.sql    |   0
 .../{python => }/tentacles/sql/user_statuses.sql    |   0
 .../src/{python => }/tentacles/sql/users.sql        |   0
 .../src/{python => }/tentacles/static/__init__.py   |   0
 .../src/{python => }/tentacles/static/cancel.svg    |   0
 .../{python => }/tentacles/static/css/BUILD.bazel   |   0
 .../tentacles/static/css/_normalize.scss            |   0
 .../tentacles/static/css/_skeleton.scss             |   0
 .../tentacles/static/css/_tirefire.scss             |   0
 .../{python => }/tentacles/static/css/style.scss    |   0
 .../tentacles/static/css/tirefire/_alerts.scss      |   0
 .../tentacles/static/css/tirefire/_basics.scss      |   0
 .../tentacles/static/css/tirefire/_colors.scss      |   0
 .../tentacles/static/css/tirefire/_dots.scss        |   0
 .../tentacles/static/css/tirefire/_fonts.scss       |   0
 .../tentacles/static/css/tirefire/_nav.scss         |   0
 .../tentacles/static/css/tirefire/_timers.scss      |   0
 .../tentacles/static/css/tirefire/_tooltips.scss    |   0
 .../src/{python => }/tentacles/static/delete.svg    |   0
 .../src/{python => }/tentacles/static/download.svg  |   0
 .../tentacles/static/font/AauxNextBlk.otf           | Bin
 .../tentacles/static/font/aauxnextbdwebfont.otf     | Bin
 .../tentacles/static/font/aauxnextltwebfont.otf     | Bin
 .../tentacles/static/font/aauxnextmdwebfont.otf     | Bin
 .../src/{python => }/tentacles/static/print.svg     |   0
 .../src/{python => }/tentacles/static/tentacles.svg |   0
 .../{python => }/tentacles/templates/__init__.py    |   0
 .../tentacles/templates/add_printer.html.j2         |   0
 .../{python => }/tentacles/templates/admin.html.j2  |   0
 .../templates/analysis_failure_email.html.j2        |   0
 .../tentacles/templates/approval_email.html.j2      |   0
 .../{python => }/tentacles/templates/base.html.j2   |   0
 .../tentacles/templates/edit_printer.html.j2        |   0
 .../{python => }/tentacles/templates/files.html.j2  |   0
 .../tentacles/templates/files_admin_list.html.j2    |   0
 .../tentacles/templates/files_list.html.j2          |   0
 .../{python => }/tentacles/templates/index.html.j2  |   0
 .../{python => }/tentacles/templates/jobs.html.j2   |   0
 .../tentacles/templates/jobs_history.html.j2        |   0
 .../tentacles/templates/jobs_list.html.j2           |   0
 .../{python => }/tentacles/templates/login.html.j2  |   0
 .../{python => }/tentacles/templates/macros.html.j2 |   0
 .../tentacles/templates/printers.html.j2            |   0
 .../tentacles/templates/printers_list.html.j2       |   0
 .../tentacles/templates/register.html.j2            |   0
 .../tentacles/templates/streams.html.j2             |   0
 .../{python => }/tentacles/templates/user.html.j2   |   0
 .../tentacles/templates/users_list.html.j2          |   0
 .../tentacles/templates/verification_email.html.j2  |   0
 .../tentacles/src/{python => }/tentacles/workers.py |   0
 68 files changed, 0 insertions(+), 0 deletions(-)
 rename projects/tentacles/src/{python => }/fastmail.py (100%)
 rename projects/tentacles/src/{python => }/gcode.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/__init__.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/__main__.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/admin_ui.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/api.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/file_ui.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/job_ui.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/user_ui.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/blueprints/util.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/db.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/globals.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/__init__.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/emails.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/files.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/jobs.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/migrations.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/printers.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/user_keys.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/user_statuses.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/sql/users.sql (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/__init__.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/cancel.svg (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/BUILD.bazel (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/_normalize.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/_skeleton.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/_tirefire.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/style.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_alerts.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_basics.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_colors.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_dots.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_fonts.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_nav.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_timers.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/css/tirefire/_tooltips.scss (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/delete.svg (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/download.svg (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/font/AauxNextBlk.otf (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/font/aauxnextbdwebfont.otf (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/font/aauxnextltwebfont.otf (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/font/aauxnextmdwebfont.otf (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/print.svg (100%)
 rename projects/tentacles/src/{python => }/tentacles/static/tentacles.svg (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/__init__.py (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/add_printer.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/admin.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/analysis_failure_email.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/approval_email.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/base.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/edit_printer.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/files.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/files_admin_list.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/files_list.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/index.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/jobs.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/jobs_history.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/jobs_list.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/login.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/macros.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/printers.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/printers_list.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/register.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/streams.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/user.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/users_list.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/templates/verification_email.html.j2 (100%)
 rename projects/tentacles/src/{python => }/tentacles/workers.py (100%)

diff --git a/projects/tentacles/src/python/fastmail.py b/projects/tentacles/src/fastmail.py
similarity index 100%
rename from projects/tentacles/src/python/fastmail.py
rename to projects/tentacles/src/fastmail.py
diff --git a/projects/tentacles/src/python/gcode.py b/projects/tentacles/src/gcode.py
similarity index 100%
rename from projects/tentacles/src/python/gcode.py
rename to projects/tentacles/src/gcode.py
diff --git a/projects/tentacles/src/python/tentacles/__init__.py b/projects/tentacles/src/tentacles/__init__.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/__init__.py
rename to projects/tentacles/src/tentacles/__init__.py
diff --git a/projects/tentacles/src/python/tentacles/__main__.py b/projects/tentacles/src/tentacles/__main__.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/__main__.py
rename to projects/tentacles/src/tentacles/__main__.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/admin_ui.py b/projects/tentacles/src/tentacles/blueprints/admin_ui.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/admin_ui.py
rename to projects/tentacles/src/tentacles/blueprints/admin_ui.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/api.py b/projects/tentacles/src/tentacles/blueprints/api.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/api.py
rename to projects/tentacles/src/tentacles/blueprints/api.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/file_ui.py b/projects/tentacles/src/tentacles/blueprints/file_ui.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/file_ui.py
rename to projects/tentacles/src/tentacles/blueprints/file_ui.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/job_ui.py b/projects/tentacles/src/tentacles/blueprints/job_ui.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/job_ui.py
rename to projects/tentacles/src/tentacles/blueprints/job_ui.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/user_ui.py b/projects/tentacles/src/tentacles/blueprints/user_ui.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/user_ui.py
rename to projects/tentacles/src/tentacles/blueprints/user_ui.py
diff --git a/projects/tentacles/src/python/tentacles/blueprints/util.py b/projects/tentacles/src/tentacles/blueprints/util.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/blueprints/util.py
rename to projects/tentacles/src/tentacles/blueprints/util.py
diff --git a/projects/tentacles/src/python/tentacles/db.py b/projects/tentacles/src/tentacles/db.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/db.py
rename to projects/tentacles/src/tentacles/db.py
diff --git a/projects/tentacles/src/python/tentacles/globals.py b/projects/tentacles/src/tentacles/globals.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/globals.py
rename to projects/tentacles/src/tentacles/globals.py
diff --git a/projects/tentacles/src/python/tentacles/sql/__init__.py b/projects/tentacles/src/tentacles/sql/__init__.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/__init__.py
rename to projects/tentacles/src/tentacles/sql/__init__.py
diff --git a/projects/tentacles/src/python/tentacles/sql/emails.sql b/projects/tentacles/src/tentacles/sql/emails.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/emails.sql
rename to projects/tentacles/src/tentacles/sql/emails.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/files.sql b/projects/tentacles/src/tentacles/sql/files.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/files.sql
rename to projects/tentacles/src/tentacles/sql/files.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/jobs.sql b/projects/tentacles/src/tentacles/sql/jobs.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/jobs.sql
rename to projects/tentacles/src/tentacles/sql/jobs.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/migrations.sql b/projects/tentacles/src/tentacles/sql/migrations.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/migrations.sql
rename to projects/tentacles/src/tentacles/sql/migrations.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/printers.sql b/projects/tentacles/src/tentacles/sql/printers.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/printers.sql
rename to projects/tentacles/src/tentacles/sql/printers.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/user_keys.sql b/projects/tentacles/src/tentacles/sql/user_keys.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/user_keys.sql
rename to projects/tentacles/src/tentacles/sql/user_keys.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/user_statuses.sql b/projects/tentacles/src/tentacles/sql/user_statuses.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/user_statuses.sql
rename to projects/tentacles/src/tentacles/sql/user_statuses.sql
diff --git a/projects/tentacles/src/python/tentacles/sql/users.sql b/projects/tentacles/src/tentacles/sql/users.sql
similarity index 100%
rename from projects/tentacles/src/python/tentacles/sql/users.sql
rename to projects/tentacles/src/tentacles/sql/users.sql
diff --git a/projects/tentacles/src/python/tentacles/static/__init__.py b/projects/tentacles/src/tentacles/static/__init__.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/__init__.py
rename to projects/tentacles/src/tentacles/static/__init__.py
diff --git a/projects/tentacles/src/python/tentacles/static/cancel.svg b/projects/tentacles/src/tentacles/static/cancel.svg
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/cancel.svg
rename to projects/tentacles/src/tentacles/static/cancel.svg
diff --git a/projects/tentacles/src/python/tentacles/static/css/BUILD.bazel b/projects/tentacles/src/tentacles/static/css/BUILD.bazel
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/BUILD.bazel
rename to projects/tentacles/src/tentacles/static/css/BUILD.bazel
diff --git a/projects/tentacles/src/python/tentacles/static/css/_normalize.scss b/projects/tentacles/src/tentacles/static/css/_normalize.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/_normalize.scss
rename to projects/tentacles/src/tentacles/static/css/_normalize.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/_skeleton.scss b/projects/tentacles/src/tentacles/static/css/_skeleton.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/_skeleton.scss
rename to projects/tentacles/src/tentacles/static/css/_skeleton.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/_tirefire.scss b/projects/tentacles/src/tentacles/static/css/_tirefire.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/_tirefire.scss
rename to projects/tentacles/src/tentacles/static/css/_tirefire.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/style.scss b/projects/tentacles/src/tentacles/static/css/style.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/style.scss
rename to projects/tentacles/src/tentacles/static/css/style.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_alerts.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_alerts.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_alerts.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_alerts.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_basics.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_basics.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_basics.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_basics.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_colors.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_colors.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_colors.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_colors.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_dots.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_dots.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_fonts.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_fonts.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_fonts.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_fonts.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_nav.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_nav.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_nav.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_nav.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_timers.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_timers.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_timers.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_timers.scss
diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_tooltips.scss b/projects/tentacles/src/tentacles/static/css/tirefire/_tooltips.scss
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/css/tirefire/_tooltips.scss
rename to projects/tentacles/src/tentacles/static/css/tirefire/_tooltips.scss
diff --git a/projects/tentacles/src/python/tentacles/static/delete.svg b/projects/tentacles/src/tentacles/static/delete.svg
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/delete.svg
rename to projects/tentacles/src/tentacles/static/delete.svg
diff --git a/projects/tentacles/src/python/tentacles/static/download.svg b/projects/tentacles/src/tentacles/static/download.svg
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/download.svg
rename to projects/tentacles/src/tentacles/static/download.svg
diff --git a/projects/tentacles/src/python/tentacles/static/font/AauxNextBlk.otf b/projects/tentacles/src/tentacles/static/font/AauxNextBlk.otf
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/font/AauxNextBlk.otf
rename to projects/tentacles/src/tentacles/static/font/AauxNextBlk.otf
diff --git a/projects/tentacles/src/python/tentacles/static/font/aauxnextbdwebfont.otf b/projects/tentacles/src/tentacles/static/font/aauxnextbdwebfont.otf
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/font/aauxnextbdwebfont.otf
rename to projects/tentacles/src/tentacles/static/font/aauxnextbdwebfont.otf
diff --git a/projects/tentacles/src/python/tentacles/static/font/aauxnextltwebfont.otf b/projects/tentacles/src/tentacles/static/font/aauxnextltwebfont.otf
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/font/aauxnextltwebfont.otf
rename to projects/tentacles/src/tentacles/static/font/aauxnextltwebfont.otf
diff --git a/projects/tentacles/src/python/tentacles/static/font/aauxnextmdwebfont.otf b/projects/tentacles/src/tentacles/static/font/aauxnextmdwebfont.otf
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/font/aauxnextmdwebfont.otf
rename to projects/tentacles/src/tentacles/static/font/aauxnextmdwebfont.otf
diff --git a/projects/tentacles/src/python/tentacles/static/print.svg b/projects/tentacles/src/tentacles/static/print.svg
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/print.svg
rename to projects/tentacles/src/tentacles/static/print.svg
diff --git a/projects/tentacles/src/python/tentacles/static/tentacles.svg b/projects/tentacles/src/tentacles/static/tentacles.svg
similarity index 100%
rename from projects/tentacles/src/python/tentacles/static/tentacles.svg
rename to projects/tentacles/src/tentacles/static/tentacles.svg
diff --git a/projects/tentacles/src/python/tentacles/templates/__init__.py b/projects/tentacles/src/tentacles/templates/__init__.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/__init__.py
rename to projects/tentacles/src/tentacles/templates/__init__.py
diff --git a/projects/tentacles/src/python/tentacles/templates/add_printer.html.j2 b/projects/tentacles/src/tentacles/templates/add_printer.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/add_printer.html.j2
rename to projects/tentacles/src/tentacles/templates/add_printer.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/admin.html.j2 b/projects/tentacles/src/tentacles/templates/admin.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/admin.html.j2
rename to projects/tentacles/src/tentacles/templates/admin.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/analysis_failure_email.html.j2 b/projects/tentacles/src/tentacles/templates/analysis_failure_email.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/analysis_failure_email.html.j2
rename to projects/tentacles/src/tentacles/templates/analysis_failure_email.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/approval_email.html.j2 b/projects/tentacles/src/tentacles/templates/approval_email.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/approval_email.html.j2
rename to projects/tentacles/src/tentacles/templates/approval_email.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/base.html.j2 b/projects/tentacles/src/tentacles/templates/base.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/base.html.j2
rename to projects/tentacles/src/tentacles/templates/base.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/edit_printer.html.j2 b/projects/tentacles/src/tentacles/templates/edit_printer.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/edit_printer.html.j2
rename to projects/tentacles/src/tentacles/templates/edit_printer.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/files.html.j2 b/projects/tentacles/src/tentacles/templates/files.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/files.html.j2
rename to projects/tentacles/src/tentacles/templates/files.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/files_admin_list.html.j2 b/projects/tentacles/src/tentacles/templates/files_admin_list.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/files_admin_list.html.j2
rename to projects/tentacles/src/tentacles/templates/files_admin_list.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/files_list.html.j2 b/projects/tentacles/src/tentacles/templates/files_list.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/files_list.html.j2
rename to projects/tentacles/src/tentacles/templates/files_list.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/index.html.j2 b/projects/tentacles/src/tentacles/templates/index.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/index.html.j2
rename to projects/tentacles/src/tentacles/templates/index.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/jobs.html.j2 b/projects/tentacles/src/tentacles/templates/jobs.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/jobs.html.j2
rename to projects/tentacles/src/tentacles/templates/jobs.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2 b/projects/tentacles/src/tentacles/templates/jobs_history.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2
rename to projects/tentacles/src/tentacles/templates/jobs_history.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/jobs_list.html.j2 b/projects/tentacles/src/tentacles/templates/jobs_list.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/jobs_list.html.j2
rename to projects/tentacles/src/tentacles/templates/jobs_list.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/login.html.j2 b/projects/tentacles/src/tentacles/templates/login.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/login.html.j2
rename to projects/tentacles/src/tentacles/templates/login.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/macros.html.j2 b/projects/tentacles/src/tentacles/templates/macros.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/macros.html.j2
rename to projects/tentacles/src/tentacles/templates/macros.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/printers.html.j2 b/projects/tentacles/src/tentacles/templates/printers.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/printers.html.j2
rename to projects/tentacles/src/tentacles/templates/printers.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/printers_list.html.j2 b/projects/tentacles/src/tentacles/templates/printers_list.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/printers_list.html.j2
rename to projects/tentacles/src/tentacles/templates/printers_list.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/register.html.j2 b/projects/tentacles/src/tentacles/templates/register.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/register.html.j2
rename to projects/tentacles/src/tentacles/templates/register.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/streams.html.j2 b/projects/tentacles/src/tentacles/templates/streams.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/streams.html.j2
rename to projects/tentacles/src/tentacles/templates/streams.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/user.html.j2 b/projects/tentacles/src/tentacles/templates/user.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/user.html.j2
rename to projects/tentacles/src/tentacles/templates/user.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/users_list.html.j2 b/projects/tentacles/src/tentacles/templates/users_list.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/users_list.html.j2
rename to projects/tentacles/src/tentacles/templates/users_list.html.j2
diff --git a/projects/tentacles/src/python/tentacles/templates/verification_email.html.j2 b/projects/tentacles/src/tentacles/templates/verification_email.html.j2
similarity index 100%
rename from projects/tentacles/src/python/tentacles/templates/verification_email.html.j2
rename to projects/tentacles/src/tentacles/templates/verification_email.html.j2
diff --git a/projects/tentacles/src/python/tentacles/workers.py b/projects/tentacles/src/tentacles/workers.py
similarity index 100%
rename from projects/tentacles/src/python/tentacles/workers.py
rename to projects/tentacles/src/tentacles/workers.py

From d0478d812410de28776f2c98c9762b2d43046a3b Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 11:20:44 -0700
Subject: [PATCH 05/15] Fix imports

---
 tools/python/defs.bzl | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/tools/python/defs.bzl b/tools/python/defs.bzl
index 5c87d12..5fa2a86 100644
--- a/tools/python/defs.bzl
+++ b/tools/python/defs.bzl
@@ -212,8 +212,7 @@ def py_project(name=None,
         deps=lib_deps,
         data=lib_data,
         imports=[
-            "src/python",
-            "src/resources",
+            "src",
         ],
         visibility = [
             "//visibility:public",
@@ -227,8 +226,7 @@ def py_project(name=None,
             deps=(main_deps or []) + [lib_name],
             data=(main_data or []),
             imports=[
-                "src/python",
-                "src/resources",
+                "src",
             ],
             visibility = [
                 "//visibility:public",
@@ -241,8 +239,7 @@ def py_project(name=None,
             deps=(main_deps or []) + [lib_name],
             data=lib_data,
             imports=[
-                "src/python",
-                "src/resources",
+                "src",
             ],
             visibility = [
                 "//visibility:public",

From 58c416f1bdb118f1bf17c7a24df46172358196c1 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 12:37:41 -0700
Subject: [PATCH 06/15] Bazelshim

---
 .envrc                                       |   2 +
 bin/bazel                                    |   2 +
 bin/bazelisk                                 |   2 +
 projects/bazelshim/src/bazelshim/__main__.py | 163 +++++++++++++++++--
 projects/bazelshim/test/test_normalizer.py   |  74 +++++++++
 projects/bazelshim/test/test_parser.py       |  52 ++++++
 6 files changed, 277 insertions(+), 18 deletions(-)
 create mode 100644 .envrc
 create mode 100755 bin/bazel
 create mode 100755 bin/bazelisk
 mode change 100644 => 100755 projects/bazelshim/src/bazelshim/__main__.py
 create mode 100644 projects/bazelshim/test/test_normalizer.py
 create mode 100644 projects/bazelshim/test/test_parser.py

diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..c589014
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,2 @@
+export SOURCE=$(dirname $(realpath $0))
+export PATH="${SOURCE}/bin:$PATH"
diff --git a/bin/bazel b/bin/bazel
new file mode 100755
index 0000000..40517be
--- /dev/null
+++ b/bin/bazel
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" --bazelshim_exclude="$(realpath "${SOURCE}")/bin" "$@"
diff --git a/bin/bazelisk b/bin/bazelisk
new file mode 100755
index 0000000..40517be
--- /dev/null
+++ b/bin/bazelisk
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" --bazelshim_exclude="$(realpath "${SOURCE}")/bin" "$@"
diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
old mode 100644
new mode 100755
index 9cc9f21..b953403
--- a/projects/bazelshim/src/bazelshim/__main__.py
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -2,15 +2,48 @@
 
 # A Bazel wrapper
 #
-# This script exists to allow for the setting of environment viariables and other context flags to Bazel on behalf of
-# the user. Consequently it has some magical (partial) knowledge of Bazel's CLI options since it's really a CLI shim.
+# This script exists to allow for the setting of environment viariables and other context flags to
+# Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
+# options since it's really a CLI shim.
 
-import sys
-from typing import List, Optional
-from shlex import split as shlex
 from dataclasses import dataclass
+from shlex import quote, split as shlex
+import sys
+import os
+from pathlib import Path
+from typing import List, Optional
+from itertools import chain
+
+
+VERBS = [
+    "aquery",
+    "build",
+    "clean",
+    "coverage",
+    "cquery",
+    "dump",
+    "fetch",
+    "help",
+    "info",
+    "mod",
+    "query",
+    "run",
+    "sync",
+    "test",
+]
+
+
+def path():
+    for it in os.getenv("PATH").split(":"):
+        yield Path(it)
+
+
+def which(cmd):
+    for it in path():
+        f: Path = (it / cmd).absolute()
+        if f.exists() and f.stat().st_mode & 0x700:
+            yield f
 
-VERBS = ["sync", "build", "aquery", "query", "cquery", "run", "test", "coverage", "dump", "fetch", "help", "info", "mod",]
 
 def normalize_opts(args: List[str]) -> List[str]:
     acc = []
@@ -24,7 +57,7 @@ def normalize_opts(args: List[str]) -> List[str]:
             acc.extend(args)
             break
 
-        elif args[0].contains("="):
+        elif "=" in args[0]:
             # If it's a k/v form pass it through
             acc.append(args.pop(0))
 
@@ -32,7 +65,11 @@ def normalize_opts(args: List[str]) -> List[str]:
             # Convert --no<foo> args to --<foo>=no
             acc.append("--" + args.pop(0).lstrip("--no") + "=false")
 
-        elif args[0].startswith("--") and not args[1].startswith("--") and args[1] not in VERBS:
+        elif (
+            args[0].startswith("--")
+            and not args[1].startswith("--")
+            and args[1] not in VERBS
+        ):
             # If the next thing isn't an opt, assume it's a '--a b' form
             acc.append(args[0] + "=" + args[1])
             args.pop(0)
@@ -42,27 +79,117 @@ def normalize_opts(args: List[str]) -> List[str]:
             # Assume it's a boolean true flag
             acc.append(args.pop(0) + "=true")
 
-        elif args[0] in VERBS:
+        else:
             acc.append(args.pop(0))
 
-        else:
-            raise ValueError(repr(args))
+    else:
+        if args:
+            acc.extend(args)
 
     return acc
 
-assert normalize_opts(shlex("bazel clean")) == ["bazel", "clean"]
-assert normalize_opts(shlex("bazel --client_debug clean")) == ["bazel", "--client_debug=true", "clean"]
-assert normalize_opts(shlex("bazel build //foo:bar //baz:*")) == ["bazel", "build", "//foo:bar", "//baz:*"]
-assert normalize_opts(shlex("bazel test //foo:bar //baz:* -- -vvv")) == ["bazel", "test", "//foo:bar", "//baz:*", "--", "-vvv"]
-assert normalize_opts(shlex("bazel run //foo:bar -- --foo=bar --baz=qux")) == ["bazel", "run", "//foo:bar", "--", "--foo=bar", "--baz=qux"]
 
 @dataclass
 class BazelCli:
+    binary: str
     startup_opts: List[str]
     command: Optional[str]
     command_opts: List[str]
     subprocess_opts: List[str]
 
     @classmethod
-    def parse_cli(cls, args: List[str]) -> BazelCLI:
-        pass
+    def parse_cli(cls, args: List[str]) -> "BazelCli":
+        args = normalize_opts(args)
+        binary = args.pop(0)
+
+        startup_opts = []
+        while args and args[0].startswith("--"):
+            startup_opts.append(args.pop(0))
+
+        command = None
+        if args and args[0] in VERBS:
+            command = args.pop(0)
+
+        command_opts = []
+        while args and args[0] != "--":
+            command_opts.append(args.pop(0))
+
+        subprocess_opts = []
+        if args:
+            if args[0] == "--":
+                args.pop(0)
+            subprocess_opts.extend(args)
+
+        return cls(
+            binary=binary,
+            startup_opts=startup_opts,
+            command=command,
+            command_opts=command_opts,
+            subprocess_opts=subprocess_opts,
+        )
+
+    def render_cli(self):
+        acc = [
+            self.binary,
+            *self.startup_opts,
+        ]
+        if self.command:
+            acc.append(self.command)
+            acc.extend(self.command_opts)
+
+            if self.command == "test":
+                acc.extend(["--test_arg=" + it for it in self.subprocess_opts])
+            elif self.command == "run":
+                acc.append("--")
+                acc.extend(self.subprocess_opts)
+            else:
+                print(
+                    f"Warning: {self.command} does not support -- args!",
+                    file=sys.stderr,
+                )
+
+        return acc
+
+    def executable(self, exclude: List[Path]):
+        """Try to resolve as via which() an executable to delegate to."""
+
+        for p in chain(which("bazelisk"), which("bazel")):
+            if p.parent not in exclude:
+                return str(p)
+
+    def render_text(self, next):
+        lines = []
+        lines.append("  " + next)
+        for arg in self.startup_opts:
+            lines.append("    " + arg)
+        if self.command:
+            lines.append("    " + self.command)
+            for arg in self.command_opts:
+                lines.append("      " + arg)
+        if self.subprocess_opts:
+            lines.append("    --")
+            for arg in self.subprocess_opts:
+                lines.append("      " + arg)
+        return "\\\n".join(lines)
+
+
+def middleware(cli):
+    return cli
+
+
+if __name__ == "__main__":
+    exclude = []
+    while len(sys.argv) > 1 and sys.argv[1].startswith("--bazelshim_exclude"):
+        exclude.append(Path(sys.argv.pop(1).split("=")[1]).absolute())
+
+    us = Path(sys.argv[0]).absolute()
+    exclude.append(us.parent)
+
+    cli = BazelCli.parse_cli(["bazel"] + sys.argv[1:])
+    cli = middleware(cli)
+    next = cli.executable(exclude=exclude)
+    print(
+        "Info: Executing\n" + cli.render_text(next),
+        file=sys.stderr,
+    )
+    os.execv(next, cli.render_cli())
diff --git a/projects/bazelshim/test/test_normalizer.py b/projects/bazelshim/test/test_normalizer.py
new file mode 100644
index 0000000..a2cf3ca
--- /dev/null
+++ b/projects/bazelshim/test/test_normalizer.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+from shlex import split as shlex
+
+from bazelshim.__main__ import normalize_opts
+
+import pytest
+
+
+@pytest.mark.parametrize(
+    "a, b",
+    [
+        (
+            "bazel clean",
+            [
+                "bazel",
+                "clean",
+            ],
+        ),
+        (
+            "bazel --client_debug clean",
+            [
+                "bazel",
+                "--client_debug=true",
+                "clean",
+            ],
+        ),
+        (
+            "bazel build //foo:bar //baz:*",
+            [
+                "bazel",
+                "build",
+                "//foo:bar",
+                "//baz:*",
+            ],
+        ),
+        (
+            "bazel test //foo:bar //baz:* -- -vvv",
+            [
+                "bazel",
+                "test",
+                "//foo:bar",
+                "//baz:*",
+                "--",
+                "-vvv",
+            ],
+        ),
+        (
+            "bazel test --shell_executable /bin/bish //foo:bar //baz:* -- -vvv",
+            [
+                "bazel",
+                "test",
+                "--shell_executable=/bin/bish",
+                "//foo:bar",
+                "//baz:*",
+                "--",
+                "-vvv",
+            ],
+        ),
+        (
+            "bazel run //foo:bar -- --foo=bar --baz=qux",
+            [
+                "bazel",
+                "run",
+                "//foo:bar",
+                "--",
+                "--foo=bar",
+                "--baz=qux",
+            ],
+        ),
+    ],
+)
+def test_normalize_opts(a, b):
+    assert normalize_opts(shlex(a)) == b
diff --git a/projects/bazelshim/test/test_parser.py b/projects/bazelshim/test/test_parser.py
new file mode 100644
index 0000000..c2cc3d0
--- /dev/null
+++ b/projects/bazelshim/test/test_parser.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+
+from shlex import split as shlex
+
+from bazelshim.__main__ import BazelCli
+
+import pytest
+
+
+@pytest.mark.parametrize(
+    "a, b",
+    [
+        (
+            "bazel clean",
+            BazelCli("bazel", [], "clean", [], []),
+        ),
+        (
+            "bazel --client_debug clean",
+            BazelCli("bazel", ["--client_debug=true"], "clean", [], []),
+        ),
+        (
+            "bazel build //foo:bar //baz:*",
+            BazelCli("bazel", [], "build", ["//foo:bar", "//baz:*"], []),
+        ),
+        (
+            "bazel test //foo:bar //baz:* -- -vvv",
+            BazelCli("bazel", [], "test", ["//foo:bar", "//baz:*"], ["-vvv"]),
+        ),
+        (
+            "bazel test --shell_executable /bin/bish //foo:bar //baz:* -- -vvv",
+            BazelCli(
+                "bazel",
+                [],
+                "test",
+                ["--shell_executable=/bin/bish", "//foo:bar", "//baz:*"],
+                ["-vvv"],
+            ),
+        ),
+        (
+            "bazel run //foo:bar -- --foo=bar --baz=qux",
+            BazelCli(
+                "bazel",
+                [],
+                "run",
+                ["//foo:bar"],
+                ["--foo=bar", "--baz=qux"],
+            ),
+        ),
+    ],
+)
+def test_normalize_opts(a, b):
+    assert BazelCli.parse_cli(shlex(a)) == b

From de8207e672a2baa5db08f84d12ddf8a15d9cde14 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 12:38:04 -0700
Subject: [PATCH 07/15] KTF support

---
 .bazelrc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.bazelrc b/.bazelrc
index b646275..c23aa74 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,4 +1,5 @@
 test --test_output=errors
+test --test_tag_filters=-known-to-fail
 
 # To enable flake8 on all build steps, uncomment this -
 # test --aspects="//tools/flake8:flake8.bzl%flake8_aspect" --output_groups=flake8_checks

From ed0eb657e5c0ecd8b1d958353f2d1123f3848b3f Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 12:50:59 -0700
Subject: [PATCH 08/15] [NO TESTS] WIP

---
 .bazelrc                                      |  1 +
 .gitignore                                    |  1 +
 WORKSPACE                                     | 78 ++-----------------
 .../src/{python => }/lilith/__init__.py       |  0
 .../src/{python => }/lilith/__main__.py       |  0
 .../src/{python => }/lilith/grammar.lark      |  0
 .../src/{python => }/lilith/interpreter.py    |  0
 .../lilith/src/{python => }/lilith/parser.py  |  0
 .../src/{python => }/lilith/prelude.lil       |  0
 .../lilith/src/{python => }/lilith/reader.py  |  0
 10 files changed, 10 insertions(+), 70 deletions(-)
 rename projects/lilith/src/{python => }/lilith/__init__.py (100%)
 rename projects/lilith/src/{python => }/lilith/__main__.py (100%)
 rename projects/lilith/src/{python => }/lilith/grammar.lark (100%)
 rename projects/lilith/src/{python => }/lilith/interpreter.py (100%)
 rename projects/lilith/src/{python => }/lilith/parser.py (100%)
 rename projects/lilith/src/{python => }/lilith/prelude.lil (100%)
 rename projects/lilith/src/{python => }/lilith/reader.py (100%)

diff --git a/.bazelrc b/.bazelrc
index c23aa74..9ab733d 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,5 +1,6 @@
 test --test_output=errors
 test --test_tag_filters=-known-to-fail
+test --keep_going
 
 # To enable flake8 on all build steps, uncomment this -
 # test --aspects="//tools/flake8:flake8.bzl%flake8_aspect" --output_groups=flake8_checks
diff --git a/.gitignore b/.gitignore
index f38a91e..66817fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ tmp/
 /**/*.sqlite*
 /**/config*.toml
 /**/config*.yml
+MODULE.bazel.lock
diff --git a/WORKSPACE b/WORKSPACE
index 0528d59..910f51c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -62,76 +62,14 @@ load("@arrdem_source_pypi//:requirements.bzl", "install_deps")
 # Call it to define repos for your requirements.
 install_deps()
 
-git_repository(
-   name = "rules_zapp",
-   remote = "https://git.arrdem.com/arrdem/rules_zapp.git",
-   commit = "961be891e5cff539e14f2050d5cd9e82845ce0f2",
-   # tag = "0.1.2",
-)
-
-# local_repository(
-#     name = "rules_zapp",
-#     path = "/home/arrdem/Documents/hobby/programming/lang/python/rules_zapp",
+# git_repository(
+#    name = "rules_zapp",
+#    remote = "https://git.arrdem.com/arrdem/rules_zapp.git",
+#    commit = "961be891e5cff539e14f2050d5cd9e82845ce0f2",
+#    # tag = "0.1.2",
 # )
 
-####################################################################################################
-# Docker support
-####################################################################################################
-
-http_archive(
-    name = "io_bazel_rules_docker",
-    sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
-    urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
-)
-
-load("@io_bazel_rules_docker//toolchains/docker:toolchain.bzl",
-    docker_toolchain_configure="toolchain_configure"
-)
-
-docker_toolchain_configure(
-  name = "docker_config",
-  docker_flags = [
-  ],
-)
-
-load(
-    "@io_bazel_rules_docker//repositories:repositories.bzl",
-    container_repositories = "repositories",
-)
-container_repositories()
-
-load(
-    "@io_bazel_rules_docker//repositories:deps.bzl",
-    container_deps = "deps"
-)
-
-container_deps()
-
-load(
-    "@io_bazel_rules_docker//container:container.bzl",
-    "container_pull",
-)
-
-# container_pull(
-#   name = "python_base",
-#   registry = "index.docker.io",
-#   repository = "library/python",
-#   tag = "3.10.8-alpine"
-#   # sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
-# )
-
-# container_pull(
-#   name = "python_base",
-#   registry = "gcr.io",
-#   repository = "distroless/python3-debian11",
-#   tag = "latest"
-#   # sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
-# )
-
-container_pull(
-  name = "python_base",
-  registry = "index.docker.io",
-  repository = "library/python",
-  tag = "3.11-buster"
-  # sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
+local_repository(
+    name = "rules_zapp",
+    path = "/home/arrdem/Documents/hobby/programming/lang/python/rules_zapp",
 )
diff --git a/projects/lilith/src/python/lilith/__init__.py b/projects/lilith/src/lilith/__init__.py
similarity index 100%
rename from projects/lilith/src/python/lilith/__init__.py
rename to projects/lilith/src/lilith/__init__.py
diff --git a/projects/lilith/src/python/lilith/__main__.py b/projects/lilith/src/lilith/__main__.py
similarity index 100%
rename from projects/lilith/src/python/lilith/__main__.py
rename to projects/lilith/src/lilith/__main__.py
diff --git a/projects/lilith/src/python/lilith/grammar.lark b/projects/lilith/src/lilith/grammar.lark
similarity index 100%
rename from projects/lilith/src/python/lilith/grammar.lark
rename to projects/lilith/src/lilith/grammar.lark
diff --git a/projects/lilith/src/python/lilith/interpreter.py b/projects/lilith/src/lilith/interpreter.py
similarity index 100%
rename from projects/lilith/src/python/lilith/interpreter.py
rename to projects/lilith/src/lilith/interpreter.py
diff --git a/projects/lilith/src/python/lilith/parser.py b/projects/lilith/src/lilith/parser.py
similarity index 100%
rename from projects/lilith/src/python/lilith/parser.py
rename to projects/lilith/src/lilith/parser.py
diff --git a/projects/lilith/src/python/lilith/prelude.lil b/projects/lilith/src/lilith/prelude.lil
similarity index 100%
rename from projects/lilith/src/python/lilith/prelude.lil
rename to projects/lilith/src/lilith/prelude.lil
diff --git a/projects/lilith/src/python/lilith/reader.py b/projects/lilith/src/lilith/reader.py
similarity index 100%
rename from projects/lilith/src/python/lilith/reader.py
rename to projects/lilith/src/lilith/reader.py

From f0a871dd91c272c2dada4c706c12bdfd7c381161 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 20:55:24 -0700
Subject: [PATCH 09/15] Finishing touches

---
 projects/bazelshim/src/bazelshim/__init__.py |  0
 projects/bazelshim/src/bazelshim/__main__.py | 28 +++++++++++++++-----
 2 files changed, 22 insertions(+), 6 deletions(-)
 create mode 100644 projects/bazelshim/src/bazelshim/__init__.py

diff --git a/projects/bazelshim/src/bazelshim/__init__.py b/projects/bazelshim/src/bazelshim/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
index b953403..5942e78 100755
--- a/projects/bazelshim/src/bazelshim/__main__.py
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -6,10 +6,18 @@
 # Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
 # options since it's really a CLI shim.
 
+# Since this can't run under Bazel, we have to set up the sys.path ourselves
+import os
+import sys
+from pathlib import Path
+
+if (p := str(Path(sys.argv[0]).absolute().parent.parent)) not in sys.path:
+    sys.path.pop(0)  # Remove '.' / ''
+    sys.path.insert(0, p)  # Insert the bazelshim root
+
 from dataclasses import dataclass
 from shlex import quote, split as shlex
 import sys
-import os
 from pathlib import Path
 from typing import List, Optional
 from itertools import chain
@@ -65,6 +73,10 @@ def normalize_opts(args: List[str]) -> List[str]:
             # Convert --no<foo> args to --<foo>=no
             acc.append("--" + args.pop(0).lstrip("--no") + "=false")
 
+        elif args[0] == "--isatty=0":
+            acc.append("--isatty=false")
+            args.pop(0)
+
         elif (
             args[0].startswith("--")
             and not args[1].startswith("--")
@@ -142,9 +154,11 @@ class BazelCli:
             elif self.command == "run":
                 acc.append("--")
                 acc.extend(self.subprocess_opts)
+            elif self.command and not self.subprocess_opts:
+                pass
             else:
                 print(
-                    f"Warning: {self.command} does not support -- args!",
+                    f"Warning: {self.command} does not support -- args! {self.subprocess_opts!r}",
                     file=sys.stderr,
                 )
 
@@ -178,6 +192,7 @@ def middleware(cli):
 
 
 if __name__ == "__main__":
+    # This script has a magical flag to help with resolving bazel
     exclude = []
     while len(sys.argv) > 1 and sys.argv[1].startswith("--bazelshim_exclude"):
         exclude.append(Path(sys.argv.pop(1).split("=")[1]).absolute())
@@ -188,8 +203,9 @@ if __name__ == "__main__":
     cli = BazelCli.parse_cli(["bazel"] + sys.argv[1:])
     cli = middleware(cli)
     next = cli.executable(exclude=exclude)
-    print(
-        "Info: Executing\n" + cli.render_text(next),
-        file=sys.stderr,
-    )
+    if sys.stderr.isatty() and not "--isatty=false" in cli.command_opts:
+        print(
+            "\u001b[33mInfo\u001b[0m: Executing\n" + cli.render_text(next),
+            file=sys.stderr,
+        )
     os.execv(next, cli.render_cli())

From ea57f8400288de12f5ea5c0818cbe62f52234251 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 20:55:36 -0700
Subject: [PATCH 10/15] Strip the .py suffix

---
 tools/python/defs.bzl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/python/defs.bzl b/tools/python/defs.bzl
index 5fa2a86..a375abf 100644
--- a/tools/python/defs.bzl
+++ b/tools/python/defs.bzl
@@ -251,7 +251,7 @@ def py_project(name=None,
     for src in test_srcs:
         if "test_" in src:
             py_pytest(
-                name=src.split("/")[-1],
+                name=src.split("/")[-1].replace(".py", ""),
                 srcs=[src] + [f for f in test_srcs if "test_" not in f],
                 deps=[lib_name] + (test_deps or []),
                 data=test_data,

From 253532ab6dcbd6a9c00dc6ddb67e1afde0521857 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 20:55:46 -0700
Subject: [PATCH 11/15] Sort

---
 .bazelrc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.bazelrc b/.bazelrc
index 9ab733d..5f30ba4 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,6 +1,9 @@
+common --curses=auto
+common --show_timestamps=true
+
+test --keep_going
 test --test_output=errors
 test --test_tag_filters=-known-to-fail
-test --keep_going
 
 # To enable flake8 on all build steps, uncomment this -
 # test --aspects="//tools/flake8:flake8.bzl%flake8_aspect" --output_groups=flake8_checks

From ebc59f83293a18d3789c03050d816ac6b66a0bd2 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Tue, 6 Feb 2024 21:28:37 -0700
Subject: [PATCH 12/15] Leave some notes

---
 projects/bazelshim/src/bazelshim/__main__.py | 34 +++++++++++++++++---
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
index 5942e78..5a0a6fb 100755
--- a/projects/bazelshim/src/bazelshim/__main__.py
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -1,10 +1,31 @@
 #!/usr/bin/env python3
 
-# A Bazel wrapper
-#
-# This script exists to allow for the setting of environment viariables and other context flags to
-# Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
-# options since it's really a CLI shim.
+"""
+A Bazel wrapper
+===============
+
+This script exists to allow for the setting of environment viariables and other context flags to
+Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
+options since it's really a CLI shim. This allows for user(s) to define their own Bazel CLI
+middleware machinery while using structured and testable parsing rather than BASH nonsense.
+
+It's important that this script stands "alone" because it needs to be usable mostly in isolation
+with a non-hermetic interpreter before we can do Bazel builds.
+
+For instance this script could be used as a basis to define custom Bazel tasks such as 'repl' (run
+with some magic) or 'watch' as an alias for punting to ibazel/bazel-watcher.
+
+Such a middleware can also be used to provide configurations which are hard to autodetect from
+within Bazel in an appropriately structured way such as
+  `--action_env=GLIBC_VERSION=$(ldd --version)`
+or
+  `--action_env=PLATFORM_FEATURE_POSTGRESQL=$(which pg_ctl >/dev/null 2>&1 && echo 'true' || echo 'false')`
+
+I suggest using a `bazel` and maybe `bazelisk` shim script on your $PATH like
+  exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" \
+    --bazelshim_exclude="$(dirname $(realpath $0))" \
+    "$@"
+"""
 
 # Since this can't run under Bazel, we have to set up the sys.path ourselves
 import os
@@ -15,6 +36,7 @@ if (p := str(Path(sys.argv[0]).absolute().parent.parent)) not in sys.path:
     sys.path.pop(0)  # Remove '.' / ''
     sys.path.insert(0, p)  # Insert the bazelshim root
 
+# Now that's out of the way...
 from dataclasses import dataclass
 from shlex import quote, split as shlex
 import sys
@@ -23,6 +45,7 @@ from typing import List, Optional
 from itertools import chain
 
 
+# FIXME: Allow user-defined extensions here
 VERBS = [
     "aquery",
     "build",
@@ -187,6 +210,7 @@ class BazelCli:
         return "\\\n".join(lines)
 
 
+# FIXME: Use some sort of plugin model here to implement interceptors
 def middleware(cli):
     return cli
 

From db2705eb53300371abd8fd697262863974854f74 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 12 Feb 2024 18:54:41 -0700
Subject: [PATCH 13/15] Bump deps

---
 tools/python/requirements_lock.txt | 79 +++++++++++++++---------------
 1 file changed, 40 insertions(+), 39 deletions(-)

diff --git a/tools/python/requirements_lock.txt b/tools/python/requirements_lock.txt
index 912d645..3e0862b 100644
--- a/tools/python/requirements_lock.txt
+++ b/tools/python/requirements_lock.txt
@@ -1,62 +1,63 @@
-aiohttp==3.8.5
+aiohttp==3.9.3
 aiohttp-basicauth==1.0.0
 aiosignal==1.3.1
-aiosql==9.0
+aiosql==9.4
 alabaster==0.7.13
 annotated-types==0.5.0
 async-lru==2.0.4
 async-timeout==4.0.2
-attrs==23.1.0
+attrs==23.2.0
 autocommand==2.2.2
-autoflake==2.2.0
+autoflake==2.2.1
 Babel==2.12.1
-beautifulsoup4==4.12.2
-black==23.7.0
+beautifulsoup4==4.12.3
+black==24.1.1
 blinker==1.6.2
 build==0.10.0
-cachetools==5.3.1
+cachetools==5.3.2
 certifi==2023.7.22
 charset-normalizer==3.2.0
 cheroot==10.0.0
 CherryPy==18.8.0
-click==8.1.6
-colored==2.2.3
+click==8.1.7
+colored==2.2.4
 commonmark==0.9.1
 coverage==7.2.7
 decorator==5.1.1
 deepmerge==1.1.0
 docutils==0.20.1
 ExifRead==3.0.0
-flake8==6.0.0
-Flask==2.3.2
+flake8==7.0.0
+Flask==3.0.2
 frozenlist==1.4.0
-hypothesis==6.82.0
-ibis==3.2.0
-icmplib==3.0.3
+hypothesis==6.98.2
+ibis==3.3.0
+icmplib==3.0.4
 idna==3.4
 imagesize==1.4.1
 inflect==7.0.0
 iniconfig==2.0.0
-isort==5.12.0
+isort==5.13.2
 itsdangerous==2.1.2
 jaraco.collections==4.3.0
 jaraco.context==4.3.0
 jaraco.functools==3.8.0
 jaraco.text @ git+https://github.com/arrdem/jaraco.text.git@0dd8d0b25a93c3fad896f3a92d11caff61ff273d
 jedi==0.18.2
-Jinja2==3.1.2
+Jinja2==3.1.3
 jsonschema==4.18.4
+jsonschema-path==0.3.2
 jsonschema-spec==0.2.3
 jsonschema-specifications==2023.7.1
-lark==1.1.7
+lark==1.1.9
 lazy-object-proxy==1.9.0
-libsass==0.22.0
+libsass==0.23.0
 livereload==2.6.3
-lxml==4.9.3
-Markdown==3.4.4
+lxml==5.1.0
+Markdown==3.5.2
 MarkupSafe==2.1.3
 mccabe==0.7.0
-meraki==1.34.0
+meraki==1.42.0
 mirakuru==2.5.1
 mistune==2.0.5
 more-itertools==10.0.0
@@ -64,43 +65,43 @@ multidict==6.0.4
 mypy-extensions==1.0.0
 octorest==0.4
 openapi-schema-validator==0.6.0
-openapi-spec-validator==0.6.0
+openapi-spec-validator==0.7.1
 packaging==23.1
 parso==0.8.3
 pathable==0.4.3
 pathspec==0.11.1
 picobox==3.0.0
 pip==23.1.2
-pip-tools==7.1.0
+pip-tools==7.3.0
 platformdirs==3.9.1
 pluggy==1.2.0
 port-for==0.7.1
 portend==3.2.0
-prompt-toolkit==3.0.39
+prompt-toolkit==3.0.43
 proquint==0.2.1
 psutil==5.9.5
 psycopg==3.1.9
-psycopg2==2.9.6
+psycopg2==2.9.9
 pudb==2022.1.3
 py==1.11.0
-pycodestyle==2.10.0
-pycryptodome==3.18.0
+pycodestyle==2.11.1
+pycryptodome==3.20.0
 pydantic==2.1.1
 pydantic_core==2.4.0
-pyflakes==3.0.1
+pyflakes==3.2.0
 Pygments==2.15.1
 pyproject_hooks==1.0.0
-pyrsistent==0.19.3
+pyrsistent==0.20.0
 pytest==7.4.0
 pytest-cov==4.1.0
-pytest-postgresql==5.0.0
+pytest-postgresql==5.1.0
 pytest-pudb==0.7.0
-pytest-timeout==2.1.0
+pytest-timeout==2.2.0
 pytimeparse==1.1.8
 pytz==2023.3
 PyYAML==6.0.1
 recommonmark==0.7.1
-redis==4.6.0
+redis==5.0.1
 referencing==0.29.3
 requests==2.31.0
 retry==0.9.2
@@ -108,21 +109,21 @@ rfc3339-validator==0.1.4
 rpds-py==0.9.2
 setuptools==68.0.0
 six==1.16.0
-smbus2==0.4.2
+smbus2==0.4.3
 snowballstemmer==2.2.0
 sortedcontainers==2.4.0
 soupsieve==2.4.1
-Sphinx==7.1.1
+Sphinx==7.2.6
 sphinx_mdinclude==0.5.3
 sphinxcontrib-applehelp==1.0.4
 sphinxcontrib-devhelp==1.0.2
 sphinxcontrib-htmlhelp==2.0.1
 sphinxcontrib-httpdomain==1.8.1
 sphinxcontrib-jsmath==1.0.1
-sphinxcontrib-openapi==0.8.1
+sphinxcontrib-openapi==0.8.3
 sphinxcontrib-programoutput==0.17
 sphinxcontrib-qthelp==1.0.3
-sphinxcontrib-serializinghtml==1.1.5
+sphinxcontrib-serializinghtml==1.1.10
 tempora==5.5.0
 termcolor==2.3.0
 toml==0.10.2
@@ -135,9 +136,9 @@ urwid==2.1.2
 urwid-readline==0.13
 wcwidth==0.2.6
 websocket-client==1.6.1
-Werkzeug==2.3.6
+Werkzeug==3.0.1
 wheel==0.40.0
-yamllint==1.32.0
+yamllint==1.34.0
 yarl==1.9.2
-yaspin==2.3.0
+yaspin==3.0.1
 zc.lockfile==3.0.post1

From f7bce623bf1427f8e406f025b5eafc976b378b95 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 12 Feb 2024 18:57:34 -0700
Subject: [PATCH 14/15] Add the MODULE.bazel file

---
 MODULE.bazel | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 MODULE.bazel

diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..00bb183
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,6 @@
+###############################################################################
+# Bazel now uses Bzlmod by default to manage external dependencies.
+# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
+#
+# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
+###############################################################################

From edec17510ece95139575448185e6fdf83afa92b4 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 12 Feb 2024 18:57:45 -0700
Subject: [PATCH 15/15] M0ar

---
 projects/bazelshim/BUILD.bazel               |  1 +
 projects/bazelshim/src/bazelshim/__main__.py | 66 +++++++-------------
 2 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/projects/bazelshim/BUILD.bazel b/projects/bazelshim/BUILD.bazel
index f5177f6..5013a2e 100644
--- a/projects/bazelshim/BUILD.bazel
+++ b/projects/bazelshim/BUILD.bazel
@@ -1,3 +1,4 @@
 py_project(
     name = "bazelshim",
+    main = "src/bazelshim/__main__.py",
 )
diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
index 5a0a6fb..62923ca 100755
--- a/projects/bazelshim/src/bazelshim/__main__.py
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -1,32 +1,5 @@
 #!/usr/bin/env python3
 
-"""
-A Bazel wrapper
-===============
-
-This script exists to allow for the setting of environment viariables and other context flags to
-Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
-options since it's really a CLI shim. This allows for user(s) to define their own Bazel CLI
-middleware machinery while using structured and testable parsing rather than BASH nonsense.
-
-It's important that this script stands "alone" because it needs to be usable mostly in isolation
-with a non-hermetic interpreter before we can do Bazel builds.
-
-For instance this script could be used as a basis to define custom Bazel tasks such as 'repl' (run
-with some magic) or 'watch' as an alias for punting to ibazel/bazel-watcher.
-
-Such a middleware can also be used to provide configurations which are hard to autodetect from
-within Bazel in an appropriately structured way such as
-  `--action_env=GLIBC_VERSION=$(ldd --version)`
-or
-  `--action_env=PLATFORM_FEATURE_POSTGRESQL=$(which pg_ctl >/dev/null 2>&1 && echo 'true' || echo 'false')`
-
-I suggest using a `bazel` and maybe `bazelisk` shim script on your $PATH like
-  exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" \
-    --bazelshim_exclude="$(dirname $(realpath $0))" \
-    "$@"
-"""
-
 # Since this can't run under Bazel, we have to set up the sys.path ourselves
 import os
 import sys
@@ -40,6 +13,7 @@ if (p := str(Path(sys.argv[0]).absolute().parent.parent)) not in sys.path:
 from dataclasses import dataclass
 from shlex import quote, split as shlex
 import sys
+import tomllib
 from pathlib import Path
 from typing import List, Optional
 from itertools import chain
@@ -61,6 +35,7 @@ VERBS = [
     "run",
     "sync",
     "test",
+    "watch",
 ]
 
 
@@ -169,8 +144,11 @@ class BazelCli:
             *self.startup_opts,
         ]
         if self.command:
-            acc.append(self.command)
-            acc.extend(self.command_opts)
+            if self.command == "watch":
+                acc.extend(self.command_opts)
+            else:
+                acc.append(self.command)
+                acc.extend(self.command_opts)
 
             if self.command == "test":
                 acc.extend(["--test_arg=" + it for it in self.subprocess_opts])
@@ -190,23 +168,27 @@ class BazelCli:
     def executable(self, exclude: List[Path]):
         """Try to resolve as via which() an executable to delegate to."""
 
-        for p in chain(which("bazelisk"), which("bazel")):
-            if p.parent not in exclude:
-                return str(p)
+        if self.command == "watch":
+            for p in chain(which("ibazel")):
+                if p.parent not in exclude:
+                    return str(p)
+
+        else:
+            for p in chain(which("bazelisk"), which("bazel")):
+                if p.parent not in exclude:
+                    return str(p)
 
     def render_text(self, next):
         lines = []
         lines.append("  " + next)
-        for arg in self.startup_opts:
-            lines.append("    " + arg)
-        if self.command:
-            lines.append("    " + self.command)
-            for arg in self.command_opts:
-                lines.append("      " + arg)
-        if self.subprocess_opts:
-            lines.append("    --")
-            for arg in self.subprocess_opts:
-                lines.append("      " + arg)
+        base_prefix = "      "
+        for arg in self.render_cli()[1:]:
+            prefix = base_prefix
+            if arg in VERBS or arg == self.command:
+                prefix = "    "
+            elif arg == "--":
+                base_prefix += "  "
+            lines.append(prefix + arg)
         return "\\\n".join(lines)