opensportslib 0.3.1.dev2__tar.gz → 0.3.1.dev3__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.
- {opensportslib-0.3.1.dev2/opensportslib.egg-info → opensportslib-0.3.1.dev3}/PKG-INFO +14 -1
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/README.md +13 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/tools/hf_transfer.py +135 -20
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3/opensportslib.egg-info}/PKG-INFO +14 -1
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/pyproject.toml +1 -1
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_hf_transfer_tools.py +147 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/LICENSE +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/LICENSE-COMMERCIAL +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/MANIFEST.in +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/examples/quickstart/basic_classification.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/examples/quickstart/basic_localization.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/examples/quickstart/basic_vqa.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/adaptation/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/adaptation/spotta.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/apis/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/apis/base_task_model.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/apis/classification.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/apis/localization.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/apis/vqa.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/cli.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/classification/default.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/classification/sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/classification/sngar_tracking.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/classification/video.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/default.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/default.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/e2e_spotta.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/h5_header_distance.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/h5_header_skeleton.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/netvladpp_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/tracking_action_spotting.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/video_dali.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/localization/video_ocv.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/default.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/qwen.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/qwen3_vl_native.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/qwen_lora.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/qwen_sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/configs/vqa/xvars.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/accessors.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/conflicts.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/loader.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/migrate.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/migrations/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/migrations/legacy_to_canonical.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/runtime_adapter.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/schema.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/schemas/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/schemas/schema_canonical.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/schemas/schema_legacy.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/config/validate.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/calf.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/ce.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/combine.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/loss/nll.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/optimizer/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/optimizer/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/sampler/weighted_sampler.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/scheduler/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/scheduler/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/trainer/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/trainer/classification_trainer.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/trainer/localization_trainer.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/trainer/vqa_trainer.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/checkpoint.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/config.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/config_normalize.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/data.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/ddp.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/default_args.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/hf_runtime.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/lightning.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/load_annotations.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/seed.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/video_processing.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/core/utils/wandb.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/classification_dataset.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/localization_dataset.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/utils/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/utils/h5_tracking.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/utils/tracking.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/datasets/vqa_dataset.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/classification.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/localization-e2e-ocv.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/localization-json_calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/localization-json_netvlad++_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/localization.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/sngar-frames.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/legacy_config/sngar-tracking.yaml +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/metrics/classification_metric.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/metrics/localization_metric.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/metrics/vqa_metric.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/backbones/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/contextaware.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/e2e.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/learnablepooling.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/qwen_vl_native.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/rule_based.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/tracking.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/vars.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/video.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/video_chatgpt_compat.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/video_mae.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/base/xvars_videochatgpt.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/heads/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/neck/builder.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/common.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/asformer.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/calf.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/gsm.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/gtad.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/impl/tsm.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/litebase.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/modules.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/shift.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/utils.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/vqa_prediction_priors.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/vqa_prompting.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/models/utils/xvars_clip_index.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/setup/setup.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/tools/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/tools/_common.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/tools/osl_json_to_parquet.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib/tools/parquet_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib.egg-info/SOURCES.txt +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib.egg-info/dependency_links.txt +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib.egg-info/entry_points.txt +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib.egg-info/requires.txt +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/opensportslib.egg-info/top_level.txt +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/scripts/run_h5_header_rule_inference.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/setup.cfg +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/conftest.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/release/__init__.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/release/_release_common.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/release/test_classification_release.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/release/test_localization_release.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/release/test_vqa_release.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_classification_dataset_paths.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_classification_trainer_dataloader.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_config_architecture.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_config_split_override_sync.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_config_utils_smoke.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_conversion_tools.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_extract_xvars_features.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_h5_header_rule_spotter.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_h5_header_skeleton_spotter.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_h5_tracking_dataset.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_localization_dali_filenames.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_localization_hf_backend_override.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_localization_intervals.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_package_smoke.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_pretrained_config_merge_policy.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_public_apis_smoke.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_setup_cli.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_spotta_e2e.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_subset_train_infer_integration.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_task_model_api_contract.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_vqa_api.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_vqa_metrics_semantic.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_vqa_qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_vqa_training_lora.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tests/test_vqa_xvars_videochatgpt.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_sn_vqa_2026_vqa.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_soccernet_gar.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_soccernet_gar_action_spotting.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_soccernet_gar_vqa.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/build_xvars_indexes.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/extract_xvars_clip_features.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/osl_json_to_parquet_webdataset.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/parquet_webdataset_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/sngar_dataset_card.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/sngar_events.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/convert/verify_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/download/download_hf_repo.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/download/download_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/download/push_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/download/upload_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/training/classification.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/training/localization.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/training/vqa.py +0 -0
- {opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/tools/upload/upload_model_hf.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.1.
|
|
3
|
+
Version: 0.3.1.dev3
|
|
4
4
|
Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
|
|
5
5
|
Author: Jeet Vora
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -392,6 +392,19 @@ The JSON records the resolved Hugging Face commit and can later be passed to
|
|
|
392
392
|
Parquet/WebDataset download always completes the local split even when a
|
|
393
393
|
metadata-only `<split>.json` already exists.
|
|
394
394
|
|
|
395
|
+
Download APIs accept `byte_progress_cb(filename, downloaded_bytes,
|
|
396
|
+
total_bytes)`. When the repository file is Xet-backed, OpenSportsLib keeps the
|
|
397
|
+
accelerated Xet transfer and adapts Xet's byte updates to this callback. It
|
|
398
|
+
falls back to classic HTTP progress when Xet is unavailable, disabled, or not
|
|
399
|
+
used by the file.
|
|
400
|
+
When byte progress is enabled, Parquet downloads also emit `[current/total]`
|
|
401
|
+
file messages through `progress_cb` so clients can present file-count progress.
|
|
402
|
+
High-level split downloads also accept `file_plan_cb(filenames)`,
|
|
403
|
+
`file_completed_cb(filename, local_path)`, and
|
|
404
|
+
`json_ready_cb(split, json_path)`. These are transfer lifecycle notifications;
|
|
405
|
+
callers remain responsible for queue policy and presentation. For non-dry-run
|
|
406
|
+
JSON datasets, pinned source metadata is persisted before `json_ready_cb` runs.
|
|
407
|
+
|
|
395
408
|
JSON uploads support partially downloaded datasets: the JSON and all
|
|
396
409
|
referenced files available locally are committed, while missing referenced
|
|
397
410
|
files are skipped and reported. Remote files not included in that commit are
|
|
@@ -356,6 +356,19 @@ The JSON records the resolved Hugging Face commit and can later be passed to
|
|
|
356
356
|
Parquet/WebDataset download always completes the local split even when a
|
|
357
357
|
metadata-only `<split>.json` already exists.
|
|
358
358
|
|
|
359
|
+
Download APIs accept `byte_progress_cb(filename, downloaded_bytes,
|
|
360
|
+
total_bytes)`. When the repository file is Xet-backed, OpenSportsLib keeps the
|
|
361
|
+
accelerated Xet transfer and adapts Xet's byte updates to this callback. It
|
|
362
|
+
falls back to classic HTTP progress when Xet is unavailable, disabled, or not
|
|
363
|
+
used by the file.
|
|
364
|
+
When byte progress is enabled, Parquet downloads also emit `[current/total]`
|
|
365
|
+
file messages through `progress_cb` so clients can present file-count progress.
|
|
366
|
+
High-level split downloads also accept `file_plan_cb(filenames)`,
|
|
367
|
+
`file_completed_cb(filename, local_path)`, and
|
|
368
|
+
`json_ready_cb(split, json_path)`. These are transfer lifecycle notifications;
|
|
369
|
+
callers remain responsible for queue policy and presentation. For non-dry-run
|
|
370
|
+
JSON datasets, pinned source metadata is persisted before `json_ready_cb` runs.
|
|
371
|
+
|
|
359
372
|
JSON uploads support partially downloaded datasets: the JSON and all
|
|
360
373
|
referenced files available locally are committed, while missing referenced
|
|
361
374
|
files are skipped and reported. Remote files not included in that commit are
|
|
@@ -9,6 +9,9 @@ from typing import Any, Callable
|
|
|
9
9
|
|
|
10
10
|
ProgressCallback = Callable[[str], None]
|
|
11
11
|
ByteProgressCallback = Callable[[str, int, int], None]
|
|
12
|
+
FilePlanCallback = Callable[[list[str]], None]
|
|
13
|
+
FileCompletedCallback = Callable[[str, str], None]
|
|
14
|
+
JsonReadyCallback = Callable[[str, str], None]
|
|
12
15
|
CancelCheck = Callable[[], bool]
|
|
13
16
|
|
|
14
17
|
HF_REPO_ID_KEY = "hf_repo_id"
|
|
@@ -101,6 +104,29 @@ def _emit_progress(progress_cb: ProgressCallback | None, message: str) -> None:
|
|
|
101
104
|
progress_cb(message)
|
|
102
105
|
|
|
103
106
|
|
|
107
|
+
def _emit_file_plan(
|
|
108
|
+
file_plan_cb: FilePlanCallback | None, filenames: list[str]
|
|
109
|
+
) -> None:
|
|
110
|
+
if file_plan_cb and filenames:
|
|
111
|
+
file_plan_cb(list(filenames))
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _emit_file_completed(
|
|
115
|
+
file_completed_cb: FileCompletedCallback | None,
|
|
116
|
+
filename: str,
|
|
117
|
+
local_path: str,
|
|
118
|
+
) -> None:
|
|
119
|
+
if file_completed_cb:
|
|
120
|
+
file_completed_cb(filename, local_path)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _emit_json_ready(
|
|
124
|
+
json_ready_cb: JsonReadyCallback | None, split: str, json_path: str
|
|
125
|
+
) -> None:
|
|
126
|
+
if json_ready_cb:
|
|
127
|
+
json_ready_cb(split, json_path)
|
|
128
|
+
|
|
129
|
+
|
|
104
130
|
def _ensure_not_cancelled(is_cancelled: CancelCheck | None) -> None:
|
|
105
131
|
if is_cancelled and is_cancelled():
|
|
106
132
|
raise HfTransferCancelled("Transfer cancelled by user.")
|
|
@@ -128,6 +154,23 @@ def _import_hf_file_system():
|
|
|
128
154
|
return HfFileSystem, TqdmCallback
|
|
129
155
|
|
|
130
156
|
|
|
157
|
+
def _import_hf_xet_download():
|
|
158
|
+
try:
|
|
159
|
+
from huggingface_hub import get_hf_file_metadata, hf_hub_url
|
|
160
|
+
from huggingface_hub.file_download import xet_get
|
|
161
|
+
from huggingface_hub.utils import build_hf_headers
|
|
162
|
+
from huggingface_hub.utils._runtime import is_xet_available
|
|
163
|
+
except ImportError:
|
|
164
|
+
return None
|
|
165
|
+
return (
|
|
166
|
+
get_hf_file_metadata,
|
|
167
|
+
hf_hub_url,
|
|
168
|
+
xet_get,
|
|
169
|
+
build_hf_headers,
|
|
170
|
+
is_xet_available,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
131
174
|
def _download_hf_file(
|
|
132
175
|
hf_hub_download,
|
|
133
176
|
*,
|
|
@@ -169,7 +212,6 @@ def _download_hf_file(
|
|
|
169
212
|
token=token or None,
|
|
170
213
|
)
|
|
171
214
|
|
|
172
|
-
HfFileSystem, TqdmCallback = _import_hf_file_system()
|
|
173
215
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
174
216
|
file_descriptor, temporary_path = tempfile.mkstemp(
|
|
175
217
|
prefix=f".{destination.name}.",
|
|
@@ -198,9 +240,43 @@ def _download_hf_file(
|
|
|
198
240
|
def close(self):
|
|
199
241
|
pass
|
|
200
242
|
|
|
201
|
-
callback = TqdmCallback(tqdm_cls=_CallbackProgress)
|
|
202
243
|
remote_path = f"datasets/{repo_id}/{normalized_filename}"
|
|
203
244
|
try:
|
|
245
|
+
xet_download = _import_hf_xet_download()
|
|
246
|
+
if xet_download is not None:
|
|
247
|
+
(
|
|
248
|
+
get_hf_file_metadata,
|
|
249
|
+
hf_hub_url,
|
|
250
|
+
xet_get,
|
|
251
|
+
build_hf_headers,
|
|
252
|
+
is_xet_available,
|
|
253
|
+
) = xet_download
|
|
254
|
+
if is_xet_available():
|
|
255
|
+
metadata = get_hf_file_metadata(
|
|
256
|
+
hf_hub_url(
|
|
257
|
+
repo_id=repo_id,
|
|
258
|
+
repo_type="dataset",
|
|
259
|
+
filename=normalized_filename,
|
|
260
|
+
revision=revision,
|
|
261
|
+
),
|
|
262
|
+
token=token or None,
|
|
263
|
+
)
|
|
264
|
+
if metadata.xet_file_data is not None:
|
|
265
|
+
progress = _CallbackProgress(total=metadata.size)
|
|
266
|
+
xet_get(
|
|
267
|
+
incomplete_path=Path(temporary_path),
|
|
268
|
+
xet_file_data=metadata.xet_file_data,
|
|
269
|
+
headers=build_hf_headers(token=token or None),
|
|
270
|
+
expected_size=metadata.size,
|
|
271
|
+
displayed_filename=normalized_filename,
|
|
272
|
+
_tqdm_bar=progress,
|
|
273
|
+
)
|
|
274
|
+
_ensure_not_cancelled(is_cancelled)
|
|
275
|
+
os.replace(temporary_path, destination)
|
|
276
|
+
return str(destination)
|
|
277
|
+
|
|
278
|
+
HfFileSystem, TqdmCallback = _import_hf_file_system()
|
|
279
|
+
callback = TqdmCallback(tqdm_cls=_CallbackProgress)
|
|
204
280
|
with callback:
|
|
205
281
|
HfFileSystem(token=token or None).get_file(
|
|
206
282
|
remote_path,
|
|
@@ -391,6 +467,9 @@ def _download_parquet_split_and_convert(
|
|
|
391
467
|
token: str | None = None,
|
|
392
468
|
progress_cb: ProgressCallback | None = None,
|
|
393
469
|
byte_progress_cb: ByteProgressCallback | None = None,
|
|
470
|
+
file_plan_cb: FilePlanCallback | None = None,
|
|
471
|
+
file_completed_cb: FileCompletedCallback | None = None,
|
|
472
|
+
json_ready_cb: JsonReadyCallback | None = None,
|
|
394
473
|
is_cancelled: CancelCheck | None = None,
|
|
395
474
|
) -> dict[str, Any]:
|
|
396
475
|
cleaned_repo_id = str(repo_id or "").strip()
|
|
@@ -413,16 +492,21 @@ def _download_parquet_split_and_convert(
|
|
|
413
492
|
tmp_dir = tempfile.mkdtemp(prefix="hf_parquet_dl_", dir=output_dir)
|
|
414
493
|
try:
|
|
415
494
|
if annotations_only:
|
|
495
|
+
metadata_filename = f"{cleaned_split}/metadata.parquet"
|
|
496
|
+
_emit_file_plan(file_plan_cb, [metadata_filename])
|
|
416
497
|
metadata_path = _download_hf_file(
|
|
417
498
|
hf_hub_download,
|
|
418
499
|
repo_id=cleaned_repo_id,
|
|
419
|
-
filename=
|
|
500
|
+
filename=metadata_filename,
|
|
420
501
|
revision=commit,
|
|
421
502
|
local_dir=tmp_dir,
|
|
422
503
|
token=token or None,
|
|
423
504
|
byte_progress_cb=byte_progress_cb,
|
|
424
505
|
is_cancelled=is_cancelled,
|
|
425
506
|
)
|
|
507
|
+
_emit_file_completed(
|
|
508
|
+
file_completed_cb, metadata_filename, metadata_path
|
|
509
|
+
)
|
|
426
510
|
else:
|
|
427
511
|
if byte_progress_cb is None:
|
|
428
512
|
snapshot_download(
|
|
@@ -447,9 +531,14 @@ def _download_parquet_split_and_convert(
|
|
|
447
531
|
raise FileNotFoundError(
|
|
448
532
|
f"No files found for Parquet split: {cleaned_split}"
|
|
449
533
|
)
|
|
450
|
-
|
|
534
|
+
_emit_file_plan(file_plan_cb, split_files)
|
|
535
|
+
for index, remote_path in enumerate(split_files, start=1):
|
|
451
536
|
_ensure_not_cancelled(is_cancelled)
|
|
452
|
-
|
|
537
|
+
_emit_progress(
|
|
538
|
+
progress_cb,
|
|
539
|
+
f"[{index}/{len(split_files)}] Downloading {remote_path}",
|
|
540
|
+
)
|
|
541
|
+
downloaded_path = _download_hf_file(
|
|
453
542
|
hf_hub_download,
|
|
454
543
|
repo_id=cleaned_repo_id,
|
|
455
544
|
filename=remote_path,
|
|
@@ -459,6 +548,9 @@ def _download_parquet_split_and_convert(
|
|
|
459
548
|
byte_progress_cb=byte_progress_cb,
|
|
460
549
|
is_cancelled=is_cancelled,
|
|
461
550
|
)
|
|
551
|
+
_emit_file_completed(
|
|
552
|
+
file_completed_cb, remote_path, downloaded_path
|
|
553
|
+
)
|
|
462
554
|
_ensure_not_cancelled(is_cancelled)
|
|
463
555
|
|
|
464
556
|
if annotations_only:
|
|
@@ -484,6 +576,9 @@ def _download_parquet_split_and_convert(
|
|
|
484
576
|
source_format="parquet",
|
|
485
577
|
commit=commit,
|
|
486
578
|
)
|
|
579
|
+
_emit_json_ready(
|
|
580
|
+
json_ready_cb, cleaned_split, str(output_json_path)
|
|
581
|
+
)
|
|
487
582
|
finally:
|
|
488
583
|
shutil.rmtree(tmp_dir, ignore_errors=True)
|
|
489
584
|
|
|
@@ -532,6 +627,9 @@ def _download_json_path_from_hf(
|
|
|
532
627
|
token: str | None = None,
|
|
533
628
|
progress_cb: ProgressCallback | None = None,
|
|
534
629
|
byte_progress_cb: ByteProgressCallback | None = None,
|
|
630
|
+
file_plan_cb: FilePlanCallback | None = None,
|
|
631
|
+
file_completed_cb: FileCompletedCallback | None = None,
|
|
632
|
+
json_ready_cb: JsonReadyCallback | None = None,
|
|
535
633
|
is_cancelled: CancelCheck | None = None,
|
|
536
634
|
) -> dict[str, Any]:
|
|
537
635
|
HfApi, hf_hub_download, _ = _import_hf_hub()
|
|
@@ -543,6 +641,7 @@ def _download_json_path_from_hf(
|
|
|
543
641
|
os.makedirs(output_dir, exist_ok=True)
|
|
544
642
|
_ensure_not_cancelled(is_cancelled)
|
|
545
643
|
_emit_progress(progress_cb, f"Downloading JSON from {repo_id}@{commit}: {path_in_repo}")
|
|
644
|
+
_emit_file_plan(file_plan_cb, [path_in_repo])
|
|
546
645
|
|
|
547
646
|
json_path = _download_hf_file(
|
|
548
647
|
hf_hub_download,
|
|
@@ -554,6 +653,7 @@ def _download_json_path_from_hf(
|
|
|
554
653
|
byte_progress_cb=byte_progress_cb,
|
|
555
654
|
is_cancelled=is_cancelled,
|
|
556
655
|
)
|
|
656
|
+
_emit_file_completed(file_completed_cb, path_in_repo, json_path)
|
|
557
657
|
|
|
558
658
|
_ensure_not_cancelled(is_cancelled)
|
|
559
659
|
with open(json_path, "r", encoding="utf-8") as handle:
|
|
@@ -564,6 +664,8 @@ def _download_json_path_from_hf(
|
|
|
564
664
|
except ValueError:
|
|
565
665
|
repo_paths = []
|
|
566
666
|
allow_patterns = _build_allow_patterns(repo_paths, repo_json_folder)
|
|
667
|
+
if not annotations_only:
|
|
668
|
+
_emit_file_plan(file_plan_cb, allow_patterns)
|
|
567
669
|
|
|
568
670
|
result: dict[str, Any] = {
|
|
569
671
|
"repo_id": repo_id,
|
|
@@ -580,8 +682,11 @@ def _download_json_path_from_hf(
|
|
|
580
682
|
"num_samples": len(osl_json.get("data", [])) if isinstance(osl_json.get("data"), list) else 0,
|
|
581
683
|
}
|
|
582
684
|
|
|
583
|
-
if
|
|
584
|
-
_emit_progress(
|
|
685
|
+
if not dry_run:
|
|
686
|
+
_emit_progress(
|
|
687
|
+
progress_cb,
|
|
688
|
+
"Persisting Hugging Face source metadata into downloaded JSON.",
|
|
689
|
+
)
|
|
585
690
|
hf_source_metadata = write_hf_source_metadata_to_dataset_json(
|
|
586
691
|
json_path,
|
|
587
692
|
repo_id=repo_id,
|
|
@@ -590,9 +695,12 @@ def _download_json_path_from_hf(
|
|
|
590
695
|
source_format="json",
|
|
591
696
|
commit=commit,
|
|
592
697
|
)
|
|
698
|
+
result["hf_source_metadata"] = hf_source_metadata
|
|
699
|
+
_emit_json_ready(json_ready_cb, cleaned_split, json_path)
|
|
700
|
+
|
|
701
|
+
if annotations_only:
|
|
593
702
|
result["download_kind"] = "json"
|
|
594
703
|
result["downloaded_file_count"] = 0
|
|
595
|
-
result["hf_source_metadata"] = hf_source_metadata
|
|
596
704
|
_emit_progress(progress_cb, "Annotation-only download completed.")
|
|
597
705
|
return result
|
|
598
706
|
|
|
@@ -651,7 +759,7 @@ def _download_json_path_from_hf(
|
|
|
651
759
|
for idx, full_repo_path in enumerate(allow_patterns, start=1):
|
|
652
760
|
_ensure_not_cancelled(is_cancelled)
|
|
653
761
|
_emit_progress(progress_cb, f"[{idx}/{len(allow_patterns)}] Downloading {full_repo_path}")
|
|
654
|
-
_download_hf_file(
|
|
762
|
+
downloaded_path = _download_hf_file(
|
|
655
763
|
hf_hub_download,
|
|
656
764
|
repo_id=repo_id,
|
|
657
765
|
filename=full_repo_path,
|
|
@@ -661,21 +769,13 @@ def _download_json_path_from_hf(
|
|
|
661
769
|
byte_progress_cb=byte_progress_cb,
|
|
662
770
|
is_cancelled=is_cancelled,
|
|
663
771
|
)
|
|
772
|
+
_emit_file_completed(
|
|
773
|
+
file_completed_cb, full_repo_path, downloaded_path
|
|
774
|
+
)
|
|
664
775
|
downloaded_count += 1
|
|
665
776
|
|
|
666
|
-
_emit_progress(progress_cb, "Persisting Hugging Face source metadata into downloaded JSON.")
|
|
667
|
-
hf_source_metadata = write_hf_source_metadata_to_dataset_json(
|
|
668
|
-
json_path,
|
|
669
|
-
repo_id=repo_id,
|
|
670
|
-
branch=revision,
|
|
671
|
-
split=cleaned_split,
|
|
672
|
-
source_format="json",
|
|
673
|
-
commit=commit,
|
|
674
|
-
)
|
|
675
|
-
|
|
676
777
|
result["download_kind"] = "json"
|
|
677
778
|
result["downloaded_file_count"] = downloaded_count
|
|
678
|
-
result["hf_source_metadata"] = hf_source_metadata
|
|
679
779
|
_emit_progress(progress_cb, "Download completed.")
|
|
680
780
|
return result
|
|
681
781
|
|
|
@@ -776,6 +876,9 @@ def download_dataset_splits_from_hf(
|
|
|
776
876
|
token: str | None = None,
|
|
777
877
|
progress_cb: ProgressCallback | None = None,
|
|
778
878
|
byte_progress_cb: ByteProgressCallback | None = None,
|
|
879
|
+
file_plan_cb: FilePlanCallback | None = None,
|
|
880
|
+
file_completed_cb: FileCompletedCallback | None = None,
|
|
881
|
+
json_ready_cb: JsonReadyCallback | None = None,
|
|
779
882
|
is_cancelled: CancelCheck | None = None,
|
|
780
883
|
) -> list[dict[str, Any]]:
|
|
781
884
|
cleaned_splits = [str(split or "").strip() for split in (splits or [])]
|
|
@@ -802,6 +905,9 @@ def download_dataset_splits_from_hf(
|
|
|
802
905
|
token=token,
|
|
803
906
|
progress_cb=_scoped_progress,
|
|
804
907
|
byte_progress_cb=byte_progress_cb,
|
|
908
|
+
file_plan_cb=file_plan_cb,
|
|
909
|
+
file_completed_cb=file_completed_cb,
|
|
910
|
+
json_ready_cb=json_ready_cb,
|
|
805
911
|
is_cancelled=is_cancelled,
|
|
806
912
|
)
|
|
807
913
|
results.append(result)
|
|
@@ -821,6 +927,9 @@ def download_dataset_split_from_hf(
|
|
|
821
927
|
token: str | None = None,
|
|
822
928
|
progress_cb: ProgressCallback | None = None,
|
|
823
929
|
byte_progress_cb: ByteProgressCallback | None = None,
|
|
930
|
+
file_plan_cb: FilePlanCallback | None = None,
|
|
931
|
+
file_completed_cb: FileCompletedCallback | None = None,
|
|
932
|
+
json_ready_cb: JsonReadyCallback | None = None,
|
|
824
933
|
is_cancelled: CancelCheck | None = None,
|
|
825
934
|
) -> dict[str, Any]:
|
|
826
935
|
cleaned_repo_id = str(repo_id or "").strip()
|
|
@@ -849,6 +958,9 @@ def download_dataset_split_from_hf(
|
|
|
849
958
|
token=token,
|
|
850
959
|
progress_cb=progress_cb,
|
|
851
960
|
byte_progress_cb=byte_progress_cb,
|
|
961
|
+
file_plan_cb=file_plan_cb,
|
|
962
|
+
file_completed_cb=file_completed_cb,
|
|
963
|
+
json_ready_cb=json_ready_cb,
|
|
852
964
|
is_cancelled=is_cancelled,
|
|
853
965
|
)
|
|
854
966
|
|
|
@@ -863,6 +975,9 @@ def download_dataset_split_from_hf(
|
|
|
863
975
|
token=token,
|
|
864
976
|
progress_cb=progress_cb,
|
|
865
977
|
byte_progress_cb=byte_progress_cb,
|
|
978
|
+
file_plan_cb=file_plan_cb,
|
|
979
|
+
file_completed_cb=file_completed_cb,
|
|
980
|
+
json_ready_cb=json_ready_cb,
|
|
866
981
|
is_cancelled=is_cancelled,
|
|
867
982
|
)
|
|
868
983
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.1.
|
|
3
|
+
Version: 0.3.1.dev3
|
|
4
4
|
Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
|
|
5
5
|
Author: Jeet Vora
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -392,6 +392,19 @@ The JSON records the resolved Hugging Face commit and can later be passed to
|
|
|
392
392
|
Parquet/WebDataset download always completes the local split even when a
|
|
393
393
|
metadata-only `<split>.json` already exists.
|
|
394
394
|
|
|
395
|
+
Download APIs accept `byte_progress_cb(filename, downloaded_bytes,
|
|
396
|
+
total_bytes)`. When the repository file is Xet-backed, OpenSportsLib keeps the
|
|
397
|
+
accelerated Xet transfer and adapts Xet's byte updates to this callback. It
|
|
398
|
+
falls back to classic HTTP progress when Xet is unavailable, disabled, or not
|
|
399
|
+
used by the file.
|
|
400
|
+
When byte progress is enabled, Parquet downloads also emit `[current/total]`
|
|
401
|
+
file messages through `progress_cb` so clients can present file-count progress.
|
|
402
|
+
High-level split downloads also accept `file_plan_cb(filenames)`,
|
|
403
|
+
`file_completed_cb(filename, local_path)`, and
|
|
404
|
+
`json_ready_cb(split, json_path)`. These are transfer lifecycle notifications;
|
|
405
|
+
callers remain responsible for queue policy and presentation. For non-dry-run
|
|
406
|
+
JSON datasets, pinned source metadata is persisted before `json_ready_cb` runs.
|
|
407
|
+
|
|
395
408
|
JSON uploads support partially downloaded datasets: the JSON and all
|
|
396
409
|
referenced files available locally are committed, while missing referenced
|
|
397
410
|
files are skipped and reported. Remote files not included in that commit are
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opensportslib"
|
|
7
|
-
version = "0.3.1.
|
|
7
|
+
version = "0.3.1.dev3"
|
|
8
8
|
description = "OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -70,6 +70,7 @@ def test_download_hf_file_reports_transferred_and_total_bytes(monkeypatch, tmp_p
|
|
|
70
70
|
"_import_hf_file_system",
|
|
71
71
|
lambda: (_FakeFileSystem, TqdmCallback),
|
|
72
72
|
)
|
|
73
|
+
monkeypatch.setattr(hf_transfer_module, "_import_hf_xet_download", lambda: None)
|
|
73
74
|
progress = []
|
|
74
75
|
|
|
75
76
|
result = hf_transfer_module._download_hf_file(
|
|
@@ -115,6 +116,7 @@ def test_download_hf_file_cancels_during_transfer_and_removes_partial(
|
|
|
115
116
|
"_import_hf_file_system",
|
|
116
117
|
lambda: (_FakeFileSystem, TqdmCallback),
|
|
117
118
|
)
|
|
119
|
+
monkeypatch.setattr(hf_transfer_module, "_import_hf_xet_download", lambda: None)
|
|
118
120
|
|
|
119
121
|
with pytest.raises(HfTransferCancelled):
|
|
120
122
|
hf_transfer_module._download_hf_file(
|
|
@@ -132,6 +134,62 @@ def test_download_hf_file_cancels_during_transfer_and_removes_partial(
|
|
|
132
134
|
assert list((tmp_path / "clips").glob("*.part")) == []
|
|
133
135
|
|
|
134
136
|
|
|
137
|
+
def test_download_hf_file_reports_bytes_while_using_xet(monkeypatch, tmp_path):
|
|
138
|
+
xet_file_data = object()
|
|
139
|
+
|
|
140
|
+
class _Metadata:
|
|
141
|
+
size = 6
|
|
142
|
+
|
|
143
|
+
_Metadata.xet_file_data = xet_file_data
|
|
144
|
+
|
|
145
|
+
def _fake_xet_get(**kwargs):
|
|
146
|
+
assert kwargs["xet_file_data"] is xet_file_data
|
|
147
|
+
assert kwargs["headers"] == {"authorization": "Bearer hf_test"}
|
|
148
|
+
assert kwargs["expected_size"] == 6
|
|
149
|
+
assert kwargs["displayed_filename"] == "clips/large.mp4"
|
|
150
|
+
Path(kwargs["incomplete_path"]).write_bytes(b"abcdef")
|
|
151
|
+
kwargs["_tqdm_bar"].update(2)
|
|
152
|
+
kwargs["_tqdm_bar"].update(4)
|
|
153
|
+
|
|
154
|
+
monkeypatch.setattr(
|
|
155
|
+
hf_transfer_module,
|
|
156
|
+
"_import_hf_xet_download",
|
|
157
|
+
lambda: (
|
|
158
|
+
lambda url, token: _Metadata(),
|
|
159
|
+
lambda **kwargs: "https://huggingface.test/file",
|
|
160
|
+
_fake_xet_get,
|
|
161
|
+
lambda token: {"authorization": f"Bearer {token}"},
|
|
162
|
+
lambda: True,
|
|
163
|
+
),
|
|
164
|
+
)
|
|
165
|
+
monkeypatch.setattr(
|
|
166
|
+
hf_transfer_module,
|
|
167
|
+
"_import_hf_file_system",
|
|
168
|
+
lambda: pytest.fail("classic HTTP fallback should not be used"),
|
|
169
|
+
)
|
|
170
|
+
progress = []
|
|
171
|
+
|
|
172
|
+
result = hf_transfer_module._download_hf_file(
|
|
173
|
+
pytest.fail,
|
|
174
|
+
repo_id="OpenSportsLab/repo",
|
|
175
|
+
filename="clips/large.mp4",
|
|
176
|
+
revision="pinned",
|
|
177
|
+
local_dir=str(tmp_path),
|
|
178
|
+
token="hf_test",
|
|
179
|
+
byte_progress_cb=lambda filename, current, total: progress.append(
|
|
180
|
+
(filename, current, total)
|
|
181
|
+
),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
assert result == str(tmp_path / "clips" / "large.mp4")
|
|
185
|
+
assert Path(result).read_bytes() == b"abcdef"
|
|
186
|
+
assert progress == [
|
|
187
|
+
("clips/large.mp4", 0, 6),
|
|
188
|
+
("clips/large.mp4", 2, 6),
|
|
189
|
+
("clips/large.mp4", 6, 6),
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
|
|
135
193
|
def test_download_hf_file_rejects_unsafe_destination(tmp_path):
|
|
136
194
|
with pytest.raises(ValueError, match="Unsafe Hugging Face file path"):
|
|
137
195
|
hf_transfer_module._download_hf_file(
|
|
@@ -1053,6 +1111,9 @@ def test_download_dataset_split_from_hf_json_downloads_split_json_and_all_inputs
|
|
|
1053
1111
|
]
|
|
1054
1112
|
}
|
|
1055
1113
|
downloaded = []
|
|
1114
|
+
planned = []
|
|
1115
|
+
completed = []
|
|
1116
|
+
json_ready = []
|
|
1056
1117
|
|
|
1057
1118
|
class _FakeApi:
|
|
1058
1119
|
def __init__(self, token=None):
|
|
@@ -1082,6 +1143,11 @@ def test_download_dataset_split_from_hf_json_downloads_split_json_and_all_inputs
|
|
|
1082
1143
|
"test",
|
|
1083
1144
|
str(tmp_path),
|
|
1084
1145
|
download_format="json",
|
|
1146
|
+
file_plan_cb=planned.append,
|
|
1147
|
+
file_completed_cb=lambda filename, path: completed.append(
|
|
1148
|
+
(filename, path)
|
|
1149
|
+
),
|
|
1150
|
+
json_ready_cb=lambda split, path: json_ready.append((split, path)),
|
|
1085
1151
|
)
|
|
1086
1152
|
|
|
1087
1153
|
assert downloaded == ["test.json", "test/captions.json", "test/clip_0.mp4"]
|
|
@@ -1094,6 +1160,12 @@ def test_download_dataset_split_from_hf_json_downloads_split_json_and_all_inputs
|
|
|
1094
1160
|
assert result["output_dir"] == str(expected_output_dir)
|
|
1095
1161
|
assert result["json_path"] == str(expected_output_dir / "test.json")
|
|
1096
1162
|
assert result["downloaded_file_count"] == 2
|
|
1163
|
+
assert planned == [
|
|
1164
|
+
["test.json"],
|
|
1165
|
+
["test/captions.json", "test/clip_0.mp4"],
|
|
1166
|
+
]
|
|
1167
|
+
assert [filename for filename, _path in completed] == downloaded
|
|
1168
|
+
assert json_ready == [("test", str(expected_output_dir / "test.json"))]
|
|
1097
1169
|
|
|
1098
1170
|
|
|
1099
1171
|
def test_download_dataset_split_from_hf_parquet_downloads_split_folder(monkeypatch, tmp_path):
|
|
@@ -1140,6 +1212,78 @@ def test_download_dataset_split_from_hf_parquet_downloads_split_folder(monkeypat
|
|
|
1140
1212
|
assert result["download_skipped"] is False
|
|
1141
1213
|
|
|
1142
1214
|
|
|
1215
|
+
def test_parquet_byte_download_reports_file_count_progress(monkeypatch, tmp_path):
|
|
1216
|
+
progress_messages = []
|
|
1217
|
+
downloaded = []
|
|
1218
|
+
planned = []
|
|
1219
|
+
completed = []
|
|
1220
|
+
json_ready = []
|
|
1221
|
+
|
|
1222
|
+
class _FakeApi:
|
|
1223
|
+
def __init__(self, token=None):
|
|
1224
|
+
pass
|
|
1225
|
+
|
|
1226
|
+
def repo_info(self, **kwargs):
|
|
1227
|
+
return type("_Info", (), {"sha": "pinned"})()
|
|
1228
|
+
|
|
1229
|
+
def list_repo_files(self, *args, **kwargs):
|
|
1230
|
+
return [
|
|
1231
|
+
"test/metadata.parquet",
|
|
1232
|
+
"test/shards/shard-000000.tar",
|
|
1233
|
+
]
|
|
1234
|
+
|
|
1235
|
+
def _fake_download_file(_hf_hub_download, **kwargs):
|
|
1236
|
+
downloaded.append(kwargs["filename"])
|
|
1237
|
+
return str(Path(kwargs["local_dir"]) / kwargs["filename"])
|
|
1238
|
+
|
|
1239
|
+
def _fake_conversion(**kwargs):
|
|
1240
|
+
kwargs["output_json_path"].write_text(
|
|
1241
|
+
json.dumps({"data": []}), encoding="utf-8"
|
|
1242
|
+
)
|
|
1243
|
+
return {"num_samples": 0, "extracted_media_files": 0}
|
|
1244
|
+
|
|
1245
|
+
monkeypatch.setattr(
|
|
1246
|
+
"opensportslib.tools.hf_transfer._import_hf_hub",
|
|
1247
|
+
lambda: (_FakeApi, object(), object()),
|
|
1248
|
+
)
|
|
1249
|
+
monkeypatch.setattr(
|
|
1250
|
+
"opensportslib.tools.hf_transfer._download_hf_file",
|
|
1251
|
+
_fake_download_file,
|
|
1252
|
+
)
|
|
1253
|
+
monkeypatch.setattr(
|
|
1254
|
+
"opensportslib.tools.hf_transfer.convert_parquet_to_json",
|
|
1255
|
+
_fake_conversion,
|
|
1256
|
+
)
|
|
1257
|
+
|
|
1258
|
+
download_dataset_split_from_hf(
|
|
1259
|
+
"OpenSportsLab/repo",
|
|
1260
|
+
"main",
|
|
1261
|
+
"test",
|
|
1262
|
+
str(tmp_path),
|
|
1263
|
+
download_format="parquet",
|
|
1264
|
+
progress_cb=progress_messages.append,
|
|
1265
|
+
byte_progress_cb=lambda *_args: None,
|
|
1266
|
+
file_plan_cb=planned.append,
|
|
1267
|
+
file_completed_cb=lambda filename, path: completed.append(
|
|
1268
|
+
(filename, path)
|
|
1269
|
+
),
|
|
1270
|
+
json_ready_cb=lambda split, path: json_ready.append((split, path)),
|
|
1271
|
+
)
|
|
1272
|
+
|
|
1273
|
+
assert downloaded == [
|
|
1274
|
+
"test/metadata.parquet",
|
|
1275
|
+
"test/shards/shard-000000.tar",
|
|
1276
|
+
]
|
|
1277
|
+
assert "[1/2] Downloading test/metadata.parquet" in progress_messages
|
|
1278
|
+
assert "[2/2] Downloading test/shards/shard-000000.tar" in progress_messages
|
|
1279
|
+
assert planned == [[
|
|
1280
|
+
"test/metadata.parquet",
|
|
1281
|
+
"test/shards/shard-000000.tar",
|
|
1282
|
+
]]
|
|
1283
|
+
assert [filename for filename, _path in completed] == downloaded
|
|
1284
|
+
assert json_ready == [("test", str(tmp_path / "main" / "test" / "test.json"))]
|
|
1285
|
+
|
|
1286
|
+
|
|
1143
1287
|
def test_download_dataset_split_from_hf_parquet_completes_existing_json(
|
|
1144
1288
|
monkeypatch, tmp_path
|
|
1145
1289
|
):
|
|
@@ -1196,6 +1340,7 @@ def test_json_annotations_only_downloads_json_and_persists_pinned_source(monkeyp
|
|
|
1196
1340
|
encoding="utf-8",
|
|
1197
1341
|
)
|
|
1198
1342
|
downloaded = []
|
|
1343
|
+
planned = []
|
|
1199
1344
|
|
|
1200
1345
|
class _FakeApi:
|
|
1201
1346
|
def __init__(self, token=None):
|
|
@@ -1215,9 +1360,11 @@ def test_json_annotations_only_downloads_json_and_persists_pinned_source(monkeyp
|
|
|
1215
1360
|
str(tmp_path / "output"),
|
|
1216
1361
|
download_format="json",
|
|
1217
1362
|
annotations_only=True,
|
|
1363
|
+
file_plan_cb=planned.append,
|
|
1218
1364
|
)
|
|
1219
1365
|
|
|
1220
1366
|
assert downloaded == ["test.json"]
|
|
1367
|
+
assert planned == [["test.json"]]
|
|
1221
1368
|
payload = json.loads(Path(result["json_path"]).read_text(encoding="utf-8"))
|
|
1222
1369
|
assert payload[HF_FORMAT_KEY] == "json"
|
|
1223
1370
|
assert payload[HF_COMMIT_KEY] == "pinned-json"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/examples/quickstart/basic_classification.py
RENAMED
|
File without changes
|
{opensportslib-0.3.1.dev2 → opensportslib-0.3.1.dev3}/examples/quickstart/basic_localization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|