weightslab 1.3.0__tar.gz → 1.3.2__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.
- {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/ci.yml +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/release.yml +249 -53
- weightslab-1.3.2/CHANGELOG.md +1 -0
- {weightslab-1.3.0/weightslab.egg-info → weightslab-1.3.2}/PKG-INFO +15 -18
- {weightslab-1.3.0 → weightslab-1.3.2}/README.md +13 -16
- {weightslab-1.3.0 → weightslab-1.3.2}/agent_config.yaml +7 -1
- weightslab-1.3.2/docs/_static/custom.css +584 -0
- weightslab-1.3.2/docs/_static/examples-gallery.js +208 -0
- weightslab-1.3.2/docs/_static/github-stars.js +17 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/version-switcher.js +10 -11
- weightslab-1.3.2/docs/_static/wl-ribbon.js +49 -0
- weightslab-1.3.2/docs/_static/wl-topnav.js +89 -0
- weightslab-1.3.2/docs/_templates/sidebar/brand.html +21 -0
- weightslab-1.3.2/docs/agent.rst +650 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/conf.py +15 -5
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/configuration.rst +398 -70
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/data_exploration.rst +6 -0
- weightslab-1.3.2/docs/examples/index.rst +21 -0
- weightslab-1.3.2/docs/examples/lightning/classification.rst +119 -0
- weightslab-1.3.2/docs/examples/lightning/index.rst +19 -0
- weightslab-1.3.2/docs/examples/pytorch/classification.rst +161 -0
- weightslab-1.3.2/docs/examples/pytorch/clustering.rst +97 -0
- weightslab-1.3.2/docs/examples/pytorch/detection.rst +129 -0
- weightslab-1.3.2/docs/examples/pytorch/generation.rst +103 -0
- weightslab-1.3.2/docs/examples/pytorch/index.rst +23 -0
- weightslab-1.3.2/docs/examples/pytorch/segmentation.rst +116 -0
- weightslab-1.3.2/docs/examples/ultralytics/detection.rst +47 -0
- weightslab-1.3.2/docs/examples/ultralytics/index.rst +19 -0
- weightslab-1.3.2/docs/examples/usecases/index.rst +20 -0
- weightslab-1.3.2/docs/examples/usecases/lidar_detection.rst +126 -0
- weightslab-1.3.2/docs/examples/usecases/loss_shape_classification.rst +210 -0
- weightslab-1.3.2/docs/four_way_approach.rst +58 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/audit_logger.rst +4 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/grpc_functions.rst +0 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/index.rst +71 -16
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/logger.rst +31 -0
- weightslab-1.3.2/docs/quickstart.rst +193 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/segmentation_usecase.rst +1 -1
- weightslab-1.3.2/docs/ultralytics.rst +224 -0
- weightslab-1.3.2/docs/usage/docker.rst +350 -0
- weightslab-1.3.2/docs/usage/good_practice.rst +211 -0
- weightslab-1.3.2/docs/usage/parameters.rst +528 -0
- weightslab-1.3.2/docs/usage.rst +18 -0
- weightslab-1.3.2/docs/user_commands.rst +440 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/user_functions.rst +437 -15
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/weights_studio.rst +19 -41
- {weightslab-1.3.0 → weightslab-1.3.2}/pyproject.toml +23 -3
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/__init__.py +1 -1
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_logger_core.py +82 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_checkpoint_workflow.py +5 -1
- weightslab-1.3.2/tests/gRPC/test_grpc_histogram_categorical.py +265 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_cli.py +95 -1
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_model_with_ops.py +1 -1
- weightslab-1.3.2/tests/trainer/services/test_agent_live_prompt_evaluation.py +1120 -0
- weightslab-1.3.2/tests/trainer/services/test_agent_model_and_safety_unit.py +1677 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_agent_prompt_unit.py +29 -1
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_agent_service_unit.py +2 -2
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/__init__.py +61 -8
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/_version.py +3 -3
- weightslab-1.3.2/weightslab/art.py +164 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/cli.py +127 -3
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/ledgers.py +14 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/logger.py +68 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/model_interface.py +18 -9
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/optimizer_interface.py +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/checkpoint_manager.py +4 -4
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/dataframe_manager.py +7 -3
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/h5_dataframe_store.py +10 -2
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/docker-compose.yml +1 -1
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx-entrypoint.sh +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/test-deployment.sh +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/build-and-deploy.sh +8 -6
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/generate-certs-auth-token.ps1 +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/generate-certs-auth-token.sh +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/test-deployment.sh +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Lightning/ws-classification/main.py +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-classification/config.yaml +0 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-classification/main.py +3 -5
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/main.py +8 -2
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/README.md +102 -0
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/config.yaml +50 -0
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/main.py +340 -0
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/criterions.py +361 -0
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/data.py +226 -0
- weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/model.py +134 -0
- weightslab-1.3.2/weightslab/examples/__init__.py +6 -0
- weightslab-1.3.2/weightslab/examples/utils/__init__.py +1 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/modules/modules_with_ops.py +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service.proto +12 -2
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service_pb2.py +66 -64
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/security/cert_auth_manager.py +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/src.py +57 -29
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/experiment_context.py +6 -2
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent.py +827 -30
- weightslab-1.3.2/weightslab/trainer/services/agent/intent_prompt.py +843 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/data_service.py +817 -66
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/experiment_service.py +3 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/model_service.py +12 -2
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/trainer_tools.py +2 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/ui_docker_bridge.py +112 -16
- {weightslab-1.3.0 → weightslab-1.3.2/weightslab.egg-info}/PKG-INFO +15 -18
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/SOURCES.txt +124 -97
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/scm_file_list.json +124 -97
- weightslab-1.3.2/weightslab.egg-info/scm_version.json +8 -0
- weightslab-1.3.0/CHANGELOG.md +0 -1
- weightslab-1.3.0/docs/_static/custom.css +0 -143
- weightslab-1.3.0/docs/four_way_approach.rst +0 -29
- weightslab-1.3.0/docs/quickstart.rst +0 -191
- weightslab-1.3.0/weightslab/art.py +0 -58
- weightslab-1.3.0/weightslab/examples/Ultralytics/ws-detection/requirements.txt +0 -1
- weightslab-1.3.0/weightslab/tests/data/test_data_samples_with_ops.py +0 -783
- weightslab-1.3.0/weightslab/tests/data/test_data_service_metadata_copy.py +0 -97
- weightslab-1.3.0/weightslab/tests/data/test_data_utils_unit.py +0 -117
- weightslab-1.3.0/weightslab/tests/data/test_dataframe_manager_unit.py +0 -428
- weightslab-1.3.0/weightslab/tests/data/test_flush_pipeline.py +0 -276
- weightslab-1.3.0/weightslab/tests/data/test_h5_array_store.py +0 -216
- weightslab-1.3.0/weightslab/tests/data/test_h5_dataframe_store.py +0 -219
- weightslab-1.3.0/weightslab/tests/data/test_point_cloud_utils.py +0 -330
- weightslab-1.3.0/weightslab/trainer/services/agent/intent_prompt.py +0 -426
- weightslab-1.3.0/weightslab/trainer/services/utils/__init__.py +0 -0
- weightslab-1.3.0/weightslab.egg-info/scm_version.json +0 -8
- {weightslab-1.3.0 → weightslab-1.3.2}/.gitattributes +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/docs-pages.yml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/.gitignore +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/AGENTS.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/LICENSE +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/.gitkeep +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/favicon.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/logo-dark.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/logo-light.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/weights_studio_architecture.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/_templates/.gitkeep +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/index.rst +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/hyperparameters.rst +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/model_interaction.rst +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/pytorch_lightning.rst +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/requirements.txt +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/docs/usecases.rst +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/setup.cfg +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2/tests}/backend/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_audit_logger.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_cli_additional_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_compare_dataloaders.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_data_loader_interface.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_instance_signal_logger.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_ledgers.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_model_interface_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_optimizer_interface.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_optimizer_interface_additional_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_ui_docker_bridge.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_write_dataframe.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_write_history.py +0 -0
- {weightslab-1.3.0/weightslab/baseline_models → weightslab-1.3.2/tests/chaos_monkeys_utests}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/chaos_monkeys_utests/test_grpc_chaos_monkey_robustness.py +0 -0
- {weightslab-1.3.0/weightslab/baseline_models/pytorch → weightslab-1.3.2/tests/components}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_experiment_hash_and_art.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_global_monitoring_unit.py +0 -0
- {weightslab-1.3.0/weightslab/data → weightslab-1.3.2/tests/gRPC}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_get_point_cloud.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_grpc_tag_operations.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_grpc_user_actions.py +0 -0
- {weightslab-1.3.0/weightslab/examples/PyTorch/ws-clustering/face → weightslab-1.3.2/tests/general}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_auditor_mode.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_hyperparams.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_logger_snapshot_rotation.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_signals.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_signals_wrapping.py +0 -0
- {weightslab-1.3.0/weightslab/models → weightslab-1.3.2/tests/integrations}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/test_pytorch_lightning_integration.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/ultralytics/ddp/ddp_ablation.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/ultralytics/ddp/ddp_test_suite.py +0 -0
- {weightslab-1.3.0/weightslab/modules → weightslab-1.3.2/tests/model}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_constraint_generation.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_dependency_patterns.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_logger.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_model_with_ops_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_tracking.py +0 -0
- {weightslab-1.3.0/weightslab/proto → weightslab-1.3.2/tests/modules}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/modules/test_modules_with_ops.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/test_secure_docker.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/test_src_functions.py +0 -0
- {weightslab-1.3.0/weightslab/tests/backend → weightslab-1.3.2/tests/trainer}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab/tests/chaos_monkeys_utests → weightslab-1.3.2/tests/trainer/services}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_trainer_services_server.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_trainer_services_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/test_trainer_tools.py +0 -0
- {weightslab-1.3.0/weightslab/tests/components → weightslab-1.3.2/tests/utils}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_computational_graph_utils_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_logs_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_modules_dependencies_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_plot_graph_render_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_plot_graph_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_shape_prop_unit.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_utils_tools_unit.py +0 -0
- {weightslab-1.3.0/weightslab/tests/data → weightslab-1.3.2/tests/watchdog}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/watchdog/test_lock_monitor.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/watchdog/test_watchdog.py +0 -0
- {weightslab-1.3.0/weightslab/tests/gRPC → weightslab-1.3.2/weightslab/backend}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/audit_logger.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/dataloader_interface.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/evaluation_controller.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/experiment_hash.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/global_monitoring.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/parallel_primitives.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/tracking.py +0 -0
- {weightslab-1.3.0/weightslab/tests/general → weightslab-1.3.2/weightslab/data}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/array_proxy.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/data_samples_with_ops.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/data_utils.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/h5_array_store.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/point_cloud_utils.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/sample_stats.py +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/Dockerfile +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/.dockerignore +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/.env.example +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/DEPLOYMENT.md +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.base-path.conf copy.template +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.base-path.conf.template +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.conf +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.downstream_plaintext.yaml +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.downstream_upstream_plaintext.yaml +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.upstream_plaintext.yaml +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.yaml +0 -0
- {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/nginx.conf +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/Dockerfile +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/docker-compose.yml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/entrypoint.sh +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/Dockerfile +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/docker-compose.yml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/entrypoint.sh +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/ui-compose.yml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Lightning/ws-classification/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/config.yaml +0 -0
- {weightslab-1.3.0/weightslab/tests/integrations → weightslab-1.3.2/weightslab/examples/PyTorch/ws-clustering/face}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/data.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/model.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/signals.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/utils.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/criterions.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/data.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/model.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-generation/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-generation/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0000f77c-6257be58.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/000f8d37-d4c09a0f.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00a0f008-a315437f.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c12bd0-bb46e479.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c29c52-f9524f1e.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00ce6f6d-50bbee62.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d1bafa-1b47b41c.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d7268f-fd4487be.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00f0dd0f-5e9c9557.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a0d7f4c-ac5c3c8f.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a1f4fce-f9cac880.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a3bb2d8-c195d91e.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1cac6a7-04e33135.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ceb32e-3f481b43.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d10d08-5b108225.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d22449-15fb948f.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d7b3ac-5af8623b.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1dce572-c6a8cb5e.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e1a7b8-0aec80e8.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e8ad72-c3c79240.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ee702d-0ae1fc10.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1f0efd9-37a14dda.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2a0648b-d8e126bc.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2b70230-bad4ff6e.jpg +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0000f77c-6257be58.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/000f8d37-d4c09a0f.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00a0f008-a315437f.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c12bd0-bb46e479.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c29c52-f9524f1e.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00ce6f6d-50bbee62.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d1bafa-1b47b41c.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d7268f-fd4487be.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00f0dd0f-5e9c9557.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a0d7f4c-ac5c3c8f.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a1f4fce-f9cac880.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a3bb2d8-c195d91e.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1cac6a7-04e33135.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ceb32e-3f481b43.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d10d08-5b108225.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d22449-15fb948f.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d7b3ac-5af8623b.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1dce572-c6a8cb5e.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e1a7b8-0aec80e8.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e8ad72-c3c79240.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ee702d-0ae1fc10.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1f0efd9-37a14dda.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2a0648b-d8e126bc.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2b70230-bad4ff6e.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/criterions.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/data.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/model.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Ultralytics/ws-detection/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Ultralytics/ws-detection/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/criterions.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/data.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/model.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/config.yaml +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/main.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/criterions.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/data.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/kitti_download.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/model.py +0 -0
- {weightslab-1.3.0/weightslab/tests/model → weightslab-1.3.2/weightslab/examples/utils/baseline_models}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab/tests/modules → weightslab-1.3.2/weightslab/examples/utils/baseline_models/pytorch}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab → weightslab-1.3.2/weightslab/examples/utils}/baseline_models/pytorch/models.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/README.md +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/_utils.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/collate.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/dataset.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/signals.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/trainer.py +0 -0
- {weightslab-1.3.0/weightslab/tests/trainer → weightslab-1.3.2/weightslab/models}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/models/model_with_ops.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/models/monkey_patcher.py +0 -0
- {weightslab-1.3.0/weightslab/tests/trainer/services → weightslab-1.3.2/weightslab/modules}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/modules/neuron_ops.py +0 -0
- {weightslab-1.3.0/weightslab/tests/utils → weightslab-1.3.2/weightslab/proto}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service_pb2_grpc.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/security/__init__.py +0 -0
- {weightslab-1.3.0/weightslab/tests/watchdog → weightslab-1.3.2/weightslab/trainer}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab/trainer → weightslab-1.3.2/weightslab/trainer/services}/__init__.py +0 -0
- {weightslab-1.3.0/weightslab/trainer/services → weightslab-1.3.2/weightslab/trainer/services/agent}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/agent.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/query_example.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/schema.png +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent_service.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/data_image_utils.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/instance_merger.py +0 -0
- {weightslab-1.3.0/weightslab/trainer/services/agent → weightslab-1.3.2/weightslab/trainer/services/utils}/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/utils/tools.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/trainer_services.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/computational_graph.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/logs.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/modules_dependencies.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/plot_graph.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/shape_prop.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/telemetry.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/tools.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/__init__.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/grpc_watchdog.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/lock_monitor.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/log_level.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/watchdog.py +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/dependency_links.txt +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/entry_points.txt +0 -0
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/requires.txt +1 -1
- {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/top_level.txt +0 -0
|
@@ -221,7 +221,7 @@ jobs:
|
|
|
221
221
|
run: |
|
|
222
222
|
export WEIGHTSLAB_LOG_LEVEL="DEBUG"
|
|
223
223
|
# A per-test timeout guards against any regression that hangs a test.
|
|
224
|
-
python -m pytest ./
|
|
224
|
+
python -m pytest ./tests -v --timeout=300
|
|
225
225
|
|
|
226
226
|
build-and-publish-dev:
|
|
227
227
|
# Only publish to TestPyPI when pushing to main (not on PRs or dev branch pushes).
|
|
@@ -16,6 +16,8 @@ jobs:
|
|
|
16
16
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
|
17
17
|
outputs:
|
|
18
18
|
is_main: ${{ steps.check.outputs.is_main }}
|
|
19
|
+
is_dev_release: ${{ steps.check.outputs.is_dev_release }}
|
|
20
|
+
should_run: ${{ steps.check.outputs.should_run }}
|
|
19
21
|
steps:
|
|
20
22
|
- uses: actions/checkout@v4
|
|
21
23
|
with:
|
|
@@ -29,14 +31,32 @@ jobs:
|
|
|
29
31
|
IS_ON_MAIN=$(git merge-base --is-ancestor "${TAG_COMMIT}" origin/main \
|
|
30
32
|
&& echo "true" || echo "false")
|
|
31
33
|
echo "is_main=${IS_ON_MAIN}" >> $GITHUB_OUTPUT
|
|
32
|
-
echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN}"
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
# Dev pre-release: a tag NOT on main whose name contains 'dev'
|
|
36
|
+
# (e.g. v1.3.1-dev0). Runs the full pipeline up to the TestPyPI install
|
|
37
|
+
# tests + a GitHub pre-release, then STOPS before the production PyPI
|
|
38
|
+
# publish. A tag off main WITHOUT 'dev' triggers nothing (should_run=false),
|
|
39
|
+
# so accidental/non-dev tags on dev never release.
|
|
40
|
+
IS_DEV_RELEASE=false
|
|
41
|
+
if [ "${IS_ON_MAIN}" != "true" ] && [[ "${GITHUB_REF_NAME}" == *dev* ]]; then
|
|
42
|
+
IS_DEV_RELEASE=true
|
|
43
|
+
fi
|
|
44
|
+
echo "is_dev_release=${IS_DEV_RELEASE}" >> $GITHUB_OUTPUT
|
|
45
|
+
|
|
46
|
+
if [ "${IS_ON_MAIN}" = "true" ] || [ "${IS_DEV_RELEASE}" = "true" ]; then
|
|
47
|
+
SHOULD_RUN=true
|
|
48
|
+
else
|
|
49
|
+
SHOULD_RUN=false
|
|
50
|
+
fi
|
|
51
|
+
echo "should_run=${SHOULD_RUN}" >> $GITHUB_OUTPUT
|
|
52
|
+
echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN} dev_release: ${IS_DEV_RELEASE} should_run: ${SHOULD_RUN}"
|
|
53
|
+
|
|
54
|
+
# ── Shared: run tests before any publish (main or dev pre-release) ────────
|
|
35
55
|
test:
|
|
36
56
|
name: Run Tests Before Release
|
|
37
57
|
needs: detect-target
|
|
38
58
|
runs-on: ubuntu-latest
|
|
39
|
-
if: ${{ needs.detect-target.outputs.
|
|
59
|
+
if: ${{ needs.detect-target.outputs.should_run == 'true' }}
|
|
40
60
|
steps:
|
|
41
61
|
- uses: actions/checkout@v4
|
|
42
62
|
|
|
@@ -57,8 +77,7 @@ jobs:
|
|
|
57
77
|
run: |
|
|
58
78
|
export WEIGHTSLAB_LOG_LEVEL="DEBUG"
|
|
59
79
|
python -m pip install pytorch_lightning
|
|
60
|
-
|
|
61
|
-
python -m pytest ./weightslab/tests -v --timeout=300
|
|
80
|
+
python -m unittest discover -s ./tests -p "test_*.py" -t . -v
|
|
62
81
|
|
|
63
82
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
64
83
|
# DEV RELEASE — tag on dev branch, not yet merged to main
|
|
@@ -67,9 +86,9 @@ jobs:
|
|
|
67
86
|
|
|
68
87
|
build-and-publish-dev-release:
|
|
69
88
|
name: Build & Publish Dev Release (TestPyPI)
|
|
70
|
-
needs: detect-target
|
|
89
|
+
needs: [detect-target,test]
|
|
71
90
|
runs-on: ubuntu-latest
|
|
72
|
-
if: ${{ needs.detect-target.outputs.
|
|
91
|
+
if: ${{ needs.detect-target.outputs.should_run == 'true' }}
|
|
73
92
|
permissions:
|
|
74
93
|
contents: read
|
|
75
94
|
outputs:
|
|
@@ -188,9 +207,11 @@ jobs:
|
|
|
188
207
|
print('installed version:', m.version('weightslab'))
|
|
189
208
|
"
|
|
190
209
|
|
|
210
|
+
# Only for a dev pre-release tag (off main, name contains 'dev').
|
|
191
211
|
create-dev-release:
|
|
192
212
|
name: Create GitHub Pre-Release
|
|
193
|
-
needs: [build-and-publish-dev-release, test-install-from-pip-dev-release]
|
|
213
|
+
needs: [detect-target, build-and-publish-dev-release, test-install-from-pip-dev-release]
|
|
214
|
+
if: ${{ needs.detect-target.outputs.is_dev_release == 'true' }}
|
|
194
215
|
runs-on: ubuntu-latest
|
|
195
216
|
permissions:
|
|
196
217
|
contents: write
|
|
@@ -213,46 +234,107 @@ jobs:
|
|
|
213
234
|
export VERSION_NO_V="${VERSION#v}"
|
|
214
235
|
export PYPI_URL="https://test.pypi.org/project/weightslab/${VERSION_NO_V}/"
|
|
215
236
|
|
|
216
|
-
|
|
237
|
+
# Walk the actual commit graph for the nearest ancestor tag, rather
|
|
238
|
+
# than a lexicographic/semver sort across ALL tags. The old sort
|
|
239
|
+
# could pick an unrelated tag from a diverging branch — e.g. a
|
|
240
|
+
# "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
|
|
241
|
+
# sorted ABOVE it, making every real PR since v1.3.0 look "older"
|
|
242
|
+
# than that bogus previous-tag date and get silently filtered out
|
|
243
|
+
# (this is why past releases showed "no pull requests found").
|
|
244
|
+
PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
|
|
217
245
|
if [ -n "$PREV_TAG" ]; then
|
|
218
|
-
|
|
246
|
+
RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
|
|
247
|
+
# Normalize to UTC "Z" form so string comparison against GitHub's
|
|
248
|
+
# mergedAt (also UTC "Z") is valid regardless of the committer's
|
|
249
|
+
# local timezone offset.
|
|
250
|
+
export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
|
|
219
251
|
export GIT_RANGE="${PREV_TAG}..HEAD"
|
|
220
252
|
else
|
|
221
253
|
export PREV_TAG_DATE="2020-01-01T00:00:00Z"
|
|
222
254
|
export GIT_RANGE="HEAD"
|
|
223
255
|
fi
|
|
224
256
|
|
|
225
|
-
export
|
|
226
|
-
|
|
227
|
-
[ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
|
|
257
|
+
export COMMITS_RAW
|
|
258
|
+
COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
|
|
228
259
|
|
|
229
260
|
export GIT_AUTHORS
|
|
230
261
|
GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
|
|
231
262
|
|
|
263
|
+
# NOTE: deliberately NOT requesting --json commits here. With
|
|
264
|
+
# --limit 100 that expands into a GraphQL query requesting 100 PRs'
|
|
265
|
+
# worth of commit nodes, which reliably exceeds GitHub's 500,000
|
|
266
|
+
# node budget and makes `gh` print a plain-text GraphQL error
|
|
267
|
+
# instead of JSON — json.loads() below then fails, prs_data
|
|
268
|
+
# silently becomes [], and every release note says "no pull
|
|
269
|
+
# requests found" regardless of the date filter. Commits are
|
|
270
|
+
# fetched below, one lightweight call per PR, only for the small
|
|
271
|
+
# number of PRs that actually match this release.
|
|
232
272
|
export PRS_JSON
|
|
233
273
|
PRS_JSON=$(gh pr list --state merged --base "dev" --limit 100 \
|
|
234
|
-
--json number,title,mergedAt,url,author,body
|
|
274
|
+
--json number,title,mergedAt,url,author,body \
|
|
235
275
|
2>/dev/null || echo "[]")
|
|
236
276
|
|
|
237
277
|
python3 << 'PYEOF'
|
|
238
|
-
import os, json
|
|
278
|
+
import os, json, re, importlib.util, subprocess
|
|
239
279
|
version = os.environ["VERSION"]
|
|
240
280
|
pypi_url = os.environ["PYPI_URL"]
|
|
241
281
|
prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
|
|
242
|
-
|
|
282
|
+
commits_raw = os.environ.get("COMMITS_RAW", "")
|
|
243
283
|
git_authors = os.environ.get("GIT_AUTHORS", "")
|
|
244
284
|
try:
|
|
245
285
|
prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
|
|
246
286
|
except Exception:
|
|
247
287
|
prs_data = []
|
|
288
|
+
|
|
289
|
+
_README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
|
|
290
|
+
|
|
291
|
+
def _strip_pr_suffix(head):
|
|
292
|
+
return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
|
|
293
|
+
|
|
294
|
+
def _collapse_readme(entries):
|
|
295
|
+
"""entries: list of (oid_or_None, head) tuples, in original order.
|
|
296
|
+
Collapse every bare "Update README[.md]" commit into a single
|
|
297
|
+
"Update README (n)" line at the position of its first occurrence —
|
|
298
|
+
these are near-duplicate housekeeping commits with no release signal."""
|
|
299
|
+
out, count, placeholder_idx = [], 0, None
|
|
300
|
+
for oid, head in entries:
|
|
301
|
+
if _README_RE.match(_strip_pr_suffix(head)):
|
|
302
|
+
count += 1
|
|
303
|
+
if placeholder_idx is None:
|
|
304
|
+
placeholder_idx = len(out)
|
|
305
|
+
out.append(None)
|
|
306
|
+
continue
|
|
307
|
+
out.append((oid, head))
|
|
308
|
+
if placeholder_idx is not None:
|
|
309
|
+
label = "Update README" if count == 1 else f"Update README ({count})"
|
|
310
|
+
out[placeholder_idx] = (None, label)
|
|
311
|
+
return out
|
|
312
|
+
|
|
313
|
+
def _format_entries(entries, indent=""):
|
|
314
|
+
return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
|
|
315
|
+
|
|
248
316
|
def _pr_entry(pr):
|
|
249
|
-
line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
|
|
250
317
|
desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
|
|
251
|
-
if desc:
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return
|
|
318
|
+
if not desc:
|
|
319
|
+
desc = pr["title"]
|
|
320
|
+
if len(desc) > 512:
|
|
321
|
+
desc = desc[:509].rstrip() + "..."
|
|
322
|
+
return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
|
|
323
|
+
|
|
324
|
+
def _fetch_pr_commits(number):
|
|
325
|
+
# One lightweight call per matched PR (see the note above the
|
|
326
|
+
# PRS_JSON fetch for why this isn't batched into the list query).
|
|
327
|
+
try:
|
|
328
|
+
out = subprocess.run(
|
|
329
|
+
["gh", "pr", "view", str(number), "--json", "commits"],
|
|
330
|
+
capture_output=True, text=True, timeout=30,
|
|
331
|
+
)
|
|
332
|
+
if out.returncode != 0:
|
|
333
|
+
return []
|
|
334
|
+
return json.loads(out.stdout).get("commits") or []
|
|
335
|
+
except Exception:
|
|
336
|
+
return []
|
|
337
|
+
|
|
256
338
|
filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
|
|
257
339
|
# "What's Changed precisely": list each merged PR's own developer commits,
|
|
258
340
|
# NOT the squashed/merge/chore commits that land on the release branch
|
|
@@ -260,8 +342,8 @@ jobs:
|
|
|
260
342
|
_seen_commits = set()
|
|
261
343
|
_commit_blocks = []
|
|
262
344
|
for pr in filtered:
|
|
263
|
-
|
|
264
|
-
for c in (pr
|
|
345
|
+
raw_entries = []
|
|
346
|
+
for c in _fetch_pr_commits(pr["number"]):
|
|
265
347
|
oid = (c.get("oid") or "")[:7]
|
|
266
348
|
head = (c.get("messageHeadline") or "").strip()
|
|
267
349
|
if not head or head.startswith("Merge "):
|
|
@@ -270,13 +352,24 @@ jobs:
|
|
|
270
352
|
if key in _seen_commits:
|
|
271
353
|
continue
|
|
272
354
|
_seen_commits.add(key)
|
|
273
|
-
|
|
274
|
-
|
|
355
|
+
raw_entries.append((oid, head))
|
|
356
|
+
commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
|
|
357
|
+
if commit_lines:
|
|
275
358
|
_commit_blocks.append(
|
|
276
|
-
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(
|
|
359
|
+
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
|
|
277
360
|
)
|
|
278
361
|
# Fall back to the raw git log only when no PR commits are available.
|
|
279
|
-
|
|
362
|
+
if _commit_blocks:
|
|
363
|
+
commits_section = "\n\n".join(_commit_blocks)
|
|
364
|
+
else:
|
|
365
|
+
fallback_entries = []
|
|
366
|
+
for line in commits_raw.splitlines():
|
|
367
|
+
if "\t" not in line:
|
|
368
|
+
continue
|
|
369
|
+
oid, head = line.split("\t", 1)
|
|
370
|
+
fallback_entries.append((oid, head))
|
|
371
|
+
fallback_entries = _collapse_readme(fallback_entries)
|
|
372
|
+
commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
|
|
280
373
|
if filtered:
|
|
281
374
|
prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
|
|
282
375
|
seen, clabels = set(), []
|
|
@@ -289,7 +382,23 @@ jobs:
|
|
|
289
382
|
else:
|
|
290
383
|
prs_lines = "_(no pull requests found since last release)_"
|
|
291
384
|
contributors = git_authors or "_(no contributors found)_"
|
|
385
|
+
|
|
386
|
+
# CLI banner (weightslab/art.py), loaded as a standalone file so we
|
|
387
|
+
# don't pull in the full package (and its heavy optional deps) just
|
|
388
|
+
# to print a logo. ANSI color codes are stripped (Markdown can't render
|
|
389
|
+
# them); the box-drawing/ASCII art itself renders fine in a code fence.
|
|
390
|
+
banner_block = ""
|
|
391
|
+
try:
|
|
392
|
+
spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
|
|
393
|
+
wl_art = importlib.util.module_from_spec(spec)
|
|
394
|
+
spec.loader.exec_module(wl_art)
|
|
395
|
+
plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
|
|
396
|
+
banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
|
|
397
|
+
except Exception:
|
|
398
|
+
pass
|
|
399
|
+
|
|
292
400
|
body = (
|
|
401
|
+
banner_block +
|
|
293
402
|
"## **Weightslab**\n\n"
|
|
294
403
|
"Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
|
|
295
404
|
" | [Graybx](https://www.graybx.com/)\n\n"
|
|
@@ -309,7 +418,7 @@ jobs:
|
|
|
309
418
|
"### Thank you!\n\n"
|
|
310
419
|
f"{contributors}\n"
|
|
311
420
|
)
|
|
312
|
-
with open("RELEASE_NOTES.md", "w") as f:
|
|
421
|
+
with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
|
|
313
422
|
f.write(body)
|
|
314
423
|
PYEOF
|
|
315
424
|
|
|
@@ -331,8 +440,7 @@ jobs:
|
|
|
331
440
|
|
|
332
441
|
build-and-publish-main:
|
|
333
442
|
name: Build & Publish Main (PyPI)
|
|
334
|
-
needs: [detect-target
|
|
335
|
-
# needs: [detect-target]
|
|
443
|
+
needs: [test-install-from-pip-dev-release, detect-target]
|
|
336
444
|
runs-on: ubuntu-latest
|
|
337
445
|
if: ${{ needs.detect-target.outputs.is_main == 'true' }}
|
|
338
446
|
permissions:
|
|
@@ -446,7 +554,7 @@ jobs:
|
|
|
446
554
|
|
|
447
555
|
create-main-release:
|
|
448
556
|
name: Create GitHub Release
|
|
449
|
-
needs: [
|
|
557
|
+
needs: [test-install-from-pip-main]
|
|
450
558
|
runs-on: ubuntu-latest
|
|
451
559
|
permissions:
|
|
452
560
|
contents: write
|
|
@@ -469,46 +577,107 @@ jobs:
|
|
|
469
577
|
export VERSION_NO_V="${VERSION#v}"
|
|
470
578
|
export PYPI_URL="https://pypi.org/project/weightslab/${VERSION_NO_V}/"
|
|
471
579
|
|
|
472
|
-
|
|
580
|
+
# Walk the actual commit graph for the nearest ancestor tag, rather
|
|
581
|
+
# than a lexicographic/semver sort across ALL tags. The old sort
|
|
582
|
+
# could pick an unrelated tag from a diverging branch — e.g. a
|
|
583
|
+
# "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
|
|
584
|
+
# sorted ABOVE it, making every real PR since v1.3.0 look "older"
|
|
585
|
+
# than that bogus previous-tag date and get silently filtered out
|
|
586
|
+
# (this is why past releases showed "no pull requests found").
|
|
587
|
+
PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
|
|
473
588
|
if [ -n "$PREV_TAG" ]; then
|
|
474
|
-
|
|
589
|
+
RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
|
|
590
|
+
# Normalize to UTC "Z" form so string comparison against GitHub's
|
|
591
|
+
# mergedAt (also UTC "Z") is valid regardless of the committer's
|
|
592
|
+
# local timezone offset.
|
|
593
|
+
export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
|
|
475
594
|
export GIT_RANGE="${PREV_TAG}..HEAD"
|
|
476
595
|
else
|
|
477
596
|
export PREV_TAG_DATE="2020-01-01T00:00:00Z"
|
|
478
597
|
export GIT_RANGE="HEAD"
|
|
479
598
|
fi
|
|
480
599
|
|
|
481
|
-
export
|
|
482
|
-
|
|
483
|
-
[ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
|
|
600
|
+
export COMMITS_RAW
|
|
601
|
+
COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
|
|
484
602
|
|
|
485
603
|
export GIT_AUTHORS
|
|
486
604
|
GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
|
|
487
605
|
|
|
606
|
+
# NOTE: deliberately NOT requesting --json commits here. With
|
|
607
|
+
# --limit 100 that expands into a GraphQL query requesting 100 PRs'
|
|
608
|
+
# worth of commit nodes, which reliably exceeds GitHub's 500,000
|
|
609
|
+
# node budget and makes `gh` print a plain-text GraphQL error
|
|
610
|
+
# instead of JSON — json.loads() below then fails, prs_data
|
|
611
|
+
# silently becomes [], and every release note says "no pull
|
|
612
|
+
# requests found" regardless of the date filter. Commits are
|
|
613
|
+
# fetched below, one lightweight call per PR, only for the small
|
|
614
|
+
# number of PRs that actually match this release.
|
|
488
615
|
export PRS_JSON
|
|
489
616
|
PRS_JSON=$(gh pr list --state merged --base "main" --limit 100 \
|
|
490
|
-
--json number,title,mergedAt,url,author,body
|
|
617
|
+
--json number,title,mergedAt,url,author,body \
|
|
491
618
|
2>/dev/null || echo "[]")
|
|
492
619
|
|
|
493
620
|
python3 << 'PYEOF'
|
|
494
|
-
import os, json
|
|
621
|
+
import os, json, re, importlib.util, subprocess
|
|
495
622
|
version = os.environ["VERSION"]
|
|
496
623
|
pypi_url = os.environ["PYPI_URL"]
|
|
497
624
|
prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
|
|
498
|
-
|
|
625
|
+
commits_raw = os.environ.get("COMMITS_RAW", "")
|
|
499
626
|
git_authors = os.environ.get("GIT_AUTHORS", "")
|
|
500
627
|
try:
|
|
501
628
|
prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
|
|
502
629
|
except Exception:
|
|
503
630
|
prs_data = []
|
|
631
|
+
|
|
632
|
+
_README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
|
|
633
|
+
|
|
634
|
+
def _strip_pr_suffix(head):
|
|
635
|
+
return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
|
|
636
|
+
|
|
637
|
+
def _collapse_readme(entries):
|
|
638
|
+
"""entries: list of (oid_or_None, head) tuples, in original order.
|
|
639
|
+
Collapse every bare "Update README[.md]" commit into a single
|
|
640
|
+
"Update README (n)" line at the position of its first occurrence —
|
|
641
|
+
these are near-duplicate housekeeping commits with no release signal."""
|
|
642
|
+
out, count, placeholder_idx = [], 0, None
|
|
643
|
+
for oid, head in entries:
|
|
644
|
+
if _README_RE.match(_strip_pr_suffix(head)):
|
|
645
|
+
count += 1
|
|
646
|
+
if placeholder_idx is None:
|
|
647
|
+
placeholder_idx = len(out)
|
|
648
|
+
out.append(None)
|
|
649
|
+
continue
|
|
650
|
+
out.append((oid, head))
|
|
651
|
+
if placeholder_idx is not None:
|
|
652
|
+
label = "Update README" if count == 1 else f"Update README ({count})"
|
|
653
|
+
out[placeholder_idx] = (None, label)
|
|
654
|
+
return out
|
|
655
|
+
|
|
656
|
+
def _format_entries(entries, indent=""):
|
|
657
|
+
return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
|
|
658
|
+
|
|
504
659
|
def _pr_entry(pr):
|
|
505
|
-
line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
|
|
506
660
|
desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
|
|
507
|
-
if desc:
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return
|
|
661
|
+
if not desc:
|
|
662
|
+
desc = pr["title"]
|
|
663
|
+
if len(desc) > 512:
|
|
664
|
+
desc = desc[:509].rstrip() + "..."
|
|
665
|
+
return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
|
|
666
|
+
|
|
667
|
+
def _fetch_pr_commits(number):
|
|
668
|
+
# One lightweight call per matched PR (see the note above the
|
|
669
|
+
# PRS_JSON fetch for why this isn't batched into the list query).
|
|
670
|
+
try:
|
|
671
|
+
out = subprocess.run(
|
|
672
|
+
["gh", "pr", "view", str(number), "--json", "commits"],
|
|
673
|
+
capture_output=True, text=True, timeout=30,
|
|
674
|
+
)
|
|
675
|
+
if out.returncode != 0:
|
|
676
|
+
return []
|
|
677
|
+
return json.loads(out.stdout).get("commits") or []
|
|
678
|
+
except Exception:
|
|
679
|
+
return []
|
|
680
|
+
|
|
512
681
|
filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
|
|
513
682
|
# "What's Changed precisely": list each merged PR's own developer commits,
|
|
514
683
|
# NOT the squashed/merge/chore commits that land on the release branch
|
|
@@ -516,8 +685,8 @@ jobs:
|
|
|
516
685
|
_seen_commits = set()
|
|
517
686
|
_commit_blocks = []
|
|
518
687
|
for pr in filtered:
|
|
519
|
-
|
|
520
|
-
for c in (pr
|
|
688
|
+
raw_entries = []
|
|
689
|
+
for c in _fetch_pr_commits(pr["number"]):
|
|
521
690
|
oid = (c.get("oid") or "")[:7]
|
|
522
691
|
head = (c.get("messageHeadline") or "").strip()
|
|
523
692
|
if not head or head.startswith("Merge "):
|
|
@@ -526,13 +695,24 @@ jobs:
|
|
|
526
695
|
if key in _seen_commits:
|
|
527
696
|
continue
|
|
528
697
|
_seen_commits.add(key)
|
|
529
|
-
|
|
530
|
-
|
|
698
|
+
raw_entries.append((oid, head))
|
|
699
|
+
commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
|
|
700
|
+
if commit_lines:
|
|
531
701
|
_commit_blocks.append(
|
|
532
|
-
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(
|
|
702
|
+
f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
|
|
533
703
|
)
|
|
534
704
|
# Fall back to the raw git log only when no PR commits are available.
|
|
535
|
-
|
|
705
|
+
if _commit_blocks:
|
|
706
|
+
commits_section = "\n\n".join(_commit_blocks)
|
|
707
|
+
else:
|
|
708
|
+
fallback_entries = []
|
|
709
|
+
for line in commits_raw.splitlines():
|
|
710
|
+
if "\t" not in line:
|
|
711
|
+
continue
|
|
712
|
+
oid, head = line.split("\t", 1)
|
|
713
|
+
fallback_entries.append((oid, head))
|
|
714
|
+
fallback_entries = _collapse_readme(fallback_entries)
|
|
715
|
+
commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
|
|
536
716
|
if filtered:
|
|
537
717
|
prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
|
|
538
718
|
seen, clabels = set(), []
|
|
@@ -545,7 +725,23 @@ jobs:
|
|
|
545
725
|
else:
|
|
546
726
|
prs_lines = "_(no pull requests found since last release)_"
|
|
547
727
|
contributors = git_authors or "_(no contributors found)_"
|
|
728
|
+
|
|
729
|
+
# CLI banner (weightslab/art.py), loaded as a standalone file so we
|
|
730
|
+
# don't pull in the full package (and its heavy optional deps) just
|
|
731
|
+
# to print a logo. ANSI color codes are stripped (Markdown can't render
|
|
732
|
+
# them); the box-drawing/ASCII art itself renders fine in a code fence.
|
|
733
|
+
banner_block = ""
|
|
734
|
+
try:
|
|
735
|
+
spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
|
|
736
|
+
wl_art = importlib.util.module_from_spec(spec)
|
|
737
|
+
spec.loader.exec_module(wl_art)
|
|
738
|
+
plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
|
|
739
|
+
banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
|
|
740
|
+
except Exception:
|
|
741
|
+
pass
|
|
742
|
+
|
|
548
743
|
body = (
|
|
744
|
+
banner_block +
|
|
549
745
|
"## **Weightslab**\n\n"
|
|
550
746
|
"Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
|
|
551
747
|
" | [Graybx](https://www.graybx.com/)\n\n"
|
|
@@ -565,7 +761,7 @@ jobs:
|
|
|
565
761
|
"### Thank you!\n\n"
|
|
566
762
|
f"{contributors}\n"
|
|
567
763
|
)
|
|
568
|
-
with open("RELEASE_NOTES.md", "w") as f:
|
|
764
|
+
with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
|
|
569
765
|
f.write(body)
|
|
570
766
|
PYEOF
|
|
571
767
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Changelog - 2026-07-07 v1.3.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: weightslab
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Paving the way between black-box and white-box modeling.
|
|
5
5
|
Author-email: Alexandru-Andrei Rotaru <alexandru@graybx.com>, Guillaue Pelluet <guillaue@graybx.com>
|
|
6
6
|
License: BSD 2-clause
|
|
@@ -32,6 +32,7 @@ Requires-Dist: grpcio<2,>=1.80
|
|
|
32
32
|
Requires-Dist: protobuf<7,>=4.25
|
|
33
33
|
Requires-Dist: pydantic<3,>=2.7
|
|
34
34
|
Requires-Dist: Pillow<12,>=10
|
|
35
|
+
Requires-Dist: graphviz<1,>=0.20
|
|
35
36
|
Requires-Dist: onnx<=1.20,>=1.15
|
|
36
37
|
Requires-Dist: tqdm<5,>=4.66
|
|
37
38
|
Requires-Dist: python-dotenv<2,>=1
|
|
@@ -53,7 +54,6 @@ Requires-Dist: torchaudio<3,>=2.9; python_version >= "3.13" and extra == "utest"
|
|
|
53
54
|
Requires-Dist: torchmetrics<2,>=1.3; extra == "utest"
|
|
54
55
|
Requires-Dist: pytorch-lightning<3,>=2.2; extra == "utest"
|
|
55
56
|
Requires-Dist: tensorboard<3,>=2.14; extra == "utest"
|
|
56
|
-
Requires-Dist: graphviz<1,>=0.20; extra == "utest"
|
|
57
57
|
Requires-Dist: pytest>=9.0.2; extra == "utest"
|
|
58
58
|
Dynamic: license-file
|
|
59
59
|
|
|
@@ -67,8 +67,8 @@ Dynamic: license-file
|
|
|
67
67
|
</a>
|
|
68
68
|
</div>
|
|
69
69
|
<div align="center">
|
|
70
|
-
<h3>
|
|
71
|
-
<p>Pause training, mine live loss signals to surface mislabels, class imbalance & outliers,<br>then curate your image, video & LiDAR data
|
|
70
|
+
<h3>Trace training signals back to the exact samples causing them</h3>
|
|
71
|
+
<p>Pause training, mine live loss signals to surface mislabels, class imbalance & outliers,<br>then curate your image, video & LiDAR data, without restarting.</p>
|
|
72
72
|
</div>
|
|
73
73
|
|
|
74
74
|
</div>
|
|
@@ -81,11 +81,16 @@ Dynamic: license-file
|
|
|
81
81
|
|
|
82
82
|
## What it does
|
|
83
83
|
|
|
84
|
-
WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets: images, video & LiDAR point clouds.
|
|
84
|
+
WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets: images, video & LiDAR point clouds.
|
|
85
|
+
Longer-term, we're building toward bringing dataset management, training, fine-tuning, and validation together in a single, unified workflow.
|
|
85
86
|
|
|
86
87
|
<br>
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
<div align="center">
|
|
89
|
+
<img src="https://github.com/GrayboxTech/assets/blob/main/GIF/weightslab_demo_bdd.gif" width="1280" alt="WeightsLab Studio demo" />
|
|
90
|
+
<!-- <sub><a href="https://youtu.be/GBBDDaJQLWk">▶ Watch full demo</a></sub> -->
|
|
91
|
+
</div>
|
|
92
|
+
<br>
|
|
93
|
+
Most data problems are invisible until your model tells you: through loss spikes, poor generalization, or silent underperformance. WeightsLab connects those training signals back to the exact samples causing them.
|
|
89
94
|
|
|
90
95
|
**Wrap your training script with the SDK** to capture per-sample signals live.
|
|
91
96
|
**Open Studio** to inspect, filter, and curate your dataset mid-training, without restarting.
|
|
@@ -93,20 +98,12 @@ Most data problems are invisible until your model tells you: through loss spikes
|
|
|
93
98
|
- **Detect** - Surface mislabels, outliers & class imbalance using live loss signals
|
|
94
99
|
- **Curate** - Discard bad samples, create data subsets, rebalance distributions
|
|
95
100
|
- **Continue** - Resume training on your cleaned dataset, no restart required
|
|
96
|
-
|
|
97
|
-
WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets (images, video & LiDAR point clouds).
|
|
98
|
-
|
|
99
|
-
<br>
|
|
100
|
-
|
|
101
|
-
→ `give it a star ⭐` and join our [`early access ⏰`](https://grayboxtech.github.io/signup/)
|
|
102
|
-
|
|
103
101
|
<br>
|
|
104
102
|
|
|
105
103
|
## Quickstart
|
|
106
104
|
|
|
107
105
|

|
|
108
106
|

|
|
109
|
-

|
|
110
107
|
|
|
111
108
|
**1. Install**
|
|
112
109
|
```bash
|
|
@@ -162,8 +159,8 @@ For a detailed installation guide and advanced configuration → [Installatio
|
|
|
162
159
|
|
|
163
160
|
2. **Wrap your parameters, model, optimizer, signals, and dataset:**
|
|
164
161
|
```python
|
|
165
|
-
parameters = wl.watch_or_edit(parameters,
|
|
166
|
-
model = wl.watch_or_edit(
|
|
162
|
+
parameters = wl.watch_or_edit(parameters, flag='hp', ...) # ← WeightsLab monitors your parameters and lets you update them from the UI
|
|
163
|
+
model = wl.watch_or_edit(model, flag='model', ...) # ← WeightsLab monitors your model state
|
|
167
164
|
optimizer = wl.watch_or_edit(optim.Adam(...), flag='opt', ...) # ← Tracks optimizer state and lets you update the learning rate from the UI
|
|
168
165
|
|
|
169
166
|
train_criterion = wl.watch_or_edit(nn.CrossEntropyLoss(reduction="none"), flag='signal', name="train_loss/sample", per_sample=True, log=True) # ← Wrap and plot your signals on the UI
|
|
@@ -257,7 +254,7 @@ def main():
|
|
|
257
254
|
# instance_id=[1, 2],
|
|
258
255
|
)
|
|
259
256
|
|
|
260
|
-
avg_loss = total_loss / len(
|
|
257
|
+
avg_loss = total_loss / len(loader)
|
|
261
258
|
print(f"Epoch {epoch+1}/5 - Loss: {avg_loss:.4f}")
|
|
262
259
|
|
|
263
260
|
print("✅ Training complete!")
|