weightslab 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 (208) hide show
  1. weightslab-1.0.0/.env.template +3 -0
  2. weightslab-1.0.0/.github/workflows/ci.yml +489 -0
  3. weightslab-1.0.0/.github/workflows/docs-pages.yml +123 -0
  4. weightslab-1.0.0/.github/workflows/release.yml +151 -0
  5. weightslab-1.0.0/.gitignore +46 -0
  6. weightslab-1.0.0/CHANGELOG.md +167 -0
  7. weightslab-1.0.0/LICENSE +201 -0
  8. weightslab-1.0.0/PKG-INFO +206 -0
  9. weightslab-1.0.0/README.md +152 -0
  10. weightslab-1.0.0/agent_config.yaml +15 -0
  11. weightslab-1.0.0/docs/_static/.gitkeep +0 -0
  12. weightslab-1.0.0/docs/_static/custom.css +135 -0
  13. weightslab-1.0.0/docs/_static/favicon.png +0 -0
  14. weightslab-1.0.0/docs/_static/logo-dark.png +0 -0
  15. weightslab-1.0.0/docs/_static/logo-light.png +0 -0
  16. weightslab-1.0.0/docs/_static/version-switcher.js +92 -0
  17. weightslab-1.0.0/docs/_static/weights_studio_architecture.png +0 -0
  18. weightslab-1.0.0/docs/_templates/.gitkeep +0 -0
  19. weightslab-1.0.0/docs/conf.py +98 -0
  20. weightslab-1.0.0/docs/data_exploration.rst +54 -0
  21. weightslab-1.0.0/docs/four_way_approach.rst +29 -0
  22. weightslab-1.0.0/docs/hyperparameters.rst +53 -0
  23. weightslab-1.0.0/docs/index.rst +94 -0
  24. weightslab-1.0.0/docs/logger.rst +64 -0
  25. weightslab-1.0.0/docs/model_interaction.rst +44 -0
  26. weightslab-1.0.0/docs/pytorch_lightning.rst +148 -0
  27. weightslab-1.0.0/docs/quickstart.rst +63 -0
  28. weightslab-1.0.0/docs/requirements.txt +7 -0
  29. weightslab-1.0.0/docs/usecases.rst +161 -0
  30. weightslab-1.0.0/docs/user_functions.rst +252 -0
  31. weightslab-1.0.0/docs/weights_studio.rst +481 -0
  32. weightslab-1.0.0/package-lock.json +6 -0
  33. weightslab-1.0.0/pyproject.toml +77 -0
  34. weightslab-1.0.0/setup.cfg +4 -0
  35. weightslab-1.0.0/weightslab/__init__.py +82 -0
  36. weightslab-1.0.0/weightslab/_version.py +34 -0
  37. weightslab-1.0.0/weightslab/art.py +58 -0
  38. weightslab-1.0.0/weightslab/backend/__init__.py +0 -0
  39. weightslab-1.0.0/weightslab/backend/cli.py +966 -0
  40. weightslab-1.0.0/weightslab/backend/dataloader_interface.py +1022 -0
  41. weightslab-1.0.0/weightslab/backend/ledgers.py +835 -0
  42. weightslab-1.0.0/weightslab/backend/model_interface.py +698 -0
  43. weightslab-1.0.0/weightslab/backend/optimizer_interface.py +176 -0
  44. weightslab-1.0.0/weightslab/baseline_models/__init__.py +0 -0
  45. weightslab-1.0.0/weightslab/baseline_models/pytorch/__init__.py +0 -0
  46. weightslab-1.0.0/weightslab/baseline_models/pytorch/models.py +1883 -0
  47. weightslab-1.0.0/weightslab/components/__init__.py +28 -0
  48. weightslab-1.0.0/weightslab/components/checkpoint_manager.py +2002 -0
  49. weightslab-1.0.0/weightslab/components/experiment_hash.py +338 -0
  50. weightslab-1.0.0/weightslab/components/global_monitoring.py +316 -0
  51. weightslab-1.0.0/weightslab/components/tracking.py +544 -0
  52. weightslab-1.0.0/weightslab/data/__init__.py +0 -0
  53. weightslab-1.0.0/weightslab/data/array_proxy.py +387 -0
  54. weightslab-1.0.0/weightslab/data/data_samples_with_ops.py +1051 -0
  55. weightslab-1.0.0/weightslab/data/data_utils.py +555 -0
  56. weightslab-1.0.0/weightslab/data/dataframe_manager.py +1036 -0
  57. weightslab-1.0.0/weightslab/data/h5_array_store.py +773 -0
  58. weightslab-1.0.0/weightslab/data/h5_dataframe_store.py +546 -0
  59. weightslab-1.0.0/weightslab/data/sample_stats.py +99 -0
  60. weightslab-1.0.0/weightslab/examples/PyTorch/ws-classification/config.yaml +40 -0
  61. weightslab-1.0.0/weightslab/examples/PyTorch/ws-classification/main.py +426 -0
  62. weightslab-1.0.0/weightslab/examples/PyTorch/ws-detection/coco.yaml +118 -0
  63. weightslab-1.0.0/weightslab/examples/PyTorch/ws-detection/config.yaml +38 -0
  64. weightslab-1.0.0/weightslab/examples/PyTorch/ws-detection/main.py +627 -0
  65. weightslab-1.0.0/weightslab/examples/PyTorch/ws-detection/requirements.txt +2 -0
  66. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0000f77c-6257be58.jpg +0 -0
  67. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/000f8d37-d4c09a0f.jpg +0 -0
  68. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00a0f008-a315437f.jpg +0 -0
  69. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c12bd0-bb46e479.jpg +0 -0
  70. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c29c52-f9524f1e.jpg +0 -0
  71. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00ce6f6d-50bbee62.jpg +0 -0
  72. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d1bafa-1b47b41c.jpg +0 -0
  73. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d7268f-fd4487be.jpg +0 -0
  74. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00f0dd0f-5e9c9557.jpg +0 -0
  75. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a0d7f4c-ac5c3c8f.jpg +0 -0
  76. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a1f4fce-f9cac880.jpg +0 -0
  77. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a3bb2d8-c195d91e.jpg +0 -0
  78. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1cac6a7-04e33135.jpg +0 -0
  79. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ceb32e-3f481b43.jpg +0 -0
  80. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d10d08-5b108225.jpg +0 -0
  81. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d22449-15fb948f.jpg +0 -0
  82. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d7b3ac-5af8623b.jpg +0 -0
  83. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1dce572-c6a8cb5e.jpg +0 -0
  84. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e1a7b8-0aec80e8.jpg +0 -0
  85. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e8ad72-c3c79240.jpg +0 -0
  86. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ee702d-0ae1fc10.jpg +0 -0
  87. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1f0efd9-37a14dda.jpg +0 -0
  88. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2a0648b-d8e126bc.jpg +0 -0
  89. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2b70230-bad4ff6e.jpg +0 -0
  90. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0000f77c-6257be58.png +0 -0
  91. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/000f8d37-d4c09a0f.png +0 -0
  92. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00a0f008-a315437f.png +0 -0
  93. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c12bd0-bb46e479.png +0 -0
  94. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c29c52-f9524f1e.png +0 -0
  95. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00ce6f6d-50bbee62.png +0 -0
  96. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d1bafa-1b47b41c.png +0 -0
  97. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d7268f-fd4487be.png +0 -0
  98. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00f0dd0f-5e9c9557.png +0 -0
  99. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a0d7f4c-ac5c3c8f.png +0 -0
  100. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a1f4fce-f9cac880.png +0 -0
  101. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a3bb2d8-c195d91e.png +0 -0
  102. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1cac6a7-04e33135.png +0 -0
  103. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ceb32e-3f481b43.png +0 -0
  104. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d10d08-5b108225.png +0 -0
  105. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d22449-15fb948f.png +0 -0
  106. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d7b3ac-5af8623b.png +0 -0
  107. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1dce572-c6a8cb5e.png +0 -0
  108. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e1a7b8-0aec80e8.png +0 -0
  109. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e8ad72-c3c79240.png +0 -0
  110. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ee702d-0ae1fc10.png +0 -0
  111. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1f0efd9-37a14dda.png +0 -0
  112. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2a0648b-d8e126bc.png +0 -0
  113. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2b70230-bad4ff6e.png +0 -0
  114. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/config.yaml +37 -0
  115. weightslab-1.0.0/weightslab/examples/PyTorch/ws-segmentation/main.py +545 -0
  116. weightslab-1.0.0/weightslab/examples/PyTorch_Lightning/ws-classification/config.yaml +59 -0
  117. weightslab-1.0.0/weightslab/examples/PyTorch_Lightning/ws-classification/main.py +409 -0
  118. weightslab-1.0.0/weightslab/models/__init__.py +0 -0
  119. weightslab-1.0.0/weightslab/models/model_with_ops.py +546 -0
  120. weightslab-1.0.0/weightslab/models/monkey_patcher.py +80 -0
  121. weightslab-1.0.0/weightslab/modules/__init__.py +0 -0
  122. weightslab-1.0.0/weightslab/modules/modules_with_ops.py +1703 -0
  123. weightslab-1.0.0/weightslab/modules/neuron_ops.py +77 -0
  124. weightslab-1.0.0/weightslab/proto/__init__.py +0 -0
  125. weightslab-1.0.0/weightslab/proto/experiment_service.proto +387 -0
  126. weightslab-1.0.0/weightslab/proto/experiment_service_pb2.py +144 -0
  127. weightslab-1.0.0/weightslab/proto/experiment_service_pb2_grpc.py +572 -0
  128. weightslab-1.0.0/weightslab/src.py +1453 -0
  129. weightslab-1.0.0/weightslab/tests/__init__.py +7 -0
  130. weightslab-1.0.0/weightslab/tests/backend/__init__.py +0 -0
  131. weightslab-1.0.0/weightslab/tests/backend/test_cli_additional_unit.py +59 -0
  132. weightslab-1.0.0/weightslab/tests/backend/test_data_loader_interface.py +306 -0
  133. weightslab-1.0.0/weightslab/tests/backend/test_ledgers.py +358 -0
  134. weightslab-1.0.0/weightslab/tests/backend/test_model_interface_unit.py +59 -0
  135. weightslab-1.0.0/weightslab/tests/backend/test_optimizer_interface.py +63 -0
  136. weightslab-1.0.0/weightslab/tests/backend/test_optimizer_interface_additional_unit.py +49 -0
  137. weightslab-1.0.0/weightslab/tests/components/__init__.py +0 -0
  138. weightslab-1.0.0/weightslab/tests/components/test_checkpoint_workflow.py +1399 -0
  139. weightslab-1.0.0/weightslab/tests/components/test_experiment_hash_and_art.py +112 -0
  140. weightslab-1.0.0/weightslab/tests/components/test_global_monitoring_unit.py +79 -0
  141. weightslab-1.0.0/weightslab/tests/data/__init__.py +0 -0
  142. weightslab-1.0.0/weightslab/tests/data/test_data_samples_with_ops.py +734 -0
  143. weightslab-1.0.0/weightslab/tests/data/test_data_service_metadata_copy.py +97 -0
  144. weightslab-1.0.0/weightslab/tests/data/test_data_utils_unit.py +117 -0
  145. weightslab-1.0.0/weightslab/tests/data/test_dataframe_manager_unit.py +77 -0
  146. weightslab-1.0.0/weightslab/tests/data/test_h5_array_store.py +98 -0
  147. weightslab-1.0.0/weightslab/tests/data/test_h5_dataframe_store.py +50 -0
  148. weightslab-1.0.0/weightslab/tests/gRPC/test_grpc_tag_operations.py +521 -0
  149. weightslab-1.0.0/weightslab/tests/gRPC/test_grpc_user_actions.py +416 -0
  150. weightslab-1.0.0/weightslab/tests/general/__init__.py +0 -0
  151. weightslab-1.0.0/weightslab/tests/general/test_auditor_mode.py +58 -0
  152. weightslab-1.0.0/weightslab/tests/general/test_cli.py +442 -0
  153. weightslab-1.0.0/weightslab/tests/general/test_hyperparams.py +51 -0
  154. weightslab-1.0.0/weightslab/tests/general/test_logger_snapshot_rotation.py +102 -0
  155. weightslab-1.0.0/weightslab/tests/general/test_signals.py +189 -0
  156. weightslab-1.0.0/weightslab/tests/integrations/__init__.py +0 -0
  157. weightslab-1.0.0/weightslab/tests/integrations/test_pytorch_lightning_integration.py +363 -0
  158. weightslab-1.0.0/weightslab/tests/model/__init__.py +0 -0
  159. weightslab-1.0.0/weightslab/tests/model/test_constraint_generation.py +238 -0
  160. weightslab-1.0.0/weightslab/tests/model/test_dependency_patterns.py +1082 -0
  161. weightslab-1.0.0/weightslab/tests/model/test_logger.py +368 -0
  162. weightslab-1.0.0/weightslab/tests/model/test_model_with_ops.py +308 -0
  163. weightslab-1.0.0/weightslab/tests/model/test_model_with_ops_unit.py +51 -0
  164. weightslab-1.0.0/weightslab/tests/model/test_tracking.py +308 -0
  165. weightslab-1.0.0/weightslab/tests/modules/__init__.py +0 -0
  166. weightslab-1.0.0/weightslab/tests/modules/test_modules_with_ops.py +554 -0
  167. weightslab-1.0.0/weightslab/tests/test_src_functions.py +176 -0
  168. weightslab-1.0.0/weightslab/tests/trainer/__init__.py +0 -0
  169. weightslab-1.0.0/weightslab/tests/trainer/services/__init__.py +0 -0
  170. weightslab-1.0.0/weightslab/tests/trainer/services/test_agent_prompt_unit.py +98 -0
  171. weightslab-1.0.0/weightslab/tests/trainer/services/test_trainer_services_server.py +73 -0
  172. weightslab-1.0.0/weightslab/tests/trainer/services/test_trainer_services_unit.py +340 -0
  173. weightslab-1.0.0/weightslab/tests/trainer/test_trainer_tools.py +197 -0
  174. weightslab-1.0.0/weightslab/tests/utils/__init__.py +0 -0
  175. weightslab-1.0.0/weightslab/tests/utils/test_computational_graph_utils_unit.py +68 -0
  176. weightslab-1.0.0/weightslab/tests/utils/test_logs_unit.py +79 -0
  177. weightslab-1.0.0/weightslab/tests/utils/test_modules_dependencies_unit.py +37 -0
  178. weightslab-1.0.0/weightslab/tests/utils/test_plot_graph_render_unit.py +46 -0
  179. weightslab-1.0.0/weightslab/tests/utils/test_plot_graph_unit.py +33 -0
  180. weightslab-1.0.0/weightslab/tests/utils/test_shape_prop_unit.py +49 -0
  181. weightslab-1.0.0/weightslab/tests/utils/test_utils_tools_unit.py +90 -0
  182. weightslab-1.0.0/weightslab/trainer/__init__.py +0 -0
  183. weightslab-1.0.0/weightslab/trainer/experiment_context.py +210 -0
  184. weightslab-1.0.0/weightslab/trainer/services/__init__.py +0 -0
  185. weightslab-1.0.0/weightslab/trainer/services/agent/__init__.py +0 -0
  186. weightslab-1.0.0/weightslab/trainer/services/agent/agent.py +779 -0
  187. weightslab-1.0.0/weightslab/trainer/services/agent/agent_overview/agent.png +0 -0
  188. weightslab-1.0.0/weightslab/trainer/services/agent/agent_overview/query_example.png +0 -0
  189. weightslab-1.0.0/weightslab/trainer/services/agent/agent_overview/schema.png +0 -0
  190. weightslab-1.0.0/weightslab/trainer/services/agent/intent_prompt.py +272 -0
  191. weightslab-1.0.0/weightslab/trainer/services/data_service.py +2365 -0
  192. weightslab-1.0.0/weightslab/trainer/services/experiment_service.py +479 -0
  193. weightslab-1.0.0/weightslab/trainer/services/model_service.py +375 -0
  194. weightslab-1.0.0/weightslab/trainer/trainer_services.py +156 -0
  195. weightslab-1.0.0/weightslab/trainer/trainer_tools.py +486 -0
  196. weightslab-1.0.0/weightslab/utils/__init__.py +3 -0
  197. weightslab-1.0.0/weightslab/utils/computational_graph.py +1726 -0
  198. weightslab-1.0.0/weightslab/utils/logger.py +329 -0
  199. weightslab-1.0.0/weightslab/utils/logs.py +209 -0
  200. weightslab-1.0.0/weightslab/utils/modules_dependencies.py +110 -0
  201. weightslab-1.0.0/weightslab/utils/plot_graph.py +182 -0
  202. weightslab-1.0.0/weightslab/utils/shape_prop.py +223 -0
  203. weightslab-1.0.0/weightslab/utils/tools.py +641 -0
  204. weightslab-1.0.0/weightslab.egg-info/PKG-INFO +206 -0
  205. weightslab-1.0.0/weightslab.egg-info/SOURCES.txt +206 -0
  206. weightslab-1.0.0/weightslab.egg-info/dependency_links.txt +1 -0
  207. weightslab-1.0.0/weightslab.egg-info/requires.txt +37 -0
  208. weightslab-1.0.0/weightslab.egg-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ OPENROUTER_API_KEY=
