spatialdds 0.7.3__tar.gz → 0.7.4__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.
- {spatialdds-0.7.3 → spatialdds-0.7.4}/PKG-INFO +19 -3
- {spatialdds-0.7.3 → spatialdds-0.7.4}/README.md +18 -2
- {spatialdds-0.7.3 → spatialdds-0.7.4}/pyproject.toml +1 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/__init__.py +1 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/openapi.html +1 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/openapi.yaml +1 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/__init__.py +2 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/_participant.py +56 -8
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/codec.py +8 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/record.py +5 -2
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/records.py +9 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/serve.py +6 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/gateway.py +19 -2
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/gw_http.py +13 -2
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/idlmodel.py +36 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/mcapmeta.py +5 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/pin.py +1 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/webjson.py +127 -1
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/PKG-INFO +19 -3
- {spatialdds-0.7.3 → spatialdds-0.7.4}/setup.cfg +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/anchors.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/argeo.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/common.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/core.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/discovery.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/events.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/lidar.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/mapping.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/provisional/owm.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/provisional/radio.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/provisional/rf_beam.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/rad.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/semantics.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/slam_frontend.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/types.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/vio.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/idl/vision.idl +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/registry.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/builtin_Time.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_anchors_AnchorDelta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_anchors_AnchorEntry.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_anchors_AnchorSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_anchors_AnchorSetRequest.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_anchors_AnchorSetResponse.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_argeo_NodeGeo.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_argeo_QualityRequirements.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_argeo_VpsRequest.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_argeo_VpsResponse.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_common_AssetRef.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_common_FrameRef.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_common_KV.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_common_MetaKV.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_common_Vec2.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_Aabb3.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_BlobChunk.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_BlobRef.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_ComponentRef.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_Edge.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_EntityBinding.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_FrameTransform.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_FramedPose.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_GeoAnchor.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_GeoPose.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_NavSatStatus.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_Node.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_PlannedTrajectory.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_PlannedWaypoint.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_PoseSE3.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_SnapshotRequest.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_SnapshotResponse.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_TileKey.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_TileMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_core_TilePatch.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_Announce.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_Capabilities.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_ContentAnnounce.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_CoverageElement.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_CoverageFilter.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_CoverageHint.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_CoverageQuery.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_CoverageResponse.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_Depart.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_KV.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_ProfileSupport.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_ServiceSummary.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_TopicMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_Transform.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_disco_ValidityWindow.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_events_CrossingLine.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_events_SpatialEvent.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_events_SpatialZone.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_events_ZoneState.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_mapping_Edge.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_mapping_MapAlignment.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_mapping_MapEvent.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_mapping_MapMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_mapping_MapQuality.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_owm_Entity.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_owm_ModelCommand.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_owm_ModelPose.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_Detection2D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_Detection2DSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_Detection3D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_Detection3DSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_FusedTrack.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_FusedTrackSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_Keypoint3D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_semantics_KeypointLink.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_Axis.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_FrameHeader.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_FrameQuality.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_Linspace.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_ROI.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_ROIReply.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_ROIRequest.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_common_StreamMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_lidar_LidarDetection.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_lidar_LidarDetectionSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_lidar_LidarFrame.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_lidar_LidarMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rad_RadDetection.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rad_RadDetectionSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rad_RadSensorMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rad_RadTensorFrame.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rad_RadTensorMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_radio_RadioObservation.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_radio_RadioScan.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_radio_RadioSensorMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rf_beam_RfBeamArraySet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rf_beam_RfBeamFrame.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_rf_beam_RfBeamMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_CamIntrinsics.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_Keypoint2D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_Track2D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_VisionDetections.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_VisionFrame.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_sensing_vision_VisionMeta.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_CameraInfo.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_Feature2D.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_FeatureMatch.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_KeyframeFeatures.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_Landmark.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_MatchSet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_TrackObs.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_slam_frontend_Tracklet.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_vio_FusedState.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_vio_ImuInfo.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_vio_ImuSample.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_vio_MagnetometerSample.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/schemas/spatial_vio_SensorFusionSample.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/artifacts/serializer_tables.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/canonical.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/canonjson.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/client.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/_extra.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/blob.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/qos.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/registry.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/_field_aliases.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/builtin/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/builtin/_types.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/anchors/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/anchors/_anchors.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/argeo/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/argeo/_argeo.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/common/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/common/_types.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/core/GnssService/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/core/GnssService/_core.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/core/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/core/_core.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/disco/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/disco/_discovery.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/crossing_direction_enum/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/crossing_direction_enum/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/event_state_enum/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/event_state_enum/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/event_type_enum/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/event_type_enum/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/severity_enum/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/severity_enum/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/zone_kind_enum/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/events/enums/zone_kind_enum/_events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/alignment_method/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/alignment_method/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/edge_type/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/edge_type/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_event_kind/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_event_kind/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_kind/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_kind/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_status/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/mapping/enums/map_status/_mapping.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/owm/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/owm/_owm.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/semantics/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/semantics/_semantics.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/common/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/common/_common.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/lidar/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/lidar/_lidar.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/rad/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/rad/_rad.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/radio/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/radio/_radio.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/rf_beam/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/rf_beam/_rf_beam.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/vision/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/sensing/vision/_vision.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/slam_frontend/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/slam_frontend/_slam_frontend.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/vio/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/dds/types/spatial/vio/_vio.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/assets/duck.gltf +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/assets/fountain-label.txt +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/assets/fountain-marker.gltf +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/fountain-anchors.mcap +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/manifests/content-fountain-label.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/demo/manifests/content-fountain-marker.json +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/errors.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/events.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/frames.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/journal.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/recency.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/__init__.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/commands.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/limits.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/publish.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/tenancy.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/server/xcdr2.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds/tokens.py +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/SOURCES.txt +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/dependency_links.txt +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/entry_points.txt +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/requires.txt +0 -0
- {spatialdds-0.7.3 → spatialdds-0.7.4}/spatialdds.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatialdds
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: SpatialDDS for programs: a client for the web binding (Appendix N), a native DDS participant, and the reference registry behind one command.
|
|
5
5
|
Author: Open AR Cloud
|
|
6
6
|
License: Apache-2.0
|
|
@@ -114,7 +114,7 @@ What it asks of you, and what it will not guess:
|
|
|
114
114
|
| `service_id` and `authority` | to write or announce |
|
|
115
115
|
| `qos_profile` | where the §3.3.2 row names none, as `model_entity`'s and `model_pose`'s do; the refusal lists the §3.3.3 profiles that fit, or pass a `sd.dds.Profile(...)` extension |
|
|
116
116
|
| `on_exit="keep"` or `"withdraw"` | on every latched, keyed writer: whether a record outlives its writer is a claim only you can make |
|
|
117
|
-
| `withdraw(key, reason
|
|
117
|
+
| `withdraw(key, reason=..., **changes)` | with an empty reason, or a change to the members it sets itself or to the key |
|
|
118
118
|
|
|
119
119
|
And what it does without being asked:
|
|
120
120
|
|
|
@@ -602,6 +602,22 @@ explicitly was tried first and is what missed two paths.
|
|
|
602
602
|
|
|
603
603
|
If your clients are not browsers, nothing here changes anything for you.
|
|
604
604
|
|
|
605
|
+
## New in 0.7.4: what the first extension found
|
|
606
|
+
|
|
607
|
+
A deployment's own type, registered with `sd.dds.extend()`, is now served
|
|
608
|
+
the way a pinned one is. The gateway publishes a schema for it, written from
|
|
609
|
+
the model it decodes the type with by the specification generator's rules,
|
|
610
|
+
because N.2 requires a schema for every type an endpoint serves. A
|
|
611
|
+
recording's extension lane is served latched when its writer opened it so,
|
|
612
|
+
and `serve --public FQN` opens it to uncredentialed readers.
|
|
613
|
+
|
|
614
|
+
- `withdraw(key, reason=..., **changes)` sets other members on the terminal
|
|
615
|
+
sample, such as a closed validity interval.
|
|
616
|
+
- `close()` finishes when a reader is slow to acknowledge (cyclonedds-python
|
|
617
|
+
11.0.1 raised on that timeout).
|
|
618
|
+
- `sd.stamp` keeps `nanosec` in range, and floors a time before the epoch.
|
|
619
|
+
- `sd.dds.extensions()` and `sd.dds.extension_of()` are exported.
|
|
620
|
+
|
|
605
621
|
## New in 0.7.3: what the first migration found
|
|
606
622
|
|
|
607
623
|
Mostly additive; one fix changes bytes. Every frame this package builds now
|
|
@@ -679,7 +695,7 @@ Two changes may need a line of yours:
|
|
|
679
695
|
The security fixes, the limits table and the details are in the
|
|
680
696
|
[changelog](https://github.com/OpenArCloud/spatialdds-py/blob/main/lib/spatialdds/CHANGELOG.md).
|
|
681
697
|
|
|
682
|
-
## Not in 0.7.
|
|
698
|
+
## Not in 0.7.4
|
|
683
699
|
|
|
684
700
|
Stated so nobody waits for them:
|
|
685
701
|
|
|
@@ -86,7 +86,7 @@ What it asks of you, and what it will not guess:
|
|
|
86
86
|
| `service_id` and `authority` | to write or announce |
|
|
87
87
|
| `qos_profile` | where the §3.3.2 row names none, as `model_entity`'s and `model_pose`'s do; the refusal lists the §3.3.3 profiles that fit, or pass a `sd.dds.Profile(...)` extension |
|
|
88
88
|
| `on_exit="keep"` or `"withdraw"` | on every latched, keyed writer: whether a record outlives its writer is a claim only you can make |
|
|
89
|
-
| `withdraw(key, reason
|
|
89
|
+
| `withdraw(key, reason=..., **changes)` | with an empty reason, or a change to the members it sets itself or to the key |
|
|
90
90
|
|
|
91
91
|
And what it does without being asked:
|
|
92
92
|
|
|
@@ -574,6 +574,22 @@ explicitly was tried first and is what missed two paths.
|
|
|
574
574
|
|
|
575
575
|
If your clients are not browsers, nothing here changes anything for you.
|
|
576
576
|
|
|
577
|
+
## New in 0.7.4: what the first extension found
|
|
578
|
+
|
|
579
|
+
A deployment's own type, registered with `sd.dds.extend()`, is now served
|
|
580
|
+
the way a pinned one is. The gateway publishes a schema for it, written from
|
|
581
|
+
the model it decodes the type with by the specification generator's rules,
|
|
582
|
+
because N.2 requires a schema for every type an endpoint serves. A
|
|
583
|
+
recording's extension lane is served latched when its writer opened it so,
|
|
584
|
+
and `serve --public FQN` opens it to uncredentialed readers.
|
|
585
|
+
|
|
586
|
+
- `withdraw(key, reason=..., **changes)` sets other members on the terminal
|
|
587
|
+
sample, such as a closed validity interval.
|
|
588
|
+
- `close()` finishes when a reader is slow to acknowledge (cyclonedds-python
|
|
589
|
+
11.0.1 raised on that timeout).
|
|
590
|
+
- `sd.stamp` keeps `nanosec` in range, and floors a time before the epoch.
|
|
591
|
+
- `sd.dds.extensions()` and `sd.dds.extension_of()` are exported.
|
|
592
|
+
|
|
577
593
|
## New in 0.7.3: what the first migration found
|
|
578
594
|
|
|
579
595
|
Mostly additive; one fix changes bytes. Every frame this package builds now
|
|
@@ -651,7 +667,7 @@ Two changes may need a line of yours:
|
|
|
651
667
|
The security fixes, the limits table and the details are in the
|
|
652
668
|
[changelog](https://github.com/OpenArCloud/spatialdds-py/blob/main/lib/spatialdds/CHANGELOG.md).
|
|
653
669
|
|
|
654
|
-
## Not in 0.7.
|
|
670
|
+
## Not in 0.7.4
|
|
655
671
|
|
|
656
672
|
Stated so nobody waits for them:
|
|
657
673
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "spatialdds"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.4"
|
|
8
8
|
description = "SpatialDDS for programs: a client for the web binding (Appendix N), a native DDS participant, and the reference registry behind one command."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -41,7 +41,7 @@ __all__ = [
|
|
|
41
41
|
"participant", "MissingExtra", "dds", "events", "frames", "Recency",
|
|
42
42
|
]
|
|
43
43
|
|
|
44
|
-
__version__ = "0.7.
|
|
44
|
+
__version__ = "0.7.4"
|
|
45
45
|
#: The SpatialDDS-spec commit whose Appendix N and generated artifacts this
|
|
46
46
|
#: package implements. Package versions and specification versions move
|
|
47
47
|
#: independently; this is the one that says what the wire looks like.
|
|
@@ -14,4 +14,4 @@ border-bottom:1px solid var(--line)}p{margin:.35rem 0}.mut,.sum .auth{color:
|
|
|
14
14
|
var(--mut)}.auth{font-size:.85rem;margin-left:.4rem}.v{display:inline-block;
|
|
15
15
|
min-width:4.2rem;font:600 12px ui-monospace,monospace;letter-spacing:.04em;
|
|
16
16
|
color:var(--acc)}.codes{font:12px ui-monospace,monospace;color:var(--mut)}
|
|
17
|
-
.s{margin-right:.5rem}.s4,.s5{color:#b5482c}a{color:var(--acc)}</style></head><body><main><h1>SpatialDDS web binding (spatialdds-py)</h1><p class=mut>Version 0.7.3 · OpenAPI 3.1.0 · generated, never hand-written · <a href='openapi'>openapi.yaml</a></p><p>Generated by <code>tools/gen_openapi.py</code> from the gateway's own tables and the published JSON Schemas; never edited by hand. Reads are open; writes take a bearer token scoped to scenes. The WebSocket streams (N.5) are described on each collection path, not modelled.</p><h2>Operations</h2><section id="search"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/search</code></h3><p class="sum">Services near a geohash (§8.2.3 manifests) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="searchPost"><h3><span class="v post">POST</span> <code>/.well-known/spatialdds/search</code></h3><p class="sum">The same search, as a POST body <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="listSchemas"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/schemas</code></h3><p class="sum">The published JSON Schemas, by type <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="getSchema"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/schemas/{type}</code></h3><p class="sum"> <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="bootstrap"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/bootstrap</code></h3><p class="sum">DDS-join material (N.2); optional <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="resolverMetadata"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/resolver</code></h3><p class="sum">§7.5.2 resolver metadata <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="openapi"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/openapi</code></h3><p class="sum">This document <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="openapiPage"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/openapi.html</code></h3><p class="sum">This document as a static reference page <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="resolve"><h3><span class="v get">GET</span> <code>/spatialdds/resolve</code></h3><p class="sum">Resolve a URI to its manifest (§7.5.2) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">400</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putManifest"><h3><span class="v put">PUT</span> <code>/spatialdds/resolve</code></h3><p class="sum">Publish a manifest, keyed by its own <code>id</code> <span class="auth">token</span></p><p>The <code>uri</code> parameter is not used; the body's <code>id</code> is the key. Its scene segment is the lane. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>).</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawManifest"><h3><span class="v delete">DELETE</span> <code>/spatialdds/resolve</code></h3><p class="sum">Withdraw a manifest; <code>resolve</code> then answers 404 <span class="auth">token</span></p><p>Owner-checked by the URI's scene segment. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>).</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="getAsset"><h3><span class="v get">GET</span> <code>/assets/{name}</code></h3><p class="sum">Asset bytes this endpoint hosts (implementation-defined) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="listAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/announce/v1</code></h3><p class="sum">Every spatial.disco.Announce instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandAnnounce"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/announce/v1</code></h3><p class="sum">An N.6 command addressed through the announce lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">One spatial.disco.Announce instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putAnnounce"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.disco.Announce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawAnnounce"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.disco.Announce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listContentAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/content_announce/v1</code></h3><p class="sum">Every spatial.disco.ContentAnnounce instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandContentAnnounce"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/content_announce/v1</code></h3><p class="sum">An N.6 command addressed through the content_announce lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getContentAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">One spatial.disco.ContentAnnounce instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putContentAnnounce"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.disco.ContentAnnounce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawContentAnnounce"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.disco.ContentAnnounce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listGeoAnchor"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/geo_anchor/v1</code></h3><p class="sum">Every spatial.core.GeoAnchor instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandGeoAnchor"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/geo_anchor/v1</code></h3><p class="sum">An N.6 command addressed through the geo_anchor lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getGeoAnchor"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">One spatial.core.GeoAnchor instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putGeoAnchor"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.core.GeoAnchor <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawGeoAnchor"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.core.GeoAnchor <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listInstances"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/{type}/{version}</code></h3><p class="sum">Any other served topic, read-only <span class="auth">token for operator-scoped</span></p><p>Latched types answer with the latched set; streamed types with the replayed window. Public or operator-scoped per the type: <code>spatial.core.FrameTransform</code> latched public, <code>spatial.events.CrossingLine</code> latched public, <code>spatial.events.SpatialEvent</code> stream bearer, <code>spatial.events.SpatialZone</code> latched public, <code>spatial.owm.Entity</code> latched bearer, <code>spatial.owm.ModelPose</code> stream bearer, <code>spatial.semantics.Detection2DSet</code> stream bearer, <code>spatial.semantics.Detection3DSet</code> stream bearer, <code>spatial.semantics.FusedTrackSet</code> stream bearer. **The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listWellKnownInstances"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/{stream}/{type}/{version}</code></h3><p class="sum">A four-segment topic's collection <span class="auth">token for operator-scoped</span></p><p>A four-segment topic (<code>spatialdds/<stream>/<type>/<version></code>, no scene), such as the discovery announce lane, served exactly as a scene-scoped collection is: latched set, <code>ETag</code>, <code>304</code>, the same access classes, and the N.5 stream by upgrading the same path. Read-only: a topic with no scene is in no lane. **The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="getWellKnownInstance"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/{stream}/{type}/{version}/{key}</code></h3><p class="sum">One instance of a four-segment topic <span class="auth">token for operator-scoped</span></p><p>A four-segment topic (<code>spatialdds/<stream>/<type>/<version></code>, no scene), such as the discovery announce lane, served exactly as a scene-scoped collection is: latched set, <code>ETag</code>, <code>304</code>, the same access classes, and the N.5 stream by upgrading the same path. Read-only: a topic with no scene is in no lane. </p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><h2>Schemas</h2><p class=mut>115 components, from the published JSON Schemas at <code>/.well-known/spatialdds/schemas</code>.</p></main></body></html>
|
|
17
|
+
.s{margin-right:.5rem}.s4,.s5{color:#b5482c}a{color:var(--acc)}</style></head><body><main><h1>SpatialDDS web binding (spatialdds-py)</h1><p class=mut>Version 0.7.4 · OpenAPI 3.1.0 · generated, never hand-written · <a href='openapi'>openapi.yaml</a></p><p>Generated by <code>tools/gen_openapi.py</code> from the gateway's own tables and the published JSON Schemas; never edited by hand. Reads are open; writes take a bearer token scoped to scenes. The WebSocket streams (N.5) are described on each collection path, not modelled.</p><h2>Operations</h2><section id="search"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/search</code></h3><p class="sum">Services near a geohash (§8.2.3 manifests) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="searchPost"><h3><span class="v post">POST</span> <code>/.well-known/spatialdds/search</code></h3><p class="sum">The same search, as a POST body <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="listSchemas"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/schemas</code></h3><p class="sum">The published JSON Schemas, by type <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="getSchema"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/schemas/{type}</code></h3><p class="sum"> <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="bootstrap"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/bootstrap</code></h3><p class="sum">DDS-join material (N.2); optional <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="resolverMetadata"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/resolver</code></h3><p class="sum">§7.5.2 resolver metadata <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="openapi"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/openapi</code></h3><p class="sum">This document <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="openapiPage"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/openapi.html</code></h3><p class="sum">This document as a static reference page <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">429</span></p></section><section id="resolve"><h3><span class="v get">GET</span> <code>/spatialdds/resolve</code></h3><p class="sum">Resolve a URI to its manifest (§7.5.2) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">400</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putManifest"><h3><span class="v put">PUT</span> <code>/spatialdds/resolve</code></h3><p class="sum">Publish a manifest, keyed by its own <code>id</code> <span class="auth">token</span></p><p>The <code>uri</code> parameter is not used; the body's <code>id</code> is the key. Its scene segment is the lane. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>).</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawManifest"><h3><span class="v delete">DELETE</span> <code>/spatialdds/resolve</code></h3><p class="sum">Withdraw a manifest; <code>resolve</code> then answers 404 <span class="auth">token</span></p><p>Owner-checked by the URI's scene segment. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>).</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="getAsset"><h3><span class="v get">GET</span> <code>/assets/{name}</code></h3><p class="sum">Asset bytes this endpoint hosts (implementation-defined) <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="listAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/announce/v1</code></h3><p class="sum">Every spatial.disco.Announce instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandAnnounce"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/announce/v1</code></h3><p class="sum">An N.6 command addressed through the announce lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">One spatial.disco.Announce instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putAnnounce"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.disco.Announce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawAnnounce"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/announce/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.disco.Announce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listContentAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/content_announce/v1</code></h3><p class="sum">Every spatial.disco.ContentAnnounce instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandContentAnnounce"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/content_announce/v1</code></h3><p class="sum">An N.6 command addressed through the content_announce lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getContentAnnounce"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">One spatial.disco.ContentAnnounce instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putContentAnnounce"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.disco.ContentAnnounce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawContentAnnounce"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/content_announce/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.disco.ContentAnnounce <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listGeoAnchor"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/geo_anchor/v1</code></h3><p class="sum">Every spatial.core.GeoAnchor instance in the latched set <span class="auth">open</span></p><p>**The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="commandGeoAnchor"><h3><span class="v post">POST</span> <code>/{scene}/{stream}/geo_anchor/v1</code></h3><p class="sum">An N.6 command addressed through the geo_anchor lane <span class="auth">token</span></p><p>Accepted only on a lane whose topic advertises <code>accepts_commands</code>; otherwise <code>405</code>. **Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch.</p><p class="codes"><span class="s s2">202</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">409</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span></p></section><section id="getGeoAnchor"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">One spatial.core.GeoAnchor instance <span class="auth">open</span></p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">404</span> <span class="s s4">429</span></p></section><section id="putGeoAnchor"><h3><span class="v put">PUT</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">Publish or replace a spatial.core.GeoAnchor <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). Every member of the record is required: a body is a whole record, never a patch. The body's key must equal the URL's. <code>If-Match</code> is honoured when present.</p><p class="codes"><span class="s s2">200</span> <span class="s s2">201</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">405</span> <span class="s s4">412</span> <span class="s s4">429</span> <span class="s s4">413</span> <span class="s s4">415</span> <span class="s s5">503</span></p></section><section id="withdrawGeoAnchor"><h3><span class="v delete">DELETE</span> <code>/{scene}/{stream}/geo_anchor/v1/{key}</code></h3><p class="sum">Withdraw (dispose) a spatial.core.GeoAnchor <span class="auth">token</span></p><p>**Writes are per lane.** The path's first segment is the scene; the bearer token must be granted it (<code>tenancy.WRITE_REFUSALS</code>). The dispose streams on the collection's WebSocket with its <code>reason</code>.</p><p class="codes"><span class="s s2">204</span> <span class="s s4">400</span> <span class="s s4">401</span> <span class="s s4">403</span> <span class="s s4">404</span> <span class="s s4">405</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listInstances"><h3><span class="v get">GET</span> <code>/{scene}/{stream}/{type}/{version}</code></h3><p class="sum">Any other served topic, read-only <span class="auth">token for operator-scoped</span></p><p>Latched types answer with the latched set; streamed types with the replayed window. Public or operator-scoped per the type: <code>spatial.core.FrameTransform</code> latched public, <code>spatial.events.CrossingLine</code> latched public, <code>spatial.events.SpatialEvent</code> stream bearer, <code>spatial.events.SpatialZone</code> latched public, <code>spatial.owm.Entity</code> latched bearer, <code>spatial.owm.ModelPose</code> stream bearer, <code>spatial.semantics.Detection2DSet</code> stream bearer, <code>spatial.semantics.Detection3DSet</code> stream bearer, <code>spatial.semantics.FusedTrackSet</code> stream bearer. **The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="listWellKnownInstances"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/{stream}/{type}/{version}</code></h3><p class="sum">A four-segment topic's collection <span class="auth">token for operator-scoped</span></p><p>A four-segment topic (<code>spatialdds/<stream>/<type>/<version></code>, no scene), such as the discovery announce lane, served exactly as a scene-scoped collection is: latched set, <code>ETag</code>, <code>304</code>, the same access classes, and the N.5 stream by upgrading the same path. Read-only: a topic with no scene is in no lane. **The same URL is also a WebSocket** (N.5): connect with <code>wss://</code> and receive the latched set as <code>sample</code> events, exactly one <code>end_of_replay</code> carrying the replay count, then live <code>sample</code> and <code>dispose</code> events (<code>{event, topic, key, data | reason}</code>). Not modelled here; see [Appendix N.5](https://spatialdds.org/v1.8/appendix-n/).</p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><section id="getWellKnownInstance"><h3><span class="v get">GET</span> <code>/.well-known/spatialdds/{stream}/{type}/{version}/{key}</code></h3><p class="sum">One instance of a four-segment topic <span class="auth">token for operator-scoped</span></p><p>A four-segment topic (<code>spatialdds/<stream>/<type>/<version></code>, no scene), such as the discovery announce lane, served exactly as a scene-scoped collection is: latched set, <code>ETag</code>, <code>304</code>, the same access classes, and the N.5 stream by upgrading the same path. Read-only: a topic with no scene is in no lane. </p><p class="codes"><span class="s s2">200</span> <span class="s s3">304</span> <span class="s s4">401</span> <span class="s s4">404</span> <span class="s s4">429</span> <span class="s s5">503</span></p></section><h2>Schemas</h2><p class=mut>115 components, from the published JSON Schemas at <code>/.well-known/spatialdds/schemas</code>.</p></main></body></html>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
openapi: 3.1.0
|
|
3
3
|
info:
|
|
4
4
|
title: SpatialDDS web binding (spatialdds-py)
|
|
5
|
-
version: 0.7.
|
|
5
|
+
version: 0.7.4
|
|
6
6
|
summary: SpatialDDS 1.8 Appendix N over HTTPS, plus this endpoint's write surface.
|
|
7
7
|
description: Generated by `tools/gen_openapi.py` from the gateway's own tables and the published JSON Schemas; never edited by hand. Reads are open; writes take a bearer token scoped to scenes. The WebSocket streams (N.5) are described on each collection path, not modelled.
|
|
8
8
|
servers:
|
|
@@ -30,7 +30,7 @@ __all__ = [
|
|
|
30
30
|
"ON_EXIT", "DOMAIN_ENV",
|
|
31
31
|
"to_json", "from_json", "validate", "SchemaInvalid", "WireError",
|
|
32
32
|
"fqn_of", "key_of",
|
|
33
|
-
"class_for", "extend", "Extension",
|
|
33
|
+
"class_for", "extend", "Extension", "extensions", "extension_of",
|
|
34
34
|
"registry", "Profile", "RegistryError", "topic_name",
|
|
35
35
|
"ANNOUNCE", "DEPART", "CONTENT", "QUERY", "COVERAGE_HINT",
|
|
36
36
|
"Recorder", "chunk", "Reassembler", "CorruptChunk", "blob_ref",
|
|
@@ -53,6 +53,7 @@ _FROM = {
|
|
|
53
53
|
"to_json": "codec", "from_json": "codec", "validate": "codec",
|
|
54
54
|
"SchemaInvalid": "codec", "WireError": "codec", "fqn_of": "codec", "key_of": "codec",
|
|
55
55
|
"class_for": "codec", "extend": "codec", "Extension": "codec",
|
|
56
|
+
"extensions": "codec", "extension_of": "codec",
|
|
56
57
|
"Profile": "registry", "RegistryError": "registry",
|
|
57
58
|
"topic_name": "registry",
|
|
58
59
|
"Recorder": "record",
|
|
@@ -109,6 +109,28 @@ def _now_time():
|
|
|
109
109
|
return Time(sec=int(t), nanosec=int((t % 1) * 1e9))
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
def _wait_for_acks(dw: Any, timeout_s: float, what: str) -> bool:
|
|
113
|
+
"""`DataWriter.wait_for_acks`, False on timeout, as it is documented.
|
|
114
|
+
|
|
115
|
+
cyclonedds-python 11.0.1's timeout branch reads
|
|
116
|
+
`Exception.DDS_RETCODE_TIMEOUT`, which does not exist (`cyclonedds/pub.py`
|
|
117
|
+
line 325), so every timeout raises AttributeError. `close()` awaits acks
|
|
118
|
+
after writing each dispose and Depart, so one slow peer made a clean stop
|
|
119
|
+
exit with a traceback and skip the remaining flushes and every recorder's
|
|
120
|
+
`flush()` (S17). That AttributeError, and only that one, is the timeout.
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
acked = bool(dw.wait_for_acks(duration(seconds=timeout_s)))
|
|
124
|
+
except AttributeError as error:
|
|
125
|
+
if "DDS_RETCODE_TIMEOUT" not in str(error):
|
|
126
|
+
raise
|
|
127
|
+
acked = False
|
|
128
|
+
if not acked:
|
|
129
|
+
log.warning("%s: not every reader acknowledged within %.1f s",
|
|
130
|
+
what, timeout_s)
|
|
131
|
+
return acked
|
|
132
|
+
|
|
133
|
+
|
|
112
134
|
def _has_member(sample: Any, name: str) -> bool:
|
|
113
135
|
return any(f.name == name for f in dataclasses.fields(sample))
|
|
114
136
|
|
|
@@ -275,7 +297,8 @@ class Writer:
|
|
|
275
297
|
with self._lock:
|
|
276
298
|
self._dw.write(sample)
|
|
277
299
|
self._last[key] = sample
|
|
278
|
-
self._p._recorded(self.topic, self._lane.fqn, sample
|
|
300
|
+
self._p._recorded(self.topic, self._lane.fqn, sample,
|
|
301
|
+
self._lane.profile.durability)
|
|
279
302
|
return sample
|
|
280
303
|
|
|
281
304
|
def _terminal(self, sample: Any, reason: str) -> Any:
|
|
@@ -298,27 +321,51 @@ class Writer:
|
|
|
298
321
|
changes["stamp"] = _now_time()
|
|
299
322
|
return dataclasses.replace(sample, **changes) if changes else sample
|
|
300
323
|
|
|
301
|
-
def withdraw(self, key: str, *, reason: str) -> None:
|
|
324
|
+
def withdraw(self, key: str, *, reason: str, **changes: Any) -> None:
|
|
302
325
|
"""Remove an instance: its terminal sample, then the dispose (§2.14, N.5.2).
|
|
303
326
|
|
|
304
327
|
`reason` is required and may not be empty. It is carried wherever a
|
|
305
328
|
carrier exists: the type's own member when it has one, the recording's
|
|
306
329
|
dispose metadata always, and this layer's log always.
|
|
330
|
+
|
|
331
|
+
`changes` are the type's other members as the terminal sample should
|
|
332
|
+
carry them, such as a validity interval closed at retirement
|
|
333
|
+
(`has_valid_until=True, valid_until=...`). They are applied to the
|
|
334
|
+
last sample before the terminal members, so the instance ends in one
|
|
335
|
+
terminal sample. Until 0.7.4 a type with such members had to write
|
|
336
|
+
its terminal state itself, and this wrote it again (S18). The members
|
|
337
|
+
this method sets (`state`, `state_reason`, `stamp`) and the key are
|
|
338
|
+
not changes a caller can make.
|
|
307
339
|
"""
|
|
308
340
|
if not isinstance(reason, str) or not reason.strip():
|
|
309
341
|
raise ValueError("withdraw() needs a non-empty reason=: a removal "
|
|
310
342
|
"is a claim, and §2.14 makes it say why")
|
|
343
|
+
fixed = {"state", "state_reason", "stamp", codec.key_member(self._lane.fqn)}
|
|
344
|
+
refused = sorted(set(changes) & fixed)
|
|
345
|
+
if refused:
|
|
346
|
+
raise ValueError(f"withdraw() sets {', '.join(refused)} itself; "
|
|
347
|
+
f"pass reason=, and the other members to change")
|
|
311
348
|
with self._lock:
|
|
312
349
|
if key not in self._last:
|
|
313
350
|
raise KeyError(f"{self.topic} holds no instance keyed {key!r} "
|
|
314
351
|
f"from this writer (held: "
|
|
315
352
|
f"{', '.join(sorted(self._last)) or 'none'})")
|
|
316
|
-
|
|
353
|
+
last = self._last[key]
|
|
354
|
+
unknown = sorted(n for n in changes if not _has_member(last, n))
|
|
355
|
+
if unknown:
|
|
356
|
+
raise ValueError(f"{self._lane.fqn} has no member "
|
|
357
|
+
f"{', '.join(unknown)}")
|
|
358
|
+
terminal = self._terminal(dataclasses.replace(last, **changes),
|
|
359
|
+
reason)
|
|
360
|
+
if changes and self.validate:
|
|
361
|
+
codec.validate(terminal)
|
|
362
|
+
del self._last[key]
|
|
317
363
|
# Immediately: nothing of this writer's may come between the
|
|
318
364
|
# terminal sample and its dispose (N.5.2).
|
|
319
365
|
self._dw.write(terminal)
|
|
320
366
|
self._dw.dispose(terminal)
|
|
321
|
-
self._p._recorded(self.topic, self._lane.fqn, terminal
|
|
367
|
+
self._p._recorded(self.topic, self._lane.fqn, terminal,
|
|
368
|
+
self._lane.profile.durability)
|
|
322
369
|
self._p._recorded_dispose(self.topic, key, reason)
|
|
323
370
|
log.info("withdrew %s from %s: %s", key, self.topic, reason)
|
|
324
371
|
|
|
@@ -353,7 +400,7 @@ class Writer:
|
|
|
353
400
|
self._dw.unregister_instance(sample)
|
|
354
401
|
|
|
355
402
|
def _flush(self, timeout_s: float) -> bool:
|
|
356
|
-
return
|
|
403
|
+
return _wait_for_acks(self._dw, timeout_s, self.topic)
|
|
357
404
|
|
|
358
405
|
def topic_meta(self) -> Dict[str, Any]:
|
|
359
406
|
"""This lane as one `TopicMeta`, through the web layer's builder."""
|
|
@@ -1008,9 +1055,10 @@ class Participant:
|
|
|
1008
1055
|
svc["last"])
|
|
1009
1056
|
return r
|
|
1010
1057
|
|
|
1011
|
-
def _recorded(self, topic: str, fqn: str, sample: Any
|
|
1058
|
+
def _recorded(self, topic: str, fqn: str, sample: Any,
|
|
1059
|
+
durability: str = "") -> None:
|
|
1012
1060
|
for r in self._recorders:
|
|
1013
|
-
r.sample(topic, fqn, sample)
|
|
1061
|
+
r.sample(topic, fqn, sample, durability)
|
|
1014
1062
|
|
|
1015
1063
|
def _recorded_dispose(self, topic: str, key: str, reason: str) -> None:
|
|
1016
1064
|
for r in self._recorders:
|
|
@@ -1039,7 +1087,7 @@ class Participant:
|
|
|
1039
1087
|
for w in self._writers:
|
|
1040
1088
|
w._flush(flush_s)
|
|
1041
1089
|
for dw in self._presence_writers():
|
|
1042
|
-
dw
|
|
1090
|
+
_wait_for_acks(dw, flush_s, "presence")
|
|
1043
1091
|
for r in self._recorders:
|
|
1044
1092
|
r.flush()
|
|
1045
1093
|
finally:
|
|
@@ -158,8 +158,15 @@ def extend(type_name: str, cls: type, idl: Any) -> Extension:
|
|
|
158
158
|
files: list = []
|
|
159
159
|
for inc in re.findall(r'^\s*#include\s+"([^"]+)"', text, re.M):
|
|
160
160
|
if not (pin.IDL_DIR / inc).is_file():
|
|
161
|
+
# Includes are rooted at the pin, where idlc given a subdirectory
|
|
162
|
+
# with -I would take a bare name. Name the rooted spelling when
|
|
163
|
+
# there is exactly one, rather than leave the author to find it.
|
|
164
|
+
rooted = sorted(str(f.relative_to(pin.IDL_DIR)) for f in
|
|
165
|
+
pin.IDL_DIR.rglob(Path(inc).name))
|
|
166
|
+
hint = (f"; includes are rooted at the pin: did you mean "
|
|
167
|
+
f"{rooted[0]!r}?" if len(rooted) == 1 else "")
|
|
161
168
|
problems.append(f"the extension's IDL includes {inc!r}, which the "
|
|
162
|
-
f"pinned IDL does not have")
|
|
169
|
+
f"pinned IDL does not have{hint}")
|
|
163
170
|
continue
|
|
164
171
|
for f in pin.file_closure(inc):
|
|
165
172
|
if f not in files:
|
|
@@ -69,7 +69,8 @@ class Recorder:
|
|
|
69
69
|
self._last = t
|
|
70
70
|
return t
|
|
71
71
|
|
|
72
|
-
def sample(self, topic: str, fqn: str, sample: Any
|
|
72
|
+
def sample(self, topic: str, fqn: str, sample: Any,
|
|
73
|
+
durability: str = "") -> None:
|
|
73
74
|
with self._lock:
|
|
74
75
|
if self._closed:
|
|
75
76
|
return
|
|
@@ -82,7 +83,9 @@ class Recorder:
|
|
|
82
83
|
if topic not in self._channels:
|
|
83
84
|
self._channels[topic] = self._w.register_channel(
|
|
84
85
|
topic=topic, message_encoding="cdr",
|
|
85
|
-
schema_id=self._schemas[fqn]
|
|
86
|
+
schema_id=self._schemas[fqn],
|
|
87
|
+
metadata=({mcapmeta.CHANNEL_DURABILITY: durability}
|
|
88
|
+
if durability else {}))
|
|
86
89
|
t = self._now()
|
|
87
90
|
self._w.add_message(channel_id=self._channels[topic], log_time=t,
|
|
88
91
|
publish_time=t, data=sample.serialize(),
|
|
@@ -237,9 +237,17 @@ def stamp(when: Any = None) -> Dict[str, Any]:
|
|
|
237
237
|
elif isinstance(when, str):
|
|
238
238
|
w = _dt.datetime.fromisoformat(when.replace("Z", "+00:00"))
|
|
239
239
|
t = (w if w.tzinfo else w.replace(tzinfo=_dt.timezone.utc)).timestamp()
|
|
240
|
+
elif isinstance(when, int):
|
|
241
|
+
t = when # exact: no float on the way through
|
|
240
242
|
else:
|
|
241
243
|
t = float(when)
|
|
242
|
-
|
|
244
|
+
# One integer count of nanoseconds, split by divmod, which floors both
|
|
245
|
+
# parts: `nanosec` is always in [0, 10^9), and a time before the epoch
|
|
246
|
+
# keeps its sign in `sec`. Until 0.7.4 the parts were computed apart, so
|
|
247
|
+
# 5.9999999999 gave nanosec 10^9, and -0.25 gave +0.75 s (S16).
|
|
248
|
+
ns = t * 1_000_000_000 if isinstance(t, int) else round(t * 1e9)
|
|
249
|
+
sec, nanosec = divmod(ns, 1_000_000_000)
|
|
250
|
+
return {"sec": str(sec), "nanosec": nanosec}
|
|
243
251
|
|
|
244
252
|
|
|
245
253
|
def earth_fixed() -> Dict[str, Any]:
|
|
@@ -58,6 +58,11 @@ def build_parser(ap: argparse.ArgumentParser) -> argparse.ArgumentParser:
|
|
|
58
58
|
help="a typed SpatialDDS MCAP to seed from. Optional: "
|
|
59
59
|
"with no recording the registry starts empty and "
|
|
60
60
|
"takes its types from the IDL pinned in this package.")
|
|
61
|
+
ap.add_argument("--public", action="append", default=[], metavar="FQN",
|
|
62
|
+
help="serve this type's lanes public (repeatable), for a "
|
|
63
|
+
"deployment's own type in --mcap, which is "
|
|
64
|
+
"operator-scoped otherwise: who may read it is the "
|
|
65
|
+
"deployment's call, not the recording's")
|
|
61
66
|
ap.add_argument("--authority", default=None,
|
|
62
67
|
help="the DNS name this registry answers as, e.g. "
|
|
63
68
|
"registry.mytown.example. Every URI it accepts and "
|
|
@@ -202,7 +207,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
202
207
|
try:
|
|
203
208
|
st = gateway.build_state(
|
|
204
209
|
a.mcap, a.manifests if a.manifests and a.manifests.is_dir()
|
|
205
|
-
else None)
|
|
210
|
+
else None, public=a.public)
|
|
206
211
|
except gateway.RecordingRefused as e:
|
|
207
212
|
raise SystemExit(str(e))
|
|
208
213
|
# The manifest hands clients absolute URLs, so the base has to be the
|
|
@@ -351,7 +351,8 @@ def _non_finite(v: Any, at: str = "") -> tuple[str, float] | None:
|
|
|
351
351
|
|
|
352
352
|
|
|
353
353
|
def build_state(path: Path | None, manifests: Path | None = None,
|
|
354
|
-
idl_dir: Path | None | object = PINNED
|
|
354
|
+
idl_dir: Path | None | object = PINNED,
|
|
355
|
+
public: Iterable[str] = ()) -> State:
|
|
355
356
|
"""The state a recording describes, or an empty registry if given none.
|
|
356
357
|
|
|
357
358
|
A seed is optional because the publish surface makes the recording one
|
|
@@ -363,7 +364,16 @@ def build_state(path: Path | None, manifests: Path | None = None,
|
|
|
363
364
|
a directory without the IDL in it, leaves the gateway typeless -- which is
|
|
364
365
|
still a legitimate read-only state, and the refusal that follows belongs
|
|
365
366
|
where publishing is switched on.
|
|
367
|
+
|
|
368
|
+
A type `DURABILITY` has no row for, a deployment's own, is latched if
|
|
369
|
+
the recording says its writer opened the lane TRANSIENT_LOCAL
|
|
370
|
+
(`mcapmeta.CHANNEL_DURABILITY`), and operator-scoped unless named in
|
|
371
|
+
`public`: who may read a lane is the deployment's call, and the file
|
|
372
|
+
cannot make it. Until 0.7.4 such a lane was always volatile and
|
|
373
|
+
operator-scoped (S20). A type with a row keeps its row: the table is
|
|
374
|
+
the specification's, and a recording does not override it.
|
|
366
375
|
"""
|
|
376
|
+
public = frozenset(public)
|
|
367
377
|
if path is None:
|
|
368
378
|
where = pin.IDL_DIR if idl_dir is PINNED else idl_dir
|
|
369
379
|
model, idl = pin.wire_model(where) if where is not None \
|
|
@@ -437,7 +447,14 @@ def build_state(path: Path | None, manifests: Path | None = None,
|
|
|
437
447
|
agg = model.get(fqn)
|
|
438
448
|
keys = [m.name for m in (agg.members if agg else [])
|
|
439
449
|
if m.is_key]
|
|
440
|
-
|
|
450
|
+
if fqn in DURABILITY:
|
|
451
|
+
latched, access = DURABILITY[fqn]
|
|
452
|
+
else:
|
|
453
|
+
latched = (ch.metadata.get(mcapmeta.CHANNEL_DURABILITY)
|
|
454
|
+
== "TRANSIENT_LOCAL")
|
|
455
|
+
access = OPERATOR
|
|
456
|
+
if fqn in public:
|
|
457
|
+
access = PUBLIC
|
|
441
458
|
res = Resource(scene, stream, type_seg, version, ch.topic, fqn,
|
|
442
459
|
keys[0] if keys else "", access, latched)
|
|
443
460
|
st.resources[res.path] = res
|
|
@@ -497,18 +497,29 @@ def _text_response(request: web.Request, text: str,
|
|
|
497
497
|
charset="utf-8", headers=headers)
|
|
498
498
|
|
|
499
499
|
|
|
500
|
+
def _schemas(request: web.Request) -> dict[str, dict]:
|
|
501
|
+
"""The vendored schemas, and one for each served type they lack (S19).
|
|
502
|
+
|
|
503
|
+
N.2: an endpoint MUST publish a schema for every type it serves. A
|
|
504
|
+
deployment's own type is described by the model it is decoded with.
|
|
505
|
+
"""
|
|
506
|
+
st: gateway.State = request.app["state"]
|
|
507
|
+
return webjson.served_schemas(st.model,
|
|
508
|
+
{r.fqn for r in st.resources.values()})
|
|
509
|
+
|
|
510
|
+
|
|
500
511
|
async def schemas_index(request: web.Request) -> web.Response:
|
|
501
512
|
base = request.app["base"]
|
|
502
513
|
doc = [{"type": fqn,
|
|
503
514
|
"url": f"{base}{WELL_KNOWN}/schemas/{webjson.schema_file_for(fqn)}",
|
|
504
515
|
"digest": f"sha256:{webjson.digest(schema)}"}
|
|
505
|
-
for fqn, schema in sorted(
|
|
516
|
+
for fqn, schema in sorted(_schemas(request).items())]
|
|
506
517
|
return _json_response(request, doc, gateway.PUBLIC)
|
|
507
518
|
|
|
508
519
|
|
|
509
520
|
async def schema_one(request: web.Request) -> web.Response:
|
|
510
521
|
name = request.match_info["type"]
|
|
511
|
-
for fqn, schema in
|
|
522
|
+
for fqn, schema in _schemas(request).items():
|
|
512
523
|
if webjson.schema_file_for(fqn) == name:
|
|
513
524
|
return _json_response(request, schema, gateway.PUBLIC)
|
|
514
525
|
raise web.HTTPNotFound(
|