pycatalyst 0.0.7.dev0__tar.gz → 0.0.9__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 (555) hide show
  1. pycatalyst-0.0.9/.github/workflows/README.md +87 -0
  2. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/.github/workflows/publish.yml +13 -2
  3. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/PKG-INFO +21 -2
  4. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/pyproject.toml +30 -1
  5. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/_types.py +17 -0
  6. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/main.py +24 -1
  7. pycatalyst-0.0.9/src/pycatalyst/api/routes/v1/ml.py +92 -0
  8. pycatalyst-0.0.9/src/pycatalyst/api/routes/v1/services.py +184 -0
  9. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/workbench.py +138 -3
  10. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/cli.py +96 -0
  11. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/workbench.py +67 -0
  12. pycatalyst-0.0.9/src/pycatalyst/data/profiles/pycharter_dev.yaml +8 -0
  13. pycatalyst-0.0.9/src/pycatalyst/data/profiles/pystator_dev.yaml +9 -0
  14. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/errors.py +103 -0
  15. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/generators/engine.py +3 -0
  16. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/generators/scalar.py +47 -3
  17. pycatalyst-0.0.9/src/pycatalyst/ml/__init__.py +72 -0
  18. pycatalyst-0.0.9/src/pycatalyst/ml/_protocols.py +113 -0
  19. pycatalyst-0.0.9/src/pycatalyst/ml/_types.py +53 -0
  20. pycatalyst-0.0.9/src/pycatalyst/ml/huggingface/__init__.py +16 -0
  21. pycatalyst-0.0.9/src/pycatalyst/ml/huggingface/config.py +67 -0
  22. pycatalyst-0.0.9/src/pycatalyst/ml/huggingface/data.py +111 -0
  23. pycatalyst-0.0.9/src/pycatalyst/ml/huggingface/engine.py +206 -0
  24. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/__init__.py +19 -0
  25. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/config.py +136 -0
  26. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/data/__init__.py +3 -0
  27. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/data/scaling.py +111 -0
  28. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/data/tabular.py +106 -0
  29. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/data/temporal.py +153 -0
  30. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/device.py +46 -0
  31. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/evaluation.py +222 -0
  32. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/__init__.py +3 -0
  33. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/base.py +81 -0
  34. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/gru.py +43 -0
  35. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/lstm.py +44 -0
  36. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/mlp.py +47 -0
  37. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/registry.py +34 -0
  38. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/tcn.py +96 -0
  39. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/models/transformer.py +73 -0
  40. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/serving.py +144 -0
  41. pycatalyst-0.0.9/src/pycatalyst/ml/pytorch/trainer.py +324 -0
  42. pycatalyst-0.0.9/src/pycatalyst/ml/registry.py +109 -0
  43. pycatalyst-0.0.9/src/pycatalyst/ml/results.py +259 -0
  44. pycatalyst-0.0.9/src/pycatalyst/ml/run.py +112 -0
  45. pycatalyst-0.0.9/src/pycatalyst/ml/sklearn/__init__.py +16 -0
  46. pycatalyst-0.0.9/src/pycatalyst/ml/sklearn/_helpers.py +334 -0
  47. pycatalyst-0.0.9/src/pycatalyst/ml/sklearn/config.py +71 -0
  48. pycatalyst-0.0.9/src/pycatalyst/ml/sklearn/engine.py +258 -0
  49. pycatalyst-0.0.9/src/pycatalyst/ml/trainers/__init__.py +42 -0
  50. pycatalyst-0.0.9/src/pycatalyst/ml/trainers/base.py +318 -0
  51. pycatalyst-0.0.9/src/pycatalyst/ml/trainers/huggingface.py +110 -0
  52. pycatalyst-0.0.9/src/pycatalyst/ml/trainers/pytorch.py +143 -0
  53. pycatalyst-0.0.9/src/pycatalyst/ml/trainers/sklearn.py +286 -0
  54. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/backends/base.py +27 -0
  55. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/backends/docker_backend.py +116 -0
  56. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/backends/venv_backend.py +87 -0
  57. pycatalyst-0.0.9/src/pycatalyst/services/profiles.py +126 -0
  58. pycatalyst-0.0.9/src/pycatalyst/services/service_containers.py +760 -0
  59. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/workbench_manager.py +241 -5
  60. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/dev.py +1 -1
  61. pycatalyst-0.0.9/src/pycatalyst/ui/out/404/index.html +1 -0
  62. pycatalyst-0.0.9/src/pycatalyst/ui/out/404.html +1 -0
  63. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/__next.__PAGE__.txt +2 -2
  64. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/__next._full.txt +8 -8
  65. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/documentation → pycatalyst-0.0.9/src/pycatalyst/ui/out}/__next._head.txt +1 -1
  66. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/__next._index.txt +7 -7
  67. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/__next._tree.txt +2 -2
  68. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/1e64a5cb4f765f55.js +5 -0
  69. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/273748ce4060ff69.js +1 -0
  70. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/2813a606ea909dac.js +17 -0
  71. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/3bc80b7de23b0505.js +34 -0
  72. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/3cf48831cd571080.js +1 -0
  73. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/cd046009fa99a225.js → pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/4f59202584037820.js +1 -1
  74. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/605de2830bad5f2c.css +2 -0
  75. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/67019a27b3bb9d9f.js +1 -0
  76. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/98a0eebf60225743.js +1 -0
  77. pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/edda94bf12eed230.js +73 -0
  78. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/826946f349a354cd.js → pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/chunks/f89f46aa53fbb172.js +14 -13
  79. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._full.txt +13 -13
  80. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._head.txt +3 -3
  81. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._index.txt +9 -9
  82. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._not-found.__PAGE__.txt +2 -2
  83. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._not-found.txt +3 -3
  84. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/__next._tree.txt +2 -2
  85. pycatalyst-0.0.9/src/pycatalyst/ui/out/_not-found/index.html +1 -0
  86. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/_not-found/index.txt +13 -13
  87. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/documentation/__next._full.txt +8 -8
  88. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/out/documentation}/__next._head.txt +1 -1
  89. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/documentation/__next._index.txt +7 -7
  90. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/documentation/__next._tree.txt +2 -2
  91. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/documentation/__next.documentation.__PAGE__.txt +2 -2
  92. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/documentation/__next.documentation.txt +1 -1
  93. pycatalyst-0.0.9/src/pycatalyst/ui/out/documentation/index.html +1 -0
  94. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/documentation/index.txt +8 -8
  95. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/generate/__next._full.txt +8 -8
  96. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/login → pycatalyst-0.0.9/src/pycatalyst/ui/out/generate}/__next._head.txt +1 -1
  97. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/login → pycatalyst-0.0.9/src/pycatalyst/ui/out/generate}/__next._index.txt +7 -7
  98. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/generate/__next._tree.txt +2 -2
  99. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/generate/__next.generate.__PAGE__.txt +2 -2
  100. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/generate/__next.generate.txt +1 -1
  101. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/recipes → pycatalyst-0.0.9/src/pycatalyst/ui/out/generate}/index.html +1 -1
  102. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/generate/index.txt +8 -8
  103. pycatalyst-0.0.9/src/pycatalyst/ui/out/index.html +1 -0
  104. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/index.txt +8 -8
  105. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/login/__next._full.txt +8 -8
  106. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/generate → pycatalyst-0.0.9/src/pycatalyst/ui/out/login}/__next._head.txt +1 -1
  107. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/generate → pycatalyst-0.0.9/src/pycatalyst/ui/out/login}/__next._index.txt +7 -7
  108. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/login/__next._tree.txt +2 -2
  109. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/login/__next.login.__PAGE__.txt +2 -2
  110. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/login/__next.login.txt +1 -1
  111. pycatalyst-0.0.9/src/pycatalyst/ui/out/login/index.html +1 -0
  112. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/login/index.txt +8 -8
  113. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next._full.txt +22 -0
  114. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next._head.txt +5 -0
  115. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next._index.txt +10 -0
  116. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next._tree.txt +2 -0
  117. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next.model-training.__PAGE__.txt +9 -0
  118. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/__next.model-training.txt +4 -0
  119. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/documentation → pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training}/index.html +1 -1
  120. pycatalyst-0.0.9/src/pycatalyst/ui/out/model-training/index.txt +22 -0
  121. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/recipes/__next._full.txt +8 -8
  122. pycatalyst-0.0.9/src/pycatalyst/ui/out/recipes/__next._head.txt +5 -0
  123. pycatalyst-0.0.9/src/pycatalyst/ui/out/recipes/__next._index.txt +10 -0
  124. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/recipes/__next._tree.txt +2 -2
  125. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/recipes/__next.recipes.__PAGE__.txt +2 -2
  126. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/recipes/__next.recipes.txt +1 -1
  127. pycatalyst-0.0.9/src/pycatalyst/ui/out/recipes/index.html +1 -0
  128. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/recipes/index.txt +8 -8
  129. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/schemas/__next._full.txt +8 -8
  130. pycatalyst-0.0.9/src/pycatalyst/ui/out/schemas/__next._head.txt +5 -0
  131. pycatalyst-0.0.9/src/pycatalyst/ui/out/schemas/__next._index.txt +10 -0
  132. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/schemas/__next._tree.txt +2 -2
  133. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/schemas/__next.schemas.__PAGE__.txt +2 -2
  134. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/schemas/__next.schemas.txt +1 -1
  135. pycatalyst-0.0.9/src/pycatalyst/ui/out/schemas/index.html +1 -0
  136. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/schemas/index.txt +8 -8
  137. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/settings/__next._full.txt +8 -8
  138. pycatalyst-0.0.9/src/pycatalyst/ui/out/settings/__next._head.txt +5 -0
  139. pycatalyst-0.0.9/src/pycatalyst/ui/out/settings/__next._index.txt +10 -0
  140. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/settings/__next._tree.txt +2 -2
  141. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/settings/__next.settings.__PAGE__.txt +2 -2
  142. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/settings/__next.settings.txt +1 -1
  143. pycatalyst-0.0.9/src/pycatalyst/ui/out/settings/index.html +1 -0
  144. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/settings/index.txt +8 -8
  145. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/sinks/__next._full.txt +8 -8
  146. pycatalyst-0.0.9/src/pycatalyst/ui/out/sinks/__next._head.txt +5 -0
  147. pycatalyst-0.0.9/src/pycatalyst/ui/out/sinks/__next._index.txt +10 -0
  148. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/sinks/__next._tree.txt +2 -2
  149. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/sinks/__next.sinks.__PAGE__.txt +2 -2
  150. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/sinks/__next.sinks.txt +1 -1
  151. pycatalyst-0.0.9/src/pycatalyst/ui/out/sinks/index.html +1 -0
  152. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static → pycatalyst-0.0.9/src/pycatalyst/ui/out}/sinks/index.txt +8 -8
  153. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/workbench/__next._full.txt +8 -8
  154. pycatalyst-0.0.9/src/pycatalyst/ui/out/workbench/__next._head.txt +5 -0
  155. pycatalyst-0.0.9/src/pycatalyst/ui/out/workbench/__next._index.txt +10 -0
  156. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/workbench/__next._tree.txt +2 -2
  157. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/workbench/__next.workbench.__PAGE__.txt +2 -2
  158. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/workbench/__next.workbench.txt +1 -1
  159. pycatalyst-0.0.9/src/pycatalyst/ui/out/workbench/index.html +1 -0
  160. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/workbench/index.txt +8 -8
  161. pycatalyst-0.0.9/src/pycatalyst/ui/src/app/generate/page.tsx +1048 -0
  162. pycatalyst-0.0.9/src/pycatalyst/ui/src/app/model-training/page.tsx +267 -0
  163. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/page.tsx +6 -19
  164. pycatalyst-0.0.9/src/pycatalyst/ui/src/app/recipes/page.tsx +18 -0
  165. pycatalyst-0.0.9/src/pycatalyst/ui/src/app/schemas/page.tsx +18 -0
  166. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/workbench/page.tsx +183 -12
  167. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/Navigation.tsx +1 -2
  168. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/sidebar/CollapsibleSidebar.tsx +188 -0
  169. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/sidebar/index.ts +2 -0
  170. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/CreateEnvDialog.tsx +157 -0
  171. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/DatabaseDialog.tsx +131 -0
  172. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/InstallPackageDialog.tsx +154 -0
  173. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/PackagePanel.tsx +173 -0
  174. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/SendDataDialog.tsx +190 -0
  175. pycatalyst-0.0.9/src/pycatalyst/ui/src/components/workbench/ServiceStatusBar.tsx +106 -0
  176. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/workbench/WorkbenchToolbar.tsx +48 -0
  177. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/api.ts +6 -0
  178. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/constants.ts +1 -0
  179. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/types/index.ts +14 -0
  180. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/workbench.ts +196 -2
  181. pycatalyst-0.0.9/src/pycatalyst/ui/static/404/index.html +1 -0
  182. pycatalyst-0.0.9/src/pycatalyst/ui/static/404.html +1 -0
  183. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/__next.__PAGE__.txt +2 -2
  184. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/__next._full.txt +8 -8
  185. pycatalyst-0.0.9/src/pycatalyst/ui/static/__next._head.txt +5 -0
  186. pycatalyst-0.0.9/src/pycatalyst/ui/static/__next._index.txt +10 -0
  187. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/__next._tree.txt +2 -2
  188. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/1e64a5cb4f765f55.js +5 -0
  189. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/273748ce4060ff69.js +1 -0
  190. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/2813a606ea909dac.js +17 -0
  191. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/3bc80b7de23b0505.js +34 -0
  192. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/3cf48831cd571080.js +1 -0
  193. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/cd046009fa99a225.js → pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/4f59202584037820.js +1 -1
  194. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/605de2830bad5f2c.css +2 -0
  195. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/67019a27b3bb9d9f.js +1 -0
  196. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/98a0eebf60225743.js +1 -0
  197. pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/edda94bf12eed230.js +73 -0
  198. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/826946f349a354cd.js → pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/chunks/f89f46aa53fbb172.js +14 -13
  199. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._full.txt +13 -13
  200. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._head.txt +3 -3
  201. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._index.txt +9 -9
  202. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._not-found.__PAGE__.txt +2 -2
  203. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._not-found.txt +3 -3
  204. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/__next._tree.txt +2 -2
  205. pycatalyst-0.0.9/src/pycatalyst/ui/static/_not-found/index.html +1 -0
  206. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/_not-found/index.txt +13 -13
  207. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/documentation/__next._full.txt +8 -8
  208. pycatalyst-0.0.9/src/pycatalyst/ui/static/documentation/__next._head.txt +5 -0
  209. pycatalyst-0.0.9/src/pycatalyst/ui/static/documentation/__next._index.txt +10 -0
  210. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/documentation/__next._tree.txt +2 -2
  211. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/documentation/__next.documentation.__PAGE__.txt +2 -2
  212. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/documentation/__next.documentation.txt +1 -1
  213. pycatalyst-0.0.9/src/pycatalyst/ui/static/documentation/index.html +1 -0
  214. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/documentation/index.txt +8 -8
  215. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/generate/__next._full.txt +8 -8
  216. pycatalyst-0.0.9/src/pycatalyst/ui/static/generate/__next._head.txt +5 -0
  217. pycatalyst-0.0.9/src/pycatalyst/ui/static/generate/__next._index.txt +10 -0
  218. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/generate/__next._tree.txt +2 -2
  219. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/generate/__next.generate.__PAGE__.txt +2 -2
  220. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/generate/__next.generate.txt +1 -1
  221. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/schemas → pycatalyst-0.0.9/src/pycatalyst/ui/static/generate}/index.html +1 -1
  222. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/generate/index.txt +8 -8
  223. pycatalyst-0.0.9/src/pycatalyst/ui/static/index.html +1 -0
  224. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/index.txt +8 -8
  225. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/login/__next._full.txt +8 -8
  226. pycatalyst-0.0.9/src/pycatalyst/ui/static/login/__next._head.txt +5 -0
  227. pycatalyst-0.0.9/src/pycatalyst/ui/static/login/__next._index.txt +10 -0
  228. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/login/__next._tree.txt +2 -2
  229. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/login/__next.login.__PAGE__.txt +2 -2
  230. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/login/__next.login.txt +1 -1
  231. pycatalyst-0.0.9/src/pycatalyst/ui/static/login/index.html +1 -0
  232. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/login/index.txt +8 -8
  233. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next._full.txt +22 -0
  234. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next._head.txt +5 -0
  235. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next._index.txt +10 -0
  236. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next._tree.txt +2 -0
  237. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next.model-training.__PAGE__.txt +9 -0
  238. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/__next.model-training.txt +4 -0
  239. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/documentation → pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training}/index.html +1 -1
  240. pycatalyst-0.0.9/src/pycatalyst/ui/static/model-training/index.txt +22 -0
  241. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/recipes/__next._full.txt +8 -8
  242. pycatalyst-0.0.9/src/pycatalyst/ui/static/recipes/__next._head.txt +5 -0
  243. pycatalyst-0.0.9/src/pycatalyst/ui/static/recipes/__next._index.txt +10 -0
  244. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/recipes/__next._tree.txt +2 -2
  245. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/recipes/__next.recipes.__PAGE__.txt +2 -2
  246. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/recipes/__next.recipes.txt +1 -1
  247. pycatalyst-0.0.9/src/pycatalyst/ui/static/recipes/index.html +1 -0
  248. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/recipes/index.txt +8 -8
  249. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/schemas/__next._full.txt +8 -8
  250. pycatalyst-0.0.9/src/pycatalyst/ui/static/schemas/__next._head.txt +5 -0
  251. pycatalyst-0.0.9/src/pycatalyst/ui/static/schemas/__next._index.txt +10 -0
  252. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/schemas/__next._tree.txt +2 -2
  253. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/schemas/__next.schemas.__PAGE__.txt +2 -2
  254. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/schemas/__next.schemas.txt +1 -1
  255. pycatalyst-0.0.9/src/pycatalyst/ui/static/schemas/index.html +1 -0
  256. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/schemas/index.txt +8 -8
  257. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/settings/__next._full.txt +8 -8
  258. pycatalyst-0.0.9/src/pycatalyst/ui/static/settings/__next._head.txt +5 -0
  259. pycatalyst-0.0.9/src/pycatalyst/ui/static/settings/__next._index.txt +10 -0
  260. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/settings/__next._tree.txt +2 -2
  261. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/settings/__next.settings.__PAGE__.txt +2 -2
  262. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/settings/__next.settings.txt +1 -1
  263. pycatalyst-0.0.9/src/pycatalyst/ui/static/settings/index.html +1 -0
  264. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/settings/index.txt +8 -8
  265. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/sinks/__next._full.txt +8 -8
  266. pycatalyst-0.0.9/src/pycatalyst/ui/static/sinks/__next._head.txt +5 -0
  267. pycatalyst-0.0.9/src/pycatalyst/ui/static/sinks/__next._index.txt +10 -0
  268. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/sinks/__next._tree.txt +2 -2
  269. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/sinks/__next.sinks.__PAGE__.txt +2 -2
  270. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/sinks/__next.sinks.txt +1 -1
  271. pycatalyst-0.0.9/src/pycatalyst/ui/static/sinks/index.html +1 -0
  272. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out → pycatalyst-0.0.9/src/pycatalyst/ui/static}/sinks/index.txt +8 -8
  273. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/workbench/__next._full.txt +8 -8
  274. pycatalyst-0.0.9/src/pycatalyst/ui/static/workbench/__next._head.txt +5 -0
  275. pycatalyst-0.0.9/src/pycatalyst/ui/static/workbench/__next._index.txt +10 -0
  276. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/workbench/__next._tree.txt +2 -2
  277. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/workbench/__next.workbench.__PAGE__.txt +2 -2
  278. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/workbench/__next.workbench.txt +1 -1
  279. pycatalyst-0.0.9/src/pycatalyst/ui/static/workbench/index.html +1 -0
  280. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/workbench/index.txt +8 -8
  281. pycatalyst-0.0.9/src/pycatalyst/ui/tsconfig.tsbuildinfo +1 -0
  282. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/PKG-INFO +21 -2
  283. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/SOURCES.txt +107 -28
  284. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/requires.txt +24 -1
  285. pycatalyst-0.0.9/tests/unit/test_base_trainer.py +237 -0
  286. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_generators.py +66 -0
  287. pycatalyst-0.0.9/tests/unit/test_ml_protocols.py +109 -0
  288. pycatalyst-0.0.9/tests/unit/test_ml_registry.py +54 -0
  289. pycatalyst-0.0.9/tests/unit/test_ml_results.py +223 -0
  290. pycatalyst-0.0.9/tests/unit/test_ml_types.py +71 -0
  291. pycatalyst-0.0.9/tests/unit/test_profiles.py +95 -0
  292. pycatalyst-0.0.9/tests/unit/test_pytorch_trainer.py +141 -0
  293. pycatalyst-0.0.9/tests/unit/test_service_containers.py +663 -0
  294. pycatalyst-0.0.9/tests/unit/test_service_routes.py +276 -0
  295. pycatalyst-0.0.9/tests/unit/test_sklearn_trainer.py +208 -0
  296. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_types.py +22 -0
  297. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_venv_backend.py +39 -0
  298. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_workbench_manager.py +54 -0
  299. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_workbench_routes.py +114 -0
  300. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/404/index.html +0 -1
  301. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/404.html +0 -1
  302. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/0664a23cd6a5f7ba.js +0 -34
  303. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/33dc0ae90f863979.js +0 -1
  304. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/3db2622c9e17684f.js +0 -1
  305. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/48f408d5c9d2a0ba.js +0 -1
  306. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/4a93e9c0c43d24a7.css +0 -2
  307. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/88a6dfcd964f4302.js +0 -73
  308. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/ab52a6590efbe138.js +0 -1
  309. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/c6ac0e3a3d0e355f.js +0 -5
  310. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/chunks/de634c2407095732.js +0 -5
  311. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_not-found/index.html +0 -1
  312. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/generate/index.html +0 -1
  313. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/index.html +0 -1
  314. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/login/index.html +0 -1
  315. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/recipes/__next._head.txt +0 -5
  316. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/recipes/__next._index.txt +0 -10
  317. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/recipes/index.html +0 -1
  318. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/schemas/__next._head.txt +0 -5
  319. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/schemas/__next._index.txt +0 -10
  320. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/settings/__next._head.txt +0 -5
  321. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/settings/__next._index.txt +0 -10
  322. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/settings/index.html +0 -1
  323. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/sinks/__next._head.txt +0 -5
  324. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/sinks/__next._index.txt +0 -10
  325. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/sinks/index.html +0 -1
  326. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/workbench/__next._head.txt +0 -5
  327. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/workbench/__next._index.txt +0 -10
  328. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/workbench/index.html +0 -1
  329. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/src/app/generate/page.tsx +0 -303
  330. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/src/app/recipes/page.tsx +0 -220
  331. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/src/app/schemas/page.tsx +0 -210
  332. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/404/index.html +0 -1
  333. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/404.html +0 -1
  334. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/__next._head.txt +0 -5
  335. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/__next._index.txt +0 -10
  336. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/0664a23cd6a5f7ba.js +0 -34
  337. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/33dc0ae90f863979.js +0 -1
  338. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/3db2622c9e17684f.js +0 -1
  339. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/48f408d5c9d2a0ba.js +0 -1
  340. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/4a93e9c0c43d24a7.css +0 -2
  341. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/88a6dfcd964f4302.js +0 -73
  342. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/ab52a6590efbe138.js +0 -1
  343. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/c6ac0e3a3d0e355f.js +0 -5
  344. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/chunks/de634c2407095732.js +0 -5
  345. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_not-found/index.html +0 -1
  346. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/documentation/__next._head.txt +0 -5
  347. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/documentation/__next._index.txt +0 -10
  348. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/generate/__next._head.txt +0 -5
  349. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/generate/__next._index.txt +0 -10
  350. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/generate/index.html +0 -1
  351. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/index.html +0 -1
  352. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/login/__next._head.txt +0 -5
  353. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/login/__next._index.txt +0 -10
  354. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/login/index.html +0 -1
  355. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/recipes/__next._head.txt +0 -5
  356. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/recipes/__next._index.txt +0 -10
  357. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/schemas/__next._head.txt +0 -5
  358. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/schemas/__next._index.txt +0 -10
  359. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/schemas/index.html +0 -1
  360. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/settings/__next._head.txt +0 -5
  361. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/settings/__next._index.txt +0 -10
  362. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/settings/index.html +0 -1
  363. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/sinks/__next._head.txt +0 -5
  364. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/sinks/__next._index.txt +0 -10
  365. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/sinks/index.html +0 -1
  366. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/workbench/__next._head.txt +0 -5
  367. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/workbench/__next._index.txt +0 -10
  368. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/workbench/index.html +0 -1
  369. pycatalyst-0.0.7.dev0/src/pycatalyst/ui/tsconfig.tsbuildinfo +0 -1
  370. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/.github/workflows/test.yml +0 -0
  371. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/.gitignore +0 -0
  372. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/.pre-commit-config.yaml +0 -0
  373. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/CHANGELOG.md +0 -0
  374. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/CONTRIBUTING.md +0 -0
  375. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/LICENSE +0 -0
  376. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/Makefile +0 -0
  377. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/README.md +0 -0
  378. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/docs/PUBLISHING.md +0 -0
  379. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/pycatalyst.cfg +0 -0
  380. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/pycatalyst.cfg.example +0 -0
  381. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/scripts/publish-once.sh +0 -0
  382. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/setup.cfg +0 -0
  383. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/setup.sh +0 -0
  384. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/__init__.py +0 -0
  385. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/_protocols.py +0 -0
  386. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/__init__.py +0 -0
  387. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/dependencies/__init__.py +0 -0
  388. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/dependencies/auth.py +0 -0
  389. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/dependencies/database.py +0 -0
  390. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/models/__init__.py +0 -0
  391. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/models/requests.py +0 -0
  392. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/models/responses.py +0 -0
  393. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/__init__.py +0 -0
  394. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/__init__.py +0 -0
  395. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/auth.py +0 -0
  396. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/generate.py +0 -0
  397. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/infer.py +0 -0
  398. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/recipes.py +0 -0
  399. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/api/routes/v1/settings.py +0 -0
  400. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/__init__.py +0 -0
  401. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/auth.py +0 -0
  402. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/database.py +0 -0
  403. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/paths.py +0 -0
  404. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/config/ui.py +0 -0
  405. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/data/seed/.gitkeep +0 -0
  406. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/data/templates/recipes/pycharter_contracts.yaml +0 -0
  407. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/data/templates/recipes/pyoptima_portfolio.yaml +0 -0
  408. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/data/templates/recipes/pystator_events.yaml +0 -0
  409. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/__init__.py +0 -0
  410. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/base.py +0 -0
  411. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/cli.py +0 -0
  412. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/config.py +0 -0
  413. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/migrations/__init__.py +0 -0
  414. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/migrations/env.py +0 -0
  415. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/migrations/versions/20260101000000_initial.py +0 -0
  416. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/migrations/versions/__init__.py +0 -0
  417. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/models/__init__.py +0 -0
  418. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/models/app_metadata.py +0 -0
  419. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/db/paths.py +0 -0
  420. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/generators/__init__.py +0 -0
  421. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/generators/compound.py +0 -0
  422. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/generators/registry.py +0 -0
  423. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/py.typed +0 -0
  424. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/recipes/__init__.py +0 -0
  425. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/recipes/loader.py +0 -0
  426. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/recipes/models.py +0 -0
  427. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/recipes/runner.py +0 -0
  428. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/schema/__init__.py +0 -0
  429. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/schema/inferrer.py +0 -0
  430. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/schema/json_schema.py +0 -0
  431. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/schema/pydantic.py +0 -0
  432. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/schema/spec.py +0 -0
  433. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/__init__.py +0 -0
  434. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/services/backends/__init__.py +0 -0
  435. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/__init__.py +0 -0
  436. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/database.py +0 -0
  437. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/file.py +0 -0
  438. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/http.py +0 -0
  439. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/kafka.py +0 -0
  440. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/memory.py +0 -0
  441. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/sinks/rabbitmq.py +0 -0
  442. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/.eslintrc.json +0 -0
  443. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/.npmrc +0 -0
  444. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/__init__.py +0 -0
  445. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/build.py +0 -0
  446. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/components.json +0 -0
  447. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/next-env.d.ts +0 -0
  448. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/next.config.js +0 -0
  449. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/node_modules/flatted/python/flatted.py +0 -0
  450. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/0575f275776d153c.js +0 -0
  451. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/31674d9a34dac40b.js +0 -0
  452. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/612195d87a9f708e.js +0 -0
  453. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/82abf2d65f5428ae.js +0 -0
  454. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  455. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/a6dad97d9634a72d.js.map +0 -0
  456. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/ace5f280042c2f7a.js +0 -0
  457. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/b7b85a15f387ab7c.css +0 -0
  458. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/b82d3555a0c5ad54.js +0 -0
  459. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/c0645d6fea057384.js +0 -0
  460. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/cc784667b24a8c60.js +0 -0
  461. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/d2be314c3ece3fbe.js +0 -0
  462. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/f2f58a7e93290fbb.js +0 -0
  463. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/ff1a16fafef87110.js +0 -0
  464. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/out/_next/static/chunks/turbopack-dc3a2def751ab70b.js +0 -0
  465. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_buildManifest.js +0 -0
  466. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_clientMiddlewareManifest.json +0 -0
  467. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/out/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/out/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_ssgManifest.js +0 -0
  468. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/package-lock.json +0 -0
  469. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/package.json +0 -0
  470. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/postcss.config.js +0 -0
  471. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/server.py +0 -0
  472. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/documentation/page.tsx +0 -0
  473. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/error.tsx +0 -0
  474. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/globals.css +0 -0
  475. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/layout.tsx +0 -0
  476. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/loading.tsx +0 -0
  477. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/login/page.tsx +0 -0
  478. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/settings/page.tsx +0 -0
  479. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/sinks/page.tsx +0 -0
  480. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/app/themes.css +0 -0
  481. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ThemeFromConfig.tsx +0 -0
  482. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ThemeSync.tsx +0 -0
  483. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/common/ErrorBoundary.tsx +0 -0
  484. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/common/ErrorDisplay.tsx +0 -0
  485. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/common/LoadingSpinner.tsx +0 -0
  486. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/common/index.ts +0 -0
  487. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/ApiUnavailableBanner.tsx +0 -0
  488. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/AppShell.tsx +0 -0
  489. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/AuthGuard.tsx +0 -0
  490. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/PageContainer.tsx +0 -0
  491. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/PageHeader.tsx +0 -0
  492. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/layout/index.ts +0 -0
  493. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/alert.tsx +0 -0
  494. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/badge.tsx +0 -0
  495. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/button.tsx +0 -0
  496. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/card.tsx +0 -0
  497. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/input.tsx +0 -0
  498. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/label.tsx +0 -0
  499. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/skeleton.tsx +0 -0
  500. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/switch.tsx +0 -0
  501. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/tabs.tsx +0 -0
  502. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/ui/textarea.tsx +0 -0
  503. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/workbench/ContainerDialog.tsx +0 -0
  504. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/components/workbench/TerminalPanel.tsx +0 -0
  505. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/hooks/use-auth-init.ts +0 -0
  506. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/auth-storage.ts +0 -0
  507. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/settings.ts +0 -0
  508. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/terminal-theme.ts +0 -0
  509. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/utils.ts +0 -0
  510. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/lib/workbench-storage.ts +0 -0
  511. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/stores/app-config.ts +0 -0
  512. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/stores/auth.ts +0 -0
  513. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/stores/index.ts +0 -0
  514. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/src/types/global.d.ts +0 -0
  515. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/0575f275776d153c.js +0 -0
  516. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/31674d9a34dac40b.js +0 -0
  517. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/612195d87a9f708e.js +0 -0
  518. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/82abf2d65f5428ae.js +0 -0
  519. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  520. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/a6dad97d9634a72d.js.map +0 -0
  521. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/ace5f280042c2f7a.js +0 -0
  522. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/b7b85a15f387ab7c.css +0 -0
  523. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/b82d3555a0c5ad54.js +0 -0
  524. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/c0645d6fea057384.js +0 -0
  525. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/cc784667b24a8c60.js +0 -0
  526. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/d2be314c3ece3fbe.js +0 -0
  527. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/f2f58a7e93290fbb.js +0 -0
  528. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  529. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/static/_next/static/chunks/turbopack-dc3a2def751ab70b.js +0 -0
  530. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_buildManifest.js +0 -0
  531. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_clientMiddlewareManifest.json +0 -0
  532. {pycatalyst-0.0.7.dev0/src/pycatalyst/ui/static/_next/static/xwVOo753r2AQr1Ieeepou → pycatalyst-0.0.9/src/pycatalyst/ui/static/_next/static/veX4Uuc-0b_OTi6i92Ndo}/_ssgManifest.js +0 -0
  533. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/tailwind.config.js +0 -0
  534. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/ui/tsconfig.json +0 -0
  535. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst/worker/__init__.py +0 -0
  536. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/dependency_links.txt +0 -0
  537. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/entry_points.txt +0 -0
  538. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/src/pycatalyst.egg-info/top_level.txt +0 -0
  539. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/__init__.py +0 -0
  540. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/conftest.py +0 -0
  541. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/integration/__init__.py +0 -0
  542. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/test_version.py +0 -0
  543. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/__init__.py +0 -0
  544. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_api.py +0 -0
  545. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_database_sink.py +0 -0
  546. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_errors.py +0 -0
  547. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_file_sink.py +0 -0
  548. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_http_sink.py +0 -0
  549. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_kafka_sink.py +0 -0
  550. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_protocols.py +0 -0
  551. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_rabbitmq_sink.py +0 -0
  552. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_recipes.py +0 -0
  553. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_schema.py +0 -0
  554. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_scrollback_buffer.py +0 -0
  555. {pycatalyst-0.0.7.dev0 → pycatalyst-0.0.9}/tests/unit/test_sinks.py +0 -0