2
+ GOOGLE_API_KEY=
3
+ OPENAI_API_KEY=
@@ -0,0 +1,489 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, dev ]
6
+ tags: [ 'v*' ]
7
+ pull_request:
8
+ branches: [ main ]
9
+ types: [ opened, reopened, ready_for_review ]
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ code-quality:
14
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout repository
18
+ uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0 # Fetch all history for comparison
21
+
22
+ - name: Set up Python
23
+ id: setup-python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: '3.11'
27
+ cache: 'pip'
28
+
29
+ - name: Cache pip and Ruff
30
+ uses: actions/cache@v4
31
+ with:
32
+ path: |
33
+ ~/.cache/pip
34
+ ~/.cache/ruff
35
+ key: ${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-lint-cache
36
+ restore-keys: |
37
+ ${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-
38
+ ${{ runner.os }}-
39
+
40
+ - name: Get changed Python files
41
+ id: changed-files
42
+ run: |
43
+ if [ "${{ github.event_name }}" == "pull_request" ]; then
44
+ BASE_SHA=${{ github.event.pull_request.base.sha }}
45
+ HEAD_SHA=${{ github.event.pull_request.head.sha }}
46
+ else
47
+ BASE_SHA=${{ github.event.before }}
48
+ HEAD_SHA=${{ github.sha }}
49
+ fi
50
+
51
+ # Get changed Python files in weightslab directory, exclude generated files
52
+ CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA $HEAD_SHA | \
53
+ grep '^weightslab/.*\.py$' | \
54
+ grep -v '_pb2\.py$' | \
55
+ grep -v '_pb2_grpc\.py$' | \
56
+ grep -v 'ui\.py$' | \
57
+ grep -v 'trainer.*\.py$' || true)
58
+
59
+ echo "changed_files<<EOF" >> $GITHUB_OUTPUT
60
+ echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
61
+ echo "EOF" >> $GITHUB_OUTPUT
62
+
63
+ if [ -z "$CHANGED_FILES" ]; then
64
+ echo "has_files=false" >> $GITHUB_OUTPUT
65
+ echo "No Python files changed in weightslab directory"
66
+ else
67
+ echo "has_files=true" >> $GITHUB_OUTPUT
68
+ echo "Changed files:"
69
+ echo "$CHANGED_FILES"
70
+ fi
71
+
72
+ - name: Install linting tools
73
+ if: steps.changed-files.outputs.has_files == 'true'
74
+ run: |
75
+ python -m pip install --upgrade pip
76
+ python -m pip install ruff pylint vulture
77
+
78
+ - name: Lint with Ruff (unused, style, bugs)
79
+ if: steps.changed-files.outputs.has_files == 'true'
80
+ run: |
81
+ FILES="${{ steps.changed-files.outputs.changed_files }}"
82
+ if [ -n "$FILES" ]; then
83
+ echo "$FILES" | xargs ruff check --select F401,F841,E9,F632,F722,F823 --ignore E501 --fix
84
+ fi
85
+
86
+ - name: Pylint (errors only)
87
+ if: steps.changed-files.outputs.has_files == 'true'
88
+ run: |
89
+ FILES="${{ steps.changed-files.outputs.changed_files }}"
90
+ if [ -n "$FILES" ]; then
91
+ echo "$FILES" | xargs pylint --disable=R0913,E0401,C0301,W0511,C0114,C0115,C0116 --fail-under=7.0
92
+ fi
93
+
94
+ - name: Vulture (unused code)
95
+ if: steps.changed-files.outputs.has_files == 'true'
96
+ run: |
97
+ FILES="${{ steps.changed-files.outputs.changed_files }}"
98
+ if [ -n "$FILES" ]; then
99
+ echo "$FILES" | xargs vulture --min-confidence 70 . || true
100
+ fi
101
+
102
+ install:
103
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
104
+ runs-on: ubuntu-latest
105
+ needs: code-quality
106
+ steps:
107
+ - name: Checkout repository
108
+ uses: actions/checkout@v4
109
+
110
+ - name: Set up Python
111
+ uses: actions/setup-python@v5
112
+ with:
113
+ python-version: '3.11'
114
+
115
+ - name: Cache pip
116
+ uses: actions/cache@v4
117
+ with:
118
+ path: ~/.cache/pip
119
+ key: ${{ runner.os }}-pip
120
+ restore-keys: |
121
+ ${{ runner.os }}-pip
122
+
123
+ - name: Install project dependencies
124
+ run: |
125
+ python -m pip install --upgrade pip
126
+ python -m pip install -e .
127
+
128
+ - name: Verify installation
129
+ run: |
130
+ python -c "import weightslab; print(f'weightslab imported successfully')"
131
+
132
+ test:
133
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
134
+ runs-on: ubuntu-latest
135
+ needs: install
136
+ steps:
137
+ - name: Checkout repository
138
+ uses: actions/checkout@v4
139
+
140
+ - name: Set up Python
141
+ uses: actions/setup-python@v5
142
+ with:
143
+ python-version: '3.11'
144
+
145
+ - name: Cache pip
146
+ uses: actions/cache@v4
147
+ with:
148
+ path: ~/.cache/pip
149
+ key: ${{ runner.os }}-pip
150
+ restore-keys: |
151
+ ${{ runner.os }}-pip
152
+
153
+ # - name: Install project dependencies
154
+ # run: |
155
+ # python -m pip install --upgrade pip
156
+ # python -m pip install .
157
+
158
+ # - name: Run unit tests - General
159
+ # run: |
160
+ # export WEIGHTSLAB_LOG_LEVEL="DEBUG"
161
+ # python -m unittest discover -s ./weightslab/tests -p "test_.py" -t . -v
162
+
163
+ # - name: Run unit tests - Model
164
+ # run: |
165
+ # export WEIGHTSLAB_LOG_LEVEL="DEBUG"
166
+ # python -m unittest discover -s ./weightslab/tests/model -v
167
+
168
+ # - name: Run unit tests - Data
169
+ # run: |
170
+ # export WEIGHTSLAB_LOG_LEVEL="DEBUG"
171
+ # python -m unittest discover -s ./weightslab/tests/data -v
172
+
173
+ # - name: Run unit tests - Integrations
174
+ # run: |
175
+ # export WEIGHTSLAB_LOG_LEVEL="DEBUG"
176
+ # python -m unittest discover -s ./weightslab/tests/integrations -v
177
+
178
+ - name: Trigger WeightsStudio CI
179
+ env:
180
+ WS_TOKEN: ${{ secrets.WEIGHTS_STUDIO_API_TOKEN }}
181
+ run: |
182
+ if [ -z "${WS_TOKEN}" ]; then
183
+ echo "WEIGHTS_STUDIO_API_TOKEN not set; skipping WeightsStudio trigger."
184
+ exit 0
185
+ fi
186
+
187
+ # Trigger the ws-ci workflow in the weights_studio repository on main.
188
+ curl -fSs -X POST "https://api.github.com/repos/GrayboxTech/weights_studio/actions/workflows/ws-ci.yml/dispatches" \
189
+ -H "Authorization: Bearer ${WS_TOKEN}" \
190
+ -H "Accept: application/vnd.github+json" \
191
+ -H "Content-Type: application/json" \
192
+ -d '{"ref":"main"}'
193
+
194
+ echo "WeightsStudio workflow dispatch requested successfully."
195
+
196
+ build-and-publish-dev:
197
+ name: Build & Publish Dev (TestPyPI)
198
+ needs: test
199
+ runs-on: ubuntu-latest
200
+ permissions:
201
+ contents: read
202
+ outputs:
203
+ published_version: ${{ steps.version.outputs.published_version }}
204
+ steps:
205
+ - name: Checkout repository
206
+ uses: actions/checkout@v4
207
+ with:
208
+ fetch-depth: 0
209
+
210
+ - name: Set up Python
211
+ uses: actions/setup-python@v5
212
+ with:
213
+ python-version: '3.11'
214
+
215
+ - name: Install build tools
216
+ run: python -m pip install --upgrade pip build twine
217
+
218
+ - name: Compute publish version
219
+ id: version
220
+ run: |
221
+ TS="$(date -u +%Y%m%d%H%M%S)"
222
+ SHA_HEX="$(git rev-parse --short=8 HEAD)"
223
+ # TestPyPI/PyPI reject local versions (+sha), so encode sha as decimal in devN.
224
+ SHA_DEC="$((16#${SHA_HEX}))"
225
+ PRETEND="${TS}.dev${SHA_DEC}"
226
+ echo "published_version=${PRETEND}" >> $GITHUB_OUTPUT
227
+ echo "Publishing version: ${PRETEND} (from sha ${SHA_HEX})"
228
+
229
+ - name: Build distributions
230
+ env:
231
+ # Package-specific override is the most reliable way with setuptools_scm.
232
+ SETUPTOOLS_SCM_PRETEND_VERSION_FOR_WEIGHTSLAB: ${{ steps.version.outputs.published_version }}
233
+ run: |
234
+ echo "Building with version ${SETUPTOOLS_SCM_PRETEND_VERSION_FOR_WEIGHTSLAB}"
235
+ python -m build
236
+
237
+ - name: Verify built artifact version
238
+ env:
239
+ WL_VERSION: ${{ steps.version.outputs.published_version }}
240
+ run: |
241
+ ls -la dist
242
+ if ls dist | grep -q "0.0.0"; then
243
+ echo "Build still produced 0.0.0 artifacts"
244
+ exit 1
245
+ fi
246
+ if ! ls dist | grep -q "${WL_VERSION}"; then
247
+ echo "Expected version ${WL_VERSION} not found in dist artifacts"
248
+ exit 1
249
+ fi
250
+
251
+ - name: Check distributions
252
+ run: python -m twine check dist/*
253
+
254
+ - name: Publish to TestPyPI
255
+ env:
256
+ TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
257
+ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
258
+ run: |
259
+ if [ -z "${{ secrets.TEST_PYPI_API_TOKEN }}" ]; then
260
+ echo "TEST_PYPI_API_TOKEN not set; skipping TestPyPI upload."
261
+ exit 0
262
+ fi
263
+ python -m twine upload --repository-url https://test.pypi.org/legacy/ --verbose dist/*
264
+
265
+ test-install-from-pip-dev:
266
+ name: Test Install From Pip Dev
267
+ needs: build-and-publish-dev
268
+ runs-on: ubuntu-latest
269
+ permissions:
270
+ contents: read
271
+ steps:
272
+ - name: Set up Python
273
+ uses: actions/setup-python@v5
274
+ with:
275
+ python-version: '3.11'
276
+
277
+ - name: Create isolated virtual environment
278
+ run: |
279
+ python -m venv .venv-ci
280
+
281
+ - name: Install from TestPyPI (with retry)
282
+ env:
283
+ WL_VERSION: ${{ needs.build-and-publish-dev.outputs.published_version }}
284
+ run: |
285
+ . .venv-ci/bin/activate
286
+ python -m pip install --upgrade pip
287
+ python -m pip install .
288
+
289
+ - name: Build distributions
290
+ run: python -m build
291
+
292
+ - name: Capture built version
293
+ id: main-version
294
+ run: |
295
+ WHEEL_PATH="$(ls dist/weightslab-*.whl | head -n 1)"
296
+ if [ -z "${WHEEL_PATH}" ]; then
297
+ echo "No wheel found in dist/"
298
+ exit 1
299
+ fi
300
+ WHEEL_FILE="$(basename "${WHEEL_PATH}")"
301
+ WL_VERSION="$(echo "${WHEEL_FILE}" | sed -E 's/^weightslab-([^-]+)-.*/\1/')"
302
+ if [ -z "${WL_VERSION}" ]; then
303
+ echo "Could not parse version from ${WHEEL_FILE}"
304
+ exit 1
305
+ fi
306
+ echo "published_version=${WL_VERSION}" >> $GITHUB_OUTPUT
307
+ echo "Main published version: ${WL_VERSION}"
308
+
309
+ - name: Check distributions
310
+ run: python -m twine check dist/*
311
+
312
+ - name: Publish to PyPI
313
+ env:
314
+ TWINE_USERNAME: __token__
315
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
316
+ run: |
317
+ if [ -z "${{ secrets.PYPI_API_TOKEN }}" ]; then
318
+ echo "PYPI_API_TOKEN not set; skipping PyPI upload."
319
+ exit 0
320
+ fi
321
+ python -m twine upload dist/* --non-interactive
322
+
323
+ test-install-from-pip-main:
324
+ name: Test Install From Pip Main
325
+ needs: build-and-publish-main
326
+ runs-on: ubuntu-latest
327
+ permissions:
328
+ contents: read
329
+ if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
330
+ steps:
331
+ - name: Set up Python
332
+ uses: actions/setup-python@v5
333
+ with:
334
+ python-version: '3.11'
335
+
336
+ - name: Create isolated virtual environment
337
+ run: |
338
+ python -m venv .venv-ci
339
+
340
+ - name: Install from TestPyPI (with retry)
341
+ env:
342
+ WL_VERSION: ${{ needs.build-and-publish-main.outputs.published_version }}
343
+ run: |
344
+ . .venv-ci/bin/activate
345
+ python -m pip install --upgrade pip
346
+ if [ -z "${WL_VERSION}" ]; then
347
+ echo "Missing published version from upstream job"
348
+ exit 1
349
+ fi
350
+ sleep 60 && python -m pip install --index-url https://pypi.org/simple --extra-index-url https://download.pytorch.org/whl/cpu "weightslab==${WL_VERSION}" --no-cache-dir
351
+ echo "weightslab==${WL_VERSION} installed from PyPI"
352
+
353
+ - name: Verify package import
354
+ run: |
355
+ export WEIGHTSLAB_LOG_LEVEL="DEBUG"
356
+ python -m unittest discover -s ./weightslab/tests/integrations -v
357
+
358
+ weightsstudio-ci:
359
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
360
+ name: WeightsStudio CI
361
+ needs: test
362
+ uses: GrayboxTech/weights_studio/.github/workflows/ws-ci.yml@dev
363
+ with:
364
+ weightslab_branch: ${{ (github.head_ref || github.ref_name) == 'main' && 'main' || 'dev' }}
365
+
366
+ build-and-publish-dev:
367
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
368
+ name: Build & Publish Dev (TestPyPI)
369
+ needs: weightsstudio-ci
370
+ runs-on: ubuntu-latest
371
+ permissions:
372
+ contents: read
373
+ outputs:
374
+ published_version: ${{ steps.version.outputs.published_version }}
375
+ steps:
376
+ - name: Checkout repository
377
+ uses: actions/checkout@v4
378
+ with:
379
+ fetch-depth: 0
380
+
381
+ - name: Set up Python
382
+ uses: actions/setup-python@v5
383
+ with:
384
+ python-version: '3.11'
385
+
386
+ - name: Install build tools
387
+ run: python -m pip install --upgrade pip build twine
388
+
389
+ - name: Compute publish version
390
+ id: version
391
+ run: |
392
+ TS="$(date -u +%Y%m%d%H%M%S)"
393
+ SHA_HEX="$(git rev-parse --short=8 HEAD)"
394
+ # TestPyPI/PyPI reject local versions (+sha), so encode sha as decimal in devN.
395
+ SHA_DEC="$((16#${SHA_HEX}))"
396
+ PRETEND="${TS}.dev${SHA_DEC}"
397
+ echo "published_version=${PRETEND}" >> $GITHUB_OUTPUT
398
+ echo "Publishing version: ${PRETEND} (from sha ${SHA_HEX})"
399
+
400
+ - name: Build distributions
401
+ env:
402
+ # Package-specific override is the most reliable way with setuptools_scm.
403
+ SETUPTOOLS_SCM_PRETEND_VERSION_FOR_WEIGHTSLAB: ${{ steps.version.outputs.published_version }}
404
+ run: |
405
+ echo "Building with version ${SETUPTOOLS_SCM_PRETEND_VERSION_FOR_WEIGHTSLAB}"
406
+ python -m build
407
+
408
+ - name: Verify built artifact version
409
+ env:
410
+ WL_VERSION: ${{ steps.version.outputs.published_version }}
411
+ run: |
412
+ ls -la dist
413
+ if ls dist | grep -q "0.0.0"; then
414
+ echo "Build still produced 0.0.0 artifacts"
415
+ exit 1
416
+ fi
417
+ if ! ls dist | grep -q "${WL_VERSION}"; then
418
+ echo "Expected version ${WL_VERSION} not found in dist artifacts"
419
+ exit 1
420
+ fi
421
+
422
+ - name: Check distributions
423
+ run: python -m twine check dist/*
424
+
425
+ - name: Publish to TestPyPI
426
+ env:
427
+ TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
428
+ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
429
+ run: |
430
+ if [ -z "${{ secrets.TEST_PYPI_API_TOKEN }}" ]; then
431
+ echo "TEST_PYPI_API_TOKEN not set; skipping TestPyPI upload."
432
+ exit 0
433
+ fi
434
+ python -m twine upload --repository-url https://test.pypi.org/legacy/ --verbose dist/*
435
+
436
+ test-install-from-pip-dev:
437
+ if: ${{ github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/') }}
438
+ name: Test Install From Pip Dev
439
+ needs: build-and-publish-dev
440
+ runs-on: ubuntu-latest
441
+ permissions:
442
+ contents: read
443
+ steps:
444
+ - name: Set up Python
445
+ uses: actions/setup-python@v5
446
+ with:
447
+ python-version: '3.11'
448
+
449
+ - name: Create isolated virtual environment
450
+ run: |
451
+ python -m venv .venv-ci
452
+
453
+ - name: Install from TestPyPI (wait until indexed)
454
+ env:
455
+ WL_VERSION: ${{ needs.build-and-publish-dev.outputs.published_version }}
456
+ run: |
457
+ . .venv-ci/bin/activate
458
+ python -m pip install --upgrade pip
459
+ if [ -z "${WL_VERSION}" ]; then
460
+ echo "Missing published version from upstream job"
461
+ exit 1
462
+ fi
463
+
464
+ # TestPyPI can take a few minutes to expose newly uploaded versions.
465
+ for attempt in $(seq 1 60); do
466
+ echo "Checking pip visibility for weightslab==${WL_VERSION} (attempt ${attempt}/60)"
467
+ if python -m pip download \
468
+ --index-url https://test.pypi.org/simple/ \
469
+ --no-deps \
470
+ "weightslab==${WL_VERSION}" \
471
+ -d /tmp/wl-probe >/dev/null 2>&1; then
472
+ echo "Found weightslab==${WL_VERSION} in TestPyPI simple index"
473
+ break
474
+ fi
475
+
476
+ if [ "${attempt}" -eq 60 ]; then
477
+ echo "Timed out waiting for weightslab==${WL_VERSION} on TestPyPI simple index"
478
+ exit 1
479
+ fi
480
+ sleep 7
481
+ done
482
+
483
+ python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://download.pytorch.org/whl/cpu --extra-index-url https://pypi.org/simple "weightslab==${WL_VERSION}" --no-cache-dir --retries 10 --timeout 60
484
+ echo "weightslab==${WL_VERSION} installed from TestPyPI"
485
+
486
+ - name: Verify package import
487
+ run: |
488
+ . .venv-ci/bin/activate
489
+ python -c "import weightslab; import importlib.metadata as m; print('weightslab import OK'); print('installed version:', m.version('weightslab'))"
@@ -0,0 +1,123 @@
1
+ name: Docs (GitHub Pages)
2
+
3
+ on:
4
+ push:
5
+ branches: [docstring, dev, main]
6
+ tags:
7
+ - 'v*'
8
+ pull_request:
9
+ branches: [main]
10
+ types: [opened, reopened, ready_for_review]
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+
18
+ concurrency:
19
+ group: docs-pages-${{ github.ref }}
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+ build:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - name: Checkout
27
+ uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 0
30
+
31
+ - name: Setup Python
32
+ uses: actions/setup-python@v5
33
+ with:
34
+ python-version: '3.11'
35
+
36
+ - name: Install docs dependencies
37
+ run: |
38
+ python -m pip install --upgrade pip
39
+ python -m pip install -r docs/requirements.txt
40
+ python -m pip install numpy pandas tqdm PyYAML
41
+
42
+ - name: Build Sphinx multiversion docs
43
+ run: sphinx-multiversion docs docs/_build/html
44
+
45
+ - name: Prepare latest alias and versions manifest
46
+ shell: bash
47
+ run: |
48
+ python - <<'PY'
49
+ import json
50
+ import re
51
+ import shutil
52
+ from pathlib import Path
53
+
54
+ root = Path("docs/_build/html")
55
+ main_dir = root / "main"
56
+ latest_dir = root / "latest"
57
+
58
+ if main_dir.exists():
59
+ shutil.copytree(main_dir, latest_dir, dirs_exist_ok=True)
60
+
61
+ versions = []
62
+ semver = re.compile(r"^v(\d+)\.(\d+)\.(\d+)$")
63
+
64
+ for d in root.iterdir():
65
+ if not d.is_dir() or not (d / "index.html").exists():
66
+ continue
67
+ name = d.name
68
+ if name not in {"latest", "dev"} and not semver.match(name):
69
+ continue
70
+
71
+ if name == "latest":
72
+ rank = (0, 0, 0, 0)
73
+ label = "latest"
74
+ elif name == "dev":
75
+ rank = (1, 0, 0, 0)
76
+ label = "dev"
77
+ else:
78
+ m = semver.match(name)
79
+ rank = (2, -int(m.group(1)), -int(m.group(2)), -int(m.group(3)))
80
+ label = name
81
+
82
+ versions.append({"name": name, "label": label, "rank": rank})
83
+
84
+ versions.sort(key=lambda v: v["rank"])
85
+ payload = [{"name": v["name"], "label": v["label"]} for v in versions]
86
+
87
+ (root / "versions.json").write_text(json.dumps(payload, indent=2), encoding="utf-8")
88
+ for v in payload:
89
+ (root / v["name"] / "versions.json").write_text(json.dumps(payload, indent=2), encoding="utf-8")
90
+
91
+ if payload:
92
+ default_name = payload[0]["name"]
93
+ redirect = f"""<!doctype html>
94
+ <html><head>
95
+ <meta charset=\"utf-8\" />
96
+ <meta http-equiv=\"refresh\" content=\"0; url=./{default_name}/index.html\" />
97
+ <title>WeightsLab Docs</title>
98
+ </head><body>
99
+ Redirecting to <a href=\"./{default_name}/index.html\">{default_name}</a>.
100
+ </body></html>
101
+ """
102
+ (root / "index.html").write_text(redirect, encoding="utf-8")
103
+ PY
104
+
105
+ - name: Setup Pages
106
+ uses: actions/configure-pages@v5
107
+
108
+ - name: Upload Pages artifact
109
+ uses: actions/upload-pages-artifact@v3
110
+ with:
111
+ path: docs/_build/html
112
+
113
+ deploy:
114
+ if: ${{ github.event_name != 'pull_request' }}
115
+ environment:
116
+ name: github-pages
117
+ url: ${{ steps.deployment.outputs.page_url }}
118
+ runs-on: ubuntu-latest
119
+ needs: build
120
+ steps:
121
+ - name: Deploy to GitHub Pages
122
+ id: deployment
123
+ uses: actions/deploy-pages@v4