coodie 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. coodie-1.0.0/.all-contributorsrc +27 -0
  2. coodie-1.0.0/.editorconfig +21 -0
  3. coodie-1.0.0/.github/FUNDING.yml +1 -0
  4. coodie-1.0.0/.github/ISSUE_TEMPLATE/1-bug_report.md +14 -0
  5. coodie-1.0.0/.github/ISSUE_TEMPLATE/2-feature-request.md +14 -0
  6. coodie-1.0.0/.github/PULL_REQUEST_TEMPLATE.md +43 -0
  7. coodie-1.0.0/.github/hooks/setup-shims.bats +121 -0
  8. coodie-1.0.0/.github/hooks/setup-shims.sh +37 -0
  9. coodie-1.0.0/.github/hooks/shims/pip +27 -0
  10. coodie-1.0.0/.github/hooks/shims/pip-shim.bats +45 -0
  11. coodie-1.0.0/.github/hooks/shims/pip3 +27 -0
  12. coodie-1.0.0/.github/hooks/shims/pipx +41 -0
  13. coodie-1.0.0/.github/hooks/shims/pipx-shim.bats +64 -0
  14. coodie-1.0.0/.github/hooks/shims/python +26 -0
  15. coodie-1.0.0/.github/hooks/shims/python-shim.bats +53 -0
  16. coodie-1.0.0/.github/hooks/shims/python3 +26 -0
  17. coodie-1.0.0/.github/hooks/shims/uv +27 -0
  18. coodie-1.0.0/.github/hooks/shims/uv-shim.bats +47 -0
  19. coodie-1.0.0/.github/labels.toml +94 -0
  20. coodie-1.0.0/.github/scripts/build-delegation-prompt.sh +35 -0
  21. coodie-1.0.0/.github/scripts/extract-plan-ref.sh +53 -0
  22. coodie-1.0.0/.github/scripts/parse-plan.py +257 -0
  23. coodie-1.0.0/.github/scripts/test_parse_plan.py +510 -0
  24. coodie-1.0.0/.github/skills/acsylla-integration-tests.md +137 -0
  25. coodie-1.0.0/.github/skills/benchmarks/SKILL.md +191 -0
  26. coodie-1.0.0/.github/skills/code-review/SKILL.md +226 -0
  27. coodie-1.0.0/.github/skills/code-review/references/bug-hunter.md +148 -0
  28. coodie-1.0.0/.github/skills/code-review/references/code-quality-reviewer.md +140 -0
  29. coodie-1.0.0/.github/skills/code-review/references/contracts-reviewer.md +128 -0
  30. coodie-1.0.0/.github/skills/code-review/references/historical-context-reviewer.md +105 -0
  31. coodie-1.0.0/.github/skills/code-review/references/security-auditor.md +123 -0
  32. coodie-1.0.0/.github/skills/code-review/references/test-coverage-reviewer.md +105 -0
  33. coodie-1.0.0/.github/skills/code-review/workflows/review-local-changes.md +191 -0
  34. coodie-1.0.0/.github/skills/code-review/workflows/review-pr.md +190 -0
  35. coodie-1.0.0/.github/skills/designing-workflow-skills/AGENTS.md +226 -0
  36. coodie-1.0.0/.github/skills/designing-workflow-skills/SKILL.md +253 -0
  37. coodie-1.0.0/.github/skills/designing-workflow-skills/references/anti-patterns.md +266 -0
  38. coodie-1.0.0/.github/skills/designing-workflow-skills/references/progressive-disclosure-guide.md +118 -0
  39. coodie-1.0.0/.github/skills/designing-workflow-skills/references/tool-assignment-guide.md +167 -0
  40. coodie-1.0.0/.github/skills/designing-workflow-skills/references/workflow-patterns.md +297 -0
  41. coodie-1.0.0/.github/skills/designing-workflow-skills/workflows/design-a-workflow-skill.md +173 -0
  42. coodie-1.0.0/.github/skills/designing-workflow-skills/workflows/review-checklist.md +66 -0
  43. coodie-1.0.0/.github/skills/integration-tests.md +57 -0
  44. coodie-1.0.0/.github/skills/modern-python/SKILL.md +365 -0
  45. coodie-1.0.0/.github/skills/modern-python/references/dependabot.md +43 -0
  46. coodie-1.0.0/.github/skills/modern-python/references/migration-checklist.md +141 -0
  47. coodie-1.0.0/.github/skills/modern-python/references/pep723-scripts.md +259 -0
  48. coodie-1.0.0/.github/skills/modern-python/references/prek.md +211 -0
  49. coodie-1.0.0/.github/skills/modern-python/references/pyproject.md +254 -0
  50. coodie-1.0.0/.github/skills/modern-python/references/ruff-config.md +240 -0
  51. coodie-1.0.0/.github/skills/modern-python/references/security-setup.md +255 -0
  52. coodie-1.0.0/.github/skills/modern-python/references/testing.md +284 -0
  53. coodie-1.0.0/.github/skills/modern-python/references/uv-commands.md +200 -0
  54. coodie-1.0.0/.github/skills/modern-python/templates/dependabot.yml +36 -0
  55. coodie-1.0.0/.github/skills/modern-python/templates/pre-commit-config.yaml +66 -0
  56. coodie-1.0.0/.github/skills/setup-environment.md +117 -0
  57. coodie-1.0.0/.github/skills/test-refactoring/SKILL.md +152 -0
  58. coodie-1.0.0/.github/skills/test-refactoring/references/parametrize-patterns.md +247 -0
  59. coodie-1.0.0/.github/skills/test-refactoring/references/sync-async-dedup.md +214 -0
  60. coodie-1.0.0/.github/skills/test-refactoring/workflows/refactor-test-file.md +99 -0
  61. coodie-1.0.0/.github/skills/writing-plans/SKILL.md +259 -0
  62. coodie-1.0.0/.github/skills/writing-plans/references/plan-templates.md +280 -0
  63. coodie-1.0.0/.github/skills/writing-plans/workflows/create-a-plan.md +118 -0
  64. coodie-1.0.0/.github/workflows/auto-approve-bot-runs.yml +156 -0
  65. coodie-1.0.0/.github/workflows/benchmark.yml +92 -0
  66. coodie-1.0.0/.github/workflows/ci.yml +122 -0
  67. coodie-1.0.0/.github/workflows/claude-code-review.yml +43 -0
  68. coodie-1.0.0/.github/workflows/claude.yml +49 -0
  69. coodie-1.0.0/.github/workflows/docs.yml +66 -0
  70. coodie-1.0.0/.github/workflows/issue-manager.yml +32 -0
  71. coodie-1.0.0/.github/workflows/labels.yml +22 -0
  72. coodie-1.0.0/.github/workflows/plan-continuation.yml +293 -0
  73. coodie-1.0.0/.github/workflows/pr-conflict-detect.yml +99 -0
  74. coodie-1.0.0/.github/workflows/test-demos.yml +49 -0
  75. coodie-1.0.0/.github/workflows/test-integration.yml +61 -0
  76. coodie-1.0.0/.github/workflows/test-unit.yml +51 -0
  77. coodie-1.0.0/.gitignore +150 -0
  78. coodie-1.0.0/.gitpod.yml +8 -0
  79. coodie-1.0.0/.pre-commit-config.yaml +39 -0
  80. coodie-1.0.0/.readthedocs.yml +23 -0
  81. coodie-1.0.0/AGENTS.md +132 -0
  82. coodie-1.0.0/CHANGELOG.md +3 -0
  83. coodie-1.0.0/CONTRIBUTING.md +263 -0
  84. coodie-1.0.0/LICENSE +22 -0
  85. coodie-1.0.0/PKG-INFO +329 -0
  86. coodie-1.0.0/README.md +300 -0
  87. coodie-1.0.0/benchmarks/README.md +148 -0
  88. coodie-1.0.0/benchmarks/__init__.py +0 -0
  89. coodie-1.0.0/benchmarks/bench_argus.py +509 -0
  90. coodie-1.0.0/benchmarks/bench_batch.py +73 -0
  91. coodie-1.0.0/benchmarks/bench_collections.py +114 -0
  92. coodie-1.0.0/benchmarks/bench_delete.py +66 -0
  93. coodie-1.0.0/benchmarks/bench_insert.py +82 -0
  94. coodie-1.0.0/benchmarks/bench_raw_dc.py +489 -0
  95. coodie-1.0.0/benchmarks/bench_read.py +147 -0
  96. coodie-1.0.0/benchmarks/bench_schema.py +80 -0
  97. coodie-1.0.0/benchmarks/bench_serialization.py +108 -0
  98. coodie-1.0.0/benchmarks/bench_udt.py +211 -0
  99. coodie-1.0.0/benchmarks/bench_update.py +83 -0
  100. coodie-1.0.0/benchmarks/conftest.py +195 -0
  101. coodie-1.0.0/benchmarks/models_argus_coodie.py +122 -0
  102. coodie-1.0.0/benchmarks/models_argus_cqlengine.py +109 -0
  103. coodie-1.0.0/benchmarks/models_coodie.py +63 -0
  104. coodie-1.0.0/benchmarks/models_cqlengine.py +49 -0
  105. coodie-1.0.0/benchmarks/models_raw_dc.py +45 -0
  106. coodie-1.0.0/commitlint.config.mjs +10 -0
  107. coodie-1.0.0/demo/README.md +111 -0
  108. coodie-1.0.0/demos/README.md +54 -0
  109. coodie-1.0.0/demos/batch-importer/Makefile +43 -0
  110. coodie-1.0.0/demos/batch-importer/README.md +149 -0
  111. coodie-1.0.0/demos/batch-importer/models.py +52 -0
  112. coodie-1.0.0/demos/batch-importer/pyproject.toml +14 -0
  113. coodie-1.0.0/demos/batch-importer/sample_manifest.csv +101 -0
  114. coodie-1.0.0/demos/batch-importer/seed.py +325 -0
  115. coodie-1.0.0/demos/batch-importer/smoke_test.py +32 -0
  116. coodie-1.0.0/demos/django-taskboard/.gitignore +4 -0
  117. coodie-1.0.0/demos/django-taskboard/Makefile +48 -0
  118. coodie-1.0.0/demos/django-taskboard/README.md +137 -0
  119. coodie-1.0.0/demos/django-taskboard/cassandra_models.py +57 -0
  120. coodie-1.0.0/demos/django-taskboard/manage.py +23 -0
  121. coodie-1.0.0/demos/django-taskboard/pyproject.toml +15 -0
  122. coodie-1.0.0/demos/django-taskboard/seed.py +245 -0
  123. coodie-1.0.0/demos/django-taskboard/taskboard/__init__.py +0 -0
  124. coodie-1.0.0/demos/django-taskboard/taskboard/settings.py +60 -0
  125. coodie-1.0.0/demos/django-taskboard/taskboard/urls.py +7 -0
  126. coodie-1.0.0/demos/django-taskboard/taskboard/wsgi.py +9 -0
  127. coodie-1.0.0/demos/django-taskboard/tasks/__init__.py +0 -0
  128. coodie-1.0.0/demos/django-taskboard/tasks/apps.py +30 -0
  129. coodie-1.0.0/demos/django-taskboard/tasks/management/__init__.py +0 -0
  130. coodie-1.0.0/demos/django-taskboard/tasks/management/commands/__init__.py +0 -0
  131. coodie-1.0.0/demos/django-taskboard/tasks/management/commands/sync_cassandra.py +40 -0
  132. coodie-1.0.0/demos/django-taskboard/tasks/templates/tasks/board.html +484 -0
  133. coodie-1.0.0/demos/django-taskboard/tasks/templatetags/__init__.py +0 -0
  134. coodie-1.0.0/demos/django-taskboard/tasks/urls.py +12 -0
  135. coodie-1.0.0/demos/django-taskboard/tasks/views.py +139 -0
  136. coodie-1.0.0/demos/docker-compose.yml +6 -0
  137. coodie-1.0.0/demos/fastapi-catalog/Makefile +42 -0
  138. coodie-1.0.0/demos/fastapi-catalog/README.md +135 -0
  139. coodie-1.0.0/demos/fastapi-catalog/main.py +248 -0
  140. coodie-1.0.0/demos/fastapi-catalog/models.py +54 -0
  141. coodie-1.0.0/demos/fastapi-catalog/pyproject.toml +18 -0
  142. coodie-1.0.0/demos/fastapi-catalog/seed.py +353 -0
  143. coodie-1.0.0/demos/fastapi-catalog/templates/base.html +315 -0
  144. coodie-1.0.0/demos/fastapi-catalog/templates/index.html +62 -0
  145. coodie-1.0.0/demos/fastapi-catalog/templates/partials/product_detail.html +45 -0
  146. coodie-1.0.0/demos/fastapi-catalog/templates/partials/product_list.html +23 -0
  147. coodie-1.0.0/demos/fastapi-catalog/templates/partials/review_list.html +22 -0
  148. coodie-1.0.0/demos/flask-blog/Makefile +42 -0
  149. coodie-1.0.0/demos/flask-blog/README.md +134 -0
  150. coodie-1.0.0/demos/flask-blog/app.py +184 -0
  151. coodie-1.0.0/demos/flask-blog/models.py +53 -0
  152. coodie-1.0.0/demos/flask-blog/pyproject.toml +16 -0
  153. coodie-1.0.0/demos/flask-blog/seed.py +255 -0
  154. coodie-1.0.0/demos/flask-blog/templates/base.html +323 -0
  155. coodie-1.0.0/demos/flask-blog/templates/index.html +36 -0
  156. coodie-1.0.0/demos/flask-blog/templates/new_post.html +32 -0
  157. coodie-1.0.0/demos/flask-blog/templates/post_detail.html +67 -0
  158. coodie-1.0.0/demos/lwt-user-registry/Makefile +42 -0
  159. coodie-1.0.0/demos/lwt-user-registry/README.md +208 -0
  160. coodie-1.0.0/demos/lwt-user-registry/main.py +315 -0
  161. coodie-1.0.0/demos/lwt-user-registry/models.py +55 -0
  162. coodie-1.0.0/demos/lwt-user-registry/pyproject.toml +18 -0
  163. coodie-1.0.0/demos/lwt-user-registry/seed.py +293 -0
  164. coodie-1.0.0/demos/lwt-user-registry/templates/base.html +314 -0
  165. coodie-1.0.0/demos/lwt-user-registry/templates/index.html +71 -0
  166. coodie-1.0.0/demos/lwt-user-registry/templates/partials/profile.html +99 -0
  167. coodie-1.0.0/demos/lwt-user-registry/templates/partials/register_result.html +26 -0
  168. coodie-1.0.0/demos/lwt-user-registry/templates/partials/user_list.html +22 -0
  169. coodie-1.0.0/demos/materialized-views/Makefile +42 -0
  170. coodie-1.0.0/demos/materialized-views/README.md +179 -0
  171. coodie-1.0.0/demos/materialized-views/main.py +207 -0
  172. coodie-1.0.0/demos/materialized-views/models.py +79 -0
  173. coodie-1.0.0/demos/materialized-views/pyproject.toml +18 -0
  174. coodie-1.0.0/demos/materialized-views/seed.py +235 -0
  175. coodie-1.0.0/demos/materialized-views/templates/base.html +296 -0
  176. coodie-1.0.0/demos/materialized-views/templates/index.html +77 -0
  177. coodie-1.0.0/demos/materialized-views/templates/partials/product_list.html +20 -0
  178. coodie-1.0.0/demos/materialized-views/templates/partials/view_results.html +26 -0
  179. coodie-1.0.0/demos/ttl-sessions/Makefile +53 -0
  180. coodie-1.0.0/demos/ttl-sessions/README.md +170 -0
  181. coodie-1.0.0/demos/ttl-sessions/main.py +145 -0
  182. coodie-1.0.0/demos/ttl-sessions/models.py +41 -0
  183. coodie-1.0.0/demos/ttl-sessions/pyproject.toml +18 -0
  184. coodie-1.0.0/demos/ttl-sessions/seed.py +184 -0
  185. coodie-1.0.0/demos/ttl-sessions/smoke_test.py +101 -0
  186. coodie-1.0.0/demos/ttl-sessions/templates/base.html +328 -0
  187. coodie-1.0.0/demos/ttl-sessions/templates/index.html +76 -0
  188. coodie-1.0.0/demos/ttl-sessions/templates/partials/session_list.html +66 -0
  189. coodie-1.0.0/docs/Makefile +20 -0
  190. coodie-1.0.0/docs/images/logo.png +0 -0
  191. coodie-1.0.0/docs/make.bat +35 -0
  192. coodie-1.0.0/docs/plans/client-encryption.md +181 -0
  193. coodie-1.0.0/docs/plans/cql-gap-analysis.md +548 -0
  194. coodie-1.0.0/docs/plans/cqlengine-feature-parity.md +992 -0
  195. coodie-1.0.0/docs/plans/cqlengine-missing-features.md +198 -0
  196. coodie-1.0.0/docs/plans/cqlengine-test-coverage-plan.md +447 -0
  197. coodie-1.0.0/docs/plans/demos-extension-plan.md +1476 -0
  198. coodie-1.0.0/docs/plans/documentation-plan.md +1251 -0
  199. coodie-1.0.0/docs/plans/github-actions-testing-plan.md +524 -0
  200. coodie-1.0.0/docs/plans/integration-test-coverage.md +147 -0
  201. coodie-1.0.0/docs/plans/migration-strategy.md +539 -0
  202. coodie-1.0.0/docs/plans/performance-improvement.md +2825 -0
  203. coodie-1.0.0/docs/plans/plan-phase-continuation-action.md +726 -0
  204. coodie-1.0.0/docs/plans/python-rs-driver-support.md +553 -0
  205. coodie-1.0.0/docs/plans/python-rs-feature-gaps.md +264 -0
  206. coodie-1.0.0/docs/plans/raw-dc-benchmark-plan.md +178 -0
  207. coodie-1.0.0/docs/plans/rewrite-coodie-plan.md +549 -0
  208. coodie-1.0.0/docs/plans/silent-exception-pass.md +134 -0
  209. coodie-1.0.0/docs/plans/sync-api-support.md +257 -0
  210. coodie-1.0.0/docs/plans/test-refactoring-plan.md +701 -0
  211. coodie-1.0.0/docs/plans/udt-support.md +707 -0
  212. coodie-1.0.0/docs/source/_benchmarks_extra/benchmarks/index.html +28 -0
  213. coodie-1.0.0/docs/source/_static/.gitkeep +0 -0
  214. coodie-1.0.0/docs/source/api/batch.md +10 -0
  215. coodie-1.0.0/docs/source/api/document.md +21 -0
  216. coodie-1.0.0/docs/source/api/drivers.md +28 -0
  217. coodie-1.0.0/docs/source/api/exceptions.md +10 -0
  218. coodie-1.0.0/docs/source/api/fields.md +10 -0
  219. coodie-1.0.0/docs/source/api/queryset.md +21 -0
  220. coodie-1.0.0/docs/source/api/results.md +9 -0
  221. coodie-1.0.0/docs/source/api/types.md +10 -0
  222. coodie-1.0.0/docs/source/api/usertype.md +9 -0
  223. coodie-1.0.0/docs/source/changelog.md +3 -0
  224. coodie-1.0.0/docs/source/conf.py +70 -0
  225. coodie-1.0.0/docs/source/contributing.md +3 -0
  226. coodie-1.0.0/docs/source/guide/batch-operations.md +197 -0
  227. coodie-1.0.0/docs/source/guide/benchmarks.md +77 -0
  228. coodie-1.0.0/docs/source/guide/collections.md +225 -0
  229. coodie-1.0.0/docs/source/guide/counters.md +111 -0
  230. coodie-1.0.0/docs/source/guide/crud.md +264 -0
  231. coodie-1.0.0/docs/source/guide/defining-documents.md +172 -0
  232. coodie-1.0.0/docs/source/guide/drivers.md +229 -0
  233. coodie-1.0.0/docs/source/guide/encryption.md +274 -0
  234. coodie-1.0.0/docs/source/guide/exceptions.md +184 -0
  235. coodie-1.0.0/docs/source/guide/field-types.md +201 -0
  236. coodie-1.0.0/docs/source/guide/filtering.md +227 -0
  237. coodie-1.0.0/docs/source/guide/integrations.md +226 -0
  238. coodie-1.0.0/docs/source/guide/keys-and-indexes.md +179 -0
  239. coodie-1.0.0/docs/source/guide/lwt.md +213 -0
  240. coodie-1.0.0/docs/source/guide/querying.md +348 -0
  241. coodie-1.0.0/docs/source/guide/recipes.md +208 -0
  242. coodie-1.0.0/docs/source/guide/schema-management.md +415 -0
  243. coodie-1.0.0/docs/source/guide/sync-vs-async.md +182 -0
  244. coodie-1.0.0/docs/source/guide/ttl.md +117 -0
  245. coodie-1.0.0/docs/source/guide/user-defined-types.md +322 -0
  246. coodie-1.0.0/docs/source/index.md +114 -0
  247. coodie-1.0.0/docs/source/installation.md +49 -0
  248. coodie-1.0.0/docs/source/llms-full.txt +386 -0
  249. coodie-1.0.0/docs/source/llms.txt +51 -0
  250. coodie-1.0.0/docs/source/migration/argus-example.md +465 -0
  251. coodie-1.0.0/docs/source/migration/from-cqlengine.md +456 -0
  252. coodie-1.0.0/docs/source/quickstart.md +117 -0
  253. coodie-1.0.0/docs/source/usage.md +61 -0
  254. coodie-1.0.0/pyproject.toml +146 -0
  255. coodie-1.0.0/renovate.json +35 -0
  256. coodie-1.0.0/src/coodie/__init__.py +98 -0
  257. coodie-1.0.0/src/coodie/_version.py +24 -0
  258. coodie-1.0.0/src/coodie/aio/__init__.py +90 -0
  259. coodie-1.0.0/src/coodie/aio/document.py +536 -0
  260. coodie-1.0.0/src/coodie/aio/query.py +473 -0
  261. coodie-1.0.0/src/coodie/batch.py +117 -0
  262. coodie-1.0.0/src/coodie/cql_builder.py +670 -0
  263. coodie-1.0.0/src/coodie/drivers/__init__.py +223 -0
  264. coodie-1.0.0/src/coodie/drivers/acsylla.py +503 -0
  265. coodie-1.0.0/src/coodie/drivers/base.py +83 -0
  266. coodie-1.0.0/src/coodie/drivers/cassandra.py +421 -0
  267. coodie-1.0.0/src/coodie/drivers/lazy.py +164 -0
  268. coodie-1.0.0/src/coodie/drivers/python_rs.py +481 -0
  269. coodie-1.0.0/src/coodie/exceptions.py +22 -0
  270. coodie-1.0.0/src/coodie/fields.py +128 -0
  271. coodie-1.0.0/src/coodie/lazy.py +54 -0
  272. coodie-1.0.0/src/coodie/migrations/__init__.py +41 -0
  273. coodie-1.0.0/src/coodie/migrations/autogen.py +547 -0
  274. coodie-1.0.0/src/coodie/migrations/base.py +203 -0
  275. coodie-1.0.0/src/coodie/migrations/cli.py +502 -0
  276. coodie-1.0.0/src/coodie/migrations/runner.py +405 -0
  277. coodie-1.0.0/src/coodie/py.typed +0 -0
  278. coodie-1.0.0/src/coodie/results.py +30 -0
  279. coodie-1.0.0/src/coodie/schema.py +255 -0
  280. coodie-1.0.0/src/coodie/sync/__init__.py +90 -0
  281. coodie-1.0.0/src/coodie/sync/document.py +536 -0
  282. coodie-1.0.0/src/coodie/sync/query.py +474 -0
  283. coodie-1.0.0/src/coodie/types.py +232 -0
  284. coodie-1.0.0/src/coodie/usertype.py +290 -0
  285. coodie-1.0.0/tests/__init__.py +0 -0
  286. coodie-1.0.0/tests/conftest.py +149 -0
  287. coodie-1.0.0/tests/conftest_scylla.py +137 -0
  288. coodie-1.0.0/tests/integration/__init__.py +0 -0
  289. coodie-1.0.0/tests/integration/conftest.py +914 -0
  290. coodie-1.0.0/tests/integration/test_basic.py +380 -0
  291. coodie-1.0.0/tests/integration/test_counter.py +100 -0
  292. coodie-1.0.0/tests/integration/test_encryption.py +418 -0
  293. coodie-1.0.0/tests/integration/test_extended.py +722 -0
  294. coodie-1.0.0/tests/integration/test_keyspace.py +57 -0
  295. coodie-1.0.0/tests/integration/test_lwt.py +216 -0
  296. coodie-1.0.0/tests/integration/test_migration.py +147 -0
  297. coodie-1.0.0/tests/integration/test_migration_phase_b.py +309 -0
  298. coodie-1.0.0/tests/integration/test_pagination.py +188 -0
  299. coodie-1.0.0/tests/integration/test_raw_cql.py +59 -0
  300. coodie-1.0.0/tests/integration/test_udt.py +194 -0
  301. coodie-1.0.0/tests/integration/test_update.py +261 -0
  302. coodie-1.0.0/tests/integration/test_views.py +83 -0
  303. coodie-1.0.0/tests/models.py +152 -0
  304. coodie-1.0.0/tests/test_api_parity.py +85 -0
  305. coodie-1.0.0/tests/test_batch.py +332 -0
  306. coodie-1.0.0/tests/test_cql_builder.py +967 -0
  307. coodie-1.0.0/tests/test_document.py +914 -0
  308. coodie-1.0.0/tests/test_drivers.py +1541 -0
  309. coodie-1.0.0/tests/test_keyspace.py +65 -0
  310. coodie-1.0.0/tests/test_lazy.py +150 -0
  311. coodie-1.0.0/tests/test_migrations.py +448 -0
  312. coodie-1.0.0/tests/test_migrations_autogen.py +702 -0
  313. coodie-1.0.0/tests/test_migrations_cli.py +73 -0
  314. coodie-1.0.0/tests/test_migrations_data.py +298 -0
  315. coodie-1.0.0/tests/test_polymorphic.py +319 -0
  316. coodie-1.0.0/tests/test_python_rs_driver.py +473 -0
  317. coodie-1.0.0/tests/test_query.py +873 -0
  318. coodie-1.0.0/tests/test_schema.py +444 -0
  319. coodie-1.0.0/tests/test_types.py +318 -0
  320. coodie-1.0.0/tests/test_usertype.py +375 -0
  321. coodie-1.0.0/tests/test_workflow_conventions.py +161 -0
  322. coodie-1.0.0/tests/workflows/__init__.py +0 -0
  323. coodie-1.0.0/tests/workflows/conftest.py +70 -0
  324. coodie-1.0.0/tests/workflows/test_build_delegation_prompt.bats +69 -0
  325. coodie-1.0.0/tests/workflows/test_extract_plan_ref.bats +186 -0
  326. coodie-1.0.0/tests/workflows/test_smoke.bats +12 -0
  327. coodie-1.0.0/uv.lock +1456 -0
