x4d-devkit 0.52.0rc2__tar.gz → 0.53.0rc1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/PKG-INFO +1 -1
  2. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/pyproject.toml +1 -1
  3. x4d_devkit-0.53.0rc1/tests/test_image_schema_migration.py +283 -0
  4. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_sdk_api.py +1 -1
  5. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_schemas.py +49 -1
  6. x4d_devkit-0.53.0rc1/x4d_devkit/image_schema_migration.py +550 -0
  7. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/PKG-INFO +1 -1
  8. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/SOURCES.txt +2 -0
  9. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/LICENSE +0 -0
  10. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/README.md +0 -0
  11. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/setup.cfg +0 -0
  12. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_accounts.py +0 -0
  13. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_annotation_contract.py +0 -0
  14. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_annotation_document_hash.py +0 -0
  15. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_annotation_reference.py +0 -0
  16. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_assets_client.py +0 -0
  17. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_boundary.py +0 -0
  18. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_box.py +0 -0
  19. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_build_info.py +0 -0
  20. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_category_audit.py +0 -0
  21. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_clean_basemap.py +0 -0
  22. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_clean_basemap_client.py +0 -0
  23. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_cli_auth.py +0 -0
  24. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_client_json_contract.py +0 -0
  25. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_client_projects.py +0 -0
  26. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_clip_archives.py +0 -0
  27. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_contract_validation.py +0 -0
  28. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_coordinate_frames.py +0 -0
  29. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_current_state.py +0 -0
  30. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_current_state_identity_consumers_example.py +0 -0
  31. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_dataset_contract.py +0 -0
  32. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_dataset_identity.py +0 -0
  33. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_detection_eval.py +0 -0
  34. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_evaluate.py +0 -0
  35. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_export_bundle.py +0 -0
  36. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_clip.py +0 -0
  37. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_conditional_rules.py +0 -0
  38. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_enum_set.py +0 -0
  39. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_export.py +0 -0
  40. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_geometry.py +0 -0
  41. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_groups.py +0 -0
  42. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_preannotation.py +0 -0
  43. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_reference.py +0 -0
  44. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_review.py +0 -0
  45. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_schema_upgrade.py +0 -0
  46. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_image_work_session.py +0 -0
  47. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_inference_input.py +0 -0
  48. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_inference_schemas.py +0 -0
  49. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_inference_service.py +0 -0
  50. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_label_schemas.py +0 -0
  51. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_lidar_materialization.py +0 -0
  52. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_loader.py +0 -0
  53. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_matching.py +0 -0
  54. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_metrics.py +0 -0
  55. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_models.py +0 -0
  56. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_parse_equivalence.py +0 -0
  57. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_platform_pose.py +0 -0
  58. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_preannotation_client.py +0 -0
  59. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_project_discovery.py +0 -0
  60. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_reconstruction_client.py +0 -0
  61. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_release_gate.py +0 -0
  62. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_roadmark_preview.py +0 -0
  63. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_semantic_scene_authoring.py +0 -0
  64. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_semantic_scene_client.py +0 -0
  65. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_semantic_scene_contract.py +0 -0
  66. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_semantic_scene_independent.py +0 -0
  67. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_semantic_scene_native_clip.py +0 -0
  68. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_source_attributes.py +0 -0
  69. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_time_contract.py +0 -0
  70. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_token.py +0 -0
  71. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_tracking_eval.py +0 -0
  72. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_training_identity.py +0 -0
  73. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_transform.py +0 -0
  74. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_transform_chain.py +0 -0
  75. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_validation.py +0 -0
  76. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_vector_map.py +0 -0
  77. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_vector_map_geometry.py +0 -0
  78. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_vector_map_session.py +0 -0
  79. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_work_session.py +0 -0
  80. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/tests/test_work_session_validation_reuse.py +0 -0
  81. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/__init__.py +0 -0
  82. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/_image_contract.py +0 -0
  83. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/accounts.py +0 -0
  84. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/annotation_contract.py +0 -0
  85. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/annotation_reference.py +0 -0
  86. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/audit.py +0 -0
  87. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/build_info.py +0 -0
  88. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/clean_basemap.py +0 -0
  89. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/cli.py +0 -0
  90. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/__init__.py +0 -0
  91. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/_origin.py +0 -0
  92. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/accounts.py +0 -0
  93. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/annotation_reference.py +0 -0
  94. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/assets.py +0 -0
  95. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/bags.py +0 -0
  96. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/capabilities.py +0 -0
  97. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/checkpoints.py +0 -0
  98. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/clean_basemap.py +0 -0
  99. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/client.py +0 -0
  100. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/clip_work_sessions.py +0 -0
  101. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/clips.py +0 -0
  102. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/dataset_identity.py +0 -0
  103. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_clips.py +0 -0
  104. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_exports.py +0 -0
  105. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_preannotations.py +0 -0
  106. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_review.py +0 -0
  107. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/image_work_sessions.py +0 -0
  108. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/label_schemas.py +0 -0
  109. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/preannotation.py +0 -0
  110. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/projects.py +0 -0
  111. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/reconstruction.py +0 -0
  112. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/semantic_scene.py +0 -0
  113. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/semantic_scene_authoring.py +0 -0
  114. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/services.py +0 -0
  115. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/client/test_sets.py +0 -0
  116. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/consumer_identity.py +0 -0
  117. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/coordinate_contract.py +0 -0
  118. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/core/__init__.py +0 -0
  119. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/core/loader.py +0 -0
  120. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/core/models.py +0 -0
  121. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/core/token.py +0 -0
  122. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/core/transform.py +0 -0
  123. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/current_state.py +0 -0
  124. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/dataset_contract.py +0 -0
  125. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/dataset_identity.py +0 -0
  126. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/__init__.py +0 -0
  127. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/api.py +0 -0
  128. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/box.py +0 -0
  129. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/detection.py +0 -0
  130. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/matching.py +0 -0
  131. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/metrics.py +0 -0
  132. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/eval/tracking.py +0 -0
  133. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/export_bundle.py +0 -0
  134. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_clip.py +0 -0
  135. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_export.py +0 -0
  136. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_geometry.py +0 -0
  137. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_groups.py +0 -0
  138. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_preannotation.py +0 -0
  139. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_reference.py +0 -0
  140. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_review.py +0 -0
  141. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_schema.py +0 -0
  142. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_schema_upgrade.py +0 -0
  143. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/image_work_session.py +0 -0
  144. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/__init__.py +0 -0
  145. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/input.py +0 -0
  146. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/models.py +0 -0
  147. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/schemas.py +0 -0
  148. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/service.py +0 -0
  149. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/inference/tasks.py +0 -0
  150. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/json_contract.py +0 -0
  151. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/label_schema.py +0 -0
  152. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/lidar_materialization.py +0 -0
  153. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/materialize.py +0 -0
  154. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/project_discovery.py +0 -0
  155. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/roadmark_preview.py +0 -0
  156. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/semantic_scene_authoring.py +0 -0
  157. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/semantic_scene_contract.py +0 -0
  158. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/time_contract.py +0 -0
  159. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/training_identity.py +0 -0
  160. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/validation/__init__.py +0 -0
  161. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/validation/contract.py +0 -0
  162. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/validation/platform_pose.py +0 -0
  163. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/validation/report.py +0 -0
  164. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/validation/validator.py +0 -0
  165. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/vector_map.py +0 -0
  166. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/vector_map_geometry.py +0 -0
  167. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit/work_session.py +0 -0
  168. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/dependency_links.txt +0 -0
  169. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/entry_points.txt +0 -0
  170. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/requires.txt +0 -0
  171. {x4d_devkit-0.52.0rc2 → x4d_devkit-0.53.0rc1}/x4d_devkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: x4d-devkit
