x4d-devkit 0.50.0__tar.gz → 0.51.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/PKG-INFO +1 -1
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/pyproject.toml +1 -1
- x4d_devkit-0.51.0/tests/test_annotation_document_hash.py +111 -0
- x4d_devkit-0.51.0/tests/test_parse_equivalence.py +978 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_sdk_api.py +1 -1
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_work_session.py +13 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/annotation_contract.py +111 -15
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/core/loader.py +31 -17
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/json_contract.py +41 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/work_session.py +184 -45
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/PKG-INFO +1 -1
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/SOURCES.txt +2 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/LICENSE +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/README.md +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/setup.cfg +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_accounts.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_annotation_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_annotation_reference.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_assets_client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_boundary.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_box.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_build_info.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_category_audit.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_clean_basemap.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_clean_basemap_client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_cli_auth.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_client_json_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_client_projects.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_clip_archives.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_contract_validation.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_coordinate_frames.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_current_state.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_current_state_identity_consumers_example.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_dataset_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_dataset_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_detection_eval.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_evaluate.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_export_bundle.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_clip.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_export.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_geometry.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_groups.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_preannotation.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_reference.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_review.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_schema_upgrade.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_image_work_session.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_inference_input.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_inference_schemas.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_inference_service.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_label_schemas.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_lidar_materialization.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_loader.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_matching.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_metrics.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_models.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_platform_pose.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_preannotation_client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_project_discovery.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_reconstruction_client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_release_gate.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_roadmark_preview.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_semantic_scene_client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_semantic_scene_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_semantic_scene_independent.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_semantic_scene_native_clip.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_source_attributes.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_time_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_token.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_tracking_eval.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_training_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_transform.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_transform_chain.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_validation.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_vector_map.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_vector_map_geometry.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_vector_map_session.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/tests/test_work_session_validation_reuse.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/_image_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/accounts.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/annotation_reference.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/audit.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/build_info.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/clean_basemap.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/cli.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/_origin.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/accounts.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/annotation_reference.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/assets.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/bags.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/capabilities.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/checkpoints.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/clean_basemap.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/client.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/clip_work_sessions.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/clips.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/dataset_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_clips.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_exports.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_preannotations.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_review.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_schemas.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/image_work_sessions.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/label_schemas.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/preannotation.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/projects.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/reconstruction.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/semantic_scene.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/services.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/client/test_sets.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/consumer_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/coordinate_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/core/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/core/models.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/core/token.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/core/transform.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/current_state.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/dataset_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/dataset_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/api.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/box.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/detection.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/matching.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/metrics.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/eval/tracking.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/export_bundle.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_clip.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_export.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_geometry.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_groups.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_preannotation.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_reference.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_review.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_schema.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_schema_upgrade.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/image_work_session.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/input.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/models.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/schemas.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/service.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/inference/tasks.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/label_schema.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/lidar_materialization.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/materialize.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/project_discovery.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/roadmark_preview.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/semantic_scene_authoring.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/semantic_scene_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/time_contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/training_identity.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/validation/__init__.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/validation/contract.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/validation/platform_pose.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/validation/report.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/validation/validator.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/vector_map.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit/vector_map_geometry.py +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/dependency_links.txt +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/entry_points.txt +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/requires.txt +0 -0
- {x4d_devkit-0.50.0 → x4d_devkit-0.51.0}/x4d_devkit.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "x4d-devkit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.51.0"
|
|
8
8
|
description = "Official X-4D external SDK and CLI for datasets, platform APIs, training bridges, and automation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import hashlib
|
|
5
|
+
import random
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
import rfc8785
|
|
9
|
+
|
|
10
|
+
from tests.test_annotation_contract import _annotation
|
|
11
|
+
from x4d_devkit.annotation_contract import (
|
|
12
|
+
ANNOTATION_CONTRACT_VERSION,
|
|
13
|
+
AnnotationContractError,
|
|
14
|
+
ClipAnnotationDocument,
|
|
15
|
+
build_clip_annotations,
|
|
16
|
+
parse_clip_annotations,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_EDGE_FLOATS = (0.0, -0.0, 1e21, 1e-7, 5e-324, 1.7976931348623157e308, 0.1 + 0.2, -123.456)
|
|
20
|
+
_EDGE_TEXT = ("", "é", "雪", "\U0001f697", "a\"b\\c", "
", "\x7f")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _sha(payload) -> str:
|
|
24
|
+
return f"sha256:{hashlib.sha256(rfc8785.dumps(payload)).hexdigest()}"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _random_rows(rng: random.Random, count: int) -> list[dict]:
|
|
28
|
+
rows = []
|
|
29
|
+
for index in range(count):
|
|
30
|
+
row = _annotation(
|
|
31
|
+
f"ann-{rng.randrange(10**9):09d}-{index}",
|
|
32
|
+
f"sample-{rng.randrange(5)}",
|
|
33
|
+
instance=f"instance-{rng.randrange(4)}",
|
|
34
|
+
)
|
|
35
|
+
row["bbox_3d"]["translation"]["x"] = rng.choice(_EDGE_FLOATS)
|
|
36
|
+
row["bbox_3d"]["size"]["width"] = rng.random() * 10
|
|
37
|
+
row["attributes"] = {rng.choice(_EDGE_TEXT) or "k": rng.choice(_EDGE_TEXT)}
|
|
38
|
+
if rng.random() < 0.5:
|
|
39
|
+
row["velocity"] = {"vx": rng.choice(_EDGE_FLOATS), "vy": 0.0, "vz": -1.5}
|
|
40
|
+
rows.append(row)
|
|
41
|
+
for instance in {row["instance_token"] for row in rows}:
|
|
42
|
+
motion = rng.choice(("auto", "static", "dynamic"))
|
|
43
|
+
for row in rows:
|
|
44
|
+
if row["instance_token"] == instance:
|
|
45
|
+
row["motion"] = motion
|
|
46
|
+
return rows
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_single_pass_digests_match_full_rfc8785_canonicalization():
|
|
50
|
+
rng = random.Random(8785)
|
|
51
|
+
for count in (0, 1, 2, 17, 120):
|
|
52
|
+
document = build_clip_annotations("clip-a", "base_link", _random_rows(rng, count))
|
|
53
|
+
payload = document.to_dict()
|
|
54
|
+
revision_payload = {key: value for key, value in payload.items() if key != "annotation_revision"}
|
|
55
|
+
assert document.annotation_revision == _sha(revision_payload)
|
|
56
|
+
assert document.document_hash() == _sha(payload)
|
|
57
|
+
|
|
58
|
+
parsed = parse_clip_annotations(payload)
|
|
59
|
+
assert parsed.annotation_revision == document.annotation_revision
|
|
60
|
+
assert parsed.document_hash() == _sha(payload)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_document_hash_is_derived_for_directly_constructed_and_replaced_documents():
|
|
64
|
+
document = build_clip_annotations("clip-a", "base_link", _random_rows(random.Random(1), 9))
|
|
65
|
+
direct = ClipAnnotationDocument(
|
|
66
|
+
clip_id=document.clip_id,
|
|
67
|
+
annotation_frame_id=document.annotation_frame_id,
|
|
68
|
+
annotation_revision=document.annotation_revision,
|
|
69
|
+
annotations=document.annotations,
|
|
70
|
+
)
|
|
71
|
+
assert direct.document_hash() == document.document_hash()
|
|
72
|
+
|
|
73
|
+
replaced = dataclasses.replace(document, annotations=document.annotations[:3])
|
|
74
|
+
assert replaced.document_hash() == _sha(replaced.to_dict())
|
|
75
|
+
assert replaced.document_hash() != document.document_hash()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_document_hash_is_not_part_of_document_equality():
|
|
79
|
+
rows = _random_rows(random.Random(2), 5)
|
|
80
|
+
built = build_clip_annotations("clip-a", "base_link", rows)
|
|
81
|
+
parsed = parse_clip_annotations(built.to_dict())
|
|
82
|
+
plain = ClipAnnotationDocument(
|
|
83
|
+
clip_id=built.clip_id,
|
|
84
|
+
annotation_frame_id=built.annotation_frame_id,
|
|
85
|
+
annotation_revision=built.annotation_revision,
|
|
86
|
+
annotations=built.annotations,
|
|
87
|
+
)
|
|
88
|
+
assert built == parsed == plain
|
|
89
|
+
assert "_document_hash" not in {field.name for field in dataclasses.fields(built)}
|
|
90
|
+
assert built.to_dict()["contract_version"] == ANNOTATION_CONTRACT_VERSION
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_parse_reuses_only_documents_this_module_verified():
|
|
94
|
+
built = build_clip_annotations("clip-a", "base_link", _random_rows(random.Random(3), 4))
|
|
95
|
+
assert parse_clip_annotations(built) is built
|
|
96
|
+
assert parse_clip_annotations(parse_clip_annotations(built.to_dict())) is not built
|
|
97
|
+
|
|
98
|
+
forged = ClipAnnotationDocument(
|
|
99
|
+
clip_id=built.clip_id,
|
|
100
|
+
annotation_frame_id=built.annotation_frame_id,
|
|
101
|
+
annotation_revision="sha256:" + "0" * 64,
|
|
102
|
+
annotations=built.annotations,
|
|
103
|
+
)
|
|
104
|
+
forged.document_hash() # caching the hash must not mark the document verified
|
|
105
|
+
with pytest.raises(AnnotationContractError) as error:
|
|
106
|
+
parse_clip_annotations(forged)
|
|
107
|
+
assert error.value.code == "annotation_revision_mismatch"
|
|
108
|
+
|
|
109
|
+
replaced = dataclasses.replace(built, annotation_revision="sha256:" + "1" * 64)
|
|
110
|
+
with pytest.raises(AnnotationContractError):
|
|
111
|
+
parse_clip_annotations(replaced)
|