@@ -0,0 +1,27 @@
1
+ {
2
+ "projectName": "coodie",
3
+ "projectOwner": "scylladb",
4
+ "repoType": "github",
5
+ "repoHost": "https://github.com",
6
+ "files": [
7
+ "README.md"
8
+ ],
9
+ "imageSize": 80,
10
+ "commit": true,
11
+ "commitConvention": "angular",
12
+ "contributors": [
13
+ {
14
+ "login": "fruch",
15
+ "name": "Israel Fruchter",
16
+ "avatar_url": "https://avatars.githubusercontent.com/u/340979?v=4",
17
+ "profile": "http://fruch.github.io/",
18
+ "contributions": [
19
+ "code",
20
+ "ideas",
21
+ "doc"
22
+ ]
23
+ }
24
+ ],
25
+ "contributorsPerLine": 7,
26
+ "skipCi": true
27
+ }
@@ -0,0 +1,21 @@
1
+ # http://editorconfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 4
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+ charset = utf-8
11
+ end_of_line = lf
12
+
13
+ [*.bat]
14
+ indent_style = tab
15
+ end_of_line = crlf
16
+
17
+ [LICENSE]
18
+ insert_final_newline = false
19
+
20
+ [Makefile]
21
+ indent_style = tab
@@ -0,0 +1 @@
1
+ github: ["scylladb"]
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ labels: bug
5
+ ---
6
+
7
+ **Describe the bug**
8
+ A clear and concise description of what the bug is.
9
+
10
+ **To Reproduce**
11
+ Steps to reproduce the behavior:
12
+
13
+ **Additional context**
14
+ Add any other context about the problem here.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ labels: enhancement
5
+ ---
6
+
7
+ **Is your feature request related to a problem? Please describe.**
8
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9
+
10
+ **Describe the solution you'd like**
11
+ A clear and concise description of what you want to happen.
12
+
13
+ **Additional context**
14
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,43 @@
1
+ ## Description
2
+
3
+ <!-- Describe the changes in this PR. -->
4
+
5
+ ## Related Issue
6
+
7
+ <!-- Link any related GitHub issues: Fixes #123 -->
8
+
9
+ ## Plan Reference
10
+
11
+ <!--
12
+ If this PR implements a phase of a multi-phase plan, add a `Plan:` line below.
13
+ The Plan Phase Continuation workflow uses this to automatically delegate the
14
+ next phase to Copilot after merge.
15
+
16
+ Format:
17
+ Plan: docs/plans/<plan-name>.md
18
+ Phase: N ← optional: the phase number this PR completes
19
+
20
+ Example:
21
+ Plan: docs/plans/udt-support.md
22
+ Phase: 2
23
+
24
+ Leave blank if this PR is not part of a plan.
25
+ -->
26
+
27
+ ## Type of Change
28
+
29
+ - [ ] Bug fix (non-breaking change which fixes an issue)
30
+ - [ ] New feature (non-breaking change which adds functionality)
31
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
32
+ - [ ] Documentation update
33
+ - [ ] Refactor / code cleanup
34
+ - [ ] Test improvements
35
+ - [ ] CI / workflow changes
36
+
37
+ ## Checklist
38
+
39
+ - [ ] My code follows the project's coding style
40
+ - [ ] I have added/updated tests that prove my fix/feature works
41
+ - [ ] All existing tests pass (`uv run pytest tests/`)
42
+ - [ ] I have run `uv run pre-commit run --all-files` and fixed any issues
43
+ - [ ] My commit messages follow the Conventional Commits format
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bats
2
+ # Tests for setup-shims.sh — supports Claude Code (CLAUDE_ENV_FILE)
3
+ # and GitHub Actions / Copilot coding agent (GITHUB_PATH)
4
+
5
+ SETUP_SCRIPT="${BATS_TEST_DIRNAME}/setup-shims.sh"
6
+
7
+ setup() {
8
+ export CLAUDE_ENV_FILE
9
+ CLAUDE_ENV_FILE="$(mktemp)"
10
+ # Create a fake uv so the guard passes
11
+ FAKE_BIN="$(mktemp -d)"
12
+ echo '#!/usr/bin/env bash' >"$FAKE_BIN/uv"
13
+ chmod +x "$FAKE_BIN/uv"
14
+ export FAKE_BIN
15
+ # Save original PATH
16
+ export ORIG_PATH="$PATH"
17
+ }
18
+
19
+ teardown() {
20
+ rm -f "$CLAUDE_ENV_FILE"
21
+ rm -rf "$FAKE_BIN"
22
+ }
23
+
24
+ @test "exits silently when neither env file is set" {
25
+ run env -u CLAUDE_ENV_FILE -u GITHUB_PATH PATH="${FAKE_BIN}:${ORIG_PATH}" \
26
+ bash "$SETUP_SCRIPT"
27
+ [[ $status -eq 0 ]]
28
+ }
29
+
30
+ @test "exits silently when uv is not available" {
31
+ # Remove fake uv dir from PATH; keep rest so bash/coreutils work
32
+ local path_without_uv=""
33
+ local IFS=:
34
+ for dir in $ORIG_PATH; do
35
+ [[ "$dir" == "$FAKE_BIN" ]] && continue
36
+ # Also skip dirs with real uv
37
+ [[ -x "$dir/uv" ]] && continue
38
+ path_without_uv="${path_without_uv:+${path_without_uv}:}$dir"
39
+ done
40
+ run env PATH="$path_without_uv" CLAUDE_ENV_FILE="$CLAUDE_ENV_FILE" \
41
+ bash "$SETUP_SCRIPT"
42
+ [[ $status -eq 0 ]]
43
+ [[ ! -s "$CLAUDE_ENV_FILE" ]]
44
+ }
45
+
46
+ # ── Claude Code (CLAUDE_ENV_FILE) ───────────────────────────────────────────
47
+
48
+ @test "writes PATH export to CLAUDE_ENV_FILE" {
49
+ run env -u GITHUB_PATH PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
50
+ [[ $status -eq 0 ]]
51
+ grep -q 'export PATH=' "$CLAUDE_ENV_FILE"
52
+ }
53
+
54
+ @test "shims dir appears in CLAUDE_ENV_FILE PATH export" {
55
+ env -u GITHUB_PATH PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
56
+ local shims_dir
57
+ shims_dir="$(cd "${BATS_TEST_DIRNAME}/shims" && pwd)"
58
+ grep -q "$shims_dir" "$CLAUDE_ENV_FILE"
59
+ }
60
+
61
+ @test "CLAUDE_ENV_FILE PATH export is absolute" {
62
+ env -u GITHUB_PATH PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
63
+ local line
64
+ line="$(cat "$CLAUDE_ENV_FILE")"
65
+ [[ "$line" =~ export\ PATH=\"/ ]]
66
+ }
67
+
68
+ @test "appends to existing CLAUDE_ENV_FILE content" {
69
+ echo 'export FOO=bar' >"$CLAUDE_ENV_FILE"
70
+ env -u GITHUB_PATH PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
71
+ grep -q 'export FOO=bar' "$CLAUDE_ENV_FILE"
72
+ grep -q 'export PATH=' "$CLAUDE_ENV_FILE"
73
+ }
74
+
75
+ # ── GitHub Actions / Copilot coding agent (GITHUB_PATH) ─────────────────────
76
+
77
+ @test "writes shims dir to GITHUB_PATH" {
78
+ local gh_path_file
79
+ gh_path_file="$(mktemp)"
80
+ run env -u CLAUDE_ENV_FILE GITHUB_PATH="$gh_path_file" \
81
+ PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
82
+ [[ $status -eq 0 ]]
83
+ [[ -s "$gh_path_file" ]]
84
+ rm -f "$gh_path_file"
85
+ }
86
+
87
+ @test "shims dir appears in GITHUB_PATH file" {
88
+ local gh_path_file
89
+ gh_path_file="$(mktemp)"
90
+ env -u CLAUDE_ENV_FILE GITHUB_PATH="$gh_path_file" \
91
+ PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
92
+ local shims_dir
93
+ shims_dir="$(cd "${BATS_TEST_DIRNAME}/shims" && pwd)"
94
+ grep -q "$shims_dir" "$gh_path_file"
95
+ rm -f "$gh_path_file"
96
+ }
97
+
98
+ @test "GITHUB_PATH entry is absolute path" {
99
+ local gh_path_file
100
+ gh_path_file="$(mktemp)"
101
+ env -u CLAUDE_ENV_FILE GITHUB_PATH="$gh_path_file" \
102
+ PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
103
+ local line
104
+ line="$(cat "$gh_path_file")"
105
+ [[ "$line" == /* ]]
106
+ rm -f "$gh_path_file"
107
+ }
108
+
109
+ @test "GITHUB_PATH takes precedence over CLAUDE_ENV_FILE" {
110
+ local gh_path_file
111
+ gh_path_file="$(mktemp)"
112
+ env GITHUB_PATH="$gh_path_file" CLAUDE_ENV_FILE="$CLAUDE_ENV_FILE" \
113
+ PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
114
+ # shims dir written to GITHUB_PATH
115
+ local shims_dir
116
+ shims_dir="$(cd "${BATS_TEST_DIRNAME}/shims" && pwd)"
117
+ grep -q "$shims_dir" "$gh_path_file"
118
+ # CLAUDE_ENV_FILE NOT written (early exit after GITHUB_PATH)
119
+ [[ ! -s "$CLAUDE_ENV_FILE" ]]
120
+ rm -f "$gh_path_file"
121
+ }
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Prepend the shims directory to PATH so that bare python/pip/pipx/uv-pip
5
+ # invocations are intercepted with uv suggestions.
6
+ #
7
+ # Supported environments:
8
+ # - Claude Code (SessionStart hook): uses CLAUDE_ENV_FILE
9
+ # - GitHub Actions / Copilot coding agent: uses GITHUB_PATH
10
+ #
11
+ # Exits cleanly (no-op) in any other environment.
12
+ #
13
+ # `uv run` is unaffected because it prepends its managed virtualenv's
14
+ # bin/ to PATH, shadowing the shims.
15
+
16
+ # Guard: only activate when uv is available
17
+ command -v uv &>/dev/null || exit 0
18
+
19
+ shims_dir="$(cd "$(dirname "$0")/shims" && pwd)" || {
20
+ echo "modern-python: shims directory not found" >&2
21
+ exit 1
22
+ }
23
+
24
+ # GitHub Actions / Copilot coding agent: prepend to PATH via $GITHUB_PATH
25
+ if [[ -n "${GITHUB_PATH:-}" ]]; then
26
+ echo "${shims_dir}" >>"$GITHUB_PATH"
27
+ exit 0
28
+ fi
29
+
30
+ # Claude Code SessionStart hook: export PATH via $CLAUDE_ENV_FILE
31
+ if [[ -n "${CLAUDE_ENV_FILE:-}" ]]; then
32
+ echo "export PATH=\"${shims_dir}:\${PATH}\"" >>"$CLAUDE_ENV_FILE"
33
+ exit 0
34
+ fi
35
+
36
+ echo "modern-python: neither GITHUB_PATH nor CLAUDE_ENV_FILE set; shims will not be installed" >&2
37
+ exit 0
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for pip/pip3 — intercepts bare invocations and
5
+ # suggests the uv equivalent. Works for both names via $0.
6
+ cmd="$(basename "$0")"
7
+
8
+ case "${1:-}" in
9
+ install)
10
+ echo "ERROR: Use \`uv add <package>\` instead of \`$cmd install\`" >&2
11
+ echo " For one-off usage without adding to project: uv run --with <package> ..." >&2
12
+ ;;
13
+ uninstall)
14
+ echo "ERROR: Use \`uv remove <package>\` instead of \`$cmd uninstall\`" >&2
15
+ ;;
16
+ freeze)
17
+ echo "ERROR: Use \`uv export\` instead of \`$cmd freeze\`" >&2
18
+ ;;
19
+ *)
20
+ echo "ERROR: Use \`uv\` commands instead of \`$cmd\`" >&2
21
+ echo " uv add <package> # install a dependency" >&2
22
+ echo " uv remove <package> # remove a dependency" >&2
23
+ echo " uv sync # sync environment" >&2
24
+ ;;
25
+ esac
26
+
27
+ exit 1
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bats
2
+ # Tests for pip/pip3 PATH shim
3
+
4
+ SHIM="${BATS_TEST_DIRNAME}/pip"
5
+
6
+ @test "exits non-zero for pip install" {
7
+ run "$SHIM" install requests
8
+ [[ $status -ne 0 ]]
9
+ [[ "$output" == *"uv add"* ]]
10
+ }
11
+
12
+ @test "suggests uv run --with for one-off usage" {
13
+ run "$SHIM" install requests
14
+ [[ "$output" == *"uv run --with"* ]]
15
+ }
16
+
17
+ @test "exits non-zero for pip uninstall" {
18
+ run "$SHIM" uninstall requests
19
+ [[ $status -ne 0 ]]
20
+ [[ "$output" == *"uv remove"* ]]
21
+ }
22
+
23
+ @test "exits non-zero for pip freeze" {
24
+ run "$SHIM" freeze
25
+ [[ $status -ne 0 ]]
26
+ [[ "$output" == *"uv export"* ]]
27
+ }
28
+
29
+ @test "exits non-zero for bare pip" {
30
+ run "$SHIM"
31
+ [[ $status -ne 0 ]]
32
+ [[ "$output" == *"uv"* ]]
33
+ }
34
+
35
+ @test "exits non-zero for pip show" {
36
+ run "$SHIM" show requests
37
+ [[ $status -ne 0 ]]
38
+ [[ "$output" == *"uv"* ]]
39
+ }
40
+
41
+ @test "works when invoked as pip3 via symlink" {
42
+ run "${BATS_TEST_DIRNAME}/pip3" install foo
43
+ [[ $status -ne 0 ]]
44
+ [[ "$output" == *"uv add"* ]]
45
+ }
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for pip/pip3 — intercepts bare invocations and
5
+ # suggests the uv equivalent. Works for both names via $0.
6
+ cmd="$(basename "$0")"
7
+
8
+ case "${1:-}" in
9
+ install)
10
+ echo "ERROR: Use \`uv add <package>\` instead of \`$cmd install\`" >&2
11
+ echo " For one-off usage without adding to project: uv run --with <package> ..." >&2
12
+ ;;
13
+ uninstall)
14
+ echo "ERROR: Use \`uv remove <package>\` instead of \`$cmd uninstall\`" >&2
15
+ ;;
16
+ freeze)
17
+ echo "ERROR: Use \`uv export\` instead of \`$cmd freeze\`" >&2
18
+ ;;
19
+ *)
20
+ echo "ERROR: Use \`uv\` commands instead of \`$cmd\`" >&2
21
+ echo " uv add <package> # install a dependency" >&2
22
+ echo " uv remove <package> # remove a dependency" >&2
23
+ echo " uv sync # sync environment" >&2
24
+ ;;
25
+ esac
26
+
27
+ exit 1
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for pipx — intercepts bare invocations and
5
+ # suggests the uv tool equivalent.
6
+
7
+ case "${1:-}" in
8
+ install)
9
+ echo "ERROR: Use \`uv tool install <package>\` instead of \`pipx install\`" >&2
10
+ ;;
11
+ uninstall)
12
+ echo "ERROR: Use \`uv tool uninstall <package>\` instead of \`pipx uninstall\`" >&2
13
+ ;;
14
+ run)
15
+ echo "ERROR: Use \`uvx <package>\` instead of \`pipx run\`" >&2
16
+ ;;
17
+ upgrade)
18
+ echo "ERROR: Use \`uv tool upgrade <package>\` instead of \`pipx upgrade\`" >&2
19
+ ;;
20
+ upgrade-all)
21
+ echo "ERROR: Use \`uv tool upgrade --all\` instead of \`pipx upgrade-all\`" >&2
22
+ ;;
23
+ ensurepath)
24
+ echo "ERROR: Use \`uv tool update-shell\` instead of \`pipx ensurepath\`" >&2
25
+ ;;
26
+ inject)
27
+ echo "ERROR: Use \`uv tool install --with <dep> <package>\` instead of \`pipx inject\`" >&2
28
+ ;;
29
+ list)
30
+ echo "ERROR: Use \`uv tool list\` instead of \`pipx list\`" >&2
31
+ ;;
32
+ *)
33
+ echo "ERROR: Use \`uv tool\` commands instead of \`pipx\`" >&2
34
+ echo " uv tool install <package> # install a CLI tool" >&2
35
+ echo " uv tool uninstall <package> # uninstall a CLI tool" >&2
36
+ echo " uvx <package> # run a tool without installing" >&2
37
+ echo " uv tool list # list installed tools" >&2
38
+ ;;
39
+ esac
40
+
41
+ exit 1
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bats
2
+ # Tests for pipx PATH shim
3
+
4
+ SHIM="${BATS_TEST_DIRNAME}/pipx"
5
+
6
+ @test "exits non-zero for pipx install" {
7
+ run "$SHIM" install black
8
+ [[ $status -ne 0 ]]
9
+ [[ "$output" == *"uv tool install"* ]]
10
+ }
11
+
12
+ @test "exits non-zero for pipx uninstall" {
13
+ run "$SHIM" uninstall black
14
+ [[ $status -ne 0 ]]
15
+ [[ "$output" == *"uv tool uninstall"* ]]
16
+ }
17
+
18
+ @test "exits non-zero for pipx run" {
19
+ run "$SHIM" run black
20
+ [[ $status -ne 0 ]]
21
+ [[ "$output" == *"uvx"* ]]
22
+ }
23
+
24
+ @test "exits non-zero for pipx upgrade" {
25
+ run "$SHIM" upgrade black
26
+ [[ $status -ne 0 ]]
27
+ [[ "$output" == *"uv tool upgrade"* ]]
28
+ }
29
+
30
+ @test "exits non-zero for pipx inject" {
31
+ run "$SHIM" inject black click
32
+ [[ $status -ne 0 ]]
33
+ [[ "$output" == *"uv tool install --with"* ]]
34
+ }
35
+
36
+ @test "exits non-zero for pipx list" {
37
+ run "$SHIM" list
38
+ [[ $status -ne 0 ]]
39
+ [[ "$output" == *"uv tool list"* ]]
40
+ }
41
+
42
+ @test "exits non-zero for pipx upgrade-all" {
43
+ run "$SHIM" upgrade-all
44
+ [[ $status -ne 0 ]]
45
+ [[ "$output" == *"uv tool upgrade --all"* ]]
46
+ }
47
+
48
+ @test "exits non-zero for pipx ensurepath" {
49
+ run "$SHIM" ensurepath
50
+ [[ $status -ne 0 ]]
51
+ [[ "$output" == *"uv tool update-shell"* ]]
52
+ }
53
+
54
+ @test "exits non-zero for bare pipx" {
55
+ run "$SHIM"
56
+ [[ $status -ne 0 ]]
57
+ [[ "$output" == *"uv tool"* ]]
58
+ }
59
+
60
+ @test "exits non-zero for unknown pipx subcommand" {
61
+ run "$SHIM" completions
62
+ [[ $status -ne 0 ]]
63
+ [[ "$output" == *"uv tool"* ]]
64
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for python/python3 — intercepts bare invocations and
5
+ # suggests the uv equivalent. Works for both names via $0.
6
+ cmd="$(basename "$0")"
7
+
8
+ case "${1:-}" in
9
+ -m)
10
+ case "${2:-}" in
11
+ pip)
12
+ echo "ERROR: \`$cmd -m pip\` is not supported. Use:" >&2
13
+ echo " uv add <package> # add a dependency" >&2
14
+ echo " uv remove <package> # remove a dependency" >&2
15
+ ;;
16
+ *)
17
+ echo "ERROR: Use \`uv run $cmd -m ${2:-<module>}\` instead of \`$cmd -m ${2:-<module>}\`" >&2
18
+ ;;
19
+ esac
20
+ ;;
21
+ *)
22
+ echo "ERROR: Use \`uv run $cmd ${*:-}\` instead of \`$cmd ${*:-}\`" >&2
23
+ ;;
24
+ esac
25
+
26
+ exit 1
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bats
2
+ # Tests for python/python3 PATH shim
3
+
4
+ SHIM="${BATS_TEST_DIRNAME}/python"
5
+
6
+ @test "exits non-zero for bare python" {
7
+ run "$SHIM"
8
+ [[ $status -ne 0 ]]
9
+ [[ "$output" == *"uv run python"* ]]
10
+ }
11
+
12
+ @test "exits non-zero for python script.py" {
13
+ run "$SHIM" script.py
14
+ [[ $status -ne 0 ]]
15
+ [[ "$output" == *"uv run python script.py"* ]]
16
+ }
17
+
18
+ @test "exits non-zero for python -c" {
19
+ run "$SHIM" -c 'print(1)'
20
+ [[ $status -ne 0 ]]
21
+ [[ "$output" == *"uv run python"* ]]
22
+ }
23
+
24
+ @test "exits non-zero for python -m pytest" {
25
+ run "$SHIM" -m pytest
26
+ [[ $status -ne 0 ]]
27
+ [[ "$output" == *"uv run python -m pytest"* ]]
28
+ }
29
+
30
+ @test "exits non-zero for python -m pip install" {
31
+ run "$SHIM" -m pip install requests
32
+ [[ $status -ne 0 ]]
33
+ [[ "$output" == *"uv add"* ]]
34
+ [[ "$output" == *"uv remove"* ]]
35
+ }
36
+
37
+ @test "suggests uv run python -m <module> for arbitrary modules" {
38
+ run "$SHIM" -m http.server
39
+ [[ $status -ne 0 ]]
40
+ [[ "$output" == *"uv run python -m http.server"* ]]
41
+ }
42
+
43
+ @test "works when invoked as python3 via symlink" {
44
+ run "${BATS_TEST_DIRNAME}/python3"
45
+ [[ $status -ne 0 ]]
46
+ [[ "$output" == *"uv run python3"* ]]
47
+ }
48
+
49
+ @test "python3 -m pip suggests uv add" {
50
+ run "${BATS_TEST_DIRNAME}/python3" -m pip install foo
51
+ [[ $status -ne 0 ]]
52
+ [[ "$output" == *"uv add"* ]]
53
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for python/python3 — intercepts bare invocations and
5
+ # suggests the uv equivalent. Works for both names via $0.
6
+ cmd="$(basename "$0")"
7
+
8
+ case "${1:-}" in
9
+ -m)
10
+ case "${2:-}" in
11
+ pip)
12
+ echo "ERROR: \`$cmd -m pip\` is not supported. Use:" >&2
13
+ echo " uv add <package> # add a dependency" >&2
14
+ echo " uv remove <package> # remove a dependency" >&2
15
+ ;;
16
+ *)
17
+ echo "ERROR: Use \`uv run $cmd -m ${2:-<module>}\` instead of \`$cmd -m ${2:-<module>}\`" >&2
18
+ ;;
19
+ esac
20
+ ;;
21
+ *)
22
+ echo "ERROR: Use \`uv run $cmd ${*:-}\` instead of \`$cmd ${*:-}\`" >&2
23
+ ;;
24
+ esac
25
+
26
+ exit 1
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PATH shim for uv — intercepts `uv pip` (legacy interface) and passes
5
+ # everything else through to the real uv binary.
6
+
7
+ if [[ "${1:-}" == "pip" ]]; then
8
+ echo "ERROR: \`uv pip\` is the legacy interface. Use instead:" >&2
9
+ echo " uv add <package> # instead of uv pip install" >&2
10
+ echo " uv remove <package> # instead of uv pip uninstall" >&2
11
+ echo " uv sync # instead of uv pip sync" >&2
12
+ exit 1
13
+ fi
14
+
15
+ # Find the real uv by skipping this shim's directory in PATH
16
+ shim_dir="$(cd "$(dirname "$0")" && pwd)"
17
+ IFS=: read -ra path_entries <<<"${PATH:-}"
18
+ for dir in "${path_entries[@]}"; do
19
+ resolved="$(cd "$dir" 2>/dev/null && pwd)" || continue
20
+ [[ "$resolved" == "$shim_dir" ]] && continue
21
+ if [[ -x "$dir/uv" ]]; then
22
+ exec "$dir/uv" "$@"
23
+ fi
24
+ done
25
+
26
+ echo "ERROR: real uv binary not found on PATH" >&2
27
+ exit 127
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bats
2
+ # Tests for uv PATH shim
3
+ # Requires: nix shell nixpkgs#uv -c bats ...
4
+
5
+ SHIM="${BATS_TEST_DIRNAME}/uv"
6
+
7
+ setup() {
8
+ command -v uv &>/dev/null || skip "uv not available — run via: nix shell nixpkgs#uv -c bats ..."
9
+ }
10
+
11
+ @test "exits non-zero for uv pip install" {
12
+ run "$SHIM" pip install requests
13
+ [[ $status -ne 0 ]]
14
+ [[ "$output" == *"uv add"* ]]
15
+ }
16
+
17
+ @test "exits non-zero for uv pip sync" {
18
+ run "$SHIM" pip sync
19
+ [[ $status -ne 0 ]]
20
+ [[ "$output" == *"uv sync"* ]]
21
+ }
22
+
23
+ @test "exits non-zero for uv pip freeze" {
24
+ run "$SHIM" pip freeze
25
+ [[ $status -ne 0 ]]
26
+ [[ "$output" == *"legacy"* ]]
27
+ }
28
+
29
+ @test "suggests uv remove for uv pip uninstall" {
30
+ run "$SHIM" pip uninstall foo
31
+ [[ $status -ne 0 ]]
32
+ [[ "$output" == *"uv remove"* ]]
33
+ }
34
+
35
+ @test "passes through to real uv for non-pip subcommands" {
36
+ run "$SHIM" --version
37
+ [[ $status -eq 0 ]]
38
+ [[ "$output" == *"uv"* ]]
39
+ }
40
+
41
+ @test "exits 127 with error when real uv is not found" {
42
+ # Include /usr/bin for coreutils but exclude dirs with a real uv
43
+ local path_no_uv="${BATS_TEST_DIRNAME}:/usr/bin:/bin"
44
+ run env PATH="$path_no_uv" "$SHIM" --version
45
+ [[ $status -eq 127 ]]
46
+ [[ "$output" == *"real uv binary not found"* ]]
47
+ }