@@ -0,0 +1,87 @@
1
+ # GitHub Actions in PyCatalyst
2
+
3
+ ## What should happen when you create a PR (develop → main)
4
+
5
+ When you open a **pull request that targets `main` or `develop`**:
6
+
7
+ 1. The **Test** workflow should run (`.github/workflows/test.yml`).
8
+ 2. You get **3 matrix jobs** (Python 3.11, 3.12, 3.13), each running:
9
+ - Install deps (`pip install -e ".[dev]"`)
10
+ - `pytest`
11
+ - Ruff format + Ruff check (linting)
12
+ - Mypy (type checking)
13
+ - Node/npm for UI (if present): `npm ci`, `npm run type-check`
14
+ 3. The run appears under the **Checks** tab of the PR and in **Actions**.
15
+
16
+ Trigger in `test.yml` is:
17
+
18
+ ```yaml
19
+ on:
20
+ pull_request:
21
+ branches: [main, develop]
22
+ ```
23
+
24
+ So the PR’s **base (target) branch** must be `main` or `develop`. A PR **develop → main** has base `main`, so it qualifies.
25
+
26
+ ---
27
+
28
+ ## Why the workflow might not run at all
29
+
30
+ ### 1. Workflow file not on the PR’s **source** branch (most common)
31
+
32
+ GitHub runs the workflow that exists on the **head** of the PR (the branch you’re merging **from**).
33
+
34
+ - PR: **develop → main**
35
+ - GitHub uses the workflow from the **develop** branch.
36
+ - If `.github/workflows/test.yml` is **not** on `develop` (e.g. you only added it on `main`), **no workflow run is created**.
37
+
38
+ **Fix:** Ensure the workflow is on the branch you use for the PR:
39
+
40
+ - Merge `main` into `develop` and push, then open (or update) the PR, or
41
+ - Cherry-pick/add the workflow on `develop` and push.
42
+
43
+ After that, new pushes to the PR or reopening it should trigger the Test workflow.
44
+
45
+ ### 2. GitHub Actions disabled or restricted
46
+
47
+ - **Settings → Actions → General**
48
+ - “Actions permissions”: should allow “Allow all actions and reusable workflows” (or your intended choice).
49
+ - If “Disable actions” is selected, no workflows run.
50
+ - **Fork PRs:** If the PR is from a **fork**, check “Fork pull request workflows from outside collaborators” (or equivalent); if disabled, workflows from fork PRs may not run.
51
+
52
+ ### 3. Default branch / branch name
53
+
54
+ - The trigger only lists `main` and `develop`. If your default branch is something else (e.g. `master`) and you open a PR **into** that branch, the workflow will not run unless you add that branch to `branches:` in `test.yml`.
55
+
56
+ ### 4. Credits / billing (unlikely to prevent the run from starting)
57
+
58
+ - **Public repos:** GitHub Actions minutes are free; you don’t run out of “credits” in a way that would stop the workflow from **starting**.
59
+ - **Private repos:** Free tier has a monthly minutes limit. Exhausting it or having a **spending limit set to $0** can block new runs. You’d usually see a billing warning in the UI or email; the run might show as “canceled” or not start.
60
+ - If **no run appears at all** (no “Test” workflow in the Actions tab for that PR), the usual cause is that the workflow didn’t trigger (e.g. workflow file not on the source branch or Actions disabled), not billing.
61
+
62
+ ---
63
+
64
+ ## Quick checklist when no runs appear for “develop → main”
65
+
66
+ 1. **Workflow on `develop`**
67
+ On GitHub, open the repo, switch to branch **develop**, and confirm `.github/workflows/test.yml` exists and has the `pull_request: branches: [main, develop]` trigger.
68
+
69
+ 2. **PR base branch**
70
+ The PR must target **main** (or **develop**). If it targets another branch, the current trigger won’t run.
71
+
72
+ 3. **Actions enabled**
73
+ **Settings → Actions → General** → Actions are not disabled.
74
+
75
+ 4. **Fork (if applicable)**
76
+ If the PR is from a fork, ensure “Fork pull request workflows” (or similar) is allowed.
77
+
78
+ 5. **Push after fixing**
79
+ If you just merged `main` into `develop` to get the workflow file onto `develop`, push that merge (or any new commit) to the PR branch so the workflow is re-evaluated.
80
+
81
+ ---
82
+
83
+ ## Summary
84
+
85
+ - **Expected:** A PR that targets `main` or `develop` (e.g. develop → main) should trigger the **Test** workflow and run tests on Python 3.11, 3.12, and 3.13.
86
+ - **Most likely reason it doesn’t:** The workflow file is not on the PR’s source branch (e.g. not on `develop`). Get `.github/workflows/test.yml` onto that branch (e.g. by merging `main` into `develop`), then push and re-open or update the PR.
87
+ - **Then check:** Settings → Actions and, for fork PRs, fork workflow permissions. Credits are rarely the cause when no run appears at all.
@@ -1,4 +1,5 @@
1
- # Build and publish to PyPI when a version tag (v*) is pushed.
1
+ # Build and publish to PyPI when a version tag (v*) is pushed or a
2
+ # GitHub Release is published via the UI.
2
3
  # Also supports manual run (workflow_dispatch).