3
- Version: 0.52.0rc2
3
+ Version: 0.53.0rc1
4
4
  Summary: Official X-4D external SDK and CLI for datasets, platform APIs, training bridges, and automation
5
5
  Author: windzu
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "x4d-devkit"
7
- version = "0.52.0rc2"
7
+ version = "0.53.0rc1"
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,283 @@
1
+ from copy import deepcopy
2
+ import json
3
+
4
+ import httpx
5
+ import pytest
6
+
7
+ from x4d_devkit import X4DClient
8
+ from x4d_devkit._image_contract import fingerprint
9
+ from x4d_devkit.image_clip import build_image_identity
10
+ from x4d_devkit.image_schema import (
11
+ build_image_schema_snapshot,
12
+ parse_image_schema_body,
13
+ parse_image_schema_record,
14
+ )
15
+ from x4d_devkit.image_schema_migration import (
16
+ MAPPING_CONTRACT,
17
+ ImageSchemaMigrationConflict,
18
+ build_image_schema_migration_preview,
19
+ build_image_schema_migration_receipt,
20
+ build_image_schema_migration_request,
21
+ image_schema_migration_candidate,
22
+ migrate_image_annotation,
23
+ parse_image_schema_migration_mapping,
24
+ parse_image_schema_migration_preview,
25
+ parse_image_schema_migration_request,
26
+ )
27
+ from x4d_devkit.image_schema_upgrade import additive_image_schema_changes
28
+ from tests.image_fixtures import clip_payload, line_object
29
+
30
+
31
+ def snapshot(body):
32
+ return build_image_schema_snapshot(
33
+ parse_image_schema_record(
34
+ {
35
+ "contract_version": "x4d-image-label-schema-record-v1",
36
+ "status": "active",
37
+ "body": body,
38
+ "fingerprint": parse_image_schema_body(body).identity.fingerprint,
39
+ }
40
+ )
41
+ )
42
+
43
+
44
+ def target(clip, **changes):
45
+ """Non-additive 2.0.0: whole-line `visible` becomes segment `occluded`,
46
+ `style` becomes object-only `pattern`, and lines become groupable."""
47
+ body = deepcopy(clip["label_schema"]["body"])
48
+ body["version"] = changes.get("version", "2.0.0")
49
+ body["schema_id"] = changes.get("schema_id", body["schema_id"])
50
+ line = body["categories"][0]
51
+ line["groupable"] = True
52
+ line["attributes"] = [
53
+ {
54
+ "id": "occluded",
55
+ "display_name": "Occluded",
56
+ "type": "boolean",
57
+ "required": False,
58
+ "scopes": ["segment"],
59
+ "values": [],
60
+ },
61
+ {
62
+ "id": "pattern",
63
+ "display_name": "Pattern",
64
+ "type": "enum",
65
+ "required": False,
66
+ "scopes": ["object"],
67
+ "values": [
68
+ {"id": "a", "display_name": "A"},
69
+ {"id": "b", "display_name": "B"},
70
+ ],
71
+ },
72
+ ]
73
+ return snapshot(body)
74
+
75
+
76
+ def mapping(*rules):
77
+ return {"contract_version": MAPPING_CONTRACT, "rules": list(rules)}
78
+
79
+
80
+ def rule(scope, attribute_id, value, action):
81
+ return {
82
+ "match": {
83
+ "category_id": "line",
84
+ "scope": scope,
85
+ "attribute_id": attribute_id,
86
+ "value": value,
87
+ },
88
+ "action": action,
89
+ }
90
+
91
+
92
+ def with_line(obj=None):
93
+ clip = clip_payload()
94
+ clip["image_annotation"]["objects"] = [obj or line_object()]
95
+ clip["identity"] = build_image_identity(clip)
96
+ return clip
97
+
98
+
99
+ VISIBLE_TO_RANGE = rule(
100
+ "object", "visible", False, {"kind": "range", "attribute_id": "occluded", "value": True}
101
+ )
102
+ DISCARD_STYLE = rule("segment", "style", "a", {"kind": "discard"})
103
+
104
+
105
+ def test_target_is_not_an_additive_upgrade():
106
+ clip = with_line()
107
+ with pytest.raises(ValueError):
108
+ additive_image_schema_changes(clip["label_schema"]["body"], target(clip)["body"])
109
+
110
+
111
+ def test_unused_vocabulary_needs_no_rule_and_keeps_the_annotation_bytes():
112
+ clip = with_line({**line_object(), "attributes": {}, "attribute_ranges": []})
113
+ candidate, report = image_schema_migration_candidate(clip, target(clip), mapping())
114
+ result = candidate.to_dict()
115
+ assert result["image_annotation"] == clip["image_annotation"]
116
+ assert result["identity"]["annotation_revision"] == clip["identity"]["annotation_revision"]
117
+ assert result["identity"]["source_revision"] == clip["identity"]["source_revision"]
118
+ assert result["identity"]["schema_fingerprint"] != clip["identity"]["schema_fingerprint"]
119
+ assert report == {"changes": [], "removed_ranges": [], "rule_usage": [], "carried_values": 0}
120
+
121
+
122
+ def test_every_unrepresentable_occurrence_is_listed_with_its_location():
123
+ clip = with_line()
124
+ with pytest.raises(ImageSchemaMigrationConflict) as caught:
125
+ image_schema_migration_candidate(clip, target(clip), mapping())
126
+ assert [
127
+ (row["code"], row["object_id"], row["range_id"], row["attribute_id"], row["value"])
128
+ for row in caught.value.conflicts
129
+ ] == [
130
+ ("value_unmapped", "line_a", None, "visible", False),
131
+ ("value_unmapped", "line_a", "r0", "style", "a"),
132
+ ]
133
+ assert caught.value.details["conflicts"] == caught.value.conflicts
134
+
135
+
136
+ def test_explicit_rules_convert_and_discard_while_preserving_identity_and_geometry():
137
+ clip = with_line()
138
+ rules = mapping(VISIBLE_TO_RANGE, DISCARD_STYLE)
139
+ candidate, report = image_schema_migration_candidate(clip, target(clip), rules)
140
+ result = candidate.to_dict()
141
+ before, after = clip["image_annotation"]["objects"][0], result["image_annotation"]["objects"][0]
142
+ assert {k: v for k, v in after.items() if k not in ("attributes", "attribute_ranges")} == {
143
+ k: v for k, v in before.items() if k not in ("attributes", "attribute_ranges")
144
+ }
145
+ assert after["attributes"] == {}
146
+ [added] = after["attribute_ranges"]
147
+ assert added["start_vertex_id"] == "p0" and added["end_vertex_id"] == "p1"
148
+ assert added["attributes"] == {"occluded": True}
149
+ assert report["removed_ranges"] == [{"object_id": "line_a", "range_id": "r0"}]
150
+ assert report["rule_usage"] == [1, 1]
151
+ assert [(c["kind"], c["before"], c["after"]) for c in report["changes"]] == [
152
+ ("range", False, {"attribute_id": "occluded", "value": True}),
153
+ ("discard", "a", None),
154
+ ]
155
+ for name in ("meta", "sample", "sample_data", "calibrated_sensor"):
156
+ assert result[name] == clip[name]
157
+ again, _ = image_schema_migration_candidate(clip, target(clip), rules)
158
+ assert again.to_dict() == result # deterministic range IDs
159
+
160
+
161
+ def test_draft_annotations_migrate_with_the_same_function():
162
+ clip = with_line()
163
+ draft, report = migrate_image_annotation(
164
+ clip["image_annotation"],
165
+ target_schema=target(clip)["body"],
166
+ mapping=mapping(VISIBLE_TO_RANGE, DISCARD_STYLE),
167
+ )
168
+ full, _ = image_schema_migration_candidate(
169
+ clip, target(clip), mapping(VISIBLE_TO_RANGE, DISCARD_STYLE)
170
+ )
171
+ assert draft == full.to_dict()["image_annotation"]
172
+ assert report["rule_usage"] == [1, 1]
173
+
174
+
175
+ def test_a_mapped_value_must_be_valid_in_the_target_scope():
176
+ clip = with_line()
177
+ bad = rule("segment", "style", "a", {"kind": "set", "attribute_id": "pattern", "value": "a"})
178
+ with pytest.raises(ImageSchemaMigrationConflict) as caught:
179
+ image_schema_migration_candidate(clip, target(clip), mapping(VISIBLE_TO_RANGE, bad))
180
+ assert [row["code"] for row in caught.value.conflicts] == ["mapped_value_invalid"]
181
+
182
+
183
+ def test_two_values_cannot_land_on_the_same_attribute():
184
+ obj = {**line_object(), "attributes": {"visible": False, "style": "b"}, "attribute_ranges": []}
185
+ clip = with_line(obj)
186
+ rules = mapping(
187
+ rule("object", "visible", False, {"kind": "set", "attribute_id": "pattern", "value": "a"}),
188
+ rule("object", "style", "b", {"kind": "set", "attribute_id": "pattern", "value": "b"}),
189
+ )
190
+ with pytest.raises(ImageSchemaMigrationConflict) as caught:
191
+ image_schema_migration_candidate(clip, target(clip), rules)
192
+ assert [row["code"] for row in caught.value.conflicts] == ["attribute_collision"]
193
+
194
+
195
+ @pytest.mark.parametrize(
196
+ "rules",
197
+ [
198
+ [VISIBLE_TO_RANGE, VISIBLE_TO_RANGE],
199
+ [rule("segment", "style", "a", {"kind": "range", "attribute_id": "occluded", "value": True})],
200
+ [rule("object", "visible", False, {"kind": "rename"})],
201
+ [rule("object", "visible", False, {"kind": "discard", "attribute_id": "x"})],
202
+ [rule("image", "visible", False, {"kind": "discard"})],
203
+ [rule("object", "visible", 3, {"kind": "discard"})],
204
+ ],
205
+ )
206
+ def test_mapping_grammar_is_closed(rules):
207
+ with pytest.raises(ValueError):
208
+ parse_image_schema_migration_mapping(mapping(*rules))
209
+
210
+
211
+ @pytest.mark.parametrize("change", [{"schema_id": "another"}, {"version": "1.0.0"}])
212
+ def test_migration_keeps_the_schema_id_and_advances_the_version(change):
213
+ clip = with_line({**line_object(), "attributes": {}, "attribute_ranges": []})
214
+ with pytest.raises(ValueError):
215
+ image_schema_migration_candidate(clip, target(clip, **change), mapping())
216
+
217
+
218
+ @pytest.mark.parametrize("part", ["digest", "source", "report", "usage", "mapping", "unknown"])
219
+ def test_preview_rejects_tampering_even_with_a_recomputed_fingerprint(part):
220
+ clip = with_line()
221
+ value = build_image_schema_migration_preview(
222
+ clip, target(clip), mapping(VISIBLE_TO_RANGE, DISCARD_STYLE)
223
+ ).to_dict()
224
+ if part == "source":
225
+ value["after_identity"]["components"]["sample"] = "sha256:" + "a" * 64
226
+ if part == "report":
227
+ value["report"]["changes"] = []
228
+ value["report"]["removed_ranges"] = []
229
+ value["report"]["rule_usage"] = [0, 0]
230
+ if part == "usage":
231
+ value["report"]["rule_usage"] = [1]
232
+ if part == "mapping":
233
+ value["mapping"]["rules"].append(VISIBLE_TO_RANGE)
234
+ if part == "unknown":
235
+ value["automatic_repair"] = True
236
+ value["preview_fingerprint"] = (
237
+ "sha256:" + "0" * 64
238
+ if part == "digest"
239
+ else fingerprint({k: v for k, v in value.items() if k != "preview_fingerprint"})
240
+ )
241
+ with pytest.raises(ValueError):
242
+ parse_image_schema_migration_preview(value)
243
+
244
+
245
+ def test_typed_client_verifies_the_exact_preview_and_receipt():
246
+ clip = with_line()
247
+ snap = target(clip)
248
+ rules = mapping(VISIBLE_TO_RANGE, DISCARD_STYLE)
249
+ preview = build_image_schema_migration_preview(clip, snap, rules).to_dict()
250
+ bad = {"enabled": False}
251
+
252
+ def handler(request):
253
+ body = json.loads(request.content)
254
+ if request.url.path.endswith("/image-schema-migrations/preview"):
255
+ assert body == {
256
+ "project_id": 7,
257
+ "clip_id": "clip_test",
258
+ "target_schema": snap["identity"],
259
+ "mapping": rules,
260
+ }
261
+ return httpx.Response(200, json=preview)
262
+ assert request.url.path.endswith("/image-schema-migrations/commit")
263
+ receipt = build_image_schema_migration_receipt(body).to_dict()
264
+ if bad["enabled"]:
265
+ receipt["idempotency_key"] = "other-request"
266
+ return httpx.Response(200, json=receipt)
267
+
268
+ with X4DClient("http://x4d.test", token="test") as client:
269
+ client._http.close()
270
+ client._http = httpx.Client(
271
+ base_url="http://x4d.test", transport=httpx.MockTransport(handler)
272
+ )
273
+ parsed = client.image_schemas.preview_migration(
274
+ clip=clip, target_schema=snap, mapping=rules
275
+ )
276
+ request = client.image_schemas.migration_request(parsed, "explicit-migration")
277
+ assert parse_image_schema_migration_request(request.to_dict())
278
+ receipt = client.image_schemas.commit_migration(request).to_dict()
279
+ assert receipt["identity"] == preview["after_identity"]
280
+ bad["enabled"] = True
281
+ with pytest.raises(ValueError, match="another request"):
282
+ client.image_schemas.commit_migration(request)
283
+ assert build_image_schema_migration_request(parsed, "k").to_dict()["preview"] == preview
@@ -11,7 +11,7 @@ from x4d_devkit.eval.matching import MetricData
11
11
 