3
4
  # Version is derived from the git tag by setuptools-scm.
4
5
 
@@ -7,6 +8,8 @@ name: Build and Publish
7
8
  on:
8
9
  push:
9
10
  tags: ['v*']
11
+ release:
12
+ types: [published]
10
13
  workflow_dispatch:
11
14
 
12
15
  permissions:
@@ -22,6 +25,12 @@ jobs:
22
25
  uses: actions/checkout@v4
23
26
  with:
24
27
  fetch-depth: 0
28
+ # Build from the release tag so setuptools-scm produces a full release version (not .dev)
29
+ ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }}
30
+
31
+ - name: Set version from tag
32
+ if: startsWith(github.ref, 'refs/tags/')
33
+ run: echo "SETUPTOOLS_SCM_PRETEND_VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
25
34
 
26
35
  - name: Set up Python
27
36
  uses: actions/setup-python@v5
@@ -75,13 +84,15 @@ jobs:
75
84
  python -m zipfile -l dist/pycatalyst-*.whl | head -30
76
85
  echo "Package built successfully"
77
86
 
87
+ # Only publish to PyPI when building from a tag (official release). Skip for workflow_dispatch so we don't publish dev versions as pre-release.
78
88
  - name: Publish to PyPI
89
+ if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'release'
79
90
  uses: pypa/gh-action-pypi-publish@release/v1
80
91
  with:
81
92
  packages-dir: dist/
82
93
 
83
94
  - name: Create GitHub Release
84
- if: startsWith(github.ref, 'refs/tags/')
95
+ if: startsWith(github.ref, 'refs/tags/') && github.event_name != 'release'
85
96
  uses: softprops/action-gh-release@v2.4.2
86
97
  with:
87
98
  tag_name: ${{ github.ref_name }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycatalyst
3
- Version: 0.0.7.dev0
3
+ Version: 0.0.9
4
4
  Summary: A schema-aware data generation and testing platform for Python
5
5
  Author-email: StatFYI <contact@statfyi.com>
6
6
  License-Expression: MIT
@@ -24,6 +24,7 @@ Requires-Python: >=3.11
24
24
  Description-Content-Type: text/markdown
25
25
  License-File: LICENSE
26
26
  Requires-Dist: pyyaml>=6.0.0
27
+ Requires-Dist: exrex>=0.11.0
27
28
  Provides-Extra: inference
28
29
  Requires-Dist: pandas>=2.0.0; extra == "inference"
29
30
  Provides-Extra: faker
@@ -59,6 +60,24 @@ Requires-Dist: pycatalyst[api,sandbox]; extra == "workbench"
59
60
  Requires-Dist: ipython>=8.0.0; extra == "workbench"
60
61
  Provides-Extra: sandbox
61
62
  Requires-Dist: docker>=7.0.0; extra == "sandbox"
63
+ Provides-Extra: ml-core
64
+ Requires-Dist: torch>=2.0.0; extra == "ml-core"
65
+ Requires-Dist: numpy>=1.24.0; extra == "ml-core"
66
+ Requires-Dist: pandas>=2.0.0; extra == "ml-core"
67
+ Requires-Dist: matplotlib>=3.7.0; extra == "ml-core"
68
+ Requires-Dist: pydantic>=2.0.0; extra == "ml-core"
69
+ Requires-Dist: joblib>=1.3.0; extra == "ml-core"
70
+ Provides-Extra: ml-sklearn
71
+ Requires-Dist: pycatalyst[ml-core]; extra == "ml-sklearn"
72
+ Requires-Dist: scikit-learn>=1.3.0; extra == "ml-sklearn"
73
+ Provides-Extra: ml-llm
74
+ Requires-Dist: pycatalyst[ml-core]; extra == "ml-llm"
75
+ Requires-Dist: transformers>=4.36.0; extra == "ml-llm"
76
+ Requires-Dist: peft>=0.7.0; extra == "ml-llm"
77
+ Requires-Dist: datasets>=2.16.0; extra == "ml-llm"
78
+ Requires-Dist: accelerate>=0.25.0; extra == "ml-llm"
79
+ Provides-Extra: ml
80
+ Requires-Dist: pycatalyst[ml-core,ml-llm,ml-sklearn]; extra == "ml"
62
81
  Provides-Extra: db
63
82
  Requires-Dist: alembic>=1.13.0; extra == "db"
64
83
  Requires-Dist: sqlalchemy>=2.0.0; extra == "db"
@@ -68,7 +87,7 @@ Provides-Extra: docs
68
87
  Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
69
88
  Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "docs"
70
89
  Provides-Extra: all
71
- Requires-Dist: pycatalyst[api,db,docs,faker,http,inference,parquet,postgres,sandbox,ui,workbench,worker]; extra == "all"
90
+ Requires-Dist: pycatalyst[api,db,docs,faker,http,inference,ml,parquet,postgres,sandbox,ui,workbench,worker]; extra == "all"
72
91
  Provides-Extra: dev
73
92
  Requires-Dist: pycatalyst[all]; extra == "dev"
74
93
  Requires-Dist: pytest>=7.0.0; extra == "dev"
@@ -12,6 +12,7 @@ requires-python = ">=3.11"
12
12
  license = "MIT"
13
13
  dependencies = [
14
14
  "pyyaml>=6.0.0",
15
+ "exrex>=0.11.0",
15
16
  ]
16
17
  authors = [
17
18
  { name = "StatFYI", email = "contact@statfyi.com" },
@@ -56,6 +57,10 @@ local_scheme = "no-local-version"
56
57
  # pip install pycatalyst[faker] -> + realistic fake data via Faker
57
58
  # pip install pycatalyst[http] -> + HTTP sink
58
59
  # pip install pycatalyst[api] -> + REST API server
60
+ # pip install pycatalyst[ml-core] -> + PyTorch ML training engine
61
+ # pip install pycatalyst[ml-sklearn] -> + scikit-learn ML engine
62
+ # pip install pycatalyst[ml-llm] -> + HuggingFace LLM fine-tuning
63
+ # pip install pycatalyst[ml] -> all ML engines
59
64
  # pip install pycatalyst[all] -> everything
60
65
  # pip install pycatalyst[dev] -> all + testing & dev tools
61
66
  # ---------------------------------------------------------------------------
@@ -120,6 +125,30 @@ sandbox = [
120
125
  "docker>=7.0.0",
121
126
  ]
122
127
 
128
+ # --- ML training and serving ---
129
+ ml-core = [
130
+ "torch>=2.0.0",
131
+ "numpy>=1.24.0",
132
+ "pandas>=2.0.0",
133
+ "matplotlib>=3.7.0",
134
+ "pydantic>=2.0.0",
135
+ "joblib>=1.3.0",
136
+ ]
137
+ ml-sklearn = [
138
+ "pycatalyst[ml-core]",
139
+ "scikit-learn>=1.3.0",
140
+ ]
141
+ ml-llm = [
142
+ "pycatalyst[ml-core]",
143
+ "transformers>=4.36.0",
144
+ "peft>=0.7.0",
145
+ "datasets>=2.16.0",
146
+ "accelerate>=0.25.0",
147
+ ]
148
+ ml = [
149
+ "pycatalyst[ml-core,ml-sklearn,ml-llm]",
150
+ ]
151
+
123
152
  # --- Package-specific extras ---
124
153
  db = [
125
154
  "alembic>=1.13.0",
@@ -136,7 +165,7 @@ docs = [
136
165
 
137
166
  # --- Aggregate extras ---
138
167
  all = [
139
- "pycatalyst[inference,faker,parquet,http,api,worker,ui,workbench,sandbox,db,postgres,docs]",
168
+ "pycatalyst[inference,faker,parquet,http,api,worker,ui,workbench,sandbox,db,postgres,docs,ml]",
140
169
  ]
141
170
  dev = [
142
171
  "pycatalyst[all]",
@@ -112,6 +112,9 @@ class FieldConstraints:
112
112
  min_items: Minimum number of items for array fields.
113
113
  max_items: Maximum number of items for array fields.
114
114
  format: Named format hint (e.g., "email", "url", "phone").
115
+ exclusive_min: If True, generated value must be strictly greater than min.
116
+ exclusive_max: If True, generated value must be strictly less than max.
117
+ multiple_of: Generated value must be a multiple of this (int/float).
115
118
  """
116
119
 
117
120
  min: int | float | None = None
@@ -126,6 +129,9 @@ class FieldConstraints:
126
129
  min_items: int | None = None
127
130
  max_items: int | None = None
128
131
  format: str | None = None
132
+ exclusive_min: bool = False
133
+ exclusive_max: bool = False
134
+ multiple_of: int | float | None = None
129
135
 
130
136
  def __post_init__(self) -> None:
131
137
  if self.min is not None and self.max is not None and self.min > self.max:
@@ -166,6 +172,14 @@ class FieldConstraints:
166
172
  if distribution and isinstance(distribution, str):
167
173
  distribution = Distribution(distribution)
168
174
 
175
+ exclusive_min = config.get(
176
+ "exclusive_min", config.get("exclusiveMinimum", False)
177
+ )
178
+ exclusive_max = config.get(
179
+ "exclusive_max", config.get("exclusiveMaximum", False)
180
+ )
181
+ multiple_of = config.get("multiple_of", config.get("multipleOf"))
182
+
169
183
  return cls(
170
184
  min=config.get("min"),
171
185
  max=config.get("max"),
@@ -179,6 +193,9 @@ class FieldConstraints:
179
193
  min_items=config.get("min_items"),
180
194
  max_items=config.get("max_items"),
181
195
  format=config.get("format"),
196
+ exclusive_min=bool(exclusive_min),
197
+ exclusive_max=bool(exclusive_max),
198
+ multiple_of=multiple_of,
182
199
  )
183
200
 
184
201
 
@@ -19,7 +19,16 @@ from fastapi.responses import JSONResponse
19
19
 
20
20
  from pycatalyst import __version__ as catalyst_version
21
21
  from pycatalyst.api.dependencies.auth import get_current_user
22
- from pycatalyst.api.routes.v1 import auth, generate, infer, recipes, settings, workbench
22
+ from pycatalyst.api.routes.v1 import (
23
+ auth,
24
+ generate,
25
+ infer,
26
+ ml,
27
+ recipes,
28
+ services,
29
+ settings,
30
+ workbench,
31
+ )
23
32
 
24
33
  API_VERSION = "v1"
25
34
  API_PREFIX = f"/api/{API_VERSION}"
@@ -142,6 +151,20 @@ def create_application() -> FastAPI:
142
151
  tags=["recipes"],
143
152
  dependencies=auth_dep,
144
153
  )
154
+ app.include_router(
155
+ ml.router,
156
+ prefix=API_PREFIX,
157
+ tags=["ml"],
158
+ dependencies=auth_dep,
159
+ )
160
+
161
+ # Service containers (database services) — protected
162
+ app.include_router(
163
+ services.router,
164
+ prefix=API_PREFIX,
165
+ tags=["services"],
166
+ dependencies=auth_dep,
167
+ )
145
168
 
146
169
  # Workbench public (capabilities — no auth)
147
170
  app.include_router(
@@ -0,0 +1,92 @@
1
+ """ML experiment endpoint — POST /api/v1/ml/run.
2
+
3
+ Runs a single experiment from YAML config. Core pycatalyst.ml remains stateless;
4
+ this route owns the HTTP contract and temporary file handling.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import tempfile
11
+ from pathlib import Path
12
+
13
+ from fastapi import APIRouter, HTTPException, status
14
+ from pydantic import BaseModel, Field
15
+
16
+ from pycatalyst.ml.run import run_experiment
17
+
18
+ router = APIRouter()
19
+
20
+
21
+ class MlRunRequest(BaseModel):
22
+ """Request body for running an ML experiment."""
23
+
24
+ config: str = Field(..., description="Experiment config as YAML string")
25
+
26
+
27
+ class MlRunResponse(BaseModel):
28
+ """Response from running an ML experiment. Mirrors ExperimentResult."""
29
+
30
+ name: str
31
+ backend: str
32
+ metrics: dict[str, float] = Field(default_factory=dict)
33
+ artifacts: dict[str, str] = Field(default_factory=dict)
34
+ training_history: list[dict] = Field(default_factory=list)
35
+ duration_seconds: float = 0.0
36
+
37
+
38
+ @router.post("/ml/run", response_model=MlRunResponse)
39
+ async def run_ml_experiment(request: MlRunRequest) -> MlRunResponse:
40
+ """Run an ML experiment from YAML config and return the result.
41
+
42
+ Writes config to a temporary file and calls stateless run_experiment() in a
43
+ thread pool so the event loop is not blocked. Long-running training may
44
+ hit timeouts; consider increasing gateway/worker timeouts for large jobs.
45
+ """
46
+ if not request.config.strip():
47
+ raise HTTPException(
48
+ status_code=status.HTTP_400_BAD_REQUEST,
49
+ detail="config must be a non-empty YAML string",
50
+ )
51
+
52
+ try:
53
+ with tempfile.NamedTemporaryFile(
54
+ mode="w",
55
+ suffix=".yaml",
56
+ delete=False,
57
+ encoding="utf-8",
58
+ ) as f:
59
+ f.write(request.config)
60
+ config_path = f.name
61
+
62
+ try:
63
+ result = await asyncio.to_thread(run_experiment, config_path)
64
+ finally:
65
+ Path(config_path).unlink(missing_ok=True)
66
+
67
+ return MlRunResponse(
68
+ name=result.name,
69
+ backend=result.backend,
70
+ metrics=dict(result.metrics),
71
+ artifacts=dict(result.artifacts),
72
+ training_history=list(result.training_history),
73
+ duration_seconds=result.duration_seconds,
74
+ )
75
+ except FileNotFoundError as exc:
76
+ raise HTTPException(
77
+ status_code=status.HTTP_400_BAD_REQUEST,
78
+ detail={"message": str(exc)},
79
+ ) from exc
80
+ except ValueError as exc:
81
+ raise HTTPException(
82
+ status_code=status.HTTP_400_BAD_REQUEST,
83
+ detail={"message": str(exc)},
84
+ ) from exc
85
+ except ImportError as exc:
86
+ raise HTTPException(
87
+ status_code=status.HTTP_400_BAD_REQUEST,
88
+ detail={
89
+ "message": str(exc),
90
+ "hint": "Install the required ML extra (e.g. pycatalyst[ml-core], pycatalyst[ml-sklearn], pycatalyst[ml-llm])",
91
+ },
92
+ ) from exc
@@ -0,0 +1,184 @@
1
+ """Service container endpoints — CRUD for dockerized database services.
2
+
3
+ Endpoints for creating, listing, inspecting, and destroying database
4
+ service containers (Postgres, MongoDB) tied to workbench environments.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from typing import Any
11
+
12
+ from fastapi import APIRouter, Depends, HTTPException, status
13
+ from pydantic import BaseModel, Field, field_validator
14
+
15
+ from pycatalyst.api.dependencies.auth import get_current_user
16
+ from pycatalyst.errors import ServiceError
17
+ from pycatalyst.services.service_containers import ServiceConfig, ServiceType
18
+ from pycatalyst.services.workbench_manager import workbench_manager
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+ router = APIRouter(prefix="/workbench")
23
+
24
+ ALLOWED_SERVICE_TYPES = frozenset(t.value for t in ServiceType)
25
+
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Helpers
29
+ # ---------------------------------------------------------------------------
30
+
31
+
32
+ def _owner_from_user(user: dict[str, Any]) -> str:
33
+ """Extract the owner identifier from the resolved user dict."""
34
+ return user.get("username", "anonymous")
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Request / Response models
39
+ # ---------------------------------------------------------------------------
40
+
41
+
42
+ class CreateServiceRequest(BaseModel):
43
+ """Request to create a database service container."""
44
+
45
+ service_type: str = Field(
46
+ description="Database type: postgres or mongodb",
47
+ )
48
+ database: str = Field(
49
+ default="pycatalyst_db",
50
+ description="Initial database name to create",
51
+ )
52
+ username: str = Field(
53
+ default="pycatalyst",
54
+ description="Database admin username",
55
+ )
56
+ password: str = Field(
57
+ default="pycatalyst_dev",
58
+ description="Database admin password",
59
+ )
60
+
61
+ @field_validator("service_type")
62
+ @classmethod
63
+ def _validate_service_type(cls, v: str) -> str:
64
+ val = v.strip().lower()
65
+ if val not in ALLOWED_SERVICE_TYPES:
66
+ allowed = ", ".join(sorted(ALLOWED_SERVICE_TYPES))
67
+ raise ValueError(f"Service type {v!r} is not supported. Allowed: {allowed}")
68
+ return val
69
+
70
+
71
+ class ServiceInfoResponse(BaseModel):
72
+ """Public representation of a database service."""
73
+
74
+ service_id: str
75
+ env_id: str
76
+ service_type: str
77
+ status: str
78
+ host_url: str
79
+ container_url: str
80
+ host_port: int
81
+ container_name: str
82
+ container_id: str
83
+ database: str
84
+ username: str
85
+ created_at: float
86
+ error_message: str
87
+
88
+
89
+ class ServiceListResponse(BaseModel):
90
+ """Wrapper for a list of services."""
91
+
92
+ services: list[ServiceInfoResponse]
93
+
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # Endpoints
97
+ # ---------------------------------------------------------------------------
98
+
99
+
100
+ @router.post(
101
+ "/environments/{env_id}/services",
102
+ response_model=ServiceInfoResponse,
103
+ status_code=status.HTTP_201_CREATED,
104
+ )
105
+ async def create_service(
106
+ env_id: str,
107
+ body: CreateServiceRequest,
108
+ user: dict[str, Any] = Depends(get_current_user),
109
+ ) -> dict[str, Any]:
110
+ """Create a database service container for an environment."""
111
+ owner = _owner_from_user(user)
112
+
113
+ config = ServiceConfig(
114
+ service_type=ServiceType(body.service_type),
115
+ database=body.database,
116
+ username=body.username,
117
+ password=body.password,
118
+ )
119
+
120
+ try:
121
+ svc = await workbench_manager.create_service(env_id, config, owner=owner)
122
+ except ValueError as exc:
123
+ raise HTTPException(status_code=404, detail=str(exc)) from exc
124
+ except RuntimeError as exc:
125
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
126
+ except ServiceError as exc:
127
+ raise HTTPException(status_code=400, detail=exc.message) from exc
128
+
129
+ return svc.to_dict()
130
+
131
+
132
+ @router.get(
133
+ "/environments/{env_id}/services",
134
+ response_model=ServiceListResponse,
135
+ )
136
+ async def list_services(
137
+ env_id: str,
138
+ user: dict[str, Any] = Depends(get_current_user),
139
+ ) -> dict[str, Any]:
140
+ """List database services for an environment."""
141
+ owner = _owner_from_user(user)
142
+
143
+ env_info = workbench_manager.get_environment(env_id, owner=owner)
144
+ if env_info is None:
145
+ raise HTTPException(status_code=404, detail=f"Unknown environment: {env_id}")
146
+
147
+ services = workbench_manager.list_services(env_id, owner=owner)
148
+ return {"services": services}
149
+
150
+
151
+ @router.get(
152
+ "/services/{service_id}",
153
+ response_model=ServiceInfoResponse,
154
+ )
155
+ async def get_service(
156
+ service_id: str,
157
+ user: dict[str, Any] = Depends(get_current_user),
158
+ ) -> dict[str, Any]:
159
+ """Get status of a database service."""
160
+ owner = _owner_from_user(user)
161
+
162
+ result = workbench_manager.get_service_status(service_id, owner=owner)
163
+ if result is None:
164
+ raise HTTPException(status_code=404, detail=f"Unknown service: {service_id}")
165
+ return result
166
+
167
+
168
+ @router.delete(
169
+ "/services/{service_id}",
170
+ status_code=status.HTTP_204_NO_CONTENT,
171
+ )
172
+ async def destroy_service(
173
+ service_id: str,
174
+ user: dict[str, Any] = Depends(get_current_user),
175
+ ) -> None:
176
+ """Destroy a database service container."""
177
+ owner = _owner_from_user(user)
178
+
179
+ try:
180
+ await workbench_manager.destroy_service(service_id, owner=owner)
181
+ except ValueError as exc:
182
+ raise HTTPException(status_code=404, detail=str(exc)) from exc
183
+ except RuntimeError as exc:
184
+ raise HTTPException(status_code=400, detail=str(exc)) from exc