12
12
 
13
13
  def test_package_version_is_current_release():
14
- assert x4d_devkit.__version__ == "0.52.0rc2"
14
+ assert x4d_devkit.__version__ == "0.53.0rc1"
15
15
 
16
16
 
17
17
  def test_loader_exposes_and_enforces_only_current_schema(tmp_path):
@@ -1,4 +1,4 @@
1
- """Separate native image registry reads and explicit admin upgrade adapters."""
1
+ """Separate native image registry reads and explicit admin upgrade/migration adapters."""
2
2
 
3
3
  from x4d_devkit._image_contract import fields, integer, require
4
4
  from x4d_devkit.image_schema import (
@@ -12,6 +12,14 @@ from x4d_devkit.image_schema_upgrade import (
12
12
  parse_image_schema_upgrade_request,
13
13
  parse_image_schema_upgrade_receipt,
14
14
  )
15
+ from x4d_devkit.image_schema_migration import (
16
+ build_image_schema_migration_preview,
17
+ build_image_schema_migration_receipt,
18
+ build_image_schema_migration_request,
19
+ parse_image_schema_migration_preview,
20
+ parse_image_schema_migration_receipt,
21
+ parse_image_schema_migration_request,
22
+ )
15
23
  from x4d_devkit.label_schema import LabelSchemaBinding
16
24
 
17
25
 
@@ -113,3 +121,43 @@ class ImageSchemasAPI:
113
121
 
114
122
  def upgrade_request(self, preview, idempotency_key):
115
123
  return build_image_schema_upgrade_request(preview, idempotency_key)
124
+
125
+ def preview_migration(self, *, clip, target_schema, mapping):
126
+ """Server preview must equal the locally computed exact migration."""
127
+ expected = build_image_schema_migration_preview(
128
+ clip, target_schema, mapping
129
+ ).to_dict()
130
+ result = parse_image_schema_migration_preview(
131
+ self._client.post(
132
+ "/image-schema-migrations/preview",
133
+ json={
134
+ "project_id": expected["project_id"],
135
+ "clip_id": expected["clip_id"],
136
+ "target_schema": target_schema["identity"],
137
+ "mapping": expected["mapping"],
138
+ },
139
+ )
140
+ )
141
+ require(
142
+ result.to_dict() == expected,
143
+ "Migration preview differs from the exact Clip, target and mapping",
144
+ "image_schemas.migration_preview",
145
+ )
146
+ return result
147
+
148
+ def commit_migration(self, request):
149
+ body = parse_image_schema_migration_request(
150
+ request.to_dict() if hasattr(request, "to_dict") else request
151
+ ).to_dict()
152
+ result = parse_image_schema_migration_receipt(
153
+ self._client.post("/image-schema-migrations/commit", json=body)
154
+ )
155
+ require(
156
+ result.to_dict() == build_image_schema_migration_receipt(body).to_dict(),
157
+ "Migration receipt belongs to another request",
158
+ "image_schemas.migration_receipt",
159
+ )
160
+ return result
161
+
162
+ def migration_request(self, preview, idempotency_key):
163
+ return build_image_schema_migration_request(preview, idempotency